diff options
Diffstat (limited to '')
| -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; |
