annotate base/StorageAdviser.cpp @ 1211:5a1198083d9a piper

Pull out model creation into the transformer thread run(), so that all communications with the plugin server happen on a single thread. Then make the model accessor wait for them to be created (which still happens right at the start of processing) before returning.
author Chris Cannam
date Mon, 17 Oct 2016 14:18:23 +0100
parents 393134235fa0
children adbd16d2c1e8
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@1104 25 //#define DEBUG_STORAGE_ADVISER 1
Chris@374 26
Chris@1038 27 size_t StorageAdviser::m_discPlanned = 0;
Chris@1038 28 size_t 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@1038 35 size_t minimumSize,
Chris@1038 36 size_t maximumSize)
Chris@168 37 {
Chris@374 38 #ifdef DEBUG_STORAGE_ADVISER
Chris@1098 39 cerr << "StorageAdviser::recommend: Criteria " << criteria
Chris@1098 40 << ", minimumSize " << minimumSize
Chris@1098 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@1038 55 ssize_t discFree = GetDiscSpaceMBAvailable(path.toLocal8Bit());
Chris@1038 56 ssize_t memoryFree, memoryTotal;
Chris@170 57 GetRealMemoryMBAvailable(memoryFree, memoryTotal);
Chris@168 58
Chris@1038 59 if (discFree > ssize_t(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@1038 65 if (memoryFree > ssize_t(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@1038 90 ssize_t minmb = ssize_t(minimumSize / 1024 + 1);
Chris@1038 91 ssize_t maxmb = ssize_t(maximumSize / 1024 + 1);
Chris@170 92
Chris@170 93 if (memoryFree == -1) memoryStatus = Unknown;
Chris@1103 94 else if (memoryFree < memoryTotal / 3 && memoryFree < 512) 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@1098 184 #ifdef DEBUG_STORAGE_ADVISER
Chris@1098 185 cerr << "StorageAdviser: returning recommendation " << recommendation << endl;
Chris@1098 186 #endif
Chris@1098 187
Chris@170 188 return Recommendation(recommendation);
Chris@168 189 }
Chris@168 190
Chris@205 191 void
Chris@1038 192 StorageAdviser::notifyPlannedAllocation(AllocationArea area, size_t size)
Chris@205 193 {
Chris@205 194 if (area == MemoryAllocation) m_memoryPlanned += size;
Chris@205 195 else if (area == DiscAllocation) m_discPlanned += size;
Chris@843 196 // cerr << "storage planned up: memory: " << m_memoryPlanned << ", disc "
Chris@843 197 // << m_discPlanned << endl;
Chris@205 198 }
Chris@205 199
Chris@205 200 void
Chris@1038 201 StorageAdviser::notifyDoneAllocation(AllocationArea area, size_t size)
Chris@205 202 {
Chris@205 203 if (area == MemoryAllocation) {
Chris@205 204 if (m_memoryPlanned > size) m_memoryPlanned -= size;
Chris@205 205 else m_memoryPlanned = 0;
Chris@205 206 } else if (area == DiscAllocation) {
Chris@205 207 if (m_discPlanned > size) m_discPlanned -= size;
Chris@205 208 else m_discPlanned = 0;
Chris@205 209 }
Chris@843 210 // cerr << "storage planned down: memory: " << m_memoryPlanned << ", disc "
Chris@843 211 // << m_discPlanned << endl;
Chris@205 212 }
Chris@205 213
Chris@411 214 void
Chris@411 215 StorageAdviser::setFixedRecommendation(Recommendation recommendation)
Chris@411 216 {
Chris@411 217 m_baseRecommendation = recommendation;
Chris@411 218 }
Chris@411 219