aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <mike@xagasoft.com>2024-08-28 11:45:51 -0700
committerMike Buland <mike@xagasoft.com>2024-08-28 11:45:51 -0700
commit0886ad4f53deb8e148f87f77b9e7ff690c02b069 (patch)
treec40ccf830b944d8172566b6e3c5d4e4ca0fc7712
parentf1e3f25d9b7a12cdedb99e4cb0bfa66157a1a972 (diff)
downloadlibbu++-0886ad4f53deb8e148f87f77b9e7ff690c02b069.tar.gz
libbu++-0886ad4f53deb8e148f87f77b9e7ff690c02b069.tar.bz2
libbu++-0886ad4f53deb8e148f87f77b9e7ff690c02b069.tar.xz
libbu++-0886ad4f53deb8e148f87f77b9e7ff690c02b069.zip
Most of the new myriad api is in.
Still to go: bootstrapping reading the initial header, saving the header, growing streams as we write?
-rw-r--r--src/stable/myriad.cpp143
-rw-r--r--src/stable/myriad.h24
-rw-r--r--src/stable/myriadstream.cpp72
-rw-r--r--src/stable/myriadstream.h4
4 files changed, 216 insertions, 27 deletions
diff --git a/src/stable/myriad.cpp b/src/stable/myriad.cpp
index 5278ac5..f3ff09a 100644
--- a/src/stable/myriad.cpp
+++ b/src/stable/myriad.cpp
@@ -81,6 +81,14 @@ bool Bu::Myriad::setSize( Bu::Myriad::StreamId /*iStream*/,
81 return false; 81 return false;
82} 82}
83 83
84Bu::String Bu::Myriad::getLocation() const
85{
86 Bu::MutexLocker l( mAccess );
87 Bu::MutexLocker l2( mBacking );
88 return Bu::String("myriad(%1,%2):%3")
89 .arg( 1 ).arg( iBlockSize ).arg( rBacking.getLocation() );
90}
91
84bool Bu::Myriad::loadMyriad() 92bool Bu::Myriad::loadMyriad()
85{ 93{
86 Bu::println("Load myriad!"); 94 Bu::println("Load myriad!");
@@ -264,6 +272,32 @@ int32_t Bu::Myriad::allocateBlock()
264 } 272 }
265} 273}
266 274
275void Bu::Myriad::releaseBlock( int32_t iBlockId, bool bBlank )
276{
277 Bu::MutexLocker l( mAccess );
278 lFreeBlocks.append( iBlockId );
279 if( bBlank )
280 {
281 blankBlock( iBlockId );
282 }
283}
284
285void Bu::Myriad::blankBlock( int32_t iBlockId )
286{
287 Bu::MutexLocker l( mBacking );
288 rBacking.setPos( iBlockId*iBlockSize );
289 int32_t iChunk = std::min( iBlockSize, 4096 );
290 uint8_t *pChunk = new uint8_t[iChunk];
291 memset( pChunk, 0, iChunk );
292 int iLeft = iBlockSize;
293 while( iLeft > 0 )
294 {
295 int32_t iWrite = rBacking.write( pChunk, std::min( iChunk, iLeft ) );
296 iLeft -= iWrite;
297 }
298 delete[] pChunk;
299}
300
267void Bu::Myriad::openStream( StreamId id ) 301void Bu::Myriad::openStream( StreamId id )
268{ 302{
269 Bu::MutexLocker l( mAccess ); 303 Bu::MutexLocker l( mAccess );
@@ -276,20 +310,36 @@ void Bu::Myriad::closeStream( StreamId id )
276 hStream.get( id )->close(); 310 hStream.get( id )->close();
277} 311}
278 312
279int32_t Bu::Myriad::blockRead( int32_t iStart, void *pTarget, int32_t iSize ) 313int32_t Bu::Myriad::blockRead( int32_t iBlock, int32_t iStart,
314 void *pTarget, int32_t iSize )
280{ 315{
281 int32_t iUpperSize = iBlockSize - (iStart%iBlockSize); 316 int32_t iUpperSize = iBlockSize - (iStart%iBlockSize);
282 Bu::println("Max size within block: %1 vs %2 (start=%3, blocksize=%4)") 317 Bu::println("Max read within block: %1 vs %2 (start=%3, blocksize=%4)")
283 .arg( iUpperSize ).arg( iSize ) 318 .arg( iUpperSize ).arg( iSize )
284 .arg( iStart ).arg( iBlockSize ); 319 .arg( iStart ).arg( iBlockSize );
285 320
286 int32_t iAmnt = std::min( iSize, iUpperSize ); 321 int32_t iAmnt = std::min( iSize, iUpperSize );
287 Bu::MutexLocker l( mBacking ); 322 Bu::MutexLocker l( mBacking );
288 rBacking.setPos( iStart ); 323 rBacking.setPos( iBlockSize*iBlock + iStart );
289 324
290 return rBacking.read( pTarget, iAmnt ); 325 return rBacking.read( pTarget, iAmnt );
291} 326}
292 327
328int32_t Bu::Myriad::blockWrite( int32_t iBlock, int32_t iStart,
329 const void *pTarget, int32_t iSize )
330{
331 int32_t iUpperSize = iBlockSize - (iStart%iBlockSize);
332 Bu::println("Max write within block: %1 vs %2 (start=%3, blocksize=%4)")
333 .arg( iUpperSize ).arg( iSize )
334 .arg( iStart ).arg( iBlockSize );
335
336 int32_t iAmnt = std::min( iSize, iUpperSize );
337 Bu::MutexLocker l( mBacking );
338 rBacking.setPos( iBlock*iBlockSize + iStart );
339
340 return rBacking.write( pTarget, iAmnt );
341}
342
293///////// 343/////////
294// Bu::Myriad::Stream 344// Bu::Myriad::Stream
295// 345//
@@ -308,22 +358,71 @@ Bu::Myriad::Stream::~Stream()
308{ 358{
309} 359}
310 360
361int32_t Bu::Myriad::Stream::getSize() const
362{
363 Bu::MutexLocker l( mAccess );
364 return iSize;
365}
366
367int32_t Bu::Myriad::Stream::getBlockSize() const
368{
369 Bu::MutexLocker l( mAccess );
370 return rParent.iBlockSize;
371}
372
373Bu::Myriad::StreamId Bu::Myriad::Stream::getStreamId() const
374{
375 return iStream;
376}
377
378int32_t Bu::Myriad::Stream::getOpenCount() const
379{
380 Bu::MutexLocker l( mAccess );
381 return iOpenCount;
382}
383
384void Bu::Myriad::Stream::setSize( int32_t iNewSize )
385{
386 // Two possible modes, shrink or grow.
387 Bu::MutexLocker l( mAccess );
388 if( iNewSize < iSize )
389 {
390 // Shrink it
391 int iNewBlocks = Bu::blkDiv( iNewSize, rParent.iBlockSize );
392 while( aBlocks.getSize() > iNewBlocks )
393 {
394 rParent.releaseBlock( aBlocks.last(), false );
395 aBlocks.eraseLast();
396 }
397 iSize = iNewSize;
398 }
399 else if( iNewSize > iSize )
400 {
401 // Grow it
402 int iNewBlocks = Bu::blkDiv( iNewSize, rParent.iBlockSize );
403 while( aBlocks.getSize() < iNewBlocks )
404 {
405 aBlocks.append( rParent.allocateBlock() );
406 }
407 iSize = iNewSize;
408 }
409}
410
311int32_t Bu::Myriad::Stream::read( int32_t iStart, void *pTarget, 411int32_t Bu::Myriad::Stream::read( int32_t iStart, void *pTarget,
312 int32_t iSize ) 412 int32_t iSize )
313{ 413{
314 int32_t iPos = iStart;
315 int32_t iRead = 0; 414 int32_t iRead = 0;
316 Bu::MutexLocker l( mAccess ); 415 Bu::MutexLocker l( mAccess );
317 while( iStart > 0 ) 416 while( iSize > 0 )
318 { 417 {
319 int32_t iBlock = aBlocks[iStart/rParent.iBlockSize]; 418 int32_t iBlock = aBlocks[iStart/rParent.iBlockSize];
320 int32_t iOffset = iPos % rParent.iBlockSize;
321 int32_t iChunkRead = rParent.blockRead( 419 int32_t iChunkRead = rParent.blockRead(
322 iBlock*rParent.iBlockSize+iOffset, pTarget, iSize 420 iBlock, iStart%rParent.iBlockSize, pTarget, iSize
323 ); 421 );
324 if( iChunkRead == 0 ) 422 if( iChunkRead == 0 )
325 break; 423 break;
326 iRead += iChunkRead; 424 iRead += iChunkRead;
425 iStart += iChunkRead;
327 reinterpret_cast<ptrdiff_t &>(pTarget) += iChunkRead; 426 reinterpret_cast<ptrdiff_t &>(pTarget) += iChunkRead;
328 iSize -= iChunkRead; 427 iSize -= iChunkRead;
329 } 428 }
@@ -331,6 +430,36 @@ int32_t Bu::Myriad::Stream::read( int32_t iStart, void *pTarget,
331 return iRead; 430 return iRead;
332} 431}
333 432
433int32_t Bu::Myriad::Stream::write( int32_t iStart, const void *pTarget,
434 int32_t iSize )
435{
436 int32_t iWrite = 0;
437 Bu::MutexLocker l( mAccess );
438 while( iSize > 0 )
439 {
440 int32_t iBlockIdx = iStart/rParent.iBlockSize;
441 int32_t iBlock = aBlocks[iBlockIdx];
442 int32_t iChunkWrite = rParent.blockWrite(
443 iBlock, iStart%rParent.iBlockSize, pTarget, iSize
444 );
445 if( iChunkWrite == 0 )
446 break;
447 iWrite += iChunkWrite;
448 iStart += iChunkWrite;
449 reinterpret_cast<ptrdiff_t &>(pTarget) += iChunkWrite;
450 iSize -= iChunkWrite;
451 }
452
453 return iWrite;
454}
455
456Bu::String Bu::Myriad::Stream::getLocation() const
457{
458 Bu::MutexLocker l( mAccess );
459 return Bu::String("%1:stream %2")\
460 .arg( rParent.getLocation() ).arg( iStream );
461}
462
334void Bu::Myriad::Stream::open() 463void Bu::Myriad::Stream::open()
335{ 464{
336 Bu::MutexLocker l( mAccess ); 465 Bu::MutexLocker l( mAccess );
diff --git a/src/stable/myriad.h b/src/stable/myriad.h
index 07b4a1d..6d99ee4 100644
--- a/src/stable/myriad.h
+++ b/src/stable/myriad.h
@@ -75,11 +75,14 @@ namespace Bu
75 MyriadStream open( StreamId iStream, Mode eMode ); 75 MyriadStream open( StreamId iStream, Mode eMode );
76 bool erase( StreamId iStream ); 76 bool erase( StreamId iStream );
77 bool setSize( StreamId iStream, int32_t iNewSize ); 77 bool setSize( StreamId iStream, int32_t iNewSize );
78 Bu::String getLocation() const;
78 79
79 private: 80 private:
80 bool loadMyriad(); 81 bool loadMyriad();
81 void createMyriad( int32_t iBlockSize, int32_t iPreallocateBlocks ); 82 void createMyriad( int32_t iBlockSize, int32_t iPreallocateBlocks );
82 int32_t allocateBlock(); 83 int32_t allocateBlock();
84 void releaseBlock( int32_t iBlockId, bool bBlank=true );
85 void blankBlock( int32_t iBlockId );
83 86
84 void openStream( StreamId id ); 87 void openStream( StreamId id );
85 void closeStream( StreamId id ); 88 void closeStream( StreamId id );
@@ -87,7 +90,16 @@ namespace Bu
87 * Block restricted read, it will not read past the end of the block 90 * Block restricted read, it will not read past the end of the block
88 * that iStart places it in. 91 * that iStart places it in.
89 */ 92 */
90 int32_t blockRead( int32_t iStart, void *pTarget, int32_t iSize ); 93 int32_t blockRead( int32_t iBlock, int32_t iStart,
94 void *pTarget, int32_t iSize );
95
96 /**
97 * Block restricted write, it will not write past the end of the block
98 * that iStart places it in. If this returns a non-zero number it's an
99 * indication that you need to allocate a new block.
100 */
101 int32_t blockWrite( int32_t iBlock, int32_t iStart,
102 const void *pTarget, int32_t iSize );
91 103
92 public: 104 public:
93 /** 105 /**
@@ -103,7 +115,15 @@ namespace Bu
103 virtual ~Stream(); 115 virtual ~Stream();
104 116
105 public: 117 public:
118 int32_t getSize() const;
119 int32_t getBlockSize() const;
120 StreamId getStreamId() const;
121 int32_t getOpenCount() const;
122
123 void setSize( int32_t iNewSize );
106 int32_t read( int32_t iStart, void *pTarget, int32_t iSize ); 124 int32_t read( int32_t iStart, void *pTarget, int32_t iSize );
125 int32_t write( int32_t iStart, const void *pTarget, int32_t iSize );
126 Bu::String getLocation() const;
107 127
108 /** 128 /**
109 * Doesn't actually open, just increments the open counter. 129 * Doesn't actually open, just increments the open counter.
@@ -134,7 +154,7 @@ namespace Bu
134 typedef Bu::Hash<StreamId, Stream *> StreamHash; 154 typedef Bu::Hash<StreamId, Stream *> StreamHash;
135 155
136 typedef Bu::List<int32_t> IndexList; 156 typedef Bu::List<int32_t> IndexList;
137 Bu::Mutex mAccess; 157 mutable Bu::Mutex mAccess;
138 mutable Bu::Mutex mBacking; 158 mutable Bu::Mutex mBacking;
139 Bu::Stream &rBacking; 159 Bu::Stream &rBacking;
140 int32_t iBlockSize; 160 int32_t iBlockSize;
diff --git a/src/stable/myriadstream.cpp b/src/stable/myriadstream.cpp
index cbbd4fe..9ea2e17 100644
--- a/src/stable/myriadstream.cpp
+++ b/src/stable/myriadstream.cpp
@@ -6,7 +6,8 @@ Bu::MyriadStream::MyriadStream( Bu::Myriad &rMyriad,
6 Bu::Myriad::Stream *pStream, Bu::Myriad::Mode eMode ) : 6 Bu::Myriad::Stream *pStream, Bu::Myriad::Mode eMode ) :
7 rMyriad( rMyriad ), 7 rMyriad( rMyriad ),
8 pStream( pStream ), 8 pStream( pStream ),
9 eMode( eMode ) 9 eMode( eMode ),
10 iPos( 0 )
10{ 11{
11 if( (eMode&Bu::Myriad::ReadWrite) == 0 ) 12 if( (eMode&Bu::Myriad::ReadWrite) == 0 )
12 { 13 {
@@ -15,6 +16,20 @@ Bu::MyriadStream::MyriadStream( Bu::Myriad &rMyriad,
15 } 16 }
16 Bu::MutexLocker l( mAccess ); 17 Bu::MutexLocker l( mAccess );
17 pStream->open(); 18 pStream->open();
19
20 if( (eMode&Bu::Myriad::Write) != 0 )
21 {
22 // Writing mode, what other options do we deal with?
23 if( (eMode&Bu::Myriad::Truncate) != 0 )
24 {
25 // Truncate, set size to zero before starting.
26 pStream->setSize( 0 );
27 }
28 else if( (eMode&Bu::Myriad::Append) != 0 )
29 {
30 iPos = pStream->getSize();
31 }
32 }
18} 33}
19 34
20Bu::MyriadStream::~MyriadStream() 35Bu::MyriadStream::~MyriadStream()
@@ -34,93 +49,120 @@ void Bu::MyriadStream::close()
34 49
35Bu::size Bu::MyriadStream::read( void *pBuf, size iBytes ) 50Bu::size Bu::MyriadStream::read( void *pBuf, size iBytes )
36{ 51{
37} 52 Bu::MutexLocker l( mAccess );
38 53 int32_t iRead = pStream->read( iPos, pBuf, iBytes );
39Bu::String Bu::MyriadStream::readLine() 54 iPos += iRead;
40{ 55 return iRead;
41}
42
43Bu::String Bu::MyriadStream::readAll()
44{
45} 56}
46 57
47Bu::size Bu::MyriadStream::write( const void *pBuf, size iBytes ) 58Bu::size Bu::MyriadStream::write( const void *pBuf, size iBytes )
48{ 59{
49} 60 Bu::MutexLocker l( mAccess );
50 61 int32_t iWrite = pStream->write( iPos, pBuf, iBytes );
51Bu::size Bu::MyriadStream::write( const Bu::String &sBuf ) 62 iPos += iWrite;
52{ 63 return iWrite;
53} 64}
54 65
55Bu::size Bu::MyriadStream::tell() 66Bu::size Bu::MyriadStream::tell()
56{ 67{
68 Bu::MutexLocker l( mAccess );
69 return iPos;
57} 70}
58 71
59void Bu::MyriadStream::seek( size offset ) 72void Bu::MyriadStream::seek( size offset )
60{ 73{
74 Bu::MutexLocker l( mAccess );
75 iPos += offset;
61} 76}
62 77
63void Bu::MyriadStream::setPos( size pos ) 78void Bu::MyriadStream::setPos( size pos )
64{ 79{
80 Bu::MutexLocker l( mAccess );
81 iPos = pos;
65} 82}
66 83
67void Bu::MyriadStream::setPosEnd( size pos ) 84void Bu::MyriadStream::setPosEnd( size pos )
68{ 85{
86 Bu::MutexLocker l( mAccess );
87 iPos = pStream->getSize()-pos;
69} 88}
70 89
71bool Bu::MyriadStream::isEos() 90bool Bu::MyriadStream::isEos()
72{ 91{
92 Bu::MutexLocker l( mAccess );
93 return iPos == pStream->getSize();
73} 94}
74 95
75bool Bu::MyriadStream::isOpen() 96bool Bu::MyriadStream::isOpen()
76{ 97{
98 return true;
77} 99}
78 100
79void Bu::MyriadStream::flush() 101void Bu::MyriadStream::flush()
80{ 102{
103 // Does this make sense?
81} 104}
82 105
83bool Bu::MyriadStream::canRead() 106bool Bu::MyriadStream::canRead()
84{ 107{
108 return true;
85} 109}
86 110
87bool Bu::MyriadStream::canWrite() 111bool Bu::MyriadStream::canWrite()
88{ 112{
113 return true;
89} 114}
90 115
91bool Bu::MyriadStream::isReadable() 116bool Bu::MyriadStream::isReadable()
92{ 117{
118 Bu::MutexLocker l( mAccess );
119 return (eMode&Bu::Myriad::Read) != 0;
93} 120}
94 121
95bool Bu::MyriadStream::isWritable() 122bool Bu::MyriadStream::isWritable()
96{ 123{
124 Bu::MutexLocker l( mAccess );
125 return (eMode&Bu::Myriad::Write) != 0;
97} 126}
98 127
99bool Bu::MyriadStream::isSeekable() 128bool Bu::MyriadStream::isSeekable()
100{ 129{
130 return true;
101} 131}
102 132
103bool Bu::MyriadStream::isBlocking() 133bool Bu::MyriadStream::isBlocking()
104{ 134{
135 return true;
105} 136}
106 137
107void Bu::MyriadStream::setBlocking( bool bBlocking ) 138void Bu::MyriadStream::setBlocking( bool /*bBlocking*/ )
108{ 139{
140 // Dunno what this would even mean here.
109} 141}
110 142
111void Bu::MyriadStream::setSize( size iSize ) 143void Bu::MyriadStream::setSize( size iSize )
112{ 144{
145 Bu::MutexLocker l( mAccess );
146 pStream->setSize( iSize );
147 if( iPos > iSize )
148 iPos = iSize;
113} 149}
114 150
115Bu::size Bu::MyriadStream::getSize() const 151Bu::size Bu::MyriadStream::getSize() const
116{ 152{
153 Bu::MutexLocker l( mAccess );
154 return pStream->getSize();
117} 155}
118 156
119Bu::size Bu::MyriadStream::getBlockSize() const 157Bu::size Bu::MyriadStream::getBlockSize() const
120{ 158{
159 Bu::MutexLocker l( mAccess );
160 return pStream->getBlockSize();
121} 161}
122 162
123Bu::String getLocation() const 163Bu::String Bu::MyriadStream::getLocation() const
124{ 164{
165 Bu::MutexLocker l( mAccess );
166 return pStream->getLocation();
125} 167}
126 168
diff --git a/src/stable/myriadstream.h b/src/stable/myriadstream.h
index 87192a9..c01cf34 100644
--- a/src/stable/myriadstream.h
+++ b/src/stable/myriadstream.h
@@ -18,10 +18,7 @@ namespace Bu
18 public: 18 public:
19 virtual void close(); 19 virtual void close();
20 virtual size read( void *pBuf, size iBytes ); 20 virtual size read( void *pBuf, size iBytes );
21 virtual Bu::String readLine();
22 virtual Bu::String readAll();
23 virtual size write( const void *pBuf, size iBytes ); 21 virtual size write( const void *pBuf, size iBytes );
24 virtual size write( const Bu::String &sBuf );
25 virtual size tell(); 22 virtual size tell();
26 virtual void seek( size offset ); 23 virtual void seek( size offset );
27 virtual void setPos( size pos ); 24 virtual void setPos( size pos );
@@ -46,6 +43,7 @@ namespace Bu
46 Bu::Myriad &rMyriad; 43 Bu::Myriad &rMyriad;
47 Bu::Myriad::Stream *pStream; 44 Bu::Myriad::Stream *pStream;
48 Bu::Myriad::Mode eMode; 45 Bu::Myriad::Mode eMode;
46 int32_t iPos;
49 }; 47 };
50}; 48};
51 49