summaryrefslogtreecommitdiff
path: root/src/myriadstream.cpp
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/myriadstream.cpp
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/myriadstream.cpp')
-rw-r--r--src/myriadstream.cpp191
1 files changed, 125 insertions, 66 deletions
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()