aboutsummaryrefslogtreecommitdiff
path: root/src/stable
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/stable/mutex.h8
-rw-r--r--src/stable/myriad.cpp167
-rw-r--r--src/stable/myriad.h81
-rw-r--r--src/stable/myriadstream.cpp6
-rw-r--r--src/stable/myriadstream.h1
5 files changed, 214 insertions, 49 deletions
diff --git a/src/stable/mutex.h b/src/stable/mutex.h
index d9e8910..8034974 100644
--- a/src/stable/mutex.h
+++ b/src/stable/mutex.h
@@ -33,7 +33,7 @@ namespace Bu
33 * wait for the mutex to unlock, the odds of which are usually farily 33 * wait for the mutex to unlock, the odds of which are usually farily
34 * low at deconstruction time. 34 * low at deconstruction time.
35 */ 35 */
36 ~Mutex(); 36 virtual ~Mutex();
37 37
38 /** 38 /**
39 * Lock the mutex. This causes all future calls to lock on this 39 * Lock the mutex. This causes all future calls to lock on this
@@ -44,13 +44,13 @@ namespace Bu
44 * computation within a locked section. This can cause thread-deadlock 44 * computation within a locked section. This can cause thread-deadlock
45 * and your program may hang. 45 * and your program may hang.
46 */ 46 */
47 int lock(); 47 virtual int lock();
48 48
49 /** 49 /**
50 * Unlock the mutex. This allows the next thread that asked for a lock 50 * Unlock the mutex. This allows the next thread that asked for a lock
51 * to lock the mutex and continue with execution. 51 * to lock the mutex and continue with execution.
52 */ 52 */
53 int unlock(); 53 virtual int unlock();
54 54
55 /** 55 /**
56 * Try to lock the mutex. This is the option to go with if you cannot 56 * Try to lock the mutex. This is the option to go with if you cannot
@@ -58,7 +58,7 @@ namespace Bu
58 * will attempt to lock the mutex, if the mutex is already locked this 58 * will attempt to lock the mutex, if the mutex is already locked this
59 * function returns immediately with an error code. 59 * function returns immediately with an error code.
60 */ 60 */
61 int trylock(); 61 virtual int trylock();
62 62
63 protected: 63 protected:
64 pthread_mutex_t mutex; /**< The internal mutex reference. */ 64 pthread_mutex_t mutex; /**< The internal mutex reference. */
diff --git a/src/stable/myriad.cpp b/src/stable/myriad.cpp
index 1bf2301..492676e 100644
--- a/src/stable/myriad.cpp
+++ b/src/stable/myriad.cpp
@@ -12,13 +12,13 @@
12#define MyriadRead( target, size ) if( rBacking.read( target, size ) < size ) \ 12#define MyriadRead( target, size ) if( rBacking.read( target, size ) < size ) \
13{ \ 13{ \
14 throw Bu::MyriadException( Bu::MyriadException::invalidFormat, \ 14 throw Bu::MyriadException( Bu::MyriadException::invalidFormat, \
15 "Insufficent data reading myriad data from backing stream."); \ 15 "Insufficient data reading myriad data from backing stream."); \
16} (void)0 16} (void)0
17 17
18#define ReqRead( stream, target, size ) if( stream.read( target, size ) < size ) \ 18#define ReqRead( stream, target, size ) if( stream.read( target, size ) < size ) \
19{ \ 19{ \
20 throw Bu::MyriadException( Bu::MyriadException::invalidFormat, \ 20 throw Bu::MyriadException( Bu::MyriadException::invalidFormat, \
21 "Insufficent data reading from myriad stream."); \ 21 "Insufficient data reading from myriad stream."); \
22} (void)0 22} (void)0
23 23
24namespace Bu 24namespace Bu
@@ -74,7 +74,7 @@ Bu::MyriadStream Bu::Myriad::create( Bu::Myriad::Mode eMode,
74 mhStream.unlock(); 74 mhStream.unlock();
75 bStructureChanged = true; 75 bStructureChanged = true;
76 76
77 return Bu::MyriadStream( *this, pStream, (Mode)(eMode&ReadWrite) ); 77 return Bu::MyriadStream( *this, pStream, eMode&ReadWrite );
78} 78}
79 79
80Bu::MyriadStream Bu::Myriad::open( Bu::Myriad::StreamId iStream, 80Bu::MyriadStream Bu::Myriad::open( Bu::Myriad::StreamId iStream,
@@ -84,7 +84,7 @@ Bu::MyriadStream Bu::Myriad::open( Bu::Myriad::StreamId iStream,
84 Bu::MutexLocker l( mhStream ); 84 Bu::MutexLocker l( mhStream );
85 if( (eMode&Create) ) 85 if( (eMode&Create) )
86 { 86 {
87 if( !hStream.has( iStream ) ) 87 if( hStream.has( iStream ) )
88 { 88 {
89 if( (eMode&Exclusive) ) 89 if( (eMode&Exclusive) )
90 { 90 {
@@ -112,7 +112,7 @@ Bu::MyriadStream Bu::Myriad::open( Bu::Myriad::StreamId iStream,
112 } 112 }
113 { 113 {
114 Bu::MutexLocker l2( mBacking ); 114 Bu::MutexLocker l2( mBacking );
115 if( (eMode&Write) && rBacking.isWritable() ) 115 if( (eMode&Write) && !rBacking.isWritable() )
116 { 116 {
117 throw Bu::MyriadException( MyriadException::badMode, 117 throw Bu::MyriadException( MyriadException::badMode,
118 "Backing stream does not support writing."); 118 "Backing stream does not support writing.");
@@ -129,8 +129,43 @@ Bu::MyriadStream Bu::Myriad::open( Bu::Myriad::StreamId iStream,
129 return Bu::MyriadStream( *this, pStream, eMode ); 129 return Bu::MyriadStream( *this, pStream, eMode );
130} 130}
131 131
132void Bu::Myriad::erase( Bu::Myriad::StreamId /*iStream*/ ) 132Bu::Myriad::StreamId Bu::Myriad::allocate()
133{ 133{
134 Bu::MutexLocker l( mAccess );
135
136 Stream *pStream = new Stream( *this, ++iLastUsedIndex, 0 );
137 mhStream.lock();
138 hStream.insert( pStream->iStream, pStream );
139 mhStream.unlock();
140 bStructureChanged = true;
141
142 return pStream->iStream;
143}
144
145void Bu::Myriad::erase( Bu::Myriad::StreamId iStream )
146{
147 // For now, let's prevent you from erasing a stream if it's open.
148 Bu::MutexLocker l( mhStream );
149 if( !hStream.has( iStream ) )
150 {
151 throw Bu::MyriadException( Bu::MyriadException::noSuchStream,
152 "No such stream exists.");
153 }
154 Stream *pStream = hStream.get( iStream );
155 Bu::MutexLocker sl( pStream->mAccess );
156 if( pStream->iOpenCount > 0 )
157 {
158 throw Bu::MyriadException( Bu::MyriadException::streamOpen,
159 "Cannot currently erase a stream while it is open.");
160 }
161
162 for( Bu::Array<int32_t>::iterator i = pStream->aBlocks.begin(); i; i++ )
163 {
164 releaseBlock( *i, false );
165 }
166 pStream->aBlocks.clear();
167 hStream.erase( iStream );
168 delete pStream;
134} 169}
135 170
136void Bu::Myriad::setSize( Bu::Myriad::StreamId iStream, 171void Bu::Myriad::setSize( Bu::Myriad::StreamId iStream,
@@ -144,6 +179,18 @@ void Bu::Myriad::setSize( Bu::Myriad::StreamId iStream,
144 pStream->setSize( iNewSize ); 179 pStream->setSize( iNewSize );
145} 180}
146 181
182int32_t Bu::Myriad::getSize( StreamId iStream ) const
183{
184 Bu::MutexLocker l( mhStream );
185 return hStream.get( iStream )->getSize();
186}
187
188bool Bu::Myriad::exists( StreamId iStream ) const
189{
190 Bu::MutexLocker l( mhStream );
191 return hStream.has( iStream );
192}
193
147Bu::String Bu::Myriad::getLocation() const 194Bu::String Bu::Myriad::getLocation() const
148{ 195{
149 Bu::MutexLocker l( mAccess ); 196 Bu::MutexLocker l( mAccess );
@@ -218,9 +265,62 @@ int32_t Bu::Myriad::getTotalUnusedBytes(int32_t iAssumeBlockSize ) const
218 return iTotal; 265 return iTotal;
219} 266}
220 267
268Bu::Myriad::StreamIdList Bu::Myriad::getStreamList() const
269{
270 mhStream.lock();
271 StreamIdList lIds = hStream.getKeys();
272 mhStream.unlock();
273 lIds.sort();
274 if( lIds.first() == 0 )
275 {
276 lIds.eraseFirst();
277 }
278 return lIds;
279}
280
281Bu::BitString Bu::Myriad::buildBlockUseMap() const
282{
283 Bu::MutexLocker l( mAccess );
284 Bu::BitString bsMap( iBlockCount );
285 bsMap.fill();
286 for( IndexList::const_iterator i = lFreeBlocks.begin(); i; i++ )
287 {
288 bsMap.setBit( *i, false );
289 }
290 return bsMap;
291}
292
293Bu::Myriad::StreamIdArray Bu::Myriad::buildBlockMap() const
294{
295 Bu::MutexLocker l( mAccess );
296 StreamIdArray bm( iBlockCount );
297 for( int j = 0; j < iBlockCount; j++ )
298 {
299 bm.append( -1 );
300 }
301 Bu::MutexLocker l2( mhStream );
302 for( StreamHash::const_iterator iStream = hStream.begin();
303 iStream; iStream++ )
304 {
305 int32_t iId = iStream.getKey();
306 Stream *pStream = iStream.getValue();
307 for( Bu::Array<int32_t>::const_iterator iBlock =
308 pStream->aBlocks.begin(); iBlock; iBlock++ )
309 {
310 bm[*iBlock] = iId;
311 }
312 }
313 return bm;
314}
315
316void Bu::Myriad::sync()
317{
318 writeHeader();
319}
320
221bool Bu::Myriad::loadMyriad() 321bool Bu::Myriad::loadMyriad()
222{ 322{
223 Bu::println("Load myriad!"); 323 //Bu::println("Load myriad!");
224 char sMagicCode[4]; 324 char sMagicCode[4];
225 rBacking.setPos( 0 ); 325 rBacking.setPos( 0 );
226 MyriadRead( sMagicCode, 4 ); 326 MyriadRead( sMagicCode, 4 );
@@ -323,7 +423,9 @@ bool Bu::Myriad::loadMyriad()
323 } 423 }
324 424
325 lFreeBlocks = hUnusedBlocks.getKeys(); 425 lFreeBlocks = hUnusedBlocks.getKeys();
326 Bu::println("Free blocks: %1").arg( lFreeBlocks.getSize() ); 426 //Bu::println("Free blocks: %1").arg( lFreeBlocks.getSize() );
427
428 bIsNewStream = false;
327 429
328 return true; 430 return true;
329} 431}
@@ -350,32 +452,21 @@ void Bu::Myriad::createMyriad( int32_t iBlockSize, int32_t iPreallocateBlocks )
350 // plus one block index. 452 // plus one block index.
351 int iHeaderStreamBlocks = blkDiv(iHeaderStreamBytes+4, iBlockSize ); 453 int iHeaderStreamBlocks = blkDiv(iHeaderStreamBytes+4, iBlockSize );
352 454
353 Bu::println("Initial estimate: %1 bytes / %2 cur blocks, %3 computed blocks (%4 target bytes).") 455 //Bu::println("Initial estimate: %1 bytes / %2 cur blocks, %3 computed blocks (%4 target bytes).").arg( iHeaderStreamBytes+(iHeaderStreamBlocks*4) ).arg( iHeaderStreamBlocks ).arg( blkDiv((iHeaderStreamBytes+(iHeaderStreamBlocks*4)), iBlockSize) ).arg( iHeaderStreamBlocks*iBlockSize );
354 .arg( iHeaderStreamBytes+(iHeaderStreamBlocks*4) )
355 .arg( iHeaderStreamBlocks )
356 .arg( blkDiv((iHeaderStreamBytes+(iHeaderStreamBlocks*4)), iBlockSize) )
357 .arg( iHeaderStreamBlocks*iBlockSize );
358 while( iHeaderStreamBytes+(iHeaderStreamBlocks*4) 456 while( iHeaderStreamBytes+(iHeaderStreamBlocks*4)
359 > iHeaderStreamBlocks*iBlockSize ) 457 > iHeaderStreamBlocks*iBlockSize )
360 { 458 {
361 iHeaderStreamBlocks = blkDiv((iHeaderStreamBytes+((iHeaderStreamBlocks+1)*4)), iBlockSize); 459 iHeaderStreamBlocks = blkDiv((iHeaderStreamBytes+((iHeaderStreamBlocks+1)*4)), iBlockSize);
362 if( iHeaderStreamBlocks > 100 ) 460 if( iHeaderStreamBlocks > 100 )
363 break; 461 break;
364 Bu::println(" Adjustment: %1 bytes / %2 cur blocks, %3 computed blocks (%4 target bytes).") 462 //Bu::println(" Adjustment: %1 bytes / %2 cur blocks, %3 computed blocks (%4 target bytes).").arg( iHeaderStreamBytes+(iHeaderStreamBlocks*4) ).arg( iHeaderStreamBlocks ).arg( blkDiv((iHeaderStreamBytes+(iHeaderStreamBlocks*4)), iBlockSize) ).arg( iHeaderStreamBlocks*iBlockSize );
365 .arg( iHeaderStreamBytes+(iHeaderStreamBlocks*4) )
366 .arg( iHeaderStreamBlocks )
367 .arg( blkDiv((iHeaderStreamBytes+(iHeaderStreamBlocks*4)), iBlockSize) )
368 .arg( iHeaderStreamBlocks*iBlockSize );
369 } 463 }
370 464
371 if( iPreallocateBlocks > iHeaderStreamBlocks ) 465 if( iPreallocateBlocks < iHeaderStreamBlocks )
372 { 466 {
373 rBacking.setSize( iBlockSize*iPreallocateBlocks ); 467 iPreallocateBlocks = iHeaderStreamBlocks;
374 }
375 else
376 {
377 rBacking.setSize( iBlockSize*iHeaderStreamBlocks );
378 } 468 }
469 rBacking.setSize( iBlockSize*iPreallocateBlocks );
379 470
380 // 471 //
381 // Write Myriad header 472 // Write Myriad header
@@ -417,12 +508,12 @@ void Bu::Myriad::createMyriad( int32_t iBlockSize, int32_t iPreallocateBlocks )
417 508
418void Bu::Myriad::writeHeader() 509void Bu::Myriad::writeHeader()
419{ 510{
511 Bu::MutexLocker l( mAccess );
420 if( !rBacking.isWritable() ) 512 if( !rBacking.isWritable() )
421 return; 513 return;
422 Bu::println("Writing stream breakdown:"); 514 //Bu::println("Writing stream breakdown:");
423 Bu::MemBuf mbHeader; 515 Bu::MemBuf mbHeader;
424 { 516 {
425 Bu::MutexLocker l( mAccess );
426 Bu::MutexLocker l2( mhStream ); 517 Bu::MutexLocker l2( mhStream );
427 518
428 int32_t iHdrStreamSize = __calcHeaderSize(); 519 int32_t iHdrStreamSize = __calcHeaderSize();
@@ -449,7 +540,7 @@ void Bu::Myriad::writeHeader()
449 psHeader->iSize = iHdrStreamSize; 540 psHeader->iSize = iHdrStreamSize;
450 } 541 }
451 542
452 Bu::println("Computed header size: %1 bytes. Ver=%2, Bpi=%3, BlockSize=%4").arg( iHdrStreamSize ).arg( 1 ).arg( 32 ).arg( iBlockSize ); 543 //Bu::println("Computed header size: %1 bytes. Ver=%2, Bpi=%3, BlockSize=%4").arg( iHdrStreamSize ).arg( 1 ).arg( 32 ).arg( iBlockSize );
453 544
454 uint8_t uVer = 1; 545 uint8_t uVer = 1;
455 uint8_t uBpi = 32; 546 uint8_t uBpi = 32;
@@ -474,17 +565,15 @@ void Bu::Myriad::writeHeader()
474 uint32_t uStreamSize = pStream->getSize(); 565 uint32_t uStreamSize = pStream->getSize();
475 mbHeader.write( &uStreamId, 4 ); 566 mbHeader.write( &uStreamId, 4 );
476 mbHeader.write( &uStreamSize, 4 ); 567 mbHeader.write( &uStreamSize, 4 );
568 int32_t iBlocks = Bu::blkDiv( uStreamSize, (uint32_t)iBlockSize );
477 Bu::Array<int32_t> aBlocks = pStream->getBlockList(); 569 Bu::Array<int32_t> aBlocks = pStream->getBlockList();
478 570
479 Bu::println(" Stream %1 is %2 bytes %3 blocks (%4 blocks computed)") 571 //Bu::println(" Stream %1 is %2 bytes %3 blocks (%4 blocks computed)").arg( *i ).arg( uStreamSize ).arg( aBlocks.getSize() ).arg( Bu::blkDiv( (int)uStreamSize, (int)iBlockSize ) );
480 .arg( *i ).arg( uStreamSize )
481 .arg( aBlocks.getSize() )
482 .arg( Bu::blkDiv( (int)uStreamSize, (int)iBlockSize ) );
483 572
484 for( Bu::Array<int32_t>::iterator i = aBlocks.begin(); i; i++ ) 573// for( Bu::Array<int32_t>::iterator i = aBlocks.begin(); i; i++ )
574 for( int j = 0; j < iBlocks; j++ )
485 { 575 {
486 int32_t iIdx = *i; 576 mbHeader.write( &aBlocks[j], 4 );
487 mbHeader.write( &iIdx, 4 );
488 } 577 }
489 } 578 }
490 579
@@ -517,15 +606,15 @@ int32_t Bu::Myriad::__calcHeaderSize()
517 } 606 }
518 } 607 }
519 608
520 Bu::println("HeaderCalc:"); 609 //Bu::println("HeaderCalc:");
521 Bu::println(" Base (no header stream): %1").arg( iHdrSize ); 610 //Bu::println(" Base (no header stream): %1").arg( iHdrSize );
522 int32_t iNewSize = iHdrSize; 611 int32_t iNewSize = iHdrSize;
523 int32_t iOldSize; 612 int32_t iOldSize;
524 613
525 do { 614 do {
526 iOldSize = iNewSize; 615 iOldSize = iNewSize;
527 iNewSize = iHdrSize + Bu::blkDiv(iNewSize, iBlockSize)*4; 616 iNewSize = iHdrSize + Bu::blkDiv(iNewSize, iBlockSize)*4;
528 Bu::println(" Recomp: %1").arg( iNewSize ); 617 //Bu::println(" Recomp: %1").arg( iNewSize );
529 } while( iOldSize != iNewSize ); 618 } while( iOldSize != iNewSize );
530 619
531 return iNewSize; 620 return iNewSize;
@@ -705,9 +794,7 @@ int32_t Bu::Myriad::Stream::read( int32_t iStart, void *pTarget,
705 794
706 if( iStart+iSize >= this->iSize ) 795 if( iStart+iSize >= this->iSize )
707 { 796 {
708 int32_t iDiff = this->iSize-(iStart+iSize); 797 iSize = this->iSize-iStart;
709 iSize -= iDiff;
710 iStart += iDiff;
711 } 798 }
712 799
713 while( iSize > 0 ) 800 while( iSize > 0 )
diff --git a/src/stable/myriad.h b/src/stable/myriad.h
index 58f700a..5accd1e 100644
--- a/src/stable/myriad.h
+++ b/src/stable/myriad.h
@@ -7,6 +7,8 @@
7#include "bu/array.h" 7#include "bu/array.h"
8#include "bu/hash.h" 8#include "bu/hash.h"
9 9
10#include "bu/bitstring.h"
11
10namespace Bu 12namespace Bu
11{ 13{
12 class MyriadStream; 14 class MyriadStream;
@@ -25,14 +27,25 @@ namespace Bu
25 invalidParameter, 27 invalidParameter,
26 invalidBackingStream, 28 invalidBackingStream,
27 badMode, 29 badMode,
30 streamOpen,
28 }; 31 };
29 subExceptionDeclEnd(); 32 subExceptionDeclEnd();
30 33
34 /**
35 * Myriad Stream Multiplexer. This is a system that allows you to store
36 * many streams within a single backing stream. This is great for databases,
37 * caching, etc. It's fairly lightweight, and allows all streams to grow
38 * dynamically using a block-allocation scheme. This is used extensively
39 * by the caching system and MyriadFs as well as other systems within
40 * libbu++.
41 */
31 class Myriad 42 class Myriad
32 { 43 {
33 public: 44 public:
34 typedef int32_t StreamId; 45 typedef int32_t StreamId;
35 enum Mode { 46 typedef Bu::Array<StreamId> StreamIdArray;
47 typedef Bu::List<StreamId> StreamIdList;
48 enum Mode : int32_t {
36 None = 0x00, 49 None = 0x00,
37 50
38 // Flags 51 // Flags
@@ -42,7 +55,7 @@ namespace Bu
42 Truncate = 0x08, ///< Truncate file if it does exist 55 Truncate = 0x08, ///< Truncate file if it does exist
43 Append = 0x10, ///< Start writing at end of file 56 Append = 0x10, ///< Start writing at end of file
44 //NonBlock = 0x20, ///< Open file in non-blocking mode 57 //NonBlock = 0x20, ///< Open file in non-blocking mode
45 Exclusive = 0x44, ///< Create file, if it exists then fail 58 Exclusive = 0x40, ///< Create file, if it exists then fail
46 59
47 // Helpful mixes 60 // Helpful mixes
48 ReadWrite = 0x03, ///< Open for reading and writing 61 ReadWrite = 0x03, ///< Open for reading and writing
@@ -52,8 +65,9 @@ namespace Bu
52 65
53 public: 66 public:
54 /** 67 /**
55 * Open existing Myriad stream, or initialize a new one if it doesn't 68 * Open existing Myriad container, or initialize a new one if the
56 * exist. 69 * backing stream is empty. If other data is already in the provided
70 * backing stream an error is thrown.
57 * 71 *
58 * Myriad format V0 72 * Myriad format V0
59 * 0 - 3: Myriad_MAGIC_CODE (0ad3fa84) 73 * 0 - 3: Myriad_MAGIC_CODE (0ad3fa84)
@@ -68,13 +82,40 @@ namespace Bu
68 * 4 - 7: Size of stream in bytes 82 * 4 - 7: Size of stream in bytes
69 * 8 - ...: List of blocks in stream (4 bytes per block 83 * 8 - ...: List of blocks in stream (4 bytes per block
70 */ 84 */
71 Myriad( Bu::Stream &rBacking, int32_t iBlockSize=-1, int32_t iPreallocateBlocks=-1 ); 85 Myriad( Bu::Stream &rBacking, int32_t iBlockSize=-1,
86 int32_t iPreallocateBlocks=-1 );
72 virtual ~Myriad(); 87 virtual ~Myriad();
73 88
89 /**
90 * Creates a new stream open in the specified eMode and, optionally,
91 * preallocates the specificed amount of space. The stream is zero
92 * bytes even if space is preallocated. The open stream is returned,
93 * ready for use. Use this if you don't care what the id is of the
94 * newly created stream.
95 */
74 MyriadStream create( Mode eMode, int32_t iPreallocateBytes=-1 ); 96 MyriadStream create( Mode eMode, int32_t iPreallocateBytes=-1 );
97
98 /**
99 * Open an existing stream or create a new stream with the specified
100 * id (iStream) with the specified eMode. This respects the normal file
101 * modes, see Bu::Myriad::Mode for details.
102 */
75 MyriadStream open( StreamId iStream, Mode eMode ); 103 MyriadStream open( StreamId iStream, Mode eMode );
104
105 /**
106 * Allocate a new stream but do not open it, just ensure it exists and
107 * return the id of the newly allocated stream.
108 */
109 StreamId allocate();
110
111 /**
112 * Erase the stream specified by iStream. This only can work when the
113 * stream is not open at the moment.
114 */
76 void erase( StreamId iStream ); 115 void erase( StreamId iStream );
77 void setSize( StreamId iStream, int32_t iNewSize ); 116 void setSize( StreamId iStream, int32_t iNewSize );
117 int32_t getSize( StreamId iStream ) const;
118 bool exists( StreamId iStream ) const;
78 Bu::String getLocation() const; 119 Bu::String getLocation() const;
79 int32_t getBlockSize() const; 120 int32_t getBlockSize() const;
80 int32_t getTotalBlocks() const; 121 int32_t getTotalBlocks() const;
@@ -83,6 +124,22 @@ namespace Bu
83 int32_t getTotalStreams() const; 124 int32_t getTotalStreams() const;
84 int32_t getTotalUsedBytes() const; 125 int32_t getTotalUsedBytes() const;
85 int32_t getTotalUnusedBytes( int32_t iAssumeBlockSize=-1 ) const; 126 int32_t getTotalUnusedBytes( int32_t iAssumeBlockSize=-1 ) const;
127 Bu::BitString buildBlockUseMap() const;
128 StreamIdArray buildBlockMap() const;
129
130 /**
131 * Lists all stream ids that you are allowed to open. Technically there
132 * is always a zero stream, but it is used by Myriad for stream/block
133 * accounting. It works like a normal stream but you should not open
134 * it.
135 */
136 StreamIdList getStreamList() const;
137
138 /**
139 * Flush all caches to the backing stream, write all structural and
140 * header changes.
141 */
142 void sync();
86 143
87 private: 144 private:
88 bool loadMyriad(); 145 bool loadMyriad();
@@ -175,6 +232,20 @@ namespace Bu
175 IndexList lFreeBlocks; 232 IndexList lFreeBlocks;
176 StreamId iLastUsedIndex; 233 StreamId iLastUsedIndex;
177 }; 234 };
235 constexpr Myriad::Mode operator&( Myriad::Mode a, Myriad::Mode b )
236 {
237 return static_cast<Myriad::Mode>(
238 static_cast<std::underlying_type<Myriad::Mode>::type>(a) &
239 static_cast<std::underlying_type<Myriad::Mode>::type>(b)
240 );
241 }
242 constexpr Myriad::Mode operator|( Myriad::Mode a, Myriad::Mode b )
243 {
244 return static_cast<Myriad::Mode>(
245 static_cast<std::underlying_type<Myriad::Mode>::type>(a) |
246 static_cast<std::underlying_type<Myriad::Mode>::type>(b)
247 );
248 }
178}; 249};
179 250
180#endif 251#endif
diff --git a/src/stable/myriadstream.cpp b/src/stable/myriadstream.cpp
index 9ea2e17..eaf91a5 100644
--- a/src/stable/myriadstream.cpp
+++ b/src/stable/myriadstream.cpp
@@ -166,3 +166,9 @@ Bu::String Bu::MyriadStream::getLocation() const
166 return pStream->getLocation(); 166 return pStream->getLocation();
167} 167}
168 168
169Bu::Myriad::StreamId Bu::MyriadStream::getId() const
170{
171 Bu::MutexLocker l( mAccess );
172 return pStream->getStreamId();
173}
174
diff --git a/src/stable/myriadstream.h b/src/stable/myriadstream.h
index b86dbd7..27a15d5 100644
--- a/src/stable/myriadstream.h
+++ b/src/stable/myriadstream.h
@@ -39,6 +39,7 @@ namespace Bu
39 virtual size getSize() const; 39 virtual size getSize() const;
40 virtual size getBlockSize() const; 40 virtual size getBlockSize() const;
41 virtual Bu::String getLocation() const; 41 virtual Bu::String getLocation() const;
42 Myriad::StreamId getId() const;
42 43
43 private: 44 private:
44 mutable Bu::Mutex mAccess; 45 mutable Bu::Mutex mAccess;