Chris@168
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@168
|
2
|
Chris@168
|
3 /*
|
Chris@168
|
4 Sonic Visualiser
|
Chris@168
|
5 An audio file viewer and annotation editor.
|
Chris@168
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@202
|
7 This file copyright 2006 QMUL.
|
Chris@168
|
8
|
Chris@168
|
9 This program is free software; you can redistribute it and/or
|
Chris@168
|
10 modify it under the terms of the GNU General Public License as
|
Chris@168
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@168
|
12 License, or (at your option) any later version. See the file
|
Chris@168
|
13 COPYING included with this distribution for more information.
|
Chris@168
|
14 */
|
Chris@168
|
15
|
Chris@168
|
16 #include "StorageAdviser.h"
|
Chris@168
|
17
|
Chris@168
|
18 #include "Exceptions.h"
|
Chris@168
|
19 #include "TempDirectory.h"
|
Chris@168
|
20
|
Chris@168
|
21 #include "system/System.h"
|
Chris@168
|
22
|
Chris@168
|
23 #include <iostream>
|
Chris@168
|
24
|
Chris@1098
|
25 #define DEBUG_STORAGE_ADVISER 1
|
Chris@374
|
26
|
Chris@1038
|
27 size_t StorageAdviser::m_discPlanned = 0;
|
Chris@1038
|
28 size_t StorageAdviser::m_memoryPlanned = 0;
|
Chris@205
|
29
|
Chris@168
|
30 StorageAdviser::Recommendation
|
Chris@411
|
31 StorageAdviser::m_baseRecommendation = StorageAdviser::NoRecommendation;
|
Chris@411
|
32
|
Chris@411
|
33 StorageAdviser::Recommendation
|
Chris@168
|
34 StorageAdviser::recommend(Criteria criteria,
|
Chris@1038
|
35 size_t minimumSize,
|
Chris@1038
|
36 size_t maximumSize)
|
Chris@168
|
37 {
|
Chris@374
|
38 #ifdef DEBUG_STORAGE_ADVISER
|
Chris@1098
|
39 cerr << "StorageAdviser::recommend: Criteria " << criteria
|
Chris@1098
|
40 << ", minimumSize " << minimumSize
|
Chris@1098
|
41 << ", maximumSize " << maximumSize << endl;
|
Chris@374
|
42 #endif
|
Chris@170
|
43
|
Chris@411
|
44 if (m_baseRecommendation != NoRecommendation) {
|
Chris@411
|
45 return m_baseRecommendation; // for now
|
Chris@411
|
46 }
|
Chris@411
|
47
|
Chris@541
|
48 QString path;
|
Chris@541
|
49 try {
|
Chris@541
|
50 path = TempDirectory::getInstance()->getPath();
|
Chris@541
|
51 } catch (std::exception e) {
|
Chris@843
|
52 cerr << "StorageAdviser::recommend: ERROR: Failed to get temporary directory path: " << e.what() << endl;
|
Chris@541
|
53 return Recommendation(UseMemory | ConserveSpace);
|
Chris@541
|
54 }
|
Chris@1038
|
55 ssize_t discFree = GetDiscSpaceMBAvailable(path.toLocal8Bit());
|
Chris@1038
|
56 ssize_t memoryFree, memoryTotal;
|
Chris@170
|
57 GetRealMemoryMBAvailable(memoryFree, memoryTotal);
|
Chris@168
|
58
|
Chris@1038
|
59 if (discFree > ssize_t(m_discPlanned / 1024 + 1)) {
|
Chris@205
|
60 discFree -= m_discPlanned / 1024 + 1;
|
Chris@205
|
61 } else if (discFree > 0) { // can also be -1 for unknown
|
Chris@205
|
62 discFree = 0;
|
Chris@205
|
63 }
|
Chris@205
|
64
|
Chris@1038
|
65 if (memoryFree > ssize_t(m_memoryPlanned / 1024 + 1)) {
|
Chris@205
|
66 memoryFree -= m_memoryPlanned / 1024 + 1;
|
Chris@205
|
67 } else if (memoryFree > 0) { // can also be -1 for unknown
|
Chris@205
|
68 memoryFree = 0;
|
Chris@205
|
69 }
|
Chris@205
|
70
|
Chris@374
|
71 #ifdef DEBUG_STORAGE_ADVISER
|
Chris@843
|
72 cerr << "Disc space: " << discFree << ", memory free: " << memoryFree << ", memory total: " << memoryTotal << ", min " << minimumSize << ", max " << maximumSize << endl;
|
Chris@374
|
73 #endif
|
Chris@168
|
74
|
Chris@192
|
75 //!!! We have a potentially serious problem here if multiple
|
Chris@192
|
76 //recommendations are made in advance of any of the resulting
|
Chris@192
|
77 //allocations, as the allocations that have been recommended for
|
Chris@192
|
78 //won't be taken into account in subsequent recommendations.
|
Chris@192
|
79
|
Chris@170
|
80 enum StorageStatus {
|
Chris@170
|
81 Unknown,
|
Chris@170
|
82 Insufficient,
|
Chris@170
|
83 Marginal,
|
Chris@170
|
84 Sufficient
|
Chris@170
|
85 };
|
Chris@168
|
86
|
Chris@170
|
87 StorageStatus memoryStatus = Unknown;
|
Chris@170
|
88 StorageStatus discStatus = Unknown;
|
Chris@170
|
89
|
Chris@1038
|
90 ssize_t minmb = ssize_t(minimumSize / 1024 + 1);
|
Chris@1038
|
91 ssize_t maxmb = ssize_t(maximumSize / 1024 + 1);
|
Chris@170
|
92
|
Chris@170
|
93 if (memoryFree == -1) memoryStatus = Unknown;
|
Chris@1103
|
94 else if (memoryFree < memoryTotal / 3 && memoryFree < 512) memoryStatus = Insufficient;
|
Chris@170
|
95 else if (minmb > (memoryFree * 3) / 4) memoryStatus = Insufficient;
|
Chris@170
|
96 else if (maxmb > (memoryFree * 3) / 4) memoryStatus = Marginal;
|
Chris@170
|
97 else if (minmb > (memoryFree / 3)) memoryStatus = Marginal;
|
Chris@170
|
98 else if (memoryTotal == -1 ||
|
Chris@170
|
99 minmb > (memoryTotal / 10)) memoryStatus = Marginal;
|
Chris@170
|
100 else memoryStatus = Sufficient;
|
Chris@170
|
101
|
Chris@170
|
102 if (discFree == -1) discStatus = Unknown;
|
Chris@170
|
103 else if (minmb > (discFree * 3) / 4) discStatus = Insufficient;
|
Chris@173
|
104 else if (maxmb > (discFree / 4)) discStatus = Marginal;
|
Chris@173
|
105 else if (minmb > (discFree / 10)) discStatus = Marginal;
|
Chris@170
|
106 else discStatus = Sufficient;
|
Chris@170
|
107
|
Chris@374
|
108 #ifdef DEBUG_STORAGE_ADVISER
|
Chris@843
|
109 cerr << "Memory status: " << memoryStatus << ", disc status "
|
Chris@843
|
110 << discStatus << endl;
|
Chris@374
|
111 #endif
|
Chris@170
|
112
|
Chris@170
|
113 int recommendation = NoRecommendation;
|
Chris@170
|
114
|
Chris@170
|
115 if (memoryStatus == Insufficient || memoryStatus == Unknown) {
|
Chris@170
|
116
|
Chris@170
|
117 recommendation |= UseDisc;
|
Chris@170
|
118
|
Chris@170
|
119 if (discStatus == Insufficient && minmb > discFree) {
|
Chris@170
|
120 throw InsufficientDiscSpace(path, minmb, discFree);
|
Chris@170
|
121 }
|
Chris@170
|
122
|
Chris@170
|
123 if (discStatus == Insufficient || discStatus == Marginal) {
|
Chris@170
|
124 recommendation |= ConserveSpace;
|
Chris@170
|
125 } else if (discStatus == Unknown && !(criteria & PrecisionCritical)) {
|
Chris@170
|
126 recommendation |= ConserveSpace;
|
Chris@170
|
127 } else {
|
Chris@170
|
128 recommendation |= UseAsMuchAsYouLike;
|
Chris@170
|
129 }
|
Chris@170
|
130
|
Chris@170
|
131 } else if (memoryStatus == Marginal) {
|
Chris@170
|
132
|
Chris@170
|
133 if (((criteria & SpeedCritical) ||
|
Chris@170
|
134 (criteria & FrequentLookupLikely)) &&
|
Chris@170
|
135 !(criteria & PrecisionCritical) &&
|
Chris@170
|
136 !(criteria & LongRetentionLikely)) {
|
Chris@170
|
137
|
Chris@170
|
138 // requirements suggest a preference for memory
|
Chris@170
|
139
|
Chris@170
|
140 if (discStatus != Insufficient) {
|
Chris@170
|
141 recommendation |= PreferMemory;
|
Chris@170
|
142 } else {
|
Chris@170
|
143 recommendation |= UseMemory;
|
Chris@170
|
144 }
|
Chris@170
|
145
|
Chris@170
|
146 recommendation |= ConserveSpace;
|
Chris@170
|
147
|
Chris@170
|
148 } else {
|
Chris@170
|
149
|
Chris@170
|
150 if (discStatus == Insufficient) {
|
Chris@170
|
151 recommendation |= (UseMemory | ConserveSpace);
|
Chris@170
|
152 } else if (discStatus == Marginal) {
|
Chris@170
|
153 recommendation |= (PreferMemory | ConserveSpace);
|
Chris@170
|
154 } else if (discStatus == Unknown) {
|
Chris@170
|
155 recommendation |= (PreferDisc | ConserveSpace);
|
Chris@170
|
156 } else {
|
Chris@170
|
157 recommendation |= (UseDisc | UseAsMuchAsYouLike);
|
Chris@170
|
158 }
|
Chris@170
|
159 }
|
Chris@170
|
160
|
Chris@170
|
161 } else {
|
Chris@170
|
162
|
Chris@170
|
163 if (discStatus == Insufficient) {
|
Chris@170
|
164 recommendation |= (UseMemory | ConserveSpace);
|
Chris@170
|
165 } else if (discStatus != Sufficient) {
|
Chris@170
|
166 recommendation |= (PreferMemory | ConserveSpace);
|
Chris@170
|
167 } else {
|
Chris@170
|
168
|
Chris@170
|
169 if ((criteria & SpeedCritical) ||
|
Chris@170
|
170 (criteria & FrequentLookupLikely)) {
|
Chris@170
|
171 recommendation |= PreferMemory;
|
Chris@170
|
172 if (criteria & PrecisionCritical) {
|
Chris@170
|
173 recommendation |= UseAsMuchAsYouLike;
|
Chris@170
|
174 } else {
|
Chris@170
|
175 recommendation |= ConserveSpace;
|
Chris@170
|
176 }
|
Chris@170
|
177 } else {
|
Chris@170
|
178 recommendation |= PreferDisc;
|
Chris@170
|
179 recommendation |= UseAsMuchAsYouLike;
|
Chris@170
|
180 }
|
Chris@170
|
181 }
|
Chris@170
|
182 }
|
Chris@170
|
183
|
Chris@1098
|
184 #ifdef DEBUG_STORAGE_ADVISER
|
Chris@1098
|
185 cerr << "StorageAdviser: returning recommendation " << recommendation << endl;
|
Chris@1098
|
186 #endif
|
Chris@1098
|
187
|
Chris@170
|
188 return Recommendation(recommendation);
|
Chris@168
|
189 }
|
Chris@168
|
190
|
Chris@205
|
191 void
|
Chris@1038
|
192 StorageAdviser::notifyPlannedAllocation(AllocationArea area, size_t size)
|
Chris@205
|
193 {
|
Chris@205
|
194 if (area == MemoryAllocation) m_memoryPlanned += size;
|
Chris@205
|
195 else if (area == DiscAllocation) m_discPlanned += size;
|
Chris@843
|
196 // cerr << "storage planned up: memory: " << m_memoryPlanned << ", disc "
|
Chris@843
|
197 // << m_discPlanned << endl;
|
Chris@205
|
198 }
|
Chris@205
|
199
|
Chris@205
|
200 void
|
Chris@1038
|
201 StorageAdviser::notifyDoneAllocation(AllocationArea area, size_t size)
|
Chris@205
|
202 {
|
Chris@205
|
203 if (area == MemoryAllocation) {
|
Chris@205
|
204 if (m_memoryPlanned > size) m_memoryPlanned -= size;
|
Chris@205
|
205 else m_memoryPlanned = 0;
|
Chris@205
|
206 } else if (area == DiscAllocation) {
|
Chris@205
|
207 if (m_discPlanned > size) m_discPlanned -= size;
|
Chris@205
|
208 else m_discPlanned = 0;
|
Chris@205
|
209 }
|
Chris@843
|
210 // cerr << "storage planned down: memory: " << m_memoryPlanned << ", disc "
|
Chris@843
|
211 // << m_discPlanned << endl;
|
Chris@205
|
212 }
|
Chris@205
|
213
|
Chris@411
|
214 void
|
Chris@411
|
215 StorageAdviser::setFixedRecommendation(Recommendation recommendation)
|
Chris@411
|
216 {
|
Chris@411
|
217 m_baseRecommendation = recommendation;
|
Chris@411
|
218 }
|
Chris@411
|
219
|