From fc2943ed980306244749d8d13796eaff690917b6 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Mon, 12 Apr 2010 17:50:37 +0000 Subject: Wow Myriad!! Myriad seems to work. I have to run it through a few more paces, and there are some known corner cases that I may just disallow, such as too-small block sizes. Beyond a little more testing, it's ready for production. I may switch some of my cache tests to using it now. --- src/myriadstream.cpp | 191 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 125 insertions(+), 66 deletions(-) (limited to 'src/myriadstream.cpp') diff --git a/src/myriadstream.cpp b/src/myriadstream.cpp index 0e6fc89..d714c23 100644 --- a/src/myriadstream.cpp +++ b/src/myriadstream.cpp @@ -13,6 +13,8 @@ using Bu::Fmt; #include +// #define MYRIAD_STREAM_DEBUG 1 + Bu::MyriadStream::MyriadStream( Bu::Myriad &rMyriad, Bu::Myriad::Stream *pStream ) : rMyriad( rMyriad ), @@ -20,8 +22,10 @@ Bu::MyriadStream::MyriadStream( Bu::Myriad &rMyriad, pCurBlock( NULL ), iPos( 0 ) { +#ifdef MYRIAD_STREAM_DEBUG sio << "MyriadStream: Created, iId=" << pStream->iId << ", iSize=" << pStream->iSize << sio.nl; +#endif //pCurBlock = rMyriad.newBlock(); //rMyriad.getBlock( uStream, pCurBlock ); //uSize = pCurBlock->uBytesUsed; @@ -41,19 +45,25 @@ void Bu::MyriadStream::close() size_t Bu::MyriadStream::read( void *pBuf, size_t nBytes ) { - sio << "MyriadStream: Read: Started, asked to read " << nBytes << "b." +#ifdef MYRIAD_STREAM_DEBUG + sio << "MyriadStream: read: Started, asked to read " << nBytes << "b." << sio.nl; - if( nBytes <= 0 ) - return 0; +#endif if( nBytes > pStream->iSize-iPos ) nBytes = pStream->iSize-iPos; + if( nBytes <= 0 ) + return 0; int iLeft = nBytes; - sio << "MyriadStream: Read: Started, going to read " << nBytes << "b." +#ifdef MYRIAD_STREAM_DEBUG + sio << "MyriadStream: read: Started, going to read " << nBytes << "b." << sio.nl; +#endif if( pCurBlock == NULL ) { - sio << "MyriadStream: Read: No block loaded, loading initial block." +#ifdef MYRIAD_STREAM_DEBUG + sio << "MyriadStream: read: No block loaded, loading initial block." << sio.nl; +#endif pCurBlock = rMyriad.getBlock( pStream->aBlocks[iPos/rMyriad.iBlockSize] ); @@ -63,25 +73,30 @@ size_t Bu::MyriadStream::read( void *pBuf, size_t nBytes ) int iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; if( pCurBlock->iBlockIndex != iCurBlock ) { - sio << "MyriadStream: Read: Loading new block " << iCurBlock << "." +#ifdef MYRIAD_STREAM_DEBUG + sio << "MyriadStream: read: Loading new block " << iCurBlock << "." << sio.nl; +#endif rMyriad.releaseBlock( pCurBlock ); pCurBlock = rMyriad.getBlock( iCurBlock ); } int iAmnt = Bu::min( - rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, - iLeft + Bu::min( + rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, + iLeft + ), + pStream->iSize-iPos ); -// if( iLeft > iAmnt ) -// iAmnt = iLeft; - sio << "MyriadStream: Read: Copying out bytes: " - << (iPos%rMyriad.iBlockSize) << " - " +#ifdef MYRIAD_STREAM_DEBUG + sio << "MyriadStream: read: Copying out bytes: " + << iPos << "(" << (iPos%rMyriad.iBlockSize) << ")+" << iAmnt << ", " << iLeft << "b left." << sio.nl; +#endif memcpy( pBuf, - pCurBlock->pData+iPos%rMyriad.iBlockSize, + pCurBlock->pData+(iPos%rMyriad.iBlockSize), iAmnt ); iPos += iAmnt; @@ -93,65 +108,109 @@ size_t Bu::MyriadStream::read( void *pBuf, size_t nBytes ) size_t Bu::MyriadStream::write( const void *pBuf, size_t nBytes ) { - if( nBytes == 0 ) + if( nBytes <= 0 ) return 0; -/* if( pCurBlock->uBytesUsed >= uBlockSize ) - { - // We're at the end of our current block, allocate another before we do - // anything. - uCurBlock = rMyriad.getNextBlock( uCurBlock, pCurBlock ); - } */ + +#ifdef MYRIAD_STREAM_DEBUG + sio << "MyriadStream: write: Started, asked to write " << nBytes << "b." + << sio.nl; +#endif + if( nBytes <= 0 ) + return 0; + int iLeft = nBytes; /* - if( (iPos%uBlockSize)+nBytes < uBlockSize ) + if( pCurBlock == NULL ) { - //printf("wa: %u:%u:%u:%u -> ", iPos, iPos%uBlockSize, uSize, pCurBlock->uBytesUsed ); - memcpy( pCurBlock->pData+(iPos%uBlockSize), pBuf, nBytes ); - //printf("write buffill: %ub, %u-%u/%u -> %d-%d/%d (a:%u:%u)\n", - // nBytes, 0, nBytes-1, nBytes, - // iPos, iPos+nBytes-1, uSize, uCurBlock, - // pCurBlock->uBytesUsed ); - if( (iPos%uBlockSize)+nBytes > pCurBlock->uBytesUsed ) - pCurBlock->uBytesUsed = (iPos%uBlockSize)+nBytes; - rMyriad.setBlock( uCurBlock, pCurBlock ); - iPos += nBytes; - if( iPos > uSize ) - uSize = iPos; - //printf("block %u = %ub (%ub total) %d:%u\n", - // uCurBlock, pCurBlock->uBytesUsed, uSize, nBytes, iPos ); - return nBytes; - } - else +#ifdef MYRIAD_STREAM_DEBUG + sio << "MyriadStream: write: No block loaded, loading initial block." + << sio.nl; +#endif + pCurBlock = rMyriad.getBlock( + pStream->aBlocks[iPos/rMyriad.iBlockSize] + ); + }*/ + + while( iLeft > 0 ) { - size_t nTotal = 0; - for(;;) + int iCurBlock; + if( iPos/rMyriad.iBlockSize < pStream->aBlocks.getSize() ) { - uint32_t uNow = uBlockSize-(iPos%uBlockSize); - //printf("uNow: %u (%u-(%u%%%u)) %d req\n", uNow, uBlockSize, iPos, uBlockSize, nBytes ); - if( nBytes < uNow ) - uNow = nBytes; - memcpy( pCurBlock->pData+(iPos%uBlockSize), - &((char *)pBuf)[nTotal], uNow ); - //printf("write buffill: %ub, %u-%u/%u -> %d-%d/%d (b:%u:%u)\n", - // uNow, nTotal, nTotal+uNow-1, nBytes, - // iPos, iPos+uNow-1, uSize, uCurBlock, pCurBlock->uBytesUsed ); - if( (iPos%uBlockSize)+uNow > pCurBlock->uBytesUsed ) - pCurBlock->uBytesUsed = (iPos%uBlockSize)+uNow; - rMyriad.setBlock( uCurBlock, pCurBlock ); - iPos += uNow; - if( iPos > uSize ) - uSize = iPos; - nTotal += uNow; - nBytes -= uNow; - //printf("wb: block %u = %ub (%ub total)\n", - // uCurBlock, pCurBlock->uBytesUsed, uSize ); - //if( pCurBlock->uBytesUsed == uBlockSize ) - if( iPos%uBlockSize == 0 ) - uCurBlock = rMyriad.getNextBlock( uCurBlock, pCurBlock ); - if( nBytes == 0 ) - return nTotal; + iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; } - }*/ - return 0; + else + { + iCurBlock = rMyriad.findEmptyBlock(); + pStream->aBlocks.append( iCurBlock ); + rMyriad.bsBlockUsed.setBit( iCurBlock ); +#ifdef MYRIAD_STREAM_DEBUG + sio << "MyriadStream: write: New block allocated and appended: " + << iCurBlock << "." << sio.nl; + +#endif + } + if( !pCurBlock || pCurBlock->iBlockIndex != iCurBlock ) + { +#ifdef MYRIAD_STREAM_DEBUG + sio << "MyriadStream: write: Loading new block " << iCurBlock << "." + << sio.nl; +#endif + rMyriad.releaseBlock( pCurBlock ); + pCurBlock = rMyriad.getBlock( iCurBlock ); + } + pCurBlock->bChanged = true; + + // There are two main writing modes when it comes down to it. + // Overwrite mode and append mode. Append is what pretty much always + // happens when creating a new stream. + if( iPos < pStream->iSize ) + { + int iAmnt = Bu::min( + Bu::min( + rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, + iLeft + ), + pStream->iSize-iPos + ); +#ifdef MYRIAD_STREAM_DEBUG + sio << "MyriadStream: write (ovr): Copying in bytes: " + << (iPos%rMyriad.iBlockSize) << "+" + << iAmnt + << ", " << iLeft << "b left." << sio.nl; +#endif + memcpy( + pCurBlock->pData+(iPos%rMyriad.iBlockSize), + pBuf, + iAmnt + ); + iPos += iAmnt; + pBuf = &((char *)pBuf)[iAmnt]; + iLeft -= iAmnt; + } + else + { + int iAmnt = Bu::min( + rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, + iLeft + ); +#ifdef MYRIAD_STREAM_DEBUG + sio << "MyriadStream: write (app): Copying in bytes: " + << (iPos%rMyriad.iBlockSize) << "+" + << iAmnt + << ", " << iLeft << "b left." << sio.nl; +#endif + memcpy( + pCurBlock->pData+(iPos%rMyriad.iBlockSize), + pBuf, + iAmnt + ); + iPos += iAmnt; + pStream->iSize += iAmnt; + pBuf = &((char *)pBuf)[iAmnt]; + iLeft -= iAmnt; + } + } + + return nBytes; } long Bu::MyriadStream::tell() -- cgit v1.2.3