annotate base/StorageAdviser.cpp @ 974:65494d0d9ded

Fix memory leak
author Chris Cannam
date Wed, 03 Sep 2014 11:22:46 +0100
parents e802e550a1f2
children cc27f35aa75c
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@690 39 SVDEBUG << "StorageAdviser::recommend: Criteria " << criteria
Chris@170 40 << ", minimumSize " << minimumSize
Chris@687 41 << ", maximumSize " << maximumSize << 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@843 52 cerr << "StorageAdviser::recommend: ERROR: Failed to get temporary directory path: " << e.what() << 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@843 72 cerr << "Disc space: " << discFree << ", memory free: " << memoryFree << ", memory total: " << memoryTotal << ", min " << minimumSize << ", max " << maximumSize << 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@843 109 cerr << "Memory status: " << memoryStatus << ", disc status "
Chris@843 110 << discStatus << 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@843 192 // cerr << "storage planned up: memory: " << m_memoryPlanned << ", disc "
Chris@843 193 // << m_discPlanned << 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@843 206 // cerr << "storage planned down: memory: " << m_memoryPlanned << ", disc "
Chris@843 207 // << m_discPlanned << 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