aboutsummaryrefslogtreecommitdiff
path: root/src/stable/myriad.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/stable/myriad.h')
-rw-r--r--src/stable/myriad.h426
1 files changed, 213 insertions, 213 deletions
diff --git a/src/stable/myriad.h b/src/stable/myriad.h
index 6b1db41..4bfd88e 100644
--- a/src/stable/myriad.h
+++ b/src/stable/myriad.h
@@ -18,219 +18,219 @@
18 18
19namespace Bu 19namespace Bu
20{ 20{
21 class Stream; 21 class Stream;
22 class MyriadStream; 22 class MyriadStream;
23 23
24 subExceptionDeclBegin( MyriadException ) 24 subExceptionDeclBegin( MyriadException )
25 enum 25 enum
26 { 26 {
27 emptyStream, 27 emptyStream,
28 invalidFormat, 28 invalidFormat,
29 badVersion, 29 badVersion,
30 invalidWordSize, 30 invalidWordSize,
31 noSuchStream, 31 noSuchStream,
32 streamExists, 32 streamExists,
33 invalidStreamId, 33 invalidStreamId,
34 protectedStream 34 protectedStream
35 }; 35 };
36 subExceptionDeclEnd(); 36 subExceptionDeclEnd();
37 37
38 /** 38 /**
39 * Myriad block-allocated stream multiplexing system. This is a system for 39 * Myriad block-allocated stream multiplexing system. This is a system for
40 * creating streams that contain other streams in a flexible and lightweight 40 * creating streams that contain other streams in a flexible and lightweight
41 * manner. Basically, you can create a file (or any other stream) that can 41 * manner. Basically, you can create a file (or any other stream) that can
42 * store any number of flexible, growing streams. The streams within the 42 * store any number of flexible, growing streams. The streams within the
43 * Myriad stream are automatically numbered, not named. This works more 43 * Myriad stream are automatically numbered, not named. This works more
44 * or less like a filesystem, but without the extra layer for managing 44 * or less like a filesystem, but without the extra layer for managing
45 * file and directory links. This would actually be very easy to add 45 * file and directory links. This would actually be very easy to add
46 * on top of Myriad, but is not required. 46 * on top of Myriad, but is not required.
47 * 47 *
48 * Header format is as follows: 48 * Header format is as follows:
49 * 49 *
50 * MMMMvBssssSSSS* 50 * MMMMvBssssSSSS*
51 * M = Magic number (0AD3FA84) 51 * M = Magic number (0AD3FA84)
52 * v = version number 52 * v = version number
53 * B = Bits per int 53 * B = Bits per int
54 * s = Blocksize in bytes 54 * s = Blocksize in bytes
55 * S = Number of Streams 55 * S = Number of Streams
56 * 56 *
57 * The * represents the Stream headers, one per stream, as follows: 57 * The * represents the Stream headers, one per stream, as follows:
58 * IIIIssss$ 58 * IIIIssss$
59 * I = Id number of the stream 59 * I = Id number of the stream
60 * s = size of stream in bytes 60 * s = size of stream in bytes
61 * 61 *
62 * The $ represents the Block headers, one per used block, as follows: 62 * The $ represents the Block headers, one per used block, as follows:
63 * IIII 63 * IIII
64 * I = Index of the block 64 * I = Index of the block
65 * 65 *
66 * The stream/block data is interleaved in the header, so all blocks stored 66 * The stream/block data is interleaved in the header, so all blocks stored
67 * with one stream are together. The block headers are in order, and the 67 * with one stream are together. The block headers are in order, and the
68 * data in them is required to be "solid" you cannot fill partial blocks 68 * data in them is required to be "solid" you cannot fill partial blocks
69 * mid-way through a stream. 69 * mid-way through a stream.
70 * 70 *
71 * The initial block starts with the nids header, and is both the zero block 71 * The initial block starts with the nids header, and is both the zero block
72 * and the zero stream. For now, the minimum block size is the size needed 72 * and the zero stream. For now, the minimum block size is the size needed
73 * to store the base header, the zero stream header, and the first two 73 * to store the base header, the zero stream header, and the first two
74 * blocks of the zero stream, so 30 bytes. Since it's reccomended to use 74 * blocks of the zero stream, so 30 bytes. Since it's reccomended to use
75 * a size that will fit evenly into filesystem blocks, then a size of 32 is 75 * a size that will fit evenly into filesystem blocks, then a size of 32 is
76 * probably the smallest reccomended size because all powers of two equal 76 * probably the smallest reccomended size because all powers of two equal
77 * to or greater than 32 are evenly divisible by 32. 77 * to or greater than 32 are evenly divisible by 32.
78 * 78 *
79 * I have had a thought that if the block size were smaller than 42 bytes 79 * I have had a thought that if the block size were smaller than 42 bytes
80 * the header would consume the first N blocks where N * block size is 80 * the header would consume the first N blocks where N * block size is
81 * enough space to house the initial header, the first stream header, and 81 * enough space to house the initial header, the first stream header, and
82 * the first N block headers. This, of course, causes you to hit an 82 * the first N block headers. This, of course, causes you to hit an
83 * infinite header if the block size is small enough. 83 * infinite header if the block size is small enough.
84 */ 84 */
85 class Myriad 85 class Myriad
86 { 86 {
87 friend class MyriadStream; 87 friend class MyriadStream;
88 public: 88 public:
89 /** 89 /**
90 * Create a Myriad object that uses the given stream to store data. 90 * Create a Myriad object that uses the given stream to store data.
91 * This stream must be random access. The block size and preallocate 91 * This stream must be random access. The block size and preallocate
92 * values passed in are values that will be used if the given stream 92 * values passed in are values that will be used if the given stream
93 * is empty. In that case the stream will be "formatted" for myriad 93 * is empty. In that case the stream will be "formatted" for myriad
94 * with the specified block size. If there is already a viable Myriad 94 * with the specified block size. If there is already a viable Myriad
95 * format present in the stream, then the blocksize and preallocate 95 * format present in the stream, then the blocksize and preallocate
96 * values will be ignored and the values from the stream will be used 96 * values will be ignored and the values from the stream will be used
97 * instead. If the stream doesn't appear to be Myriad formatted an 97 * instead. If the stream doesn't appear to be Myriad formatted an
98 * exception will be thrown. 98 * exception will be thrown.
99 */ 99 */
100 Myriad( Bu::Stream &sStore, int iBlockSize=512, int iPreallocate=8 ); 100 Myriad( Bu::Stream &sStore, int iBlockSize=512, int iPreallocate=8 );
101 virtual ~Myriad(); 101 virtual ~Myriad();
102 102
103 /** 103 /**
104 * Destroy whatever data may be in the base stream and create a new 104 * Destroy whatever data may be in the base stream and create a new
105 * Myriad system there with the given blocksize. Use this with care, 105 * Myriad system there with the given blocksize. Use this with care,
106 * it will destroy anything that was already in the stream, and 106 * it will destroy anything that was already in the stream, and
107 * generally, should not ever have to be used. 107 * generally, should not ever have to be used.
108 */ 108 */
109 void initialize( int iBlockSize, int iPreAllocate=1 ); 109 void initialize( int iBlockSize, int iPreAllocate=1 );
110 110
111 /** 111 /**
112 * Create a new stream within the Myriad system. The ID of the new 112 * Create a new stream within the Myriad system. The ID of the new
113 * stream is returned. 113 * stream is returned.
114 */ 114 */
115 int createStream( int iPreAllocate=1 ); 115 int createStream( int iPreAllocate=1 );
116 116
117 /** 117 /**
118 * Create a new stream within the Myriad system with a given id. The 118 * Create a new stream within the Myriad system with a given id. The
119 * id that you provide will be the new id of the stream unless it's 119 * id that you provide will be the new id of the stream unless it's
120 * already used, in which case an error is thrown. This is primarilly 120 * already used, in which case an error is thrown. This is primarilly
121 * useful when copying an old Myriad file into a new one. 121 * useful when copying an old Myriad file into a new one.
122 */ 122 */
123 int createStreamWithId( int iId, int iPreAllocate=1 ); 123 int createStreamWithId( int iId, int iPreAllocate=1 );
124 124
125 /** 125 /**
126 * Delete a stream that's already within the Myriad. 126 * Delete a stream that's already within the Myriad.
127 */ 127 */
128 void deleteStream( int iId ); 128 void deleteStream( int iId );
129 129
130 /** 130 /**
131 * Return a new Stream object assosiated with the given stream ID. 131 * Return a new Stream object assosiated with the given stream ID.
132 */ 132 */
133 MyriadStream openStream( int iId ); 133 MyriadStream openStream( int iId );
134 134
135 Bu::Array<int> getStreamIds(); 135 Bu::Array<int> getStreamIds();
136 int getStreamSize( int iId ); 136 int getStreamSize( int iId );
137 bool hasStream( int iId ); 137 bool hasStream( int iId );
138 138
139 int getNumStreams(); 139 int getNumStreams();
140 int getBlockSize(); 140 int getBlockSize();
141 int getNumBlocks(); 141 int getNumBlocks();
142 int getNumUsedBlocks(); 142 int getNumUsedBlocks();
143 Bu::size getTotalUsedBytes(); 143 Bu::size getTotalUsedBytes();
144 Bu::size getTotalUnusedBytes(); 144 Bu::size getTotalUnusedBytes();
145 Bu::size getTotalUnusedBytes( int iFakeBlockSize ); 145 Bu::size getTotalUnusedBytes( int iFakeBlockSize );
146 146
147 /** 147 /**
148 * Syncronize the header data, etc. with the storage stream. It's not 148 * Syncronize the header data, etc. with the storage stream. It's not
149 * a bad idea to call this periodically. 149 * a bad idea to call this periodically.
150 */ 150 */
151 void sync(); 151 void sync();
152 152
153 /** 153 /**
154 * Read the first few bytes from the given stream and return true/false 154 * Read the first few bytes from the given stream and return true/false
155 * depending on weather or not it's a Myriad stream. This will throw 155 * depending on weather or not it's a Myriad stream. This will throw
156 * an exception if the stream is empty, or is not random access. 156 * an exception if the stream is empty, or is not random access.
157 */ 157 */
158 static bool isMyriad( Bu::Stream &sStore, uint8_t &uVer ); 158 static bool isMyriad( Bu::Stream &sStore, uint8_t &uVer );
159 159
160 /** 160 /**
161 * Read the first few bytes from the given stream and return true/false 161 * Read the first few bytes from the given stream and return true/false
162 * depending on weather or not it's a Myriad stream. This will throw 162 * depending on weather or not it's a Myriad stream. This will throw
163 * an exception if the stream is empty, or is not random access. 163 * an exception if the stream is empty, or is not random access.
164 */ 164 */
165 static bool isMyriad( Bu::Stream &sStore ); 165 static bool isMyriad( Bu::Stream &sStore );
166 166
167 const Bu::BitString getBlocksUsed() const; 167 const Bu::BitString getBlocksUsed() const;
168 168
169 private: 169 private:
170 /** 170 /**
171 * Initialize this object based on the data already in the assosiated 171 * Initialize this object based on the data already in the assosiated
172 * stream. This will be called automatically for you if you forget, 172 * stream. This will be called automatically for you if you forget,
173 * but if you want to pre-initialize for some reason, just call this 173 * but if you want to pre-initialize for some reason, just call this
174 * once before you actually start doing anything with your Myriad. 174 * once before you actually start doing anything with your Myriad.
175 */ 175 */
176 void initialize(); 176 void initialize();
177 177
178 enum 178 enum
179 { 179 {
180 blockUnused = 0xFFFFFFFFUL 180 blockUnused = 0xFFFFFFFFUL
181 }; 181 };
182 182
183 typedef Bu::Array<int> BlockArray; 183 typedef Bu::Array<int> BlockArray;
184 class Stream 184 class Stream
185 { 185 {
186 public: 186 public:
187 int iId; 187 int iId;
188 int iSize; 188 int iSize;
189 BlockArray aBlocks; 189 BlockArray aBlocks;
190 }; 190 };
191 typedef Bu::Array<Stream *> StreamArray; 191 typedef Bu::Array<Stream *> StreamArray;
192 192
193 class Block 193 class Block
194 { 194 {
195 public: 195 public:
196 char *pData; 196 char *pData;
197 bool bChanged; 197 bool bChanged;
198 int iBlockIndex; 198 int iBlockIndex;
199 }; 199 };
200 200
201 void updateHeader(); 201 void updateHeader();
202 int findEmptyBlock(); 202 int findEmptyBlock();
203 203
204 /** 204 /**
205 *@todo Change this to use a binary search, it's nicer. 205 *@todo Change this to use a binary search, it's nicer.
206 */ 206 */
207 Stream *findStream( int iId ); 207 Stream *findStream( int iId );
208 208
209 Block *getBlock( int iBlock ); 209 Block *getBlock( int iBlock );
210 void releaseBlock( Block *pBlock ); 210 void releaseBlock( Block *pBlock );
211 void syncBlock( Block *pBlock ); 211 void syncBlock( Block *pBlock );
212 212
213 int streamAddBlock( Stream *pStream ); 213 int streamAddBlock( Stream *pStream );
214 void setStreamSize( Stream *pStream, long iSize ); 214 void setStreamSize( Stream *pStream, long iSize );
215 215
216 void headerChanged(); 216 void headerChanged();
217 217
218 private: 218 private:
219 Bu::Stream &sStore; 219 Bu::Stream &sStore;
220 int iBlockSize; 220 int iBlockSize;
221 int iBlocks; 221 int iBlocks;
222 int iUsed; 222 int iUsed;
223 typedef Bu::List<int> IndexList; 223 typedef Bu::List<int> IndexList;
224 IndexList lFreeBlocks; 224 IndexList lFreeBlocks;
225// Bu::BitString bsBlockUsed; 225// Bu::BitString bsBlockUsed;
226 StreamArray aStreams; 226 StreamArray aStreams;
227 typedef Bu::Hash<int, Block *> BlockHash; 227 typedef Bu::Hash<int, Block *> BlockHash;
228 BlockHash hActiveBlocks; 228 BlockHash hActiveBlocks;
229 bool bHeaderChanged; 229 bool bHeaderChanged;
230 230
231 Bu::Mutex mHeader; 231 Bu::Mutex mHeader;
232 Bu::Mutex mActiveBlocks; 232 Bu::Mutex mActiveBlocks;
233 }; 233 };
234}; 234};
235 235
236#endif 236#endif