annotate base/StorageAdviser.cpp @ 263:71dfc6ab3b54

* Threaded mp3/ogg file reading. Not activated yet, as it doesn't work in context (SV needs to know the duration of its main model at the outset)
author Chris Cannam
date Thu, 24 May 2007 16:20:22 +0000
parents dc46851837d6
children aa8dbac62024
rev   line source
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@205 25 long StorageAdviser::m_discPlanned = 0;
Chris@205 26 long StorageAdviser::m_memoryPlanned = 0;
Chris@205 27
Chris@168 28 StorageAdviser::Recommendation
Chris@168 29 StorageAdviser::recommend(Criteria criteria,
Chris@168 30 int minimumSize,
Chris@168 31 int maximumSize)
Chris@168 32 {
Chris@170 33 std::cerr << "StorageAdviser::recommend: Criteria " << criteria
Chris@170 34 << ", minimumSize " << minimumSize
Chris@170 35 << ", maximumSize " << maximumSize << std::endl;
Chris@170 36
Chris@168 37 QString path = TempDirectory::getInstance()->getPath();
Chris@170 38 int discFree = GetDiscSpaceMBAvailable(path.toLocal8Bit());
Chris@170 39 int memoryFree, memoryTotal;
Chris@170 40 GetRealMemoryMBAvailable(memoryFree, memoryTotal);
Chris@168 41
Chris@205 42 if (discFree > m_discPlanned / 1024 + 1) {
Chris@205 43 discFree -= m_discPlanned / 1024 + 1;
Chris@205 44 } else if (discFree > 0) { // can also be -1 for unknown
Chris@205 45 discFree = 0;
Chris@205 46 }
Chris@205 47
Chris@205 48 if (memoryFree > m_memoryPlanned / 1024 + 1) {
Chris@205 49 memoryFree -= m_memoryPlanned / 1024 + 1;
Chris@205 50 } else if (memoryFree > 0) { // can also be -1 for unknown
Chris@205 51 memoryFree = 0;
Chris@205 52 }
Chris@205 53
Chris@170 54 std::cerr << "Disc space: " << discFree << ", memory free: " << memoryFree << ", memory total: " << memoryTotal << std::endl;
Chris@168 55
Chris@192 56 //!!! We have a potentially serious problem here if multiple
Chris@192 57 //recommendations are made in advance of any of the resulting
Chris@192 58 //allocations, as the allocations that have been recommended for
Chris@192 59 //won't be taken into account in subsequent recommendations.
Chris@192 60
Chris@170 61 enum StorageStatus {
Chris@170 62 Unknown,
Chris@170 63 Insufficient,
Chris@170 64 Marginal,
Chris@170 65 Sufficient
Chris@170 66 };
Chris@168 67
Chris@170 68 StorageStatus memoryStatus = Unknown;
Chris@170 69 StorageStatus discStatus = Unknown;
Chris@170 70
Chris@170 71 int minmb = minimumSize / 1024 + 1;
Chris@170 72 int maxmb = maximumSize / 1024 + 1;
Chris@170 73
Chris@170 74 if (memoryFree == -1) memoryStatus = Unknown;
Chris@170 75 else if (minmb > (memoryFree * 3) / 4) memoryStatus = Insufficient;
Chris@170 76 else if (maxmb > (memoryFree * 3) / 4) memoryStatus = Marginal;
Chris@170 77 else if (minmb > (memoryFree / 3)) memoryStatus = Marginal;
Chris@170 78 else if (memoryTotal == -1 ||
Chris@170 79 minmb > (memoryTotal / 10)) memoryStatus = Marginal;
Chris@170 80 else memoryStatus = Sufficient;
Chris@170 81
Chris@170 82 if (discFree == -1) discStatus = Unknown;
Chris@170 83 else if (minmb > (discFree * 3) / 4) discStatus = Insufficient;
Chris@173 84 else if (maxmb > (discFree / 4)) discStatus = Marginal;
Chris@173 85 else if (minmb > (discFree / 10)) discStatus = Marginal;
Chris@170 86 else discStatus = Sufficient;
Chris@170 87
Chris@170 88 std::cerr << "Memory status: " << memoryStatus << ", disc status "
Chris@170 89 << discStatus << std::endl;
Chris@170 90
Chris@170 91 int recommendation = NoRecommendation;
Chris@170 92
Chris@170 93 if (memoryStatus == Insufficient || memoryStatus == Unknown) {
Chris@170 94
Chris@170 95 recommendation |= UseDisc;
Chris@170 96
Chris@170 97 if (discStatus == Insufficient && minmb > discFree) {
Chris@170 98 throw InsufficientDiscSpace(path, minmb, discFree);
Chris@170 99 }
Chris@170 100
Chris@170 101 if (discStatus == Insufficient || discStatus == Marginal) {
Chris@170 102 recommendation |= ConserveSpace;
Chris@170 103 } else if (discStatus == Unknown && !(criteria & PrecisionCritical)) {
Chris@170 104 recommendation |= ConserveSpace;
Chris@170 105 } else {
Chris@170 106 recommendation |= UseAsMuchAsYouLike;
Chris@170 107 }
Chris@170 108
Chris@170 109 } else if (memoryStatus == Marginal) {
Chris@170 110
Chris@170 111 if (((criteria & SpeedCritical) ||
Chris@170 112 (criteria & FrequentLookupLikely)) &&
Chris@170 113 !(criteria & PrecisionCritical) &&
Chris@170 114 !(criteria & LongRetentionLikely)) {
Chris@170 115
Chris@170 116 // requirements suggest a preference for memory
Chris@170 117
Chris@170 118 if (discStatus != Insufficient) {
Chris@170 119 recommendation |= PreferMemory;
Chris@170 120 } else {
Chris@170 121 recommendation |= UseMemory;
Chris@170 122 }
Chris@170 123
Chris@170 124 recommendation |= ConserveSpace;
Chris@170 125
Chris@170 126 } else {
Chris@170 127
Chris@170 128 if (discStatus == Insufficient) {
Chris@170 129 recommendation |= (UseMemory | ConserveSpace);
Chris@170 130 } else if (discStatus == Marginal) {
Chris@170 131 recommendation |= (PreferMemory | ConserveSpace);
Chris@170 132 } else if (discStatus == Unknown) {
Chris@170 133 recommendation |= (PreferDisc | ConserveSpace);
Chris@170 134 } else {
Chris@170 135 recommendation |= (UseDisc | UseAsMuchAsYouLike);
Chris@170 136 }
Chris@170 137 }
Chris@170 138
Chris@170 139 } else {
Chris@170 140
Chris@170 141 if (discStatus == Insufficient) {
Chris@170 142 recommendation |= (UseMemory | ConserveSpace);
Chris@170 143 } else if (discStatus != Sufficient) {
Chris@170 144 recommendation |= (PreferMemory | ConserveSpace);
Chris@170 145 } else {
Chris@170 146
Chris@170 147 if ((criteria & SpeedCritical) ||
Chris@170 148 (criteria & FrequentLookupLikely)) {
Chris@170 149 recommendation |= PreferMemory;
Chris@170 150 if (criteria & PrecisionCritical) {
Chris@170 151 recommendation |= UseAsMuchAsYouLike;
Chris@170 152 } else {
Chris@170 153 recommendation |= ConserveSpace;
Chris@170 154 }
Chris@170 155 } else {
Chris@170 156 recommendation |= PreferDisc;
Chris@170 157 recommendation |= UseAsMuchAsYouLike;
Chris@170 158 }
Chris@170 159 }
Chris@170 160 }
Chris@170 161
Chris@170 162 return Recommendation(recommendation);
Chris@168 163 }
Chris@168 164
Chris@205 165 void
Chris@205 166 StorageAdviser::notifyPlannedAllocation(AllocationArea area, int size)
Chris@205 167 {
Chris@205 168 if (area == MemoryAllocation) m_memoryPlanned += size;
Chris@205 169 else if (area == DiscAllocation) m_discPlanned += size;
Chris@259 170 // std::cerr << "storage planned up: memory: " << m_memoryPlanned << ", disc "
Chris@259 171 // << m_discPlanned << std::endl;
Chris@205 172 }
Chris@205 173
Chris@205 174 void
Chris@205 175 StorageAdviser::notifyDoneAllocation(AllocationArea area, int size)
Chris@205 176 {
Chris@205 177 if (area == MemoryAllocation) {
Chris@205 178 if (m_memoryPlanned > size) m_memoryPlanned -= size;
Chris@205 179 else m_memoryPlanned = 0;
Chris@205 180 } else if (area == DiscAllocation) {
Chris@205 181 if (m_discPlanned > size) m_discPlanned -= size;
Chris@205 182 else m_discPlanned = 0;
Chris@205 183 }
Chris@259 184 // std::cerr << "storage planned down: memory: " << m_memoryPlanned << ", disc "
Chris@259 185 // << m_discPlanned << std::endl;
Chris@205 186 }
Chris@205 187