annotate base/StorageAdviser.cpp @ 363:0e30c8ec15a0

* Add wave file model method for reading more than one channel at once, avoiding ludicrously expensive backward seeks and double-reads when playing multi-channel files or using them as inputs to feature extraction plugins
author Chris Cannam
date Thu, 24 Jan 2008 14:35:43 +0000
parents 824ee993ca8d
children 7cc6b7b0d819
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@334 54 std::cerr << "Disc space: " << discFree << ", memory free: " << memoryFree << ", memory total: " << memoryTotal << ", min " << minimumSize << ", max " << maximumSize << 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@359 80 else if (memoryFree < memoryTotal / 4) memoryStatus = Marginal;
Chris@170 81 else memoryStatus = Sufficient;
Chris@170 82
Chris@170 83 if (discFree == -1) discStatus = Unknown;
Chris@170 84 else if (minmb > (discFree * 3) / 4) discStatus = Insufficient;
Chris@173 85 else if (maxmb > (discFree / 4)) discStatus = Marginal;
Chris@173 86 else if (minmb > (discFree / 10)) discStatus = Marginal;
Chris@170 87 else discStatus = Sufficient;
Chris@170 88
Chris@170 89 std::cerr << "Memory status: " << memoryStatus << ", disc status "
Chris@170 90 << discStatus << std::endl;
Chris@170 91
Chris@170 92 int recommendation = NoRecommendation;
Chris@170 93
Chris@170 94 if (memoryStatus == Insufficient || memoryStatus == Unknown) {
Chris@170 95
Chris@170 96 recommendation |= UseDisc;
Chris@170 97
Chris@170 98 if (discStatus == Insufficient && minmb > discFree) {
Chris@170 99 throw InsufficientDiscSpace(path, minmb, discFree);
Chris@170 100 }
Chris@170 101
Chris@170 102 if (discStatus == Insufficient || discStatus == Marginal) {
Chris@170 103 recommendation |= ConserveSpace;
Chris@170 104 } else if (discStatus == Unknown && !(criteria & PrecisionCritical)) {
Chris@170 105 recommendation |= ConserveSpace;
Chris@170 106 } else {
Chris@170 107 recommendation |= UseAsMuchAsYouLike;
Chris@170 108 }
Chris@170 109
Chris@170 110 } else if (memoryStatus == Marginal) {
Chris@170 111
Chris@170 112 if (((criteria & SpeedCritical) ||
Chris@170 113 (criteria & FrequentLookupLikely)) &&
Chris@170 114 !(criteria & PrecisionCritical) &&
Chris@170 115 !(criteria & LongRetentionLikely)) {
Chris@170 116
Chris@170 117 // requirements suggest a preference for memory
Chris@170 118
Chris@170 119 if (discStatus != Insufficient) {
Chris@170 120 recommendation |= PreferMemory;
Chris@170 121 } else {
Chris@170 122 recommendation |= UseMemory;
Chris@170 123 }
Chris@170 124
Chris@170 125 recommendation |= ConserveSpace;
Chris@170 126
Chris@170 127 } else {
Chris@170 128
Chris@170 129 if (discStatus == Insufficient) {
Chris@170 130 recommendation |= (UseMemory | ConserveSpace);
Chris@170 131 } else if (discStatus == Marginal) {
Chris@170 132 recommendation |= (PreferMemory | ConserveSpace);
Chris@170 133 } else if (discStatus == Unknown) {
Chris@170 134 recommendation |= (PreferDisc | ConserveSpace);
Chris@170 135 } else {
Chris@170 136 recommendation |= (UseDisc | UseAsMuchAsYouLike);
Chris@170 137 }
Chris@170 138 }
Chris@170 139
Chris@170 140 } else {
Chris@170 141
Chris@170 142 if (discStatus == Insufficient) {
Chris@170 143 recommendation |= (UseMemory | ConserveSpace);
Chris@170 144 } else if (discStatus != Sufficient) {
Chris@170 145 recommendation |= (PreferMemory | ConserveSpace);
Chris@170 146 } else {
Chris@170 147
Chris@170 148 if ((criteria & SpeedCritical) ||
Chris@170 149 (criteria & FrequentLookupLikely)) {
Chris@170 150 recommendation |= PreferMemory;
Chris@170 151 if (criteria & PrecisionCritical) {
Chris@170 152 recommendation |= UseAsMuchAsYouLike;
Chris@170 153 } else {
Chris@170 154 recommendation |= ConserveSpace;
Chris@170 155 }
Chris@170 156 } else {
Chris@170 157 recommendation |= PreferDisc;
Chris@170 158 recommendation |= UseAsMuchAsYouLike;
Chris@170 159 }
Chris@170 160 }
Chris@170 161 }
Chris@170 162
Chris@170 163 return Recommendation(recommendation);
Chris@168 164 }
Chris@168 165
Chris@205 166 void
Chris@205 167 StorageAdviser::notifyPlannedAllocation(AllocationArea area, int size)
Chris@205 168 {
Chris@205 169 if (area == MemoryAllocation) m_memoryPlanned += size;
Chris@205 170 else if (area == DiscAllocation) m_discPlanned += size;
Chris@259 171 // std::cerr << "storage planned up: memory: " << m_memoryPlanned << ", disc "
Chris@259 172 // << m_discPlanned << std::endl;
Chris@205 173 }
Chris@205 174
Chris@205 175 void
Chris@205 176 StorageAdviser::notifyDoneAllocation(AllocationArea area, int size)
Chris@205 177 {
Chris@205 178 if (area == MemoryAllocation) {
Chris@205 179 if (m_memoryPlanned > size) m_memoryPlanned -= size;
Chris@205 180 else m_memoryPlanned = 0;
Chris@205 181 } else if (area == DiscAllocation) {
Chris@205 182 if (m_discPlanned > size) m_discPlanned -= size;
Chris@205 183 else m_discPlanned = 0;
Chris@205 184 }
Chris@259 185 // std::cerr << "storage planned down: memory: " << m_memoryPlanned << ", disc "
Chris@259 186 // << m_discPlanned << std::endl;
Chris@205 187 }
Chris@205 188