StorageAdviser.cpp

Go to the documentation of this file.
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::recommend(Criteria criteria,
00032                           int minimumSize,
00033                           int maximumSize)
00034 {
00035 #ifdef DEBUG_STORAGE_ADVISER
00036     std::cerr << "StorageAdviser::recommend: Criteria " << criteria 
00037               << ", minimumSize " << minimumSize
00038               << ", maximumSize " << maximumSize << std::endl;
00039 #endif
00040 
00041     QString path = TempDirectory::getInstance()->getPath();
00042     int discFree = GetDiscSpaceMBAvailable(path.toLocal8Bit());
00043     int memoryFree, memoryTotal;
00044     GetRealMemoryMBAvailable(memoryFree, memoryTotal);
00045 
00046     if (discFree > m_discPlanned / 1024 + 1) {
00047         discFree -= m_discPlanned / 1024 + 1;
00048     } else if (discFree > 0) { // can also be -1 for unknown
00049         discFree = 0;
00050     }
00051 
00052     if (memoryFree > m_memoryPlanned / 1024 + 1) {
00053         memoryFree -= m_memoryPlanned / 1024 + 1;
00054     } else if (memoryFree > 0) { // can also be -1 for unknown
00055         memoryFree = 0;
00056     }
00057 
00058 #ifdef DEBUG_STORAGE_ADVISER
00059     std::cerr << "Disc space: " << discFree << ", memory free: " << memoryFree << ", memory total: " << memoryTotal << ", min " << minimumSize << ", max " << maximumSize << std::endl;
00060 #endif
00061 
00063     //recommendations are made in advance of any of the resulting
00064     //allocations, as the allocations that have been recommended for
00065     //won't be taken into account in subsequent recommendations.
00066 
00067     enum StorageStatus {
00068         Unknown,
00069         Insufficient,
00070         Marginal,
00071         Sufficient
00072     };
00073 
00074     StorageStatus memoryStatus = Unknown;
00075     StorageStatus discStatus = Unknown;
00076 
00077     int minmb = minimumSize / 1024 + 1;
00078     int maxmb = maximumSize / 1024 + 1;
00079 
00080     if (memoryFree == -1) memoryStatus = Unknown;
00081     else if (minmb > (memoryFree * 3) / 4) memoryStatus = Insufficient;
00082     else if (maxmb > (memoryFree * 3) / 4) memoryStatus = Marginal;
00083     else if (minmb > (memoryFree / 3)) memoryStatus = Marginal;
00084     else if (memoryTotal == -1 ||
00085              minmb > (memoryTotal / 10)) memoryStatus = Marginal;
00086     else if (memoryFree < memoryTotal / 4) memoryStatus = Marginal;
00087     else memoryStatus = Sufficient;
00088 
00089     if (discFree == -1) discStatus = Unknown;
00090     else if (minmb > (discFree * 3) / 4) discStatus = Insufficient;
00091     else if (maxmb > (discFree / 4)) discStatus = Marginal;
00092     else if (minmb > (discFree / 10)) discStatus = Marginal;
00093     else discStatus = Sufficient;
00094 
00095 #ifdef DEBUG_STORAGE_ADVISER
00096     std::cerr << "Memory status: " << memoryStatus << ", disc status "
00097               << discStatus << std::endl;
00098 #endif
00099 
00100     int recommendation = NoRecommendation;
00101 
00102     if (memoryStatus == Insufficient || memoryStatus == Unknown) {
00103 
00104         recommendation |= UseDisc;
00105 
00106         if (discStatus == Insufficient && minmb > discFree) {
00107             throw InsufficientDiscSpace(path, minmb, discFree);
00108         }
00109 
00110         if (discStatus == Insufficient || discStatus == Marginal) {
00111             recommendation |= ConserveSpace;
00112         } else if (discStatus == Unknown && !(criteria & PrecisionCritical)) {
00113             recommendation |= ConserveSpace;
00114         } else {
00115             recommendation |= UseAsMuchAsYouLike;
00116         }
00117 
00118     } else if (memoryStatus == Marginal) {
00119 
00120         if (((criteria & SpeedCritical) ||
00121              (criteria & FrequentLookupLikely)) &&
00122             !(criteria & PrecisionCritical) &&
00123             !(criteria & LongRetentionLikely)) {
00124 
00125             // requirements suggest a preference for memory
00126 
00127             if (discStatus != Insufficient) {
00128                 recommendation |= PreferMemory;
00129             } else {
00130                 recommendation |= UseMemory;
00131             }
00132 
00133             recommendation |= ConserveSpace;
00134 
00135         } else {
00136 
00137             if (discStatus == Insufficient) {
00138                 recommendation |= (UseMemory | ConserveSpace);
00139             } else if (discStatus == Marginal) {
00140                 recommendation |= (PreferMemory | ConserveSpace);
00141             } else if (discStatus == Unknown) {
00142                 recommendation |= (PreferDisc | ConserveSpace);
00143             } else {
00144                 recommendation |= (UseDisc | UseAsMuchAsYouLike);
00145             }
00146         }    
00147 
00148     } else {
00149 
00150         if (discStatus == Insufficient) {
00151             recommendation |= (UseMemory | ConserveSpace);
00152         } else if (discStatus != Sufficient) {
00153             recommendation |= (PreferMemory | ConserveSpace);
00154         } else {
00155 
00156             if ((criteria & SpeedCritical) ||
00157                 (criteria & FrequentLookupLikely)) {
00158                 recommendation |= PreferMemory;
00159                 if (criteria & PrecisionCritical) {
00160                     recommendation |= UseAsMuchAsYouLike;
00161                 } else {
00162                     recommendation |= ConserveSpace;
00163                 }
00164             } else {
00165                 recommendation |= PreferDisc;
00166                 recommendation |= UseAsMuchAsYouLike;
00167             }
00168         }
00169     }
00170 
00171     return Recommendation(recommendation);
00172 }
00173 
00174 void
00175 StorageAdviser::notifyPlannedAllocation(AllocationArea area, int size)
00176 {
00177     if (area == MemoryAllocation) m_memoryPlanned += size;
00178     else if (area == DiscAllocation) m_discPlanned += size;
00179 //    std::cerr << "storage planned up: memory: " << m_memoryPlanned << ", disc "
00180 //              << m_discPlanned << std::endl;
00181 }
00182 
00183 void
00184 StorageAdviser::notifyDoneAllocation(AllocationArea area, int size)
00185 {
00186     if (area == MemoryAllocation) {
00187         if (m_memoryPlanned > size) m_memoryPlanned -= size;
00188         else m_memoryPlanned = 0;
00189     } else if (area == DiscAllocation) {
00190         if (m_discPlanned > size) m_discPlanned -= size; 
00191         else m_discPlanned = 0;
00192     }
00193 //    std::cerr << "storage planned down: memory: " << m_memoryPlanned << ", disc "
00194 //              << m_discPlanned << std::endl;
00195 }
00196 

Generated on Wed Feb 20 15:45:28 2008 for SonicVisualiser by  doxygen 1.5.1