annotate base/StorageAdviser.cpp @ 661:a4faa1840384

* If a FileSource URL won't convert at all in strict mode, try again in tolerant mode (necessary for e.g. filenames with square brackets in them)
author Chris Cannam
date Tue, 19 Oct 2010 21:47:55 +0100
parents 57f3eec55957
children 06f13a3b9e9e
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@436 25 //#define DEBUG_STORAGE_ADVISER 1
Chris@374 26
Chris@205 27 long StorageAdviser::m_discPlanned = 0;
Chris@205 28 long 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@168 35 int minimumSize,
Chris@168 36 int maximumSize)
Chris@168 37 {
Chris@374 38 #ifdef DEBUG_STORAGE_ADVISER
Chris@170 39 std::cerr << "StorageAdviser::recommend: Criteria " << criteria
Chris@170 40 << ", minimumSize " << minimumSize
Chris@170 41 << ", maximumSize " << maximumSize << std::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@541 52 std::cerr << "StorageAdviser::recommend: ERROR: Failed to get temporary directory path: " << e.what() << std::endl;
Chris@541 53 return Recommendation(UseMemory | ConserveSpace);
Chris@541 54 }
Chris@170 55 int discFree = GetDiscSpaceMBAvailable(path.toLocal8Bit());
Chris@170 56 int memoryFree, memoryTotal;
Chris@170 57 GetRealMemoryMBAvailable(memoryFree, memoryTotal);
Chris@168 58
Chris@205 59 if (discFree > 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@205 65 if (memoryFree > 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@334 72 std::cerr << "Disc space: " << discFree << ", memory free: " << memoryFree << ", memory total: " << memoryTotal << ", min " << minimumSize << ", max " << maximumSize << std::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@170 90 int minmb = minimumSize / 1024 + 1;
Chris@170 91 int maxmb = maximumSize / 1024 + 1;
Chris@170 92
Chris@170 93 if (memoryFree == -1) memoryStatus = Unknown;
Chris@415 94 else if (memoryFree < memoryTotal / 3) 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@170 109 std::cerr << "Memory status: " << memoryStatus << ", disc status "
Chris@170 110 << discStatus << std::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@170 184 return Recommendation(recommendation);
Chris@168 185 }
Chris@168 186
Chris@205 187 void
Chris@205 188 StorageAdviser::notifyPlannedAllocation(AllocationArea area, int size)
Chris@205 189 {
Chris@205 190 if (area == MemoryAllocation) m_memoryPlanned += size;
Chris@205 191 else if (area == DiscAllocation) m_discPlanned += size;
Chris@259 192 // std::cerr << "storage planned up: memory: " << m_memoryPlanned << ", disc "
Chris@259 193 // << m_discPlanned << std::endl;
Chris@205 194 }
Chris@205 195
Chris@205 196 void
Chris@205 197 StorageAdviser::notifyDoneAllocation(AllocationArea area, int size)
Chris@205 198 {
Chris@205 199 if (area == MemoryAllocation) {
Chris@205 200 if (m_memoryPlanned > size) m_memoryPlanned -= size;
Chris@205 201 else m_memoryPlanned = 0;
Chris@205 202 } else if (area == DiscAllocation) {
Chris@205 203 if (m_discPlanned > size) m_discPlanned -= size;
Chris@205 204 else m_discPlanned = 0;
Chris@205 205 }
Chris@259 206 // std::cerr << "storage planned down: memory: " << m_memoryPlanned << ", disc "
Chris@259 207 // << m_discPlanned << std::endl;
Chris@205 208 }
Chris@205 209
Chris@411 210 void
Chris@411 211 StorageAdviser::setFixedRecommendation(Recommendation recommendation)
Chris@411 212 {
Chris@411 213 m_baseRecommendation = recommendation;
Chris@411 214 }
Chris@411 215