lbajardsilogic@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: Sonic Visualiser lbajardsilogic@0: An audio file viewer and annotation editor. lbajardsilogic@0: Centre for Digital Music, Queen Mary, University of London. lbajardsilogic@0: This file copyright 2006 QMUL. lbajardsilogic@0: lbajardsilogic@0: This program is free software; you can redistribute it and/or lbajardsilogic@0: modify it under the terms of the GNU General Public License as lbajardsilogic@0: published by the Free Software Foundation; either version 2 of the lbajardsilogic@0: License, or (at your option) any later version. See the file lbajardsilogic@0: COPYING included with this distribution for more information. lbajardsilogic@0: */ lbajardsilogic@0: lbarthelemy@187: #include lbarthelemy@187: lbajardsilogic@0: #include "StorageAdviser.h" lbajardsilogic@0: lbajardsilogic@0: #include "Exceptions.h" lbajardsilogic@0: #include "TempDirectory.h" lbajardsilogic@0: lbajardsilogic@0: #include "system/System.h" lbajardsilogic@0: lbarthelemy@187: lbajardsilogic@0: lbajardsilogic@0: long StorageAdviser::m_discPlanned = 0; lbajardsilogic@0: long StorageAdviser::m_memoryPlanned = 0; lbajardsilogic@0: lbajardsilogic@0: StorageAdviser::Recommendation lbajardsilogic@0: StorageAdviser::recommend(Criteria criteria, lbajardsilogic@0: int minimumSize, lbajardsilogic@0: int maximumSize) lbajardsilogic@0: { lbajardsilogic@0: std::cerr << "StorageAdviser::recommend: Criteria " << criteria lbajardsilogic@0: << ", minimumSize " << minimumSize lbajardsilogic@0: << ", maximumSize " << maximumSize << std::endl; lbajardsilogic@0: lbajardsilogic@0: QString path = TempDirectory::getInstance()->getPath(); lbajardsilogic@0: int discFree = GetDiscSpaceMBAvailable(path.toLocal8Bit()); lbajardsilogic@0: int memoryFree, memoryTotal; lbajardsilogic@0: GetRealMemoryMBAvailable(memoryFree, memoryTotal); lbajardsilogic@0: lbajardsilogic@0: if (discFree > m_discPlanned / 1024 + 1) { lbajardsilogic@0: discFree -= m_discPlanned / 1024 + 1; lbajardsilogic@0: } else if (discFree > 0) { // can also be -1 for unknown lbajardsilogic@0: discFree = 0; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (memoryFree > m_memoryPlanned / 1024 + 1) { lbajardsilogic@0: memoryFree -= m_memoryPlanned / 1024 + 1; lbajardsilogic@0: } else if (memoryFree > 0) { // can also be -1 for unknown lbajardsilogic@0: memoryFree = 0; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: std::cerr << "Disc space: " << discFree << ", memory free: " << memoryFree << ", memory total: " << memoryTotal << std::endl; lbajardsilogic@0: lbajardsilogic@0: //!!! We have a potentially serious problem here if multiple lbajardsilogic@0: //recommendations are made in advance of any of the resulting lbajardsilogic@0: //allocations, as the allocations that have been recommended for lbajardsilogic@0: //won't be taken into account in subsequent recommendations. lbajardsilogic@0: lbajardsilogic@0: enum StorageStatus { lbajardsilogic@0: Unknown, lbajardsilogic@0: Insufficient, lbajardsilogic@0: Marginal, lbajardsilogic@0: Sufficient lbajardsilogic@0: }; lbajardsilogic@0: lbajardsilogic@0: StorageStatus memoryStatus = Unknown; lbajardsilogic@0: StorageStatus discStatus = Unknown; lbajardsilogic@0: lbajardsilogic@0: int minmb = minimumSize / 1024 + 1; lbajardsilogic@0: int maxmb = maximumSize / 1024 + 1; lbajardsilogic@0: lbajardsilogic@0: if (memoryFree == -1) memoryStatus = Unknown; lbajardsilogic@0: else if (minmb > (memoryFree * 3) / 4) memoryStatus = Insufficient; lbajardsilogic@0: else if (maxmb > (memoryFree * 3) / 4) memoryStatus = Marginal; lbajardsilogic@0: else if (minmb > (memoryFree / 3)) memoryStatus = Marginal; lbajardsilogic@0: else if (memoryTotal == -1 || lbajardsilogic@0: minmb > (memoryTotal / 10)) memoryStatus = Marginal; lbajardsilogic@0: else memoryStatus = Sufficient; lbajardsilogic@0: lbajardsilogic@0: if (discFree == -1) discStatus = Unknown; lbajardsilogic@0: else if (minmb > (discFree * 3) / 4) discStatus = Insufficient; lbajardsilogic@0: else if (maxmb > (discFree / 4)) discStatus = Marginal; lbajardsilogic@0: else if (minmb > (discFree / 10)) discStatus = Marginal; lbajardsilogic@0: else discStatus = Sufficient; lbajardsilogic@0: lbajardsilogic@0: std::cerr << "Memory status: " << memoryStatus << ", disc status " lbajardsilogic@0: << discStatus << std::endl; lbajardsilogic@0: lbajardsilogic@0: int recommendation = NoRecommendation; lbajardsilogic@0: lbajardsilogic@0: if (memoryStatus == Insufficient || memoryStatus == Unknown) { lbajardsilogic@0: lbajardsilogic@0: recommendation |= UseDisc; lbajardsilogic@0: lbajardsilogic@0: if (discStatus == Insufficient && minmb > discFree) { lbajardsilogic@0: throw InsufficientDiscSpace(path, minmb, discFree); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (discStatus == Insufficient || discStatus == Marginal) { lbajardsilogic@0: recommendation |= ConserveSpace; lbajardsilogic@0: } else if (discStatus == Unknown && !(criteria & PrecisionCritical)) { lbajardsilogic@0: recommendation |= ConserveSpace; lbajardsilogic@0: } else { lbajardsilogic@0: recommendation |= UseAsMuchAsYouLike; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (memoryStatus == Marginal) { lbajardsilogic@0: lbajardsilogic@0: if (((criteria & SpeedCritical) || lbajardsilogic@0: (criteria & FrequentLookupLikely)) && lbajardsilogic@0: !(criteria & PrecisionCritical) && lbajardsilogic@0: !(criteria & LongRetentionLikely)) { lbajardsilogic@0: lbajardsilogic@0: // requirements suggest a preference for memory lbajardsilogic@0: lbajardsilogic@0: if (discStatus != Insufficient) { lbajardsilogic@0: recommendation |= PreferMemory; lbajardsilogic@0: } else { lbajardsilogic@0: recommendation |= UseMemory; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: recommendation |= ConserveSpace; lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: if (discStatus == Insufficient) { lbajardsilogic@0: recommendation |= (UseMemory | ConserveSpace); lbajardsilogic@0: } else if (discStatus == Marginal) { lbajardsilogic@0: recommendation |= (PreferMemory | ConserveSpace); lbajardsilogic@0: } else if (discStatus == Unknown) { lbajardsilogic@0: recommendation |= (PreferDisc | ConserveSpace); lbajardsilogic@0: } else { lbajardsilogic@0: recommendation |= (UseDisc | UseAsMuchAsYouLike); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: if (discStatus == Insufficient) { lbajardsilogic@0: recommendation |= (UseMemory | ConserveSpace); lbajardsilogic@0: } else if (discStatus != Sufficient) { lbajardsilogic@0: recommendation |= (PreferMemory | ConserveSpace); lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: if ((criteria & SpeedCritical) || lbajardsilogic@0: (criteria & FrequentLookupLikely)) { lbajardsilogic@0: recommendation |= PreferMemory; lbajardsilogic@0: if (criteria & PrecisionCritical) { lbajardsilogic@0: recommendation |= UseAsMuchAsYouLike; lbajardsilogic@0: } else { lbajardsilogic@0: recommendation |= ConserveSpace; lbajardsilogic@0: } lbajardsilogic@0: } else { lbajardsilogic@0: recommendation |= PreferDisc; lbajardsilogic@0: recommendation |= UseAsMuchAsYouLike; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: return Recommendation(recommendation); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: StorageAdviser::notifyPlannedAllocation(AllocationArea area, int size) lbajardsilogic@0: { lbajardsilogic@0: if (area == MemoryAllocation) m_memoryPlanned += size; lbajardsilogic@0: else if (area == DiscAllocation) m_discPlanned += size; lbajardsilogic@0: // std::cerr << "storage planned up: memory: " << m_memoryPlanned << ", disc " lbajardsilogic@0: // << m_discPlanned << std::endl; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: StorageAdviser::notifyDoneAllocation(AllocationArea area, int size) lbajardsilogic@0: { lbajardsilogic@0: if (area == MemoryAllocation) { lbajardsilogic@0: if (m_memoryPlanned > size) m_memoryPlanned -= size; lbajardsilogic@0: else m_memoryPlanned = 0; lbajardsilogic@0: } else if (area == DiscAllocation) { lbajardsilogic@0: if (m_discPlanned > size) m_discPlanned -= size; lbajardsilogic@0: else m_discPlanned = 0; lbajardsilogic@0: } lbajardsilogic@0: // std::cerr << "storage planned down: memory: " << m_memoryPlanned << ", disc " lbajardsilogic@0: // << m_discPlanned << std::endl; lbajardsilogic@0: } lbajardsilogic@0: