diff options
| author | Mike Buland <mike@xagasoft.com> | 2024-09-16 10:27:52 -0700 |
|---|---|---|
| committer | Mike Buland <mike@xagasoft.com> | 2024-09-16 10:27:52 -0700 |
| commit | d1f985c8191326292dd2ae5a85a63993ad68ddd7 (patch) | |
| tree | 51d3f648936f28421bacc18c3bb0d4670b58259e /src | |
| parent | 0886ad4f53deb8e148f87f77b9e7ff690c02b069 (diff) | |
| download | libbu++-d1f985c8191326292dd2ae5a85a63993ad68ddd7.tar.gz libbu++-d1f985c8191326292dd2ae5a85a63993ad68ddd7.tar.bz2 libbu++-d1f985c8191326292dd2ae5a85a63993ad68ddd7.tar.xz libbu++-d1f985c8191326292dd2ae5a85a63993ad68ddd7.zip | |
It could use more testing, but...it works.
Diffstat (limited to '')
| -rw-r--r-- | src/stable/myriad.cpp | 222 | ||||
| -rw-r--r-- | src/stable/myriad.h | 13 | ||||
| -rw-r--r-- | src/stable/myriadstream.h | 2 | ||||
| -rw-r--r-- | src/tests/bigmyriad.cpp | 14 |
4 files changed, 218 insertions, 33 deletions
diff --git a/src/stable/myriad.cpp b/src/stable/myriad.cpp index f3ff09a..44a990a 100644 --- a/src/stable/myriad.cpp +++ b/src/stable/myriad.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include "bu/myriad.h" | 1 | #include "bu/myriad.h" |
| 2 | #include "bu/myriadstream.h" | 2 | #include "bu/myriadstream.h" |
| 3 | 3 | ||
| 4 | #include "bu/membuf.h" | ||
| 4 | #include "bu/mutexlocker.h" | 5 | #include "bu/mutexlocker.h" |
| 5 | #include "bu/util.h" | 6 | #include "bu/util.h" |
| 6 | 7 | ||
| @@ -27,27 +28,45 @@ Bu::Myriad::Myriad( Bu::Stream &rBacking, int iBlockSize, | |||
| 27 | rBacking( rBacking ), | 28 | rBacking( rBacking ), |
| 28 | iBlockSize( iBlockSize ), | 29 | iBlockSize( iBlockSize ), |
| 29 | iBlockCount( 0 ), | 30 | iBlockCount( 0 ), |
| 30 | bIsNewStream( true ) | 31 | bIsNewStream( true ), |
| 32 | bStructureChanged( false ), | ||
| 33 | iLastUsedIndex( -1 ) | ||
| 31 | { | 34 | { |
| 32 | if( !rBacking.isSeekable() ) | 35 | if( !rBacking.isSeekable() ) |
| 33 | { | 36 | { |
| 34 | throw Bu::MyriadException( Bu::MyriadException::invalidBackingStream, | 37 | throw Bu::MyriadException( Bu::MyriadException::invalidBackingStream, |
| 35 | "Myriad backing stream must be random access (seekable)."); | 38 | "Myriad backing stream must be random access (seekable)."); |
| 36 | } | 39 | } |
| 37 | if( !loadMyriad() ) | 40 | if( rBacking.getSize() == 0 ) |
| 38 | { | 41 | { |
| 39 | createMyriad( iBlockSize, iPreallocateBlocks ); | 42 | createMyriad( iBlockSize, iPreallocateBlocks ); |
| 40 | } | 43 | } |
| 44 | else | ||
| 45 | { | ||
| 46 | loadMyriad(); | ||
| 47 | } | ||
| 41 | } | 48 | } |
| 42 | 49 | ||
| 43 | Bu::Myriad::~Myriad() | 50 | Bu::Myriad::~Myriad() |
| 44 | { | 51 | { |
| 52 | writeHeader(); | ||
| 45 | } | 53 | } |
| 46 | 54 | ||
| 47 | Bu::MyriadStream Bu::Myriad::create( Bu::Myriad::Mode /*eMode*/, | 55 | Bu::MyriadStream Bu::Myriad::create( Bu::Myriad::Mode eMode, |
| 48 | int32_t /*iPreallocateBytes*/ ) | 56 | int32_t iPreallocateBytes ) |
| 49 | { | 57 | { |
| 50 | return Bu::MyriadStream( *this, NULL, (Mode)0 ); | 58 | Bu::MutexLocker l( mAccess ); |
| 59 | |||
| 60 | Stream *pStream = new Stream( *this, ++iLastUsedIndex, 0 ); | ||
| 61 | int iBlocks = std::max(1, blkDiv( iPreallocateBytes, iBlockSize )); | ||
| 62 | for( int j = 0; j < iBlocks; j++ ) | ||
| 63 | { | ||
| 64 | pStream->aBlocks.append( __allocateBlock() ); | ||
| 65 | } | ||
| 66 | hStream.insert( pStream->iStream, pStream ); | ||
| 67 | bStructureChanged = true; | ||
| 68 | |||
| 69 | return Bu::MyriadStream( *this, pStream, (Mode)(eMode&ReadWrite) ); | ||
| 51 | } | 70 | } |
| 52 | 71 | ||
| 53 | Bu::MyriadStream Bu::Myriad::open( Bu::Myriad::StreamId iStream, | 72 | Bu::MyriadStream Bu::Myriad::open( Bu::Myriad::StreamId iStream, |
| @@ -110,7 +129,7 @@ bool Bu::Myriad::loadMyriad() | |||
| 110 | } | 129 | } |
| 111 | MyriadRead( &uBitsPerInt, 1 ); | 130 | MyriadRead( &uBitsPerInt, 1 ); |
| 112 | if( uBitsPerInt != 32 ) | 131 | if( uBitsPerInt != 32 ) |
| 113 | { | 132 | { |
| 114 | throw Bu::MyriadException( Bu::MyriadException::invalidFormat, | 133 | throw Bu::MyriadException( Bu::MyriadException::invalidFormat, |
| 115 | "Only 32 bits per int are supported at this time."); | 134 | "Only 32 bits per int are supported at this time."); |
| 116 | } | 135 | } |
| @@ -128,28 +147,53 @@ bool Bu::Myriad::loadMyriad() | |||
| 128 | throw Bu::MyriadException( Bu::MyriadException::invalidFormat, | 147 | throw Bu::MyriadException( Bu::MyriadException::invalidFormat, |
| 129 | "The first stream defined must be the header/zero stream."); | 148 | "The first stream defined must be the header/zero stream."); |
| 130 | } | 149 | } |
| 150 | iLastUsedIndex = iStream; | ||
| 131 | int32_t iHeaderStreamBytes; | 151 | int32_t iHeaderStreamBytes; |
| 132 | MyriadRead( &iHeaderStreamBytes, 4 ); | 152 | MyriadRead( &iHeaderStreamBytes, 4 ); |
| 133 | 153 | ||
| 134 | Stream *pHeaderStream = new Stream( *this, iStream, iHeaderStreamBytes ); | 154 | Stream *pHeaderStream = new Stream( *this, iStream, iHeaderStreamBytes ); |
| 135 | int iHeaderStreamBlocks = blkDiv(iHeaderStreamBytes+4, iBlockSize ); | 155 | hStream.insert( iStream, pHeaderStream ); |
| 136 | 156 | int iHeaderStreamBlocks = blkDiv(iHeaderStreamBytes, iBlockSize ); | |
| 137 | while( iHeaderStreamBytes+(iHeaderStreamBlocks*4) | 157 | MyriadStream sHeader( *this, pHeaderStream, Read ); |
| 138 | > iHeaderStreamBlocks*iBlockSize ) | ||
| 139 | { | ||
| 140 | iHeaderStreamBlocks = blkDiv( | ||
| 141 | (iHeaderStreamBytes+((iHeaderStreamBlocks+1)*4)), iBlockSize | ||
| 142 | ); | ||
| 143 | } | ||
| 144 | 158 | ||
| 159 | // We need to read enough so that we can gurantee that we're within a block | ||
| 160 | // that we have read the index to, plus one index. | ||
| 145 | for( int32_t j = 0; j < iHeaderStreamBlocks; j++ ) | 161 | for( int32_t j = 0; j < iHeaderStreamBlocks; j++ ) |
| 146 | { | 162 | { |
| 147 | int32_t iBlockIndex; | 163 | int32_t iBlockIndex; |
| 148 | MyriadRead( &iBlockIndex, 4 ); | 164 | MyriadRead( &iBlockIndex, 4 ); |
| 149 | pHeaderStream->aBlocks.append( iBlockIndex ); | 165 | pHeaderStream->aBlocks.append( iBlockIndex ); |
| 166 | if( rBacking.tell()+4 <= (j+1)*iBlockSize ) | ||
| 167 | break; | ||
| 150 | } | 168 | } |
| 151 | 169 | ||
| 152 | // Bootstrap now using the header stream to read the rest of the data. | 170 | // Bootstrap now using the header stream to read the rest of the data. |
| 171 | sHeader.setPos( rBacking.tell() ); | ||
| 172 | while( pHeaderStream->aBlocks.getSize() < iHeaderStreamBlocks ) | ||
| 173 | { | ||
| 174 | int32_t iBlockIndex; | ||
| 175 | sHeader.read( &iBlockIndex, 4 ); | ||
| 176 | pHeaderStream->aBlocks.append( iBlockIndex ); | ||
| 177 | } | ||
| 178 | |||
| 179 | // Ok, now we can read the rest of the header in. | ||
| 180 | for( int j = 1; j < iStreamCount; j++ ) | ||
| 181 | { | ||
| 182 | int32_t iStreamBytes; | ||
| 183 | sHeader.read( &iStream, 4 ); | ||
| 184 | sHeader.read( &iStreamBytes, 4 ); | ||
| 185 | Stream *pStream = new Stream( *this, iStream, iStreamBytes ); | ||
| 186 | int32_t iBlocks = blkDiv(iStreamBytes, iBlockSize ); | ||
| 187 | for( int k = 0; k < iBlocks; k++ ) | ||
| 188 | { | ||
| 189 | int32_t iBlockIndex; | ||
| 190 | sHeader.read( &iBlockIndex, 4 ); | ||
| 191 | pStream->aBlocks.append( iBlockIndex ); | ||
| 192 | } | ||
| 193 | hStream.insert( iStream, pStream ); | ||
| 194 | if( iLastUsedIndex < iStream ) | ||
| 195 | iLastUsedIndex = iStream; | ||
| 196 | } | ||
| 153 | 197 | ||
| 154 | return true; | 198 | return true; |
| 155 | } | 199 | } |
| @@ -165,7 +209,8 @@ void Bu::Myriad::createMyriad( int32_t iBlockSize, int32_t iPreallocateBlocks ) | |||
| 165 | { | 209 | { |
| 166 | throw Bu::MyriadException( Bu::MyriadException::invalidFormat, | 210 | throw Bu::MyriadException( Bu::MyriadException::invalidFormat, |
| 167 | "Backing stream contains data, but not a myriad structure."); | 211 | "Backing stream contains data, but not a myriad structure."); |
| 168 | } | 212 | } |
| 213 | |||
| 169 | /* | 214 | /* |
| 170 | struct { | 215 | struct { |
| 171 | char sMagicCode[4]; | 216 | char sMagicCode[4]; |
| @@ -253,11 +298,128 @@ void Bu::Myriad::createMyriad( int32_t iBlockSize, int32_t iPreallocateBlocks ) | |||
| 253 | { | 298 | { |
| 254 | lFreeBlocks.append( j ); | 299 | lFreeBlocks.append( j ); |
| 255 | } | 300 | } |
| 301 | iLastUsedIndex = 0; | ||
| 302 | } | ||
| 303 | |||
| 304 | void Bu::Myriad::writeHeader() | ||
| 305 | { | ||
| 306 | if( !rBacking.isWritable() ) | ||
| 307 | return; | ||
| 308 | Bu::println("Writing stream breakdown:"); | ||
| 309 | Bu::MemBuf mbHeader; | ||
| 310 | { | ||
| 311 | Bu::MutexLocker l( mAccess ); | ||
| 312 | |||
| 313 | int32_t iHdrStreamSize = __calcHeaderSize(); | ||
| 314 | // Maybe just do stream surgery here. | ||
| 315 | { | ||
| 316 | Stream *psHeader = hStream.get( 0 ); | ||
| 317 | Bu::MutexLocker l2( psHeader->mAccess ); | ||
| 318 | int iNewBlocks = Bu::blkDiv( iHdrStreamSize, iBlockSize ); | ||
| 319 | if( iHdrStreamSize < psHeader->iSize ) | ||
| 320 | { | ||
| 321 | while( psHeader->aBlocks.getSize() > iNewBlocks ) | ||
| 322 | { | ||
| 323 | __releaseBlock( psHeader->aBlocks.last(), false ); | ||
| 324 | psHeader->aBlocks.eraseLast(); | ||
| 325 | } | ||
| 326 | } | ||
| 327 | else if( iHdrStreamSize > psHeader->iSize ) | ||
| 328 | { | ||
| 329 | while( psHeader->aBlocks.getSize() < iNewBlocks ) | ||
| 330 | { | ||
| 331 | psHeader->aBlocks.append( __allocateBlock() ); | ||
| 332 | } | ||
| 333 | } | ||
| 334 | psHeader->iSize = iHdrStreamSize; | ||
| 335 | } | ||
| 336 | |||
| 337 | Bu::println("Computed header size: %1 bytes. Ver=%2, Bpi=%3, BlockSize=%4").arg( iHdrStreamSize ).arg( 1 ).arg( 32 ).arg( iBlockSize ); | ||
| 338 | |||
| 339 | uint8_t uVer = 1; | ||
| 340 | uint8_t uBpi = 32; | ||
| 341 | int32_t iStreamCount = hStream.getSize(); | ||
| 342 | |||
| 343 | mbHeader.write( Myriad_MAGIC_CODE, 4 ); | ||
| 344 | mbHeader.write( &uVer, 1 ); | ||
| 345 | mbHeader.write( &uBpi, 1 ); | ||
| 346 | mbHeader.write( &iBlockSize, 4 ); | ||
| 347 | mbHeader.write( &iStreamCount, 4 ); | ||
| 348 | StreamHash::KeyList lStreamId = hStream.getKeys(); | ||
| 349 | lStreamId.sort(); | ||
| 350 | if( lStreamId.first() != 0 ) | ||
| 351 | { | ||
| 352 | throw Bu::MyriadException( Bu::MyriadException::invalidFormat, | ||
| 353 | "There doesn't appear to be a zero (header) stream."); | ||
| 354 | } | ||
| 355 | for( StreamHash::KeyList::iterator i = lStreamId.begin(); i; i++ ) | ||
| 356 | { | ||
| 357 | uint32_t uStreamId = *i; | ||
| 358 | Stream *pStream = hStream.get( uStreamId ); | ||
| 359 | uint32_t uStreamSize = pStream->getSize(); | ||
| 360 | mbHeader.write( &uStreamId, 4 ); | ||
| 361 | mbHeader.write( &uStreamSize, 4 ); | ||
| 362 | Bu::Array<int32_t> aBlocks = pStream->getBlockList(); | ||
| 363 | |||
| 364 | Bu::println(" Stream %1 is %2 bytes %3 blocks (%4 blocks computed)") | ||
| 365 | .arg( *i ).arg( uStreamSize ) | ||
| 366 | .arg( aBlocks.getSize() ) | ||
| 367 | .arg( Bu::blkDiv( (int)uStreamSize, (int)iBlockSize ) ); | ||
| 368 | |||
| 369 | for( Bu::Array<int32_t>::iterator i = aBlocks.begin(); i; i++ ) | ||
| 370 | { | ||
| 371 | int32_t iIdx = *i; | ||
| 372 | mbHeader.write( &iIdx, 4 ); | ||
| 373 | } | ||
| 374 | } | ||
| 375 | |||
| 376 | |||
| 377 | } | ||
| 378 | |||
| 379 | Bu::MyriadStream sHeader( *this, hStream.get( 0 ), Bu::Myriad::Write ); | ||
| 380 | sHeader.write( mbHeader.getString() ); | ||
| 381 | } | ||
| 382 | |||
| 383 | int32_t Bu::Myriad::__calcHeaderSize() | ||
| 384 | { | ||
| 385 | int32_t iHdrSize = 4+1+1+4+4; | ||
| 386 | |||
| 387 | StreamHash::KeyList lStreamId = hStream.getKeys(); | ||
| 388 | lStreamId.sort(); | ||
| 389 | if( lStreamId.first() != 0 ) | ||
| 390 | { | ||
| 391 | throw Bu::MyriadException( Bu::MyriadException::invalidFormat, | ||
| 392 | "There doesn't appear to be a zero (header) stream."); | ||
| 393 | } | ||
| 394 | for( StreamHash::KeyList::iterator i = lStreamId.begin(); i; i++ ) | ||
| 395 | { | ||
| 396 | iHdrSize += 4+4; | ||
| 397 | int32_t iStreamSize = hStream.get( *i )->getSize(); | ||
| 398 | if( (*i) != 0 ) | ||
| 399 | { | ||
| 400 | iHdrSize += Bu::blkDiv( iStreamSize, iBlockSize )*4; | ||
| 401 | } | ||
| 402 | } | ||
| 403 | |||
| 404 | int32_t iNewSize = iHdrSize; | ||
| 405 | int32_t iOldSize; | ||
| 406 | |||
| 407 | do { | ||
| 408 | iOldSize = iNewSize; | ||
| 409 | iNewSize = iHdrSize + Bu::blkDiv(iNewSize, iBlockSize); | ||
| 410 | } while( iOldSize != iNewSize ); | ||
| 411 | |||
| 412 | return iNewSize; | ||
| 256 | } | 413 | } |
| 257 | 414 | ||
| 258 | int32_t Bu::Myriad::allocateBlock() | 415 | int32_t Bu::Myriad::allocateBlock() |
| 259 | { | 416 | { |
| 260 | Bu::MutexLocker l( mAccess ); | 417 | Bu::MutexLocker l( mAccess ); |
| 418 | return __allocateBlock(); | ||
| 419 | } | ||
| 420 | |||
| 421 | int32_t Bu::Myriad::__allocateBlock() | ||
| 422 | { | ||
| 261 | if( lFreeBlocks.isEmpty() ) | 423 | if( lFreeBlocks.isEmpty() ) |
| 262 | { | 424 | { |
| 263 | // Increase the size of the backing stream | 425 | // Increase the size of the backing stream |
| @@ -275,6 +437,11 @@ int32_t Bu::Myriad::allocateBlock() | |||
| 275 | void Bu::Myriad::releaseBlock( int32_t iBlockId, bool bBlank ) | 437 | void Bu::Myriad::releaseBlock( int32_t iBlockId, bool bBlank ) |
| 276 | { | 438 | { |
| 277 | Bu::MutexLocker l( mAccess ); | 439 | Bu::MutexLocker l( mAccess ); |
| 440 | __releaseBlock( iBlockId, bBlank ); | ||
| 441 | } | ||
| 442 | |||
| 443 | void Bu::Myriad::__releaseBlock( int32_t iBlockId, bool bBlank ) | ||
| 444 | { | ||
| 278 | lFreeBlocks.append( iBlockId ); | 445 | lFreeBlocks.append( iBlockId ); |
| 279 | if( bBlank ) | 446 | if( bBlank ) |
| 280 | { | 447 | { |
| @@ -314,10 +481,10 @@ int32_t Bu::Myriad::blockRead( int32_t iBlock, int32_t iStart, | |||
| 314 | void *pTarget, int32_t iSize ) | 481 | void *pTarget, int32_t iSize ) |
| 315 | { | 482 | { |
| 316 | int32_t iUpperSize = iBlockSize - (iStart%iBlockSize); | 483 | int32_t iUpperSize = iBlockSize - (iStart%iBlockSize); |
| 317 | Bu::println("Max read within block: %1 vs %2 (start=%3, blocksize=%4)") | 484 | /* Bu::println("Max read within block: %1 vs %2 (start=%3, blocksize=%4)") |
| 318 | .arg( iUpperSize ).arg( iSize ) | 485 | .arg( iUpperSize ).arg( iSize ) |
| 319 | .arg( iStart ).arg( iBlockSize ); | 486 | .arg( iStart ).arg( iBlockSize ); |
| 320 | 487 | */ | |
| 321 | int32_t iAmnt = std::min( iSize, iUpperSize ); | 488 | int32_t iAmnt = std::min( iSize, iUpperSize ); |
| 322 | Bu::MutexLocker l( mBacking ); | 489 | Bu::MutexLocker l( mBacking ); |
| 323 | rBacking.setPos( iBlockSize*iBlock + iStart ); | 490 | rBacking.setPos( iBlockSize*iBlock + iStart ); |
| @@ -329,10 +496,10 @@ int32_t Bu::Myriad::blockWrite( int32_t iBlock, int32_t iStart, | |||
| 329 | const void *pTarget, int32_t iSize ) | 496 | const void *pTarget, int32_t iSize ) |
| 330 | { | 497 | { |
| 331 | int32_t iUpperSize = iBlockSize - (iStart%iBlockSize); | 498 | int32_t iUpperSize = iBlockSize - (iStart%iBlockSize); |
| 332 | Bu::println("Max write within block: %1 vs %2 (start=%3, blocksize=%4)") | 499 | /* Bu::println("Max write within block: %1 vs %2 (start=%3, blocksize=%4)") |
| 333 | .arg( iUpperSize ).arg( iSize ) | 500 | .arg( iUpperSize ).arg( iSize ) |
| 334 | .arg( iStart ).arg( iBlockSize ); | 501 | .arg( iStart ).arg( iBlockSize ); |
| 335 | 502 | */ | |
| 336 | int32_t iAmnt = std::min( iSize, iUpperSize ); | 503 | int32_t iAmnt = std::min( iSize, iUpperSize ); |
| 337 | Bu::MutexLocker l( mBacking ); | 504 | Bu::MutexLocker l( mBacking ); |
| 338 | rBacking.setPos( iBlock*iBlockSize + iStart ); | 505 | rBacking.setPos( iBlock*iBlockSize + iStart ); |
| @@ -385,10 +552,10 @@ void Bu::Myriad::Stream::setSize( int32_t iNewSize ) | |||
| 385 | { | 552 | { |
| 386 | // Two possible modes, shrink or grow. | 553 | // Two possible modes, shrink or grow. |
| 387 | Bu::MutexLocker l( mAccess ); | 554 | Bu::MutexLocker l( mAccess ); |
| 555 | int iNewBlocks = Bu::blkDiv( iNewSize, rParent.iBlockSize ); | ||
| 388 | if( iNewSize < iSize ) | 556 | if( iNewSize < iSize ) |
| 389 | { | 557 | { |
| 390 | // Shrink it | 558 | // Shrink it |
| 391 | int iNewBlocks = Bu::blkDiv( iNewSize, rParent.iBlockSize ); | ||
| 392 | while( aBlocks.getSize() > iNewBlocks ) | 559 | while( aBlocks.getSize() > iNewBlocks ) |
| 393 | { | 560 | { |
| 394 | rParent.releaseBlock( aBlocks.last(), false ); | 561 | rParent.releaseBlock( aBlocks.last(), false ); |
| @@ -399,7 +566,6 @@ void Bu::Myriad::Stream::setSize( int32_t iNewSize ) | |||
| 399 | else if( iNewSize > iSize ) | 566 | else if( iNewSize > iSize ) |
| 400 | { | 567 | { |
| 401 | // Grow it | 568 | // Grow it |
| 402 | int iNewBlocks = Bu::blkDiv( iNewSize, rParent.iBlockSize ); | ||
| 403 | while( aBlocks.getSize() < iNewBlocks ) | 569 | while( aBlocks.getSize() < iNewBlocks ) |
| 404 | { | 570 | { |
| 405 | aBlocks.append( rParent.allocateBlock() ); | 571 | aBlocks.append( rParent.allocateBlock() ); |
| @@ -438,6 +604,10 @@ int32_t Bu::Myriad::Stream::write( int32_t iStart, const void *pTarget, | |||
| 438 | while( iSize > 0 ) | 604 | while( iSize > 0 ) |
| 439 | { | 605 | { |
| 440 | int32_t iBlockIdx = iStart/rParent.iBlockSize; | 606 | int32_t iBlockIdx = iStart/rParent.iBlockSize; |
| 607 | while( iBlockIdx >= aBlocks.getSize() ) | ||
| 608 | { | ||
| 609 | aBlocks.append( rParent.allocateBlock() ); | ||
| 610 | } | ||
| 441 | int32_t iBlock = aBlocks[iBlockIdx]; | 611 | int32_t iBlock = aBlocks[iBlockIdx]; |
| 442 | int32_t iChunkWrite = rParent.blockWrite( | 612 | int32_t iChunkWrite = rParent.blockWrite( |
| 443 | iBlock, iStart%rParent.iBlockSize, pTarget, iSize | 613 | iBlock, iStart%rParent.iBlockSize, pTarget, iSize |
| @@ -449,6 +619,8 @@ int32_t Bu::Myriad::Stream::write( int32_t iStart, const void *pTarget, | |||
| 449 | reinterpret_cast<ptrdiff_t &>(pTarget) += iChunkWrite; | 619 | reinterpret_cast<ptrdiff_t &>(pTarget) += iChunkWrite; |
| 450 | iSize -= iChunkWrite; | 620 | iSize -= iChunkWrite; |
| 451 | } | 621 | } |
| 622 | if( this->iSize < iStart ) | ||
| 623 | this->iSize = iStart; | ||
| 452 | 624 | ||
| 453 | return iWrite; | 625 | return iWrite; |
| 454 | } | 626 | } |
| @@ -460,6 +632,12 @@ Bu::String Bu::Myriad::Stream::getLocation() const | |||
| 460 | .arg( rParent.getLocation() ).arg( iStream ); | 632 | .arg( rParent.getLocation() ).arg( iStream ); |
| 461 | } | 633 | } |
| 462 | 634 | ||
| 635 | Bu::Array<int32_t> Bu::Myriad::Stream::getBlockList() const | ||
| 636 | { | ||
| 637 | Bu::MutexLocker l( mAccess ); | ||
| 638 | return aBlocks.clone(); | ||
| 639 | } | ||
| 640 | |||
| 463 | void Bu::Myriad::Stream::open() | 641 | void Bu::Myriad::Stream::open() |
| 464 | { | 642 | { |
| 465 | Bu::MutexLocker l( mAccess ); | 643 | Bu::MutexLocker l( mAccess ); |
diff --git a/src/stable/myriad.h b/src/stable/myriad.h index 6d99ee4..7cf6041 100644 --- a/src/stable/myriad.h +++ b/src/stable/myriad.h | |||
| @@ -40,8 +40,8 @@ namespace Bu | |||
| 40 | Write = 0x02, ///< Open file for writing | 40 | Write = 0x02, ///< Open file for writing |
| 41 | Create = 0x04, ///< Create file if it doesn't exist | 41 | Create = 0x04, ///< Create file if it doesn't exist |
| 42 | Truncate = 0x08, ///< Truncate file if it does exist | 42 | Truncate = 0x08, ///< Truncate file if it does exist |
| 43 | Append = 0x10, ///< Always append on every write | 43 | Append = 0x10, ///< Start writing at end of file |
| 44 | NonBlock = 0x20, ///< Open file in non-blocking mode | 44 | //NonBlock = 0x20, ///< Open file in non-blocking mode |
| 45 | Exclusive = 0x44, ///< Create file, if it exists then fail | 45 | Exclusive = 0x44, ///< Create file, if it exists then fail |
| 46 | 46 | ||
| 47 | // Helpful mixes | 47 | // Helpful mixes |
| @@ -80,8 +80,12 @@ namespace Bu | |||
| 80 | private: | 80 | private: |
| 81 | bool loadMyriad(); | 81 | bool loadMyriad(); |
| 82 | void createMyriad( int32_t iBlockSize, int32_t iPreallocateBlocks ); | 82 | void createMyriad( int32_t iBlockSize, int32_t iPreallocateBlocks ); |
| 83 | void writeHeader(); | ||
| 84 | int32_t __calcHeaderSize(); | ||
| 83 | int32_t allocateBlock(); | 85 | int32_t allocateBlock(); |
| 86 | int32_t __allocateBlock(); | ||
| 84 | void releaseBlock( int32_t iBlockId, bool bBlank=true ); | 87 | void releaseBlock( int32_t iBlockId, bool bBlank=true ); |
| 88 | void __releaseBlock( int32_t iBlockId, bool bBlank=true ); | ||
| 85 | void blankBlock( int32_t iBlockId ); | 89 | void blankBlock( int32_t iBlockId ); |
| 86 | 90 | ||
| 87 | void openStream( StreamId id ); | 91 | void openStream( StreamId id ); |
| @@ -124,6 +128,7 @@ namespace Bu | |||
| 124 | int32_t read( int32_t iStart, void *pTarget, int32_t iSize ); | 128 | int32_t read( int32_t iStart, void *pTarget, int32_t iSize ); |
| 125 | int32_t write( int32_t iStart, const void *pTarget, int32_t iSize ); | 129 | int32_t write( int32_t iStart, const void *pTarget, int32_t iSize ); |
| 126 | Bu::String getLocation() const; | 130 | Bu::String getLocation() const; |
| 131 | Bu::Array<int32_t> getBlockList() const; | ||
| 127 | 132 | ||
| 128 | /** | 133 | /** |
| 129 | * Doesn't actually open, just increments the open counter. | 134 | * Doesn't actually open, just increments the open counter. |
| @@ -150,9 +155,7 @@ namespace Bu | |||
| 150 | }; | 155 | }; |
| 151 | 156 | ||
| 152 | private: | 157 | private: |
| 153 | |||
| 154 | typedef Bu::Hash<StreamId, Stream *> StreamHash; | 158 | typedef Bu::Hash<StreamId, Stream *> StreamHash; |
| 155 | |||
| 156 | typedef Bu::List<int32_t> IndexList; | 159 | typedef Bu::List<int32_t> IndexList; |
| 157 | mutable Bu::Mutex mAccess; | 160 | mutable Bu::Mutex mAccess; |
| 158 | mutable Bu::Mutex mBacking; | 161 | mutable Bu::Mutex mBacking; |
| @@ -160,8 +163,10 @@ namespace Bu | |||
| 160 | int32_t iBlockSize; | 163 | int32_t iBlockSize; |
| 161 | int32_t iBlockCount; | 164 | int32_t iBlockCount; |
| 162 | bool bIsNewStream; | 165 | bool bIsNewStream; |
| 166 | bool bStructureChanged; | ||
| 163 | StreamHash hStream; | 167 | StreamHash hStream; |
| 164 | IndexList lFreeBlocks; | 168 | IndexList lFreeBlocks; |
| 169 | StreamId iLastUsedIndex; | ||
| 165 | }; | 170 | }; |
| 166 | }; | 171 | }; |
| 167 | 172 | ||
diff --git a/src/stable/myriadstream.h b/src/stable/myriadstream.h index c01cf34..b86dbd7 100644 --- a/src/stable/myriadstream.h +++ b/src/stable/myriadstream.h | |||
| @@ -13,12 +13,14 @@ namespace Bu | |||
| 13 | private: | 13 | private: |
| 14 | MyriadStream( Bu::Myriad &rMyriad, Bu::Myriad::Stream *pStream, | 14 | MyriadStream( Bu::Myriad &rMyriad, Bu::Myriad::Stream *pStream, |
| 15 | Bu::Myriad::Mode eMode ); | 15 | Bu::Myriad::Mode eMode ); |
| 16 | public: | ||
| 16 | virtual ~MyriadStream(); | 17 | virtual ~MyriadStream(); |
| 17 | 18 | ||
| 18 | public: | 19 | public: |
| 19 | virtual void close(); | 20 | virtual void close(); |
| 20 | virtual size read( void *pBuf, size iBytes ); | 21 | virtual size read( void *pBuf, size iBytes ); |
| 21 | virtual size write( const void *pBuf, size iBytes ); | 22 | virtual size write( const void *pBuf, size iBytes ); |
| 23 | using Stream::write; | ||
| 22 | virtual size tell(); | 24 | virtual size tell(); |
| 23 | virtual void seek( size offset ); | 25 | virtual void seek( size offset ); |
| 24 | virtual void setPos( size pos ); | 26 | virtual void setPos( size pos ); |
diff --git a/src/tests/bigmyriad.cpp b/src/tests/bigmyriad.cpp index 21c5ff2..9d24741 100644 --- a/src/tests/bigmyriad.cpp +++ b/src/tests/bigmyriad.cpp | |||
| @@ -5,17 +5,17 @@ | |||
| 5 | int main() | 5 | int main() |
| 6 | { | 6 | { |
| 7 | Bu::File f("big.myr", Bu::File::Read|Bu::File::Write|Bu::File::Create ); | 7 | Bu::File f("big.myr", Bu::File::Read|Bu::File::Write|Bu::File::Create ); |
| 8 | Bu::Myriad m( f, 8, 12 ); | 8 | Bu::Myriad m( f, 256, 12 ); |
| 9 | 9 | ||
| 10 | char *buf = new char[1024*1024*10]; | 10 | char *buf = new char[1024*1024*10]; |
| 11 | memset( buf, 0, 1024*1024*10 ); | ||
| 12 | 11 | ||
| 13 | for( int j = 0; j < 250; j++ ) | 12 | for( int j = 0; j < 25; j++ ) |
| 14 | { | 13 | { |
| 15 | // m.openStream( m.createStream() ).write( buf, 1024*1024*10 ); | 14 | memset( buf, j, 1024*1024*10 ); |
| 16 | // m.sync(); | 15 | m.create( Bu::Myriad::Write ).write( buf, 1024*1024*10 ); |
| 17 | // printf("\r%03d%%", (j+1)*100/250 ); | 16 | // m.sync(); |
| 18 | // fflush( stdout ); | 17 | printf("\r%03d%%", (j+1)*100/25 ); |
| 18 | fflush( stdout ); | ||
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | printf("\n\n"); | 21 | printf("\n\n"); |
