svcore  1.9
StorageAdviser.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006 QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "StorageAdviser.h"
17 
18 #include "Exceptions.h"
19 #include "TempDirectory.h"
20 
21 #include "system/System.h"
22 
23 #include <iostream>
24 
25 //#define DEBUG_STORAGE_ADVISER 1
26 
29 
32 
35  int minimumSize,
36  int maximumSize)
37 {
38 #ifdef DEBUG_STORAGE_ADVISER
39  SVDEBUG << "StorageAdviser::recommend: Criteria " << criteria
40  << ", minimumSize " << minimumSize
41  << ", maximumSize " << maximumSize << endl;
42 #endif
43 
45  return m_baseRecommendation; // for now
46  }
47 
48  QString path;
49  try {
51  } catch (std::exception e) {
52  cerr << "StorageAdviser::recommend: ERROR: Failed to get temporary directory path: " << e.what() << endl;
54  }
55  int discFree = GetDiscSpaceMBAvailable(path.toLocal8Bit());
56  int memoryFree, memoryTotal;
57  GetRealMemoryMBAvailable(memoryFree, memoryTotal);
58 
59  if (discFree > m_discPlanned / 1024 + 1) {
60  discFree -= m_discPlanned / 1024 + 1;
61  } else if (discFree > 0) { // can also be -1 for unknown
62  discFree = 0;
63  }
64 
65  if (memoryFree > m_memoryPlanned / 1024 + 1) {
66  memoryFree -= m_memoryPlanned / 1024 + 1;
67  } else if (memoryFree > 0) { // can also be -1 for unknown
68  memoryFree = 0;
69  }
70 
71 #ifdef DEBUG_STORAGE_ADVISER
72  cerr << "Disc space: " << discFree << ", memory free: " << memoryFree << ", memory total: " << memoryTotal << ", min " << minimumSize << ", max " << maximumSize << endl;
73 #endif
74 
76  //recommendations are made in advance of any of the resulting
77  //allocations, as the allocations that have been recommended for
78  //won't be taken into account in subsequent recommendations.
79 
80  enum StorageStatus {
81  Unknown,
82  Insufficient,
83  Marginal,
84  Sufficient
85  };
86 
87  StorageStatus memoryStatus = Unknown;
88  StorageStatus discStatus = Unknown;
89 
90  int minmb = minimumSize / 1024 + 1;
91  int maxmb = maximumSize / 1024 + 1;
92 
93  if (memoryFree == -1) memoryStatus = Unknown;
94  else if (memoryFree < memoryTotal / 3) memoryStatus = Insufficient;
95  else if (minmb > (memoryFree * 3) / 4) memoryStatus = Insufficient;
96  else if (maxmb > (memoryFree * 3) / 4) memoryStatus = Marginal;
97  else if (minmb > (memoryFree / 3)) memoryStatus = Marginal;
98  else if (memoryTotal == -1 ||
99  minmb > (memoryTotal / 10)) memoryStatus = Marginal;
100  else memoryStatus = Sufficient;
101 
102  if (discFree == -1) discStatus = Unknown;
103  else if (minmb > (discFree * 3) / 4) discStatus = Insufficient;
104  else if (maxmb > (discFree / 4)) discStatus = Marginal;
105  else if (minmb > (discFree / 10)) discStatus = Marginal;
106  else discStatus = Sufficient;
107 
108 #ifdef DEBUG_STORAGE_ADVISER
109  cerr << "Memory status: " << memoryStatus << ", disc status "
110  << discStatus << endl;
111 #endif
112 
113  int recommendation = NoRecommendation;
114 
115  if (memoryStatus == Insufficient || memoryStatus == Unknown) {
116 
117  recommendation |= UseDisc;
118 
119  if (discStatus == Insufficient && minmb > discFree) {
120  throw InsufficientDiscSpace(path, minmb, discFree);
121  }
122 
123  if (discStatus == Insufficient || discStatus == Marginal) {
124  recommendation |= ConserveSpace;
125  } else if (discStatus == Unknown && !(criteria & PrecisionCritical)) {
126  recommendation |= ConserveSpace;
127  } else {
128  recommendation |= UseAsMuchAsYouLike;
129  }
130 
131  } else if (memoryStatus == Marginal) {
132 
133  if (((criteria & SpeedCritical) ||
134  (criteria & FrequentLookupLikely)) &&
135  !(criteria & PrecisionCritical) &&
136  !(criteria & LongRetentionLikely)) {
137 
138  // requirements suggest a preference for memory
139 
140  if (discStatus != Insufficient) {
141  recommendation |= PreferMemory;
142  } else {
143  recommendation |= UseMemory;
144  }
145 
146  recommendation |= ConserveSpace;
147 
148  } else {
149 
150  if (discStatus == Insufficient) {
151  recommendation |= (UseMemory | ConserveSpace);
152  } else if (discStatus == Marginal) {
153  recommendation |= (PreferMemory | ConserveSpace);
154  } else if (discStatus == Unknown) {
155  recommendation |= (PreferDisc | ConserveSpace);
156  } else {
157  recommendation |= (UseDisc | UseAsMuchAsYouLike);
158  }
159  }
160 
161  } else {
162 
163  if (discStatus == Insufficient) {
164  recommendation |= (UseMemory | ConserveSpace);
165  } else if (discStatus != Sufficient) {
166  recommendation |= (PreferMemory | ConserveSpace);
167  } else {
168 
169  if ((criteria & SpeedCritical) ||
170  (criteria & FrequentLookupLikely)) {
171  recommendation |= PreferMemory;
172  if (criteria & PrecisionCritical) {
173  recommendation |= UseAsMuchAsYouLike;
174  } else {
175  recommendation |= ConserveSpace;
176  }
177  } else {
178  recommendation |= PreferDisc;
179  recommendation |= UseAsMuchAsYouLike;
180  }
181  }
182  }
183 
184  return Recommendation(recommendation);
185 }
186 
187 void
189 {
190  if (area == MemoryAllocation) m_memoryPlanned += size;
191  else if (area == DiscAllocation) m_discPlanned += size;
192 // cerr << "storage planned up: memory: " << m_memoryPlanned << ", disc "
193 // << m_discPlanned << endl;
194 }
195 
196 void
198 {
199  if (area == MemoryAllocation) {
200  if (m_memoryPlanned > size) m_memoryPlanned -= size;
201  else m_memoryPlanned = 0;
202  } else if (area == DiscAllocation) {
203  if (m_discPlanned > size) m_discPlanned -= size;
204  else m_discPlanned = 0;
205  }
206 // cerr << "storage planned down: memory: " << m_memoryPlanned << ", disc "
207 // << m_discPlanned << endl;
208 }
209 
210 void
212 {
213  m_baseRecommendation = recommendation;
214 }
215 
static void notifyPlannedAllocation(AllocationArea area, int size)
Specify that we are planning to use a given amount of storage (in kilobytes), but haven't allocated i...
static long m_memoryPlanned
QString getPath()
Create the root temporary directory if necessary, and return its path.
static long m_discPlanned
int GetDiscSpaceMBAvailable(const char *path)
Definition: System.cpp:247
static Recommendation m_baseRecommendation
static TempDirectory * getInstance()
static void notifyDoneAllocation(AllocationArea area, int size)
Specify that we have now allocated, or abandoned the allocation of, the given amount (in kilobytes) o...
void GetRealMemoryMBAvailable(int &available, int &total)
Definition: System.cpp:126
static Recommendation recommend(Criteria criteria, int minimumSize, int maximumSize)
Recommend where to store some data, given certain storage and recall criteria.
#define SVDEBUG
Definition: Debug.h:42
static void setFixedRecommendation(Recommendation recommendation)
Force all subsequent recommendations to use the (perhaps partial) specification given here.