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
|
/**
* @file llvfs.h
* @brief Definition of virtual file system
*
* Copyright (c) 2002-2007, Linden Research, Inc.
*
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlife.com/developers/opensource/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at http://secondlife.com/developers/opensource/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
*/
#ifndef LL_LLVFS_H
#define LL_LLVFS_H
#include <stdio.h>
#include <map>
#include <deque>
#include "lluuid.h"
#include "linked_lists.h"
#include "llassettype.h"
#include "llthread.h"
enum EVFSValid
{
VFSVALID_UNKNOWN = 0,
VFSVALID_OK = 1,
VFSVALID_BAD_CORRUPT = 2,
VFSVALID_BAD_CANNOT_OPEN_READONLY = 3,
VFSVALID_BAD_CANNOT_CREATE = 4
};
// Lock types for open vfiles, pending async reads, and pending async appends
// (There are no async normal writes, currently)
enum EVFSLock
{
VFSLOCK_OPEN = 0,
VFSLOCK_READ = 1,
VFSLOCK_APPEND = 2,
VFSLOCK_COUNT = 3
};
// internal classes
class LLVFSBlock;
class LLVFSFileBlock;
class LLVFSFileSpecifier
{
public:
LLVFSFileSpecifier();
LLVFSFileSpecifier(const LLUUID &file_id, const LLAssetType::EType file_type);
bool operator<(const LLVFSFileSpecifier &rhs) const;
bool operator==(const LLVFSFileSpecifier &rhs) const;
public:
LLUUID mFileID;
LLAssetType::EType mFileType;
};
class LLVFS
{
public:
// Pass 0 to not presize
LLVFS(const char *index_filename, const char *data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash);
~LLVFS();
BOOL isValid() const { return (VFSVALID_OK == mValid); }
EVFSValid getValidState() const { return mValid; }
// ---------- The following fucntions lock/unlock mDataMutex ----------
BOOL getExists(const LLUUID &file_id, const LLAssetType::EType file_type);
S32 getSize(const LLUUID &file_id, const LLAssetType::EType file_type);
BOOL checkAvailable(S32 max_size);
S32 getMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type);
BOOL setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type, S32 max_size);
void renameFile(const LLUUID &file_id, const LLAssetType::EType file_type,
const LLUUID &new_id, const LLAssetType::EType &new_type);
void removeFile(const LLUUID &file_id, const LLAssetType::EType file_type);
S32 getData(const LLUUID &file_id, const LLAssetType::EType file_type, U8 *buffer, S32 location, S32 length);
S32 storeData(const LLUUID &file_id, const LLAssetType::EType file_type, const U8 *buffer, S32 location, S32 length);
void incLock(const LLUUID &file_id, const LLAssetType::EType file_type, EVFSLock lock);
void decLock(const LLUUID &file_id, const LLAssetType::EType file_type, EVFSLock lock);
BOOL isLocked(const LLUUID &file_id, const LLAssetType::EType file_type, EVFSLock lock);
// ----------------------------------------------------------------
// Used to trigger evil WinXP behavior of "preloading" entire file into memory.
void pokeFiles();
// Verify that the index file contents match the in-memory file structure
// Very slow, do not call routinely. JC
void audit();
// Check for uninitialized blocks. Slow, do not call in release. JC
void checkMem();
// for debugging, prints a map of the vfs
void dumpMap();
void dumpLockCounts();
void dumpStatistics();
void listFiles();
void dumpFiles();
protected:
void removeFileBlock(LLVFSFileBlock *fileblock);
void eraseBlockLength(LLVFSBlock *block);
void eraseBlock(LLVFSBlock *block);
void addFreeBlock(LLVFSBlock *block);
//void mergeFreeBlocks();
void useFreeSpace(LLVFSBlock *free_block, S32 length);
void sync(LLVFSFileBlock *block, BOOL remove = FALSE);
void presizeDataFile(const U32 size);
static FILE *openAndLock(const char *filename, const char *mode, BOOL read_lock);
static void unlockAndClose(FILE *fp);
// Can initiate LRU-based file removal to make space.
// The immune file block will not be removed.
LLVFSBlock *findFreeBlock(S32 size, LLVFSFileBlock *immune = NULL);
// lock/unlock data mutex (mDataMutex)
void lockData() { mDataMutex->lock(); }
void unlockData() { mDataMutex->unlock(); }
protected:
LLMutex* mDataMutex;
typedef std::map<LLVFSFileSpecifier, LLVFSFileBlock*> fileblock_map;
fileblock_map mFileBlocks;
typedef std::multimap<S32, LLVFSBlock*> blocks_length_map_t;
blocks_length_map_t mFreeBlocksByLength;
typedef std::multimap<U32, LLVFSBlock*> blocks_location_map_t;
blocks_location_map_t mFreeBlocksByLocation;
FILE *mDataFP;
FILE *mIndexFP;
std::deque<S32> mIndexHoles;
char *mIndexFilename;
char *mDataFilename;
BOOL mReadOnly;
EVFSValid mValid;
S32 mLockCounts[VFSLOCK_COUNT];
BOOL mRemoveAfterCrash;
};
extern LLVFS *gVFS;
#endif
|