forked from audacity/audacity
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DirManager.h
282 lines (214 loc) · 9.69 KB
/
DirManager.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
/**********************************************************************
Audacity: A Digital Audio Editor
DirManager.h
Dominic Mazzoni
**********************************************************************/
#ifndef _DIRMANAGER_
#define _DIRMANAGER_
#include "audacity/Types.h"
#include "xml/XMLTagHandler.h"
#include <functional>
#include <memory>
#include <unordered_map>
#include "ClientData.h"
class wxFileNameWrapper;
class AudacityProject;
class BlockArray;
class BlockFile;
class ProgressDialog;
using DirHash = std::unordered_map<int, int>;
class BlockFile;
using BlockFilePtr = std::shared_ptr<BlockFile>;
using BlockHash = std::unordered_map< wxString, std::weak_ptr<BlockFile> >;
wxMemorySize GetFreeMemory();
enum {
kCleanTopDirToo = 1, // The top directory can be excluded from clean.
kCleanDirsOnlyIfEmpty = 2, // Otherwise non empty dirs may be removed.
kCleanFiles = 4, // Remove files
kCleanDirs = 8 // Remove dirs.
};
class PROFILE_DLL_API DirManager final
: public XMLTagHandler
, public ClientData::Base
, public std::enable_shared_from_this< DirManager >
{
public:
static DirManager &Get( AudacityProject &project );
static const DirManager &Get( const AudacityProject &project );
static DirManager &Reset( AudacityProject &project );
static void Destroy( AudacityProject &project );
static int RecursivelyEnumerate(const FilePath &dirPath,
FilePaths& filePathArray, // output: all files in dirPath tree
wxString dirspec,
wxString filespec,
bool bFiles, bool bDirs,
int progress_count = 0,
int progress_bias = 0,
ProgressDialog* progress = nullptr);
static int RecursivelyEnumerateWithProgress(const FilePath &dirPath,
FilePaths& filePathArray, // output: all files in dirPath tree
wxString dirspec,
wxString filespec,
bool bFiles, bool bDirs,
int progress_count,
const wxChar* message);
static int RecursivelyCountSubdirs( const FilePath &dirPath );
static int RecursivelyRemoveEmptyDirs(const FilePath &dirPath,
int nDirCount = 0,
ProgressDialog* pProgress = nullptr);
static void RecursivelyRemove(const FilePaths& filePathArray, int count, int bias,
int flags, const wxChar* message = nullptr);
// Type of a function that builds a block file, using attributes from XML
using BlockFileDeserializer =
std::function< BlockFilePtr( DirManager&, const wxChar ** ) >;
// Typically a statically declared object,
// registers a function for an XML tag
struct RegisteredBlockFileDeserializer {
RegisteredBlockFileDeserializer(
const wxString &tag, BlockFileDeserializer function );
};
private:
// MM: Construct DirManager
// Don't call this directly but use Create() instead
DirManager();
public:
static std::shared_ptr< DirManager > Create();
virtual ~DirManager();
size_t NumBlockFiles() const { return mBlockFileHash.size(); }
static void SetTempDir(const wxString &_temp) { globaltemp = _temp; }
class ProjectSetter
{
public:
ProjectSetter(
DirManager &dirManager,
FilePath& newProjPath, // assigns it if empty
const FilePath& newProjName, const bool bCreate, bool moving);
~ProjectSetter();
bool Ok();
void Commit();
private:
struct Impl;
std::unique_ptr<Impl> mpImpl;
};
// Returns true on success.
// If SetProject is told NOT to create the directory
// but it doesn't already exist, SetProject fails and returns false.
// This function simply creates a ProjectSetter and commits it if successful.
// Using ProjectSetter directly allows separation of those steps.
bool SetProject(
FilePath& newProjPath, // assigns it if empty
const FilePath& newProjName, const bool bCreate);
FilePath GetProjectDataDir();
FilePath GetProjectName();
wxLongLong GetFreeDiskSpace();
using BlockFileFactory = std::function< BlockFilePtr( wxFileNameWrapper ) >;
BlockFilePtr NewBlockFile( const BlockFileFactory &factory );
/// Returns true if the blockfile pointed to by b is contained by the DirManager
bool ContainsBlockFile(const BlockFile *b) const;
/// Check for existing using filename using complete filename
bool ContainsBlockFile(const wxString &filepath) const;
// Adds one to the reference count of the block file,
// UNLESS it is "locked", then it makes a NEW copy of
// the BlockFile.
// May throw an exception in case of disk space exhaustion, otherwise
// returns non-null.
BlockFilePtr CopyBlockFile(const BlockFilePtr &b);
BlockFile *LoadBlockFile(const wxChar **attrs, sampleFormat format);
void SaveBlockFile(BlockFile *f, int depth, FILE *fp);
#if LEGACY_PROJECT_FILE_SUPPORT
BlockFile *LoadBlockFile(wxTextFile * in, sampleFormat format);
void SaveBlockFile(BlockFile * f, wxTextFile * out);
#endif
std::pair<bool, FilePath>
LinkOrCopyToNewProjectDirectory(BlockFile *f, bool &link);
bool EnsureSafeFilename(const wxFileName &fName);
using LoadingTarget = std::function< BlockFilePtr &() >;
void SetLoadingTarget( LoadingTarget loadingTarget )
{
mLoadingTarget = loadingTarget;
}
sampleFormat GetLoadingFormat() const { return mLoadingFormat; }
void SetLoadingFormat(sampleFormat format) { mLoadingFormat = format; }
size_t GetLoadingBlockLength() const { return mLoadingBlockLen; }
void SetLoadingBlockLength(size_t len) { mLoadingBlockLen = len; }
// Note: following affects only the loading of block files when opening a project
void SetLoadingMaxSamples(size_t max) { mMaxSamples = max; }
bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override;
XMLTagHandler *HandleXMLChild(const wxChar * WXUNUSED(tag)) override
{ return NULL; }
bool AssignFile(wxFileNameWrapper &filename, const wxString &value, bool check);
// Clean the temp dir. Note that now where we have auto recovery the temp
// dir is not cleaned at start up anymore. But it is cleaned when the
// program is exited normally.
static void CleanTempDir();
static void CleanDir(
const FilePath &path,
const wxString &dirSpec,
const wxString &fileSpec,
const wxString &msg,
int flags = 0);
void FindMissingAliasFiles(
BlockHash& missingAliasFilesAUFHash, // output: (.auf) AliasBlockFiles whose aliased files are missing
BlockHash& missingAliasFilesPathHash); // output: full paths of missing aliased files
void FindMissingAUFs(
BlockHash& missingAUFHash); // output: missing (.auf) AliasBlockFiles
void FindMissingAUs(
BlockHash& missingAUHash); // missing data (.au) blockfiles
// Find .au and .auf files that are not in the project.
void FindOrphanBlockFiles(
const FilePaths &filePathArray, // input: all files in project directory
FilePaths &orphanFilePathArray); // output: orphan files
// Remove all orphaned blockfiles without user interaction. This is
// generally safe, because orphaned blockfiles are not referenced by the
// project and thus worthless anyway.
void RemoveOrphanBlockfiles();
// Get directory where data files are in. Note that projects are normally
// not interested in this information, but it is important for the
// auto-save functionality
FilePath GetDataFilesDir() const;
// This should only be used by the auto save functionality
void SetLocalTempDir(const wxString &path);
// Do not DELETE any temporary files on exit. This is only called if
// auto recovery is cancelled and should be retried later
static void SetDontDeleteTempFiles() { dontDeleteTempFiles = true; }
// Write all write-cached block files to disc, if any
void WriteCacheToDisk();
// (Try to) fill cache of blockfiles, if caching is enabled (otherwise do
// nothing)
// A no-fail operation that does not throw
void FillBlockfilesCache();
private:
wxFileNameWrapper MakeBlockFileName();
wxFileNameWrapper MakeBlockFilePath(const wxString &value);
BlockHash mBlockFileHash; // repository for blockfiles
// Hashes for management of the sub-directory tree of _data
struct BalanceInfo
{
DirHash dirTopPool; // available toplevel dirs
DirHash dirTopFull; // full toplevel dirs
DirHash dirMidPool; // available two-level dirs
DirHash dirMidFull; // full two-level dirs
} mBalanceInfo;
// Accessor for the balance info, may need to do a delayed update for
// deletion in case other threads DELETE block files
BalanceInfo &GetBalanceInfo();
void BalanceInfoDel(const wxString&);
void BalanceInfoAdd(const wxString&);
void BalanceFileAdd(int);
int BalanceMidAdd(int, int);
FilePath projName;
FilePath projPath;
FilePath projFull;
wxString lastProject;
FilePaths aliasList;
LoadingTarget mLoadingTarget;
sampleFormat mLoadingFormat;
size_t mLoadingBlockLen;
size_t mMaxSamples; // max samples per block
unsigned long mLastBlockFileDestructionCount { 0 };
static wxString globaltemp;
wxString mytemp;
static int numDirManagers;
static bool dontDeleteTempFiles;
};
#endif