summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2010-04-12 17:50:37 +0000
committerMike Buland <eichlan@xagasoft.com>2010-04-12 17:50:37 +0000
commitfc2943ed980306244749d8d13796eaff690917b6 (patch)
tree78e2c058295b76299f9e1c9560d150e0f124f640 /src
parent41c9581b48f055f6559335ffc0316f27ed1b3657 (diff)
downloadlibbu++-fc2943ed980306244749d8d13796eaff690917b6.tar.gz
libbu++-fc2943ed980306244749d8d13796eaff690917b6.tar.bz2
libbu++-fc2943ed980306244749d8d13796eaff690917b6.tar.xz
libbu++-fc2943ed980306244749d8d13796eaff690917b6.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/myriad.cpp121
-rw-r--r--src/myriadstream.cpp191
-rw-r--r--src/server.cpp12
-rw-r--r--src/tools/myriad.cpp49
4 files changed, 269 insertions, 104 deletions
diff --git a/src/myriad.cpp b/src/myriad.cpp
index a1a5c38..58270c5 100644
--- a/src/myriad.cpp
+++ b/src/myriad.cpp
@@ -78,10 +78,6 @@ void Bu::Myriad::initialize()
78 sio << "Myriad: iSize=" << iSize << ", iBlockSize=" << iBlockSize 78 sio << "Myriad: iSize=" << iSize << ", iBlockSize=" << iBlockSize
79 << ", iBlocks=" << iBlocks << ", iStreams=" << iStreams << sio.nl; 79 << ", iBlocks=" << iBlocks << ", iStreams=" << iStreams << sio.nl;
80 80
81 // Don't do this, just read the damn header.
82 sio << "Myriad: Don't do this, just read the damn header (line 82)"
83 << sio.nl;
84
85 int iHeaderSize = 14 + 8 + 4; 81 int iHeaderSize = 14 + 8 + 4;
86 int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize ); 82 int iHeaderBlocks = 0; //blkDiv( iHeaderSize+4, iBlockSize );
87 83
@@ -93,30 +89,38 @@ void Bu::Myriad::initialize()
93 89
94 sio << "Myriad: iHeaderSize=" << iHeaderSize 90 sio << "Myriad: iHeaderSize=" << iHeaderSize
95 << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; 91 << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl;
92
93 Stream *pFakeHdr = new Stream;
94 pFakeHdr->iId = 0;
95 pFakeHdr->iSize = iHeaderSize;
96 for( int j = 0; j < iHeaderBlocks; j++ )
97 {
98 pFakeHdr->aBlocks.append( j );
99 }
96 100
97 bsBlockUsed.setSize( iBlocks, true ); 101 bsBlockUsed.setSize( iBlocks, true );
98 102
99 bool bCanSkip = false; // Can skip around, post initial header stream i/o 103 bool bCanSkip = false; // Can skip around, post initial header stream i/o
104 MyriadStream *pIn = new MyriadStream( *this, pFakeHdr );
105 pIn->setPos( sStore.tell() );
100 for( int j = 0; j < iStreams; j++ ) 106 for( int j = 0; j < iStreams; j++ )
101 { 107 {
102 int iHdrBlock = 0;
103 int iCurBlock = 0;
104 aStreams.append( new Stream() ); 108 aStreams.append( new Stream() );
105 Stream &s = *aStreams[j]; 109 Stream &s = *aStreams[j];
106 sStore.read( &s.iId, 4 ); 110 pIn->read( &s.iId, 4 );
107 sStore.read( &s.iSize, 4 ); 111 pIn->read( &s.iSize, 4 );
108 int iSBlocks = blkDiv(s.iSize, iBlockSize); 112 int iSBlocks = blkDiv(s.iSize, iBlockSize);
109 sio << "Myriad: - Stream::iId=" << s.iId 113 sio << "Myriad: - Stream::iId=" << s.iId
110 << ", Stream::iSize=" << s.iSize 114 << ", Stream::iSize=" << s.iSize
111 << ", Stream::aBlocks=" << iSBlocks 115 << ", Stream::aBlocks=" << iSBlocks
112 << ", sStore.tell()=" << sStore.tell() << sio.nl; 116 << ", pIn->tell()=" << pIn->tell() << sio.nl;
113 for( int k = 0; k < iSBlocks; k++ ) 117 for( int k = 0; k < iSBlocks; k++ )
114 { 118 {
115 int iBId; 119 int iBId;
116 sStore.read( &iBId, 4 ); 120 pIn->read( &iBId, 4 );
117 sio << "Myriad: - iBId=" << iBId 121 sio << "Myriad: - iBId=" << iBId
118 << ", iStartPos=" << iBId*iBlockSize 122 << ", iStartPos=" << iBId*iBlockSize
119 << ", sStore.tell()=" << sStore.tell() << sio.nl; 123 << ", pIn->tell()=" << pIn->tell() << sio.nl;
120 s.aBlocks.append( iBId ); 124 s.aBlocks.append( iBId );
121 bsBlockUsed.setBit( iBId ); 125 bsBlockUsed.setBit( iBId );
122 if( (j == 0 && k == iHeaderBlocks-1) ) 126 if( (j == 0 && k == iHeaderBlocks-1) )
@@ -124,25 +128,18 @@ void Bu::Myriad::initialize()
124 sio << "Myriad: - End of prepartition, unlocking skipping." 128 sio << "Myriad: - End of prepartition, unlocking skipping."
125 << sio.nl; 129 << sio.nl;
126 bCanSkip = true; 130 bCanSkip = true;
127 iCurBlock = blkDiv( (int)sStore.tell(), iBlockSize ); 131 MyriadStream *pTmp = new MyriadStream( *this, aStreams[0] );
128 } 132 sio << "Myriad - Position = " << pIn->tell() << sio.nl;
129 if( bCanSkip && sStore.tell() >= iCurBlock*iBlockSize+iBlockSize ) 133 pTmp->setPos( pIn->tell() );
130 { 134 delete pIn;
131 iHdrBlock++; 135 delete pFakeHdr;
132 iCurBlock = aStreams[0]->aBlocks[iHdrBlock]; 136 pIn = pTmp;
133 sio << "Myriad: Ran out of data in block, finding next header "
134 "block: " << iHdrBlock << " = " << iCurBlock << " ("
135 << iCurBlock*iBlockSize << "b)" << sio.nl;
136 sStore.setPos( iCurBlock*iBlockSize );
137 } 137 }
138 } 138 }
139 } 139 }
140 delete pIn;
140 141
141 sio << "Myriad: Blocks used: " << bsBlockUsed.toString() << sio.nl; 142 sio << "Myriad: Blocks used: " << bsBlockUsed.toString() << sio.nl;
142
143 //printf("%d blocks, %db each, %db block offset\n",
144 // iBlocks, iBlockSize, iBlockStart );
145
146} 143}
147 144
148void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate ) 145void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate )
@@ -211,6 +208,14 @@ void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate )
211 pStr->iSize = sStore.tell(); 208 pStr->iSize = sStore.tell();
212 sio << "Myriad: Actual end of header stream = " << pStr->iSize << sio.nl; 209 sio << "Myriad: Actual end of header stream = " << pStr->iSize << sio.nl;
213 210
211 pStr->iSize = iHeaderSize;
212 for( int j = 0; j < iHeaderBlocks; j++ )
213 {
214 pStr->aBlocks.append( j );
215 }
216
217 aStreams.append( pStr );
218
214 //hStreams.insert( 0, BlockArray( 0 ) ); 219 //hStreams.insert( 0, BlockArray( 0 ) );
215} 220}
216 221
@@ -219,9 +224,64 @@ void Bu::Myriad::updateHeader()
219 if( !sStore.canWrite() ) 224 if( !sStore.canWrite() )
220 return; 225 return;
221 226
222 227 char cBuf;
228 int iBuf;
223 229
224 // TODO: Use the stream class to access this really smoothly, I hope :) 230 // Compute the new size of the header.
231 int iHeaderSize = 14 + 8*aStreams.getSize();
232 sio << "Myriad: updateHeader: aStreams.getSize() = " << aStreams.getSize()
233 << sio.nl;
234 for( StreamArray::iterator i = aStreams.begin(); i; i++ )
235 {
236 iHeaderSize += 4*(*i)->aBlocks.getSize();
237 sio << "Myriad: updateHeader: (*i)->aBlocks.getSize() = "
238 << (*i)->aBlocks.getSize() << sio.nl;
239 }
240 int iNewBlocks = blkDiv( iHeaderSize, iBlockSize );
241 while( iNewBlocks > aStreams[0]->aBlocks.getSize() )
242 {
243 int iBlock = findEmptyBlock();
244 sio << "Myriad: updateHeader: Appending block " << iBlock
245 << " to header." << sio.nl;
246 aStreams[0]->aBlocks.append( iBlock );
247 bsBlockUsed.setBit( iBlock );
248 iHeaderSize += 4;
249 iNewBlocks = blkDiv( iHeaderSize, iBlockSize );
250 }
251 aStreams[0]->iSize = iHeaderSize;
252 sio << "Myriad: updateHeader: iHeaderSize=" << iHeaderSize
253 << ", iNewBlocks=" << iNewBlocks << ", curBlocks="
254 << aStreams[0]->aBlocks.getSize() << sio.nl;
255
256 MyriadStream sHdr( *this, aStreams[0] );
257 sHdr.write( Myriad_MAGIC_CODE, 4 );
258
259 // Version (1)
260 cBuf = 1;
261 sHdr.write( &cBuf, 1 );
262
263 // Bits per int
264 cBuf = 32;
265 sHdr.write( &cBuf, 1 );
266
267 // The size of each block
268 sHdr.write( &iBlockSize, 4 );
269
270 iBuf = aStreams.getSize();
271 // The number of streams
272 sHdr.write( &iBuf, 4 );
273
274 for( StreamArray::iterator i = aStreams.begin(); i; i++ )
275 {
276 sHdr.write( &(*i)->iId, 4 );
277 sHdr.write( &(*i)->iSize, 4 );
278 int iUsedBlocks = blkDiv( (*i)->iSize, iBlockSize );
279// for( BlockArray::iterator j = (*i)->aBlocks.begin(); j; j++ )
280 for( int j = 0; j < iUsedBlocks; j++ )
281 {
282 sHdr.write( &(*i)->aBlocks[j], 4 );
283 }
284 }
225} 285}
226 286
227int Bu::Myriad::createStream( int iPreAllocate ) 287int Bu::Myriad::createStream( int iPreAllocate )
@@ -231,6 +291,7 @@ int Bu::Myriad::createStream( int iPreAllocate )
231 sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" 291 sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate="
232 << iPreAllocate << sio.nl; 292 << iPreAllocate << sio.nl;
233 pStr->iSize = 0; 293 pStr->iSize = 0;
294 aStreams.append( pStr );
234 295
235 for( int j = 0; j < iPreAllocate; j++ ) 296 for( int j = 0; j < iPreAllocate; j++ )
236 { 297 {
@@ -240,7 +301,7 @@ int Bu::Myriad::createStream( int iPreAllocate )
240 bsBlockUsed.setBit( iFreeBlock ); 301 bsBlockUsed.setBit( iFreeBlock );
241 } 302 }
242 303
243 return 0; 304 return pStr->iId;
244} 305}
245 306
246int Bu::Myriad::findEmptyBlock() 307int Bu::Myriad::findEmptyBlock()
@@ -260,7 +321,7 @@ int Bu::Myriad::findEmptyBlock()
260 sStore.write( pBlock, iBlockSize ); 321 sStore.write( pBlock, iBlockSize );
261 delete pBlock; 322 delete pBlock;
262 323
263 return iBlockSize++; 324 return iBlocks++;
264} 325}
265 326
266void Bu::Myriad::deleteStream( int /*iID*/ ) 327void Bu::Myriad::deleteStream( int /*iID*/ )
@@ -314,6 +375,8 @@ Bu::Myriad::Block *Bu::Myriad::getBlock( int iBlock )
314 375
315void Bu::Myriad::releaseBlock( Bu::Myriad::Block *pBlock ) 376void Bu::Myriad::releaseBlock( Bu::Myriad::Block *pBlock )
316{ 377{
378 if( pBlock == NULL )
379 return;
317 sio << "Myriad: Releasing block " << pBlock->iBlockIndex << sio.nl; 380 sio << "Myriad: Releasing block " << pBlock->iBlockIndex << sio.nl;
318 if( pBlock->bChanged ) 381 if( pBlock->bChanged )
319 { 382 {
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;
13 13
14#include <string.h> 14#include <string.h>
15 15
16// #define MYRIAD_STREAM_DEBUG 1
17
16Bu::MyriadStream::MyriadStream( Bu::Myriad &rMyriad, 18Bu::MyriadStream::MyriadStream( Bu::Myriad &rMyriad,
17 Bu::Myriad::Stream *pStream ) : 19 Bu::Myriad::Stream *pStream ) :
18 rMyriad( rMyriad ), 20 rMyriad( rMyriad ),
@@ -20,8 +22,10 @@ Bu::MyriadStream::MyriadStream( Bu::Myriad &rMyriad,
20 pCurBlock( NULL ), 22 pCurBlock( NULL ),
21 iPos( 0 ) 23 iPos( 0 )
22{ 24{
25#ifdef MYRIAD_STREAM_DEBUG
23 sio << "MyriadStream: Created, iId=" << pStream->iId << ", iSize=" 26 sio << "MyriadStream: Created, iId=" << pStream->iId << ", iSize="
24 << pStream->iSize << sio.nl; 27 << pStream->iSize << sio.nl;
28#endif
25 //pCurBlock = rMyriad.newBlock(); 29 //pCurBlock = rMyriad.newBlock();
26 //rMyriad.getBlock( uStream, pCurBlock ); 30 //rMyriad.getBlock( uStream, pCurBlock );
27 //uSize = pCurBlock->uBytesUsed; 31 //uSize = pCurBlock->uBytesUsed;
@@ -41,19 +45,25 @@ void Bu::MyriadStream::close()
41 45
42size_t Bu::MyriadStream::read( void *pBuf, size_t nBytes ) 46size_t Bu::MyriadStream::read( void *pBuf, size_t nBytes )
43{ 47{
44 sio << "MyriadStream: Read: Started, asked to read " << nBytes << "b." 48#ifdef MYRIAD_STREAM_DEBUG
49 sio << "MyriadStream: read: Started, asked to read " << nBytes << "b."
45 << sio.nl; 50 << sio.nl;
46 if( nBytes <= 0 ) 51#endif
47 return 0;
48 if( nBytes > pStream->iSize-iPos ) 52 if( nBytes > pStream->iSize-iPos )
49 nBytes = pStream->iSize-iPos; 53 nBytes = pStream->iSize-iPos;
54 if( nBytes <= 0 )
55 return 0;
50 int iLeft = nBytes; 56 int iLeft = nBytes;
51 sio << "MyriadStream: Read: Started, going to read " << nBytes << "b." 57#ifdef MYRIAD_STREAM_DEBUG
58 sio << "MyriadStream: read: Started, going to read " << nBytes << "b."
52 << sio.nl; 59 << sio.nl;
60#endif
53 if( pCurBlock == NULL ) 61 if( pCurBlock == NULL )
54 { 62 {
55 sio << "MyriadStream: Read: No block loaded, loading initial block." 63#ifdef MYRIAD_STREAM_DEBUG
64 sio << "MyriadStream: read: No block loaded, loading initial block."
56 << sio.nl; 65 << sio.nl;
66#endif
57 pCurBlock = rMyriad.getBlock( 67 pCurBlock = rMyriad.getBlock(
58 pStream->aBlocks[iPos/rMyriad.iBlockSize] 68 pStream->aBlocks[iPos/rMyriad.iBlockSize]
59 ); 69 );
@@ -63,25 +73,30 @@ size_t Bu::MyriadStream::read( void *pBuf, size_t nBytes )
63 int iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize]; 73 int iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize];
64 if( pCurBlock->iBlockIndex != iCurBlock ) 74 if( pCurBlock->iBlockIndex != iCurBlock )
65 { 75 {
66 sio << "MyriadStream: Read: Loading new block " << iCurBlock << "." 76#ifdef MYRIAD_STREAM_DEBUG
77 sio << "MyriadStream: read: Loading new block " << iCurBlock << "."
67 << sio.nl; 78 << sio.nl;
79#endif
68 rMyriad.releaseBlock( pCurBlock ); 80 rMyriad.releaseBlock( pCurBlock );
69 pCurBlock = rMyriad.getBlock( iCurBlock ); 81 pCurBlock = rMyriad.getBlock( iCurBlock );
70 } 82 }
71 83
72 int iAmnt = Bu::min( 84 int iAmnt = Bu::min(
73 rMyriad.iBlockSize - iPos%rMyriad.iBlockSize, 85 Bu::min(
74 iLeft 86 rMyriad.iBlockSize - iPos%rMyriad.iBlockSize,
87 iLeft
88 ),
89 pStream->iSize-iPos
75 ); 90 );
76// if( iLeft > iAmnt ) 91#ifdef MYRIAD_STREAM_DEBUG
77// iAmnt = iLeft; 92 sio << "MyriadStream: read: Copying out bytes: "
78 sio << "MyriadStream: Read: Copying out bytes: " 93 << iPos << "(" << (iPos%rMyriad.iBlockSize) << ")+"
79 << (iPos%rMyriad.iBlockSize) << " - "
80 << iAmnt 94 << iAmnt
81 << ", " << iLeft << "b left." << sio.nl; 95 << ", " << iLeft << "b left." << sio.nl;
96#endif
82 memcpy( 97 memcpy(
83 pBuf, 98 pBuf,
84 pCurBlock->pData+iPos%rMyriad.iBlockSize, 99 pCurBlock->pData+(iPos%rMyriad.iBlockSize),
85 iAmnt 100 iAmnt
86 ); 101 );
87 iPos += iAmnt; 102 iPos += iAmnt;
@@ -93,65 +108,109 @@ size_t Bu::MyriadStream::read( void *pBuf, size_t nBytes )
93 108
94size_t Bu::MyriadStream::write( const void *pBuf, size_t nBytes ) 109size_t Bu::MyriadStream::write( const void *pBuf, size_t nBytes )
95{ 110{
96 if( nBytes == 0 ) 111 if( nBytes <= 0 )
97 return 0; 112 return 0;
98/* if( pCurBlock->uBytesUsed >= uBlockSize ) 113
99 { 114#ifdef MYRIAD_STREAM_DEBUG
100 // We're at the end of our current block, allocate another before we do 115 sio << "MyriadStream: write: Started, asked to write " << nBytes << "b."
101 // anything. 116 << sio.nl;
102 uCurBlock = rMyriad.getNextBlock( uCurBlock, pCurBlock ); 117#endif
103 } */ 118 if( nBytes <= 0 )
119 return 0;
120 int iLeft = nBytes;
104 /* 121 /*
105 if( (iPos%uBlockSize)+nBytes < uBlockSize ) 122 if( pCurBlock == NULL )
106 { 123 {
107 //printf("wa: %u:%u:%u:%u -> ", iPos, iPos%uBlockSize, uSize, pCurBlock->uBytesUsed ); 124#ifdef MYRIAD_STREAM_DEBUG
108 memcpy( pCurBlock->pData+(iPos%uBlockSize), pBuf, nBytes ); 125 sio << "MyriadStream: write: No block loaded, loading initial block."
109 //printf("write buffill: %ub, %u-%u/%u -> %d-%d/%d (a:%u:%u)\n", 126 << sio.nl;
110 // nBytes, 0, nBytes-1, nBytes, 127#endif
111 // iPos, iPos+nBytes-1, uSize, uCurBlock, 128 pCurBlock = rMyriad.getBlock(
112 // pCurBlock->uBytesUsed ); 129 pStream->aBlocks[iPos/rMyriad.iBlockSize]
113 if( (iPos%uBlockSize)+nBytes > pCurBlock->uBytesUsed ) 130 );
114 pCurBlock->uBytesUsed = (iPos%uBlockSize)+nBytes; 131 }*/
115 rMyriad.setBlock( uCurBlock, pCurBlock ); 132
116 iPos += nBytes; 133 while( iLeft > 0 )
117 if( iPos > uSize )
118 uSize = iPos;
119 //printf("block %u = %ub (%ub total) %d:%u\n",
120 // uCurBlock, pCurBlock->uBytesUsed, uSize, nBytes, iPos );
121 return nBytes;
122 }
123 else
124 { 134 {
125 size_t nTotal = 0; 135 int iCurBlock;
126 for(;;) 136 if( iPos/rMyriad.iBlockSize < pStream->aBlocks.getSize() )
127 { 137 {
128 uint32_t uNow = uBlockSize-(iPos%uBlockSize); 138 iCurBlock = pStream->aBlocks[iPos/rMyriad.iBlockSize];
129 //printf("uNow: %u (%u-(%u%%%u)) %d req\n", uNow, uBlockSize, iPos, uBlockSize, nBytes );
130 if( nBytes < uNow )
131 uNow = nBytes;
132 memcpy( pCurBlock->pData+(iPos%uBlockSize),
133 &((char *)pBuf)[nTotal], uNow );
134 //printf("write buffill: %ub, %u-%u/%u -> %d-%d/%d (b:%u:%u)\n",
135 // uNow, nTotal, nTotal+uNow-1, nBytes,
136 // iPos, iPos+uNow-1, uSize, uCurBlock, pCurBlock->uBytesUsed );
137 if( (iPos%uBlockSize)+uNow > pCurBlock->uBytesUsed )
138 pCurBlock->uBytesUsed = (iPos%uBlockSize)+uNow;
139 rMyriad.setBlock( uCurBlock, pCurBlock );
140 iPos += uNow;
141 if( iPos > uSize )
142 uSize = iPos;
143 nTotal += uNow;
144 nBytes -= uNow;
145 //printf("wb: block %u = %ub (%ub total)\n",
146 // uCurBlock, pCurBlock->uBytesUsed, uSize );
147 //if( pCurBlock->uBytesUsed == uBlockSize )
148 if( iPos%uBlockSize == 0 )
149 uCurBlock = rMyriad.getNextBlock( uCurBlock, pCurBlock );
150 if( nBytes == 0 )
151 return nTotal;
152 } 139 }
153 }*/ 140 else
154 return 0; 141 {
142 iCurBlock = rMyriad.findEmptyBlock();
143 pStream->aBlocks.append( iCurBlock );
144 rMyriad.bsBlockUsed.setBit( iCurBlock );
145#ifdef MYRIAD_STREAM_DEBUG
146 sio << "MyriadStream: write: New block allocated and appended: "
147 << iCurBlock << "." << sio.nl;
148
149#endif
150 }
151 if( !pCurBlock || pCurBlock->iBlockIndex != iCurBlock )
152 {
153#ifdef MYRIAD_STREAM_DEBUG
154 sio << "MyriadStream: write: Loading new block " << iCurBlock << "."
155 << sio.nl;
156#endif
157 rMyriad.releaseBlock( pCurBlock );
158 pCurBlock = rMyriad.getBlock( iCurBlock );
159 }
160 pCurBlock->bChanged = true;
161
162 // There are two main writing modes when it comes down to it.
163 // Overwrite mode and append mode. Append is what pretty much always
164 // happens when creating a new stream.
165 if( iPos < pStream->iSize )
166 {
167 int iAmnt = Bu::min(
168 Bu::min(
169 rMyriad.iBlockSize - iPos%rMyriad.iBlockSize,
170 iLeft
171 ),
172 pStream->iSize-iPos
173 );
174#ifdef MYRIAD_STREAM_DEBUG
175 sio << "MyriadStream: write (ovr): Copying in bytes: "
176 << (iPos%rMyriad.iBlockSize) << "+"
177 << iAmnt
178 << ", " << iLeft << "b left." << sio.nl;
179#endif
180 memcpy(
181 pCurBlock->pData+(iPos%rMyriad.iBlockSize),
182 pBuf,
183 iAmnt
184 );
185 iPos += iAmnt;
186 pBuf = &((char *)pBuf)[iAmnt];
187 iLeft -= iAmnt;
188 }
189 else
190 {
191 int iAmnt = Bu::min(
192 rMyriad.iBlockSize - iPos%rMyriad.iBlockSize,
193 iLeft
194 );
195#ifdef MYRIAD_STREAM_DEBUG
196 sio << "MyriadStream: write (app): Copying in bytes: "
197 << (iPos%rMyriad.iBlockSize) << "+"
198 << iAmnt
199 << ", " << iLeft << "b left." << sio.nl;
200#endif
201 memcpy(
202 pCurBlock->pData+(iPos%rMyriad.iBlockSize),
203 pBuf,
204 iAmnt
205 );
206 iPos += iAmnt;
207 pStream->iSize += iAmnt;
208 pBuf = &((char *)pBuf)[iAmnt];
209 iLeft -= iAmnt;
210 }
211 }
212
213 return nBytes;
155} 214}
156 215
157long Bu::MyriadStream::tell() 216long Bu::MyriadStream::tell()
diff --git a/src/server.cpp b/src/server.cpp
index 80ed509..36d9d6c 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -93,8 +93,16 @@ void Bu::Server::scan()
93 } 93 }
94 if( FD_ISSET( j, &fdWrite ) ) 94 if( FD_ISSET( j, &fdWrite ) )
95 { 95 {
96 Client *pClient = hClients.get( j ); 96 try
97 pClient->processOutput(); 97 {
98 Client *pClient = hClients.get( j );
99 pClient->processOutput();
100 }
101 catch( Bu::HashException &e )
102 {
103 // Do nothing, I guess, the client is already dead...
104 // TODO: Someday, we may want to handle this more graceully.
105 }
98 } 106 }
99 } 107 }
100 108
diff --git a/src/tools/myriad.cpp b/src/tools/myriad.cpp
index 95b4503..605aac9 100644
--- a/src/tools/myriad.cpp
+++ b/src/tools/myriad.cpp
@@ -20,7 +20,8 @@ enum Mode
20 modeCreate, 20 modeCreate,
21 modeInfo, 21 modeInfo,
22 modeStreamNew, 22 modeStreamNew,
23 modeStreamRead, 23 modeStreamDump,
24 modeStreamPut,
24 25
25 modeNone 26 modeNone
26}; 27};
@@ -41,8 +42,10 @@ public:
41 "Display some info about a Myriad file." ); 42 "Display some info about a Myriad file." );
42 addOption( eMode, 'n', "new", 43 addOption( eMode, 'n', "new",
43 "Create a new sub-stream in a Myriad file."); 44 "Create a new sub-stream in a Myriad file.");
44 addOption( eMode, 'r', "read", 45 addOption( eMode, 'd', "dump",
45 "Read a stream from a Myriad file."); 46 "Read a stream from a Myriad file.");
47 addOption( eMode, "put",
48 "Put a file into a Myriad stream.");
46 addHelpOption(); 49 addHelpOption();
47 50
48 addHelpBanner("\nGeneral options:"); 51 addHelpBanner("\nGeneral options:");
@@ -56,7 +59,8 @@ public:
56 setOverride( "create", "create" ); 59 setOverride( "create", "create" );
57 setOverride( "info", "info" ); 60 setOverride( "info", "info" );
58 setOverride( "new", "new" ); 61 setOverride( "new", "new" );
59 setOverride( "read", "read" ); 62 setOverride( "dump", "dump" );
63 setOverride( "put", "put" );
60 64
61 parse( argc, argv ); 65 parse( argc, argv );
62 } 66 }
@@ -78,8 +82,10 @@ Bu::Formatter &operator>>( Bu::Formatter &f, Mode &m )
78 m = modeInfo; 82 m = modeInfo;
79 else if( sTok == "new" ) 83 else if( sTok == "new" )
80 m = modeStreamNew; 84 m = modeStreamNew;
81 else if( sTok == "read" ) 85 else if( sTok == "dump" )
82 m = modeStreamRead; 86 m = modeStreamDump;
87 else if( sTok == "put" )
88 m = modeStreamPut;
83 else 89 else
84 m = modeNone; 90 m = modeNone;
85 return f; 91 return f;
@@ -99,7 +105,7 @@ int main( int argc, char *argv[] )
99 } 105 }
100 else 106 else
101 { 107 {
102 File fOut( opts.sFile, File::WriteNew ); 108 File fOut( opts.sFile, File::WriteNew|File::Read );
103 Myriad m( fOut ); 109 Myriad m( fOut );
104 m.initialize( opts.iBlockSize, opts.iPreallocate ); 110 m.initialize( opts.iBlockSize, opts.iPreallocate );
105 } 111 }
@@ -134,7 +140,7 @@ int main( int argc, char *argv[] )
134 } 140 }
135 break; 141 break;
136 142
137 case modeStreamRead: 143 case modeStreamDump:
138 if( !opts.sFile.isSet() ) 144 if( !opts.sFile.isSet() )
139 { 145 {
140 sio << "Please specify a file manipulate." << sio.nl; 146 sio << "Please specify a file manipulate." << sio.nl;
@@ -173,6 +179,35 @@ int main( int argc, char *argv[] )
173 } 179 }
174 sio << sio.nl; 180 sio << sio.nl;
175 } 181 }
182 sio << "Position: " << s.tell() << ", isEos()=" << s.isEos()
183 << sio.nl;
184 }
185 break;
186
187 case modeStreamPut:
188 if( !opts.sFile.isSet() )
189 {
190 sio << "Please specify a file manipulate." << sio.nl;
191 return 0;
192 }
193 else if( !opts.sSrc.isSet() )
194 {
195 sio << "Please specify a source file to read." << sio.nl;
196 }
197 else
198 {
199 File fOut( opts.sFile, File::Write|File::Read );
200 Myriad m( fOut );
201 m.initialize();
202 MyriadStream sOut = m.openStream(
203 m.createStream( opts.iPreallocate )
204 );
205 File fIn( opts.sSrc, File::Read );
206 char buf[1024];
207 while( !fIn.isEos() )
208 {
209 sOut.write( buf, fIn.read( buf, 1024 ) );
210 }
176 } 211 }
177 break; 212 break;
178 213