aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/stable/file.cpp22
-rw-r--r--src/stable/myriad.cpp159
-rw-r--r--src/stable/myriad.h13
3 files changed, 149 insertions, 45 deletions
diff --git a/src/stable/file.cpp b/src/stable/file.cpp
index 05e4af1..55766ea 100644
--- a/src/stable/file.cpp
+++ b/src/stable/file.cpp
@@ -142,6 +142,16 @@ bool Bu::File::isEos()
142 142
143bool Bu::File::canRead() 143bool Bu::File::canRead()
144{ 144{
145 return isReadable();
146}
147
148bool Bu::File::canWrite()
149{
150 return isWritable();
151}
152
153bool Bu::File::isReadable()
154{
145#ifdef WIN32 155#ifdef WIN32
146 return true; 156 return true;
147#else 157#else
@@ -152,7 +162,7 @@ bool Bu::File::canRead()
152#endif 162#endif
153} 163}
154 164
155bool Bu::File::canWrite() 165bool Bu::File::isWritable()
156{ 166{
157#ifdef WIN32 167#ifdef WIN32
158 return true; 168 return true;
@@ -164,16 +174,6 @@ bool Bu::File::canWrite()
164#endif 174#endif
165} 175}
166 176
167bool Bu::File::isReadable()
168{
169 return true;
170}
171
172bool Bu::File::isWritable()
173{
174 return true;
175}
176
177bool Bu::File::isSeekable() 177bool Bu::File::isSeekable()
178{ 178{
179 return true; 179 return true;
diff --git a/src/stable/myriad.cpp b/src/stable/myriad.cpp
index 44a990a..4edd004 100644
--- a/src/stable/myriad.cpp
+++ b/src/stable/myriad.cpp
@@ -15,6 +15,12 @@
15 "Insufficent data reading myriad data from backing stream."); \ 15 "Insufficent 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 ) \
19{ \
20 throw Bu::MyriadException( Bu::MyriadException::invalidFormat, \
21 "Insufficent data reading from myriad stream."); \
22} (void)0
23
18namespace Bu 24namespace Bu
19{ 25{
20 subExceptionDef( MyriadException ) 26 subExceptionDef( MyriadException )
@@ -63,7 +69,9 @@ Bu::MyriadStream Bu::Myriad::create( Bu::Myriad::Mode eMode,
63 { 69 {
64 pStream->aBlocks.append( __allocateBlock() ); 70 pStream->aBlocks.append( __allocateBlock() );
65 } 71 }
72 mhStream.lock();
66 hStream.insert( pStream->iStream, pStream ); 73 hStream.insert( pStream->iStream, pStream );
74 mhStream.unlock();
67 bStructureChanged = true; 75 bStructureChanged = true;
68 76
69 return Bu::MyriadStream( *this, pStream, (Mode)(eMode&ReadWrite) ); 77 return Bu::MyriadStream( *this, pStream, (Mode)(eMode&ReadWrite) );
@@ -72,7 +80,7 @@ Bu::MyriadStream Bu::Myriad::create( Bu::Myriad::Mode eMode,
72Bu::MyriadStream Bu::Myriad::open( Bu::Myriad::StreamId iStream, 80Bu::MyriadStream Bu::Myriad::open( Bu::Myriad::StreamId iStream,
73 Bu::Myriad::Mode eMode ) 81 Bu::Myriad::Mode eMode )
74{ 82{
75 Bu::MutexLocker l( mAccess ); 83 Bu::MutexLocker l( mhStream );
76 if( !hStream.has( iStream ) ) 84 if( !hStream.has( iStream ) )
77 { 85 {
78 throw Bu::MyriadException( MyriadException::noSuchStream, 86 throw Bu::MyriadException( MyriadException::noSuchStream,
@@ -89,15 +97,19 @@ Bu::MyriadStream Bu::Myriad::open( Bu::Myriad::StreamId iStream,
89 return Bu::MyriadStream( *this, hStream.get( iStream ), eMode ); 97 return Bu::MyriadStream( *this, hStream.get( iStream ), eMode );
90} 98}
91 99
92bool Bu::Myriad::erase( Bu::Myriad::StreamId /*iStream*/ ) 100void Bu::Myriad::erase( Bu::Myriad::StreamId /*iStream*/ )
93{ 101{
94 return false;
95} 102}
96 103
97bool Bu::Myriad::setSize( Bu::Myriad::StreamId /*iStream*/, 104void Bu::Myriad::setSize( Bu::Myriad::StreamId iStream,
98 int32_t /*iNewSize*/ ) 105 int32_t iNewSize )
99{ 106{
100 return false; 107 Stream *pStream;
108 {
109 Bu::MutexLocker l( mhStream );
110 pStream = hStream.get( iStream );
111 }
112 pStream->setSize( iNewSize );
101} 113}
102 114
103Bu::String Bu::Myriad::getLocation() const 115Bu::String Bu::Myriad::getLocation() const
@@ -108,6 +120,72 @@ Bu::String Bu::Myriad::getLocation() const
108 .arg( 1 ).arg( iBlockSize ).arg( rBacking.getLocation() ); 120 .arg( 1 ).arg( iBlockSize ).arg( rBacking.getLocation() );
109} 121}
110 122
123int32_t Bu::Myriad::getBlockSize() const
124{
125 Bu::MutexLocker l( mAccess );
126 return iBlockSize;
127}
128
129int32_t Bu::Myriad::getTotalBlocks() const
130{
131 Bu::MutexLocker l( mAccess );
132 return iBlockCount;
133}
134
135int32_t Bu::Myriad::getUsedBlocks() const
136{
137 Bu::MutexLocker l( mAccess );
138 return iBlockCount-lFreeBlocks.getSize();
139}
140
141int32_t Bu::Myriad::getFreeBlocks() const
142{
143 Bu::MutexLocker l( mAccess );
144 return lFreeBlocks.getSize();
145}
146
147int32_t Bu::Myriad::getTotalStreams() const
148{
149 Bu::MutexLocker l( mhStream );
150 return hStream.getSize();
151}
152
153int32_t Bu::Myriad::getTotalUsedBytes() const
154{
155 Bu::MutexLocker l( mhStream );
156 int32_t iTotal = 0;
157 for( StreamHash::const_iterator i = hStream.begin(); i; i++ )
158 {
159 iTotal += i.getValue()->getSize();
160 }
161
162 return iTotal;
163}
164
165int32_t Bu::Myriad::getTotalUnusedBytes(int32_t iAssumeBlockSize ) const
166{
167 if( iAssumeBlockSize < 0 )
168 {
169 iAssumeBlockSize = getBlockSize();
170 }
171 int32_t iTotal = 0;
172 {
173 Bu::MutexLocker l( mhStream );
174 for( StreamHash::const_iterator i = hStream.begin(); i; i++ )
175 {
176 if( (i.getValue()->getSize()%iAssumeBlockSize) > 0 )
177 iTotal += iBlockSize-(i.getValue()->getSize()%iAssumeBlockSize);
178 }
179 }
180
181 {
182 Bu::MutexLocker l( mAccess );
183 iTotal += lFreeBlocks.getSize()*iBlockSize;
184 }
185
186 return iTotal;
187}
188
111bool Bu::Myriad::loadMyriad() 189bool Bu::Myriad::loadMyriad()
112{ 190{
113 Bu::println("Load myriad!"); 191 Bu::println("Load myriad!");
@@ -129,11 +207,25 @@ bool Bu::Myriad::loadMyriad()
129 } 207 }
130 MyriadRead( &uBitsPerInt, 1 ); 208 MyriadRead( &uBitsPerInt, 1 );
131 if( uBitsPerInt != 32 ) 209 if( uBitsPerInt != 32 )
132{ 210 {
133 throw Bu::MyriadException( Bu::MyriadException::invalidFormat, 211 throw Bu::MyriadException( Bu::MyriadException::invalidFormat,
134 "Only 32 bits per int are supported at this time."); 212 "Only 32 bits per int are supported at this time.");
135 } 213 }
136 MyriadRead( &iBlockSize, 4 ); 214 MyriadRead( &iBlockSize, 4 );
215
216 iBlockCount = rBacking.getSize()/iBlockSize;
217 if( (rBacking.getSize()%iBlockSize) != 0 )
218 {
219 throw Bu::MyriadException( Bu::MyriadException::invalidFormat,
220 "Backing stream is not cleanly divisibly by the block size.");
221 }
222
223 Bu::Hash<int32_t,bool> hUnusedBlocks;
224 for( int32_t j = 0; j < iBlockCount; j++ )
225 {
226 hUnusedBlocks.insert( j, true );
227 }
228
137 int iStreamCount; 229 int iStreamCount;
138 MyriadRead( &iStreamCount, 4 ); 230 MyriadRead( &iStreamCount, 4 );
139 231
@@ -162,6 +254,7 @@ bool Bu::Myriad::loadMyriad()
162 { 254 {
163 int32_t iBlockIndex; 255 int32_t iBlockIndex;
164 MyriadRead( &iBlockIndex, 4 ); 256 MyriadRead( &iBlockIndex, 4 );
257 hUnusedBlocks.erase( iBlockIndex );
165 pHeaderStream->aBlocks.append( iBlockIndex ); 258 pHeaderStream->aBlocks.append( iBlockIndex );
166 if( rBacking.tell()+4 <= (j+1)*iBlockSize ) 259 if( rBacking.tell()+4 <= (j+1)*iBlockSize )
167 break; 260 break;
@@ -172,7 +265,8 @@ bool Bu::Myriad::loadMyriad()
172 while( pHeaderStream->aBlocks.getSize() < iHeaderStreamBlocks ) 265 while( pHeaderStream->aBlocks.getSize() < iHeaderStreamBlocks )
173 { 266 {
174 int32_t iBlockIndex; 267 int32_t iBlockIndex;
175 sHeader.read( &iBlockIndex, 4 ); 268 ReqRead( sHeader, &iBlockIndex, 4 );
269 hUnusedBlocks.erase( iBlockIndex );
176 pHeaderStream->aBlocks.append( iBlockIndex ); 270 pHeaderStream->aBlocks.append( iBlockIndex );
177 } 271 }
178 272
@@ -180,14 +274,15 @@ bool Bu::Myriad::loadMyriad()
180 for( int j = 1; j < iStreamCount; j++ ) 274 for( int j = 1; j < iStreamCount; j++ )
181 { 275 {
182 int32_t iStreamBytes; 276 int32_t iStreamBytes;
183 sHeader.read( &iStream, 4 ); 277 ReqRead( sHeader, &iStream, 4 );
184 sHeader.read( &iStreamBytes, 4 ); 278 ReqRead( sHeader, &iStreamBytes, 4 );
185 Stream *pStream = new Stream( *this, iStream, iStreamBytes ); 279 Stream *pStream = new Stream( *this, iStream, iStreamBytes );
186 int32_t iBlocks = blkDiv(iStreamBytes, iBlockSize ); 280 int32_t iBlocks = blkDiv(iStreamBytes, iBlockSize );
187 for( int k = 0; k < iBlocks; k++ ) 281 for( int k = 0; k < iBlocks; k++ )
188 { 282 {
189 int32_t iBlockIndex; 283 int32_t iBlockIndex;
190 sHeader.read( &iBlockIndex, 4 ); 284 ReqRead( sHeader, &iBlockIndex, 4 );
285 hUnusedBlocks.erase( iBlockIndex );
191 pStream->aBlocks.append( iBlockIndex ); 286 pStream->aBlocks.append( iBlockIndex );
192 } 287 }
193 hStream.insert( iStream, pStream ); 288 hStream.insert( iStream, pStream );
@@ -195,6 +290,9 @@ bool Bu::Myriad::loadMyriad()
195 iLastUsedIndex = iStream; 290 iLastUsedIndex = iStream;
196 } 291 }
197 292
293 lFreeBlocks = hUnusedBlocks.getKeys();
294 Bu::println("Free blocks: %1").arg( lFreeBlocks.getSize() );
295
198 return true; 296 return true;
199} 297}
200 298
@@ -211,23 +309,6 @@ void Bu::Myriad::createMyriad( int32_t iBlockSize, int32_t iPreallocateBlocks )
211 "Backing stream contains data, but not a myriad structure."); 309 "Backing stream contains data, but not a myriad structure.");
212 } 310 }
213 311
214/*
215 struct {
216 char sMagicCode[4];
217 uint8_t uVer;
218 uint8_t uBitsPerInt;
219 uint32_t uBlockSize;
220 uint32_t uStreamCount;
221 } sHeader;
222
223 struct {
224 uint32_t uStreamId;
225 uint32_t uStreamSize;
226 } sStreamHeader;
227
228 Bu::println("sHeader = %1, sStreamHeader = %2").arg( sizeof(sHeader) ).arg( sizeof(sStreamHeader) );
229*/
230
231 // Start with the bytes for the file header and initial stream header 312 // Start with the bytes for the file header and initial stream header
232 int iHeaderStreamBytes 313 int iHeaderStreamBytes
233 = 14 // Base header 314 = 14 // Base header
@@ -299,6 +380,7 @@ void Bu::Myriad::createMyriad( int32_t iBlockSize, int32_t iPreallocateBlocks )
299 lFreeBlocks.append( j ); 380 lFreeBlocks.append( j );
300 } 381 }
301 iLastUsedIndex = 0; 382 iLastUsedIndex = 0;
383 iBlockCount = iPreallocateBlocks;
302} 384}
303 385
304void Bu::Myriad::writeHeader() 386void Bu::Myriad::writeHeader()
@@ -309,6 +391,7 @@ void Bu::Myriad::writeHeader()
309 Bu::MemBuf mbHeader; 391 Bu::MemBuf mbHeader;
310 { 392 {
311 Bu::MutexLocker l( mAccess ); 393 Bu::MutexLocker l( mAccess );
394 Bu::MutexLocker l2( mhStream );
312 395
313 int32_t iHdrStreamSize = __calcHeaderSize(); 396 int32_t iHdrStreamSize = __calcHeaderSize();
314 // Maybe just do stream surgery here. 397 // Maybe just do stream surgery here.
@@ -401,12 +484,15 @@ int32_t Bu::Myriad::__calcHeaderSize()
401 } 484 }
402 } 485 }
403 486
487 Bu::println("HeaderCalc:");
488 Bu::println(" Base (no header stream): %1").arg( iHdrSize );
404 int32_t iNewSize = iHdrSize; 489 int32_t iNewSize = iHdrSize;
405 int32_t iOldSize; 490 int32_t iOldSize;
406 491
407 do { 492 do {
408 iOldSize = iNewSize; 493 iOldSize = iNewSize;
409 iNewSize = iHdrSize + Bu::blkDiv(iNewSize, iBlockSize); 494 iNewSize = iHdrSize + Bu::blkDiv(iNewSize, iBlockSize)*4;
495 Bu::println(" Recomp: %1").arg( iNewSize );
410 } while( iOldSize != iNewSize ); 496 } while( iOldSize != iNewSize );
411 497
412 return iNewSize; 498 return iNewSize;
@@ -467,13 +553,13 @@ void Bu::Myriad::blankBlock( int32_t iBlockId )
467 553
468void Bu::Myriad::openStream( StreamId id ) 554void Bu::Myriad::openStream( StreamId id )
469{ 555{
470 Bu::MutexLocker l( mAccess ); 556 Bu::MutexLocker l( mhStream );
471 hStream.get( id )->open(); 557 hStream.get( id )->open();
472} 558}
473 559
474void Bu::Myriad::closeStream( StreamId id ) 560void Bu::Myriad::closeStream( StreamId id )
475{ 561{
476 Bu::MutexLocker l( mAccess ); 562 Bu::MutexLocker l( mhStream );
477 hStream.get( id )->close(); 563 hStream.get( id )->close();
478} 564}
479 565
@@ -579,6 +665,17 @@ int32_t Bu::Myriad::Stream::read( int32_t iStart, void *pTarget,
579{ 665{
580 int32_t iRead = 0; 666 int32_t iRead = 0;
581 Bu::MutexLocker l( mAccess ); 667 Bu::MutexLocker l( mAccess );
668
669 if( iStart >= this->iSize )
670 return 0;
671
672 if( iStart+iSize >= this->iSize )
673 {
674 int32_t iDiff = this->iSize-(iStart+iSize);
675 iSize -= iDiff;
676 iStart += iDiff;
677 }
678
582 while( iSize > 0 ) 679 while( iSize > 0 )
583 { 680 {
584 int32_t iBlock = aBlocks[iStart/rParent.iBlockSize]; 681 int32_t iBlock = aBlocks[iStart/rParent.iBlockSize];
diff --git a/src/stable/myriad.h b/src/stable/myriad.h
index 7cf6041..58f700a 100644
--- a/src/stable/myriad.h
+++ b/src/stable/myriad.h
@@ -73,9 +73,16 @@ namespace Bu
73 73
74 MyriadStream create( Mode eMode, int32_t iPreallocateBytes=-1 ); 74 MyriadStream create( Mode eMode, int32_t iPreallocateBytes=-1 );
75 MyriadStream open( StreamId iStream, Mode eMode ); 75 MyriadStream open( StreamId iStream, Mode eMode );
76 bool erase( StreamId iStream ); 76 void erase( StreamId iStream );
77 bool setSize( StreamId iStream, int32_t iNewSize ); 77 void setSize( StreamId iStream, int32_t iNewSize );
78 Bu::String getLocation() const; 78 Bu::String getLocation() const;
79 int32_t getBlockSize() const;
80 int32_t getTotalBlocks() const;
81 int32_t getUsedBlocks() const;
82 int32_t getFreeBlocks() const;
83 int32_t getTotalStreams() const;
84 int32_t getTotalUsedBytes() const;
85 int32_t getTotalUnusedBytes( int32_t iAssumeBlockSize=-1 ) const;
79 86
80 private: 87 private:
81 bool loadMyriad(); 88 bool loadMyriad();
@@ -151,7 +158,6 @@ namespace Bu
151 int32_t iSize; 158 int32_t iSize;
152 Bu::Array<int32_t> aBlocks; 159 Bu::Array<int32_t> aBlocks;
153 int32_t iOpenCount; 160 int32_t iOpenCount;
154 bool bStructureChanged;
155 }; 161 };
156 162
157 private: 163 private:
@@ -164,6 +170,7 @@ namespace Bu
164 int32_t iBlockCount; 170 int32_t iBlockCount;
165 bool bIsNewStream; 171 bool bIsNewStream;
166 bool bStructureChanged; 172 bool bStructureChanged;
173 mutable Bu::Mutex mhStream;
167 StreamHash hStream; 174 StreamHash hStream;
168 IndexList lFreeBlocks; 175 IndexList lFreeBlocks;
169 StreamId iLastUsedIndex; 176 StreamId iLastUsedIndex;