diff options
-rw-r--r-- | src/stable/file.cpp | 22 | ||||
-rw-r--r-- | src/stable/myriad.cpp | 159 | ||||
-rw-r--r-- | src/stable/myriad.h | 13 |
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 | ||
143 | bool Bu::File::canRead() | 143 | bool Bu::File::canRead() |
144 | { | 144 | { |
145 | return isReadable(); | ||
146 | } | ||
147 | |||
148 | bool Bu::File::canWrite() | ||
149 | { | ||
150 | return isWritable(); | ||
151 | } | ||
152 | |||
153 | bool 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 | ||
155 | bool Bu::File::canWrite() | 165 | bool 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 | ||
167 | bool Bu::File::isReadable() | ||
168 | { | ||
169 | return true; | ||
170 | } | ||
171 | |||
172 | bool Bu::File::isWritable() | ||
173 | { | ||
174 | return true; | ||
175 | } | ||
176 | |||
177 | bool Bu::File::isSeekable() | 177 | bool 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 | |||
18 | namespace Bu | 24 | namespace 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, | |||
72 | Bu::MyriadStream Bu::Myriad::open( Bu::Myriad::StreamId iStream, | 80 | Bu::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 | ||
92 | bool Bu::Myriad::erase( Bu::Myriad::StreamId /*iStream*/ ) | 100 | void Bu::Myriad::erase( Bu::Myriad::StreamId /*iStream*/ ) |
93 | { | 101 | { |
94 | return false; | ||
95 | } | 102 | } |
96 | 103 | ||
97 | bool Bu::Myriad::setSize( Bu::Myriad::StreamId /*iStream*/, | 104 | void 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 | ||
103 | Bu::String Bu::Myriad::getLocation() const | 115 | Bu::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 | ||
123 | int32_t Bu::Myriad::getBlockSize() const | ||
124 | { | ||
125 | Bu::MutexLocker l( mAccess ); | ||
126 | return iBlockSize; | ||
127 | } | ||
128 | |||
129 | int32_t Bu::Myriad::getTotalBlocks() const | ||
130 | { | ||
131 | Bu::MutexLocker l( mAccess ); | ||
132 | return iBlockCount; | ||
133 | } | ||
134 | |||
135 | int32_t Bu::Myriad::getUsedBlocks() const | ||
136 | { | ||
137 | Bu::MutexLocker l( mAccess ); | ||
138 | return iBlockCount-lFreeBlocks.getSize(); | ||
139 | } | ||
140 | |||
141 | int32_t Bu::Myriad::getFreeBlocks() const | ||
142 | { | ||
143 | Bu::MutexLocker l( mAccess ); | ||
144 | return lFreeBlocks.getSize(); | ||
145 | } | ||
146 | |||
147 | int32_t Bu::Myriad::getTotalStreams() const | ||
148 | { | ||
149 | Bu::MutexLocker l( mhStream ); | ||
150 | return hStream.getSize(); | ||
151 | } | ||
152 | |||
153 | int32_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 | |||
165 | int32_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 | |||
111 | bool Bu::Myriad::loadMyriad() | 189 | bool 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 | ||
304 | void Bu::Myriad::writeHeader() | 386 | void 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 | ||
468 | void Bu::Myriad::openStream( StreamId id ) | 554 | void 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 | ||
474 | void Bu::Myriad::closeStream( StreamId id ) | 560 | void 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; |