diff options
author | Mike Buland <eichlan@xagasoft.com> | 2010-04-12 17:50:37 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2010-04-12 17:50:37 +0000 |
commit | fc2943ed980306244749d8d13796eaff690917b6 (patch) | |
tree | 78e2c058295b76299f9e1c9560d150e0f124f640 /src/myriadstream.cpp | |
parent | 41c9581b48f055f6559335ffc0316f27ed1b3657 (diff) | |
download | libbu++-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 '')
-rw-r--r-- | src/myriadstream.cpp | 191 |
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 | |||
16 | Bu::MyriadStream::MyriadStream( Bu::Myriad &rMyriad, | 18 | Bu::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 | ||
42 | size_t Bu::MyriadStream::read( void *pBuf, size_t nBytes ) | 46 | size_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 | ||
94 | size_t Bu::MyriadStream::write( const void *pBuf, size_t nBytes ) | 109 | size_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 | ||
157 | long Bu::MyriadStream::tell() | 216 | long Bu::MyriadStream::tell() |