diff options
author | Mike Buland <eichlan@xagasoft.com> | 2010-02-10 18:20:40 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2010-02-10 18:20:40 +0000 |
commit | 79b7b631750b69cbe06daedb0453306595dea6ad (patch) | |
tree | 284dc89fa2ee6ec88e9b0625a412185d5d1348b0 /src/myriad.cpp | |
parent | 1f29dc180b5a86ddf2115f97ad410e0e9b1beb4b (diff) | |
download | libbu++-79b7b631750b69cbe06daedb0453306595dea6ad.tar.gz libbu++-79b7b631750b69cbe06daedb0453306595dea6ad.tar.bz2 libbu++-79b7b631750b69cbe06daedb0453306595dea6ad.tar.xz libbu++-79b7b631750b69cbe06daedb0453306595dea6ad.zip |
Changed the name of nids to Myriad, I like it, but I'm not getting rid of nids
until I can safely migrate to Myriad.
Diffstat (limited to 'src/myriad.cpp')
-rw-r--r-- | src/myriad.cpp | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/src/myriad.cpp b/src/myriad.cpp new file mode 100644 index 0000000..64c8d20 --- /dev/null +++ b/src/myriad.cpp | |||
@@ -0,0 +1,284 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2008 Xagasoft, All rights reserved. | ||
3 | * | ||
4 | * This file is part of the libbu++ library and is released under the | ||
5 | * terms of the license contained in the file LICENSE. | ||
6 | */ | ||
7 | |||
8 | #include "bu/myriad.h" | ||
9 | #include "bu/stream.h" | ||
10 | #include "bu/myriadstream.h" | ||
11 | #include <stdio.h> | ||
12 | |||
13 | #include "bu/sio.h" | ||
14 | using Bu::sio; | ||
15 | using Bu::Fmt; | ||
16 | |||
17 | #define Myriad_MAGIC_CODE ((unsigned char *)"\xFF\xC3\x99\xBD") | ||
18 | |||
19 | namespace Bu | ||
20 | { | ||
21 | subExceptionDef( MyriadException ) | ||
22 | template<typename t> t blkDiv( t total, t block ) { | ||
23 | return (total/block)+((total%block==0)?(0):(1)); | ||
24 | } | ||
25 | } | ||
26 | |||
27 | Bu::Myriad::Myriad( Bu::Stream &sStore ) : | ||
28 | sStore( sStore ), | ||
29 | iBlockSize( 0 ), | ||
30 | iBlocks( 0 ), | ||
31 | iUsed( 0 ) | ||
32 | { | ||
33 | } | ||
34 | |||
35 | Bu::Myriad::~Myriad() | ||
36 | { | ||
37 | updateHeader(); | ||
38 | |||
39 | for( StreamArray::iterator i = aStreams.begin(); i; i++ ) | ||
40 | { | ||
41 | delete *i; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | void Bu::Myriad::sync() | ||
46 | { | ||
47 | updateHeader(); | ||
48 | |||
49 | // Later, also flush all caches. | ||
50 | } | ||
51 | |||
52 | void Bu::Myriad::initialize() | ||
53 | { | ||
54 | sStore.setPosEnd( 0 ); | ||
55 | int iSize = sStore.tell(); | ||
56 | sStore.setPos( 0 ); | ||
57 | |||
58 | unsigned char buf[4]; | ||
59 | if( sStore.read( buf, 4 ) < 4 ) | ||
60 | throw MyriadException("Input stream appears to be empty."); | ||
61 | if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) ) | ||
62 | { | ||
63 | throw MyriadException( | ||
64 | "Stream does not appear to be a valid Myriad format."); | ||
65 | } | ||
66 | sStore.read( buf, 2 ); | ||
67 | if( buf[0] != 1 ) | ||
68 | throw MyriadException( | ||
69 | "We can only handle version 1 for now."); | ||
70 | if( buf[1] != 32 ) | ||
71 | throw MyriadException( | ||
72 | "We can only handle 32-bit words at the moment."); | ||
73 | sStore.read( &iBlockSize, 4 ); | ||
74 | int iStreams; | ||
75 | sStore.read( &iStreams, 4 ); | ||
76 | |||
77 | iBlocks = iSize/iBlockSize; | ||
78 | sio << "Myriad: iSize=" << iSize << ", iBlockSize=" << iBlockSize | ||
79 | << ", iBlocks=" << iBlocks << ", iStreams=" << iStreams << sio.nl; | ||
80 | |||
81 | int iHeaderSize = 14 + 8 + 4; | ||
82 | int iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); | ||
83 | |||
84 | while( iHeaderSize > iHeaderBlocks*iBlockSize ) | ||
85 | { | ||
86 | iHeaderSize = 14 + 8 + 4*iHeaderBlocks; | ||
87 | iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); | ||
88 | } | ||
89 | |||
90 | sio << "Myriad: iHeaderSize=" << iHeaderSize | ||
91 | << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; | ||
92 | |||
93 | bsBlockUsed.setSize( iBlocks, true ); | ||
94 | |||
95 | bool bCanSkip = false; // Can skip around, post initial header stream i/o | ||
96 | for( int j = 0; j < iStreams; j++ ) | ||
97 | { | ||
98 | int iHdrBlock = 0; | ||
99 | int iCurBlock = 0; | ||
100 | aStreams.append( new Stream() ); | ||
101 | Stream &s = *aStreams[j]; | ||
102 | sStore.read( &s.iId, 4 ); | ||
103 | sStore.read( &s.iSize, 4 ); | ||
104 | int iSBlocks = blkDiv(s.iSize, iBlockSize); | ||
105 | sio << "Myriad: - Stream::iId=" << s.iId << ", Stream::iSize=" << s.iSize | ||
106 | << ", Stream::aBlocks=" << iSBlocks | ||
107 | << ", sStore.tell()=" << sStore.tell() << sio.nl; | ||
108 | for( int k = 0; k < iSBlocks; k++ ) | ||
109 | { | ||
110 | int iBId; | ||
111 | sStore.read( &iBId, 4 ); | ||
112 | sio << "Myriad: - iBId=" << iBId | ||
113 | << ", iStartPos=" << iBId*iBlockSize | ||
114 | << ", sStore.tell()=" << sStore.tell() << sio.nl; | ||
115 | s.aBlocks.append( iBId ); | ||
116 | bsBlockUsed.setBit( iBId ); | ||
117 | if( (j == 0 && k == iHeaderBlocks-1) ) | ||
118 | { | ||
119 | sio << "Myriad: - End of prepartition, unlocking skipping." | ||
120 | << sio.nl; | ||
121 | bCanSkip = true; | ||
122 | iCurBlock = blkDiv( (int)sStore.tell(), iBlockSize ); | ||
123 | } | ||
124 | if( bCanSkip && sStore.tell() >= iCurBlock*iBlockSize+iBlockSize ) | ||
125 | { | ||
126 | iHdrBlock++; | ||
127 | iCurBlock = aStreams[0]->aBlocks[iHdrBlock]; | ||
128 | sio << "Myriad: Ran out of data in block, finding next header " | ||
129 | "block: " << iHdrBlock << " = " << iCurBlock << " (" | ||
130 | << iCurBlock*iBlockSize << "b)" << sio.nl; | ||
131 | sStore.setPos( iCurBlock*iBlockSize ); | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | |||
136 | sio << bsBlockUsed.toString() << sio.nl; | ||
137 | |||
138 | //printf("%d blocks, %db each, %db block offset\n", | ||
139 | // iBlocks, iBlockSize, iBlockStart ); | ||
140 | |||
141 | } | ||
142 | |||
143 | void Bu::Myriad::initialize( int iBlockSize, int iPreAllocate ) | ||
144 | { | ||
145 | int iHeaderSize = 14 + 8 + 4; | ||
146 | int iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); | ||
147 | char cBuf = 1; | ||
148 | int iBuf = 0; | ||
149 | |||
150 | Stream *pStr = new Stream; | ||
151 | pStr->iId = 0; | ||
152 | |||
153 | while( iHeaderSize > iHeaderBlocks*iBlockSize ) | ||
154 | { | ||
155 | iHeaderSize = 14 + 8 + 4*iHeaderBlocks; | ||
156 | iHeaderBlocks = blkDiv( iHeaderSize+4, iBlockSize ); | ||
157 | } | ||
158 | |||
159 | iPreAllocate += iHeaderBlocks; | ||
160 | |||
161 | sio << "Myriad: iHeaderSize=" << iHeaderSize << ", iBlockSize=" | ||
162 | << iBlockSize << ", iHeaderBlocks=" << iHeaderBlocks << sio.nl; | ||
163 | |||
164 | bsBlockUsed.setSize( iPreAllocate, true ); | ||
165 | |||
166 | char *pBlock = new char[iBlockSize]; | ||
167 | memset( pBlock, 0, iBlockSize ); | ||
168 | for( int j = 0; j < iPreAllocate; j++ ) | ||
169 | { | ||
170 | sStore.write( pBlock, iBlockSize ); | ||
171 | pStr->aBlocks.append( j ); | ||
172 | } | ||
173 | delete[] (char *)pBlock; | ||
174 | |||
175 | sStore.setPos( 0 ); | ||
176 | |||
177 | // Magic number | ||
178 | sStore.write( Myriad_MAGIC_CODE, 4 ); | ||
179 | |||
180 | // Version (0) | ||
181 | sStore.write( &cBuf, 1 ); | ||
182 | |||
183 | // Bits per int | ||
184 | cBuf = 32; | ||
185 | sStore.write( &cBuf, 1 ); | ||
186 | |||
187 | // The size of each block | ||
188 | sStore.write( &iBlockSize, 4 ); | ||
189 | |||
190 | iBuf = 1; | ||
191 | // The number of streams | ||
192 | sStore.write( &iBuf, 4 ); | ||
193 | |||
194 | // Stream header | ||
195 | iBuf = 0; | ||
196 | sStore.write( &iBuf, 4 ); | ||
197 | sStore.write( &iHeaderSize, 4 ); | ||
198 | for( iBuf = 0; iBuf < iHeaderBlocks; iBuf++ ) | ||
199 | { | ||
200 | sStore.write( &iBuf, 4 ); | ||
201 | } | ||
202 | |||
203 | this->iBlockSize = iBlockSize; | ||
204 | this->iBlocks = iPreAllocate; | ||
205 | |||
206 | pStr->iSize = sStore.tell(); | ||
207 | |||
208 | //hStreams.insert( 0, BlockArray( 0 ) ); | ||
209 | } | ||
210 | |||
211 | void Bu::Myriad::updateHeader() | ||
212 | { | ||
213 | if( !sStore.canWrite() ) | ||
214 | return; | ||
215 | |||
216 | |||
217 | |||
218 | // TODO: Use the stream class to access this really smoothly, I hope :) | ||
219 | } | ||
220 | |||
221 | int Bu::Myriad::createStream( int iPreAllocate ) | ||
222 | { | ||
223 | Stream *pStr = new Stream(); | ||
224 | pStr->iId = aStreams.last()->iId+1; | ||
225 | sio << "Myriad: New stream id=" << pStr->iId << ", iPreAllocate=" | ||
226 | << iPreAllocate << sio.nl; | ||
227 | pStr->iSize = 0; | ||
228 | |||
229 | for( int j = 0; j < iPreAllocate; j++ ) | ||
230 | { | ||
231 | int iFreeBlock = findEmptyBlock(); | ||
232 | sio << "Myriad: Adding block " << j << sio.nl; | ||
233 | pStr->aBlocks.append( j ); | ||
234 | bsBlockUsed.setBit( j ); | ||
235 | } | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | int Bu::Myriad::findEmptyBlock() | ||
241 | { | ||
242 | for( int j = 0; j < bsBlockUsed.getSize(); j++ ) | ||
243 | { | ||
244 | if( bsBlockUsed.getBit( j ) == false ) | ||
245 | return j; | ||
246 | } | ||
247 | sio << "Myriad: findEmptyBlock(): No empty blocks, adding new one." << sio.nl; | ||
248 | |||
249 | bsBlockUsed.setSize( bsBlockUsed.getSize()+1, false ); | ||
250 | sStore.setPos( iBlockSize*iBlocks ); | ||
251 | |||
252 | char *pBlock = new char[iBlockSize]; | ||
253 | memset( pBlock, 0, iBlockSize ); | ||
254 | sStore.write( pBlock, iBlockSize ); | ||
255 | delete pBlock; | ||
256 | |||
257 | return iBlockSize++; | ||
258 | } | ||
259 | |||
260 | void Bu::Myriad::deleteStream( int /*iID*/ ) | ||
261 | { | ||
262 | } | ||
263 | |||
264 | Bu::MyriadStream Bu::Myriad::openStream( int iID ) | ||
265 | { | ||
266 | return MyriadStream( *this, iID ); | ||
267 | } | ||
268 | |||
269 | int Bu::Myriad::getBlockSize() | ||
270 | { | ||
271 | return iBlockSize; | ||
272 | } | ||
273 | |||
274 | int Bu::Myriad::getNumBlocks() | ||
275 | { | ||
276 | return iBlocks; | ||
277 | } | ||
278 | |||
279 | int Bu::Myriad::getNumUsedBlocks() | ||
280 | { | ||
281 | return iUsed; | ||
282 | } | ||
283 | |||
284 | |||