svcore
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006 QMUL. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #include "StorageAdviser.h" 00017 00018 #include "Exceptions.h" 00019 #include "TempDirectory.h" 00020 00021 #include "system/System.h" 00022 00023 #include <iostream> 00024 00025 //#define DEBUG_STORAGE_ADVISER 1 00026 00027 long StorageAdviser::m_discPlanned = 0; 00028 long StorageAdviser::m_memoryPlanned = 0; 00029 00030 StorageAdviser::Recommendation 00031 StorageAdviser::m_baseRecommendation = StorageAdviser::NoRecommendation; 00032 00033 StorageAdviser::Recommendation 00034 StorageAdviser::recommend(Criteria criteria, 00035 int minimumSize, 00036 int maximumSize) 00037 { 00038 #ifdef DEBUG_STORAGE_ADVISER 00039 SVDEBUG << "StorageAdviser::recommend: Criteria " << criteria 00040 << ", minimumSize " << minimumSize 00041 << ", maximumSize " << maximumSize << endl; 00042 #endif 00043 00044 if (m_baseRecommendation != NoRecommendation) { 00045 return m_baseRecommendation; // for now 00046 } 00047 00048 QString path; 00049 try { 00050 path = TempDirectory::getInstance()->getPath(); 00051 } catch (std::exception e) { 00052 cerr << "StorageAdviser::recommend: ERROR: Failed to get temporary directory path: " << e.what() << endl; 00053 return Recommendation(UseMemory | ConserveSpace); 00054 } 00055 int discFree = GetDiscSpaceMBAvailable(path.toLocal8Bit()); 00056 int memoryFree, memoryTotal; 00057 GetRealMemoryMBAvailable(memoryFree, memoryTotal); 00058 00059 if (discFree > m_discPlanned / 1024 + 1) { 00060 discFree -= m_discPlanned / 1024 + 1; 00061 } else if (discFree > 0) { // can also be -1 for unknown 00062 discFree = 0; 00063 } 00064 00065 if (memoryFree > m_memoryPlanned / 1024 + 1) { 00066 memoryFree -= m_memoryPlanned / 1024 + 1; 00067 } else if (memoryFree > 0) { // can also be -1 for unknown 00068 memoryFree = 0; 00069 } 00070 00071 #ifdef DEBUG_STORAGE_ADVISER 00072 cerr << "Disc space: " << discFree << ", memory free: " << memoryFree << ", memory total: " << memoryTotal << ", min " << minimumSize << ", max " << maximumSize << endl; 00073 #endif 00074 00076 //recommendations are made in advance of any of the resulting 00077 //allocations, as the allocations that have been recommended for 00078 //won't be taken into account in subsequent recommendations. 00079 00080 enum StorageStatus { 00081 Unknown, 00082 Insufficient, 00083 Marginal, 00084 Sufficient 00085 }; 00086 00087 StorageStatus memoryStatus = Unknown; 00088 StorageStatus discStatus = Unknown; 00089 00090 int minmb = minimumSize / 1024 + 1; 00091 int maxmb = maximumSize / 1024 + 1; 00092 00093 if (memoryFree == -1) memoryStatus = Unknown; 00094 else if (memoryFree < memoryTotal / 3) memoryStatus = Insufficient; 00095 else if (minmb > (memoryFree * 3) / 4) memoryStatus = Insufficient; 00096 else if (maxmb > (memoryFree * 3) / 4) memoryStatus = Marginal; 00097 else if (minmb > (memoryFree / 3)) memoryStatus = Marginal; 00098 else if (memoryTotal == -1 || 00099 minmb > (memoryTotal / 10)) memoryStatus = Marginal; 00100 else memoryStatus = Sufficient; 00101 00102 if (discFree == -1) discStatus = Unknown; 00103 else if (minmb > (discFree * 3) / 4) discStatus = Insufficient; 00104 else if (maxmb > (discFree / 4)) discStatus = Marginal; 00105 else if (minmb > (discFree / 10)) discStatus = Marginal; 00106 else discStatus = Sufficient; 00107 00108 #ifdef DEBUG_STORAGE_ADVISER 00109 cerr << "Memory status: " << memoryStatus << ", disc status " 00110 << discStatus << endl; 00111 #endif 00112 00113 int recommendation = NoRecommendation; 00114 00115 if (memoryStatus == Insufficient || memoryStatus == Unknown) { 00116 00117 recommendation |= UseDisc; 00118 00119 if (discStatus == Insufficient && minmb > discFree) { 00120 throw InsufficientDiscSpace(path, minmb, discFree); 00121 } 00122 00123 if (discStatus == Insufficient || discStatus == Marginal) { 00124 recommendation |= ConserveSpace; 00125 } else if (discStatus == Unknown && !(criteria & PrecisionCritical)) { 00126 recommendation |= ConserveSpace; 00127 } else { 00128 recommendation |= UseAsMuchAsYouLike; 00129 } 00130 00131 } else if (memoryStatus == Marginal) { 00132 00133 if (((criteria & SpeedCritical) || 00134 (criteria & FrequentLookupLikely)) && 00135 !(criteria & PrecisionCritical) && 00136 !(criteria & LongRetentionLikely)) { 00137 00138 // requirements suggest a preference for memory 00139 00140 if (discStatus != Insufficient) { 00141 recommendation |= PreferMemory; 00142 } else { 00143 recommendation |= UseMemory; 00144 } 00145 00146 recommendation |= ConserveSpace; 00147 00148 } else { 00149 00150 if (discStatus == Insufficient) { 00151 recommendation |= (UseMemory | ConserveSpace); 00152 } else if (discStatus == Marginal) { 00153 recommendation |= (PreferMemory | ConserveSpace); 00154 } else if (discStatus == Unknown) { 00155 recommendation |= (PreferDisc | ConserveSpace); 00156 } else { 00157 recommendation |= (UseDisc | UseAsMuchAsYouLike); 00158 } 00159 } 00160 00161 } else { 00162 00163 if (discStatus == Insufficient) { 00164 recommendation |= (UseMemory | ConserveSpace); 00165 } else if (discStatus != Sufficient) { 00166 recommendation |= (PreferMemory | ConserveSpace); 00167 } else { 00168 00169 if ((criteria & SpeedCritical) || 00170 (criteria & FrequentLookupLikely)) { 00171 recommendation |= PreferMemory; 00172 if (criteria & PrecisionCritical) { 00173 recommendation |= UseAsMuchAsYouLike; 00174 } else { 00175 recommendation |= ConserveSpace; 00176 } 00177 } else { 00178 recommendation |= PreferDisc; 00179 recommendation |= UseAsMuchAsYouLike; 00180 } 00181 } 00182 } 00183 00184 return Recommendation(recommendation); 00185 } 00186 00187 void 00188 StorageAdviser::notifyPlannedAllocation(AllocationArea area, int size) 00189 { 00190 if (area == MemoryAllocation) m_memoryPlanned += size; 00191 else if (area == DiscAllocation) m_discPlanned += size; 00192 // cerr << "storage planned up: memory: " << m_memoryPlanned << ", disc " 00193 // << m_discPlanned << endl; 00194 } 00195 00196 void 00197 StorageAdviser::notifyDoneAllocation(AllocationArea area, int size) 00198 { 00199 if (area == MemoryAllocation) { 00200 if (m_memoryPlanned > size) m_memoryPlanned -= size; 00201 else m_memoryPlanned = 0; 00202 } else if (area == DiscAllocation) { 00203 if (m_discPlanned > size) m_discPlanned -= size; 00204 else m_discPlanned = 0; 00205 } 00206 // cerr << "storage planned down: memory: " << m_memoryPlanned << ", disc " 00207 // << m_discPlanned << endl; 00208 } 00209 00210 void 00211 StorageAdviser::setFixedRecommendation(Recommendation recommendation) 00212 { 00213 m_baseRecommendation = recommendation; 00214 } 00215