37 static constexpr
unsigned MAX_ENTRIES = 2048;
41 uint8_t packetFlags = 0;
42 uint16_t packetLogicalLengthMinus1 = 0;
43 uint16_t entryCount = 0;
44 uint8_t indexLevel = 0;
45 uint8_t reserved1[9] = {};
49 uint64_t chunkRecordNumber = 0;
50 uint64_t chunkPhysicalOffset = 0;
51 } entries[MAX_ENTRIES];
53 void verify(
unsigned bufferLength = 0, uint64_t totalRecordCount = 0, uint64_t fileSize = 0 )
const;
56 void dump(
int indent = 0, std::ostream &os = std::cout )
const;
64 uint8_t reserved1 = 0;
65 uint16_t packetLogicalLengthMinus1 = 0;
67 void verify(
unsigned bufferLength = 0 )
const;
70 void dump(
int indent = 0, std::ostream &os = std::cout )
const;
79 if ( packetCount == 0 )
87 #ifdef E57_MAX_VERBOSE
88 std::cout <<
"PacketReadCache::lock() called, packetLogicalOffset=" << packetLogicalOffset <<
std::endl;
98 if ( packetLogicalOffset == 0 )
104 for (
unsigned i = 0; i <
entries_.size(); ++i )
108 if ( packetLogicalOffset == entry.logicalOffset_ )
111 #ifdef E57_MAX_VERBOSE
112 std::cout <<
" Found matching cache entry, index=" << i <<
std::endl;
122 std::unique_ptr<PacketLock> plock(
new PacketLock(
this, i ) );
133 unsigned oldestEntry = 0;
134 unsigned oldestUsed =
entries_.at( 0 ).lastUsed_;
136 for (
unsigned i = 0; i <
entries_.size(); ++i )
140 if ( entry.lastUsed_ < oldestUsed )
143 oldestUsed = entry.lastUsed_;
146 #ifdef E57_MAX_VERBOSE
147 std::cout <<
" Oldest entry=" << oldestEntry <<
" lastUsed=" << oldestUsed <<
std::endl;
150 readPacket( oldestEntry, packetLogicalOffset );
153 pkt =
entries_[oldestEntry].buffer_;
156 std::unique_ptr<PacketLock> plock(
new PacketLock(
this, oldestEntry ) );
167 #ifdef E57_MAX_VERBOSE
168 std::cout <<
"PacketReadCache::unlock() called, cacheIndex=" << cacheIndex <<
std::endl;
181 #ifdef E57_MAX_VERBOSE
182 std::cout <<
"PacketReadCache::readPacket() called, oldestEntry=" << oldestEntry
183 <<
" packetLogicalOffset=" << packetLogicalOffset <<
std::endl;
191 cFile_->
read(
reinterpret_cast<char *
>( &header ),
sizeof( header ) );
203 auto &entry =
entries_.at( oldestEntry );
214 auto dpkt =
reinterpret_cast<DataPacket *
>( entry.buffer_ );
216 dpkt->
verify( packetLength );
217 #ifdef E57_MAX_VERBOSE
218 std::cout <<
" data packet:" <<
std::endl;
225 auto ipkt =
reinterpret_cast<IndexPacket *
>( entry.buffer_ );
227 ipkt->
verify( packetLength );
228 #ifdef E57_MAX_VERBOSE
229 std::cout <<
" index packet:" <<
std::endl;
238 hp->
verify( packetLength );
239 #ifdef E57_MAX_VERBOSE
240 std::cout <<
" empty packet:" <<
std::endl;
249 entry.logicalOffset_ = packetLogicalOffset;
262 for (
unsigned i = 0; i <
entries_.size(); i++ )
267 if (
entries_[i].logicalOffset_ != 0 )
275 dpkt->
dump( indent + 6, os );
281 ipkt->
dump( indent + 6, os );
287 hp->
dump( indent + 6, os );
304 PacketLock::PacketLock(
PacketReadCache *cache,
unsigned cacheIndex ) : cache_( cache ), cacheIndex_( cacheIndex )
306 #ifdef E57_MAX_VERBOSE
307 std::cout <<
"PacketLock() called" <<
std::endl;
313 #ifdef E57_MAX_VERBOSE
314 std::cout <<
"~PacketLock() called" <<
std::endl;
334 static_assert(
sizeof(
DataPacketHeader ) == 6,
"Unexpected size of DataPacketHeader" );
356 if ( packetLength <
sizeof( *
this ) )
362 if ( packetLength % 4 )
368 if ( bufferLength > 0 && packetLength > bufferLength )
371 "packetLength=" +
toString( packetLength ) +
" bufferLength=" +
toString( bufferLength ) );
406 static_assert(
sizeof(
DataPacket ) == 64 * 1024,
"Unexpected size of DataPacket" );
418 hp->
verify( bufferLength );
421 auto bsbLength =
reinterpret_cast<const uint16_t *
>( &
payload[0] );
422 unsigned totalStreamByteCount = 0;
426 totalStreamByteCount += bsbLength[i];
432 #ifdef E57_MAX_VERBOSE
433 std::cout <<
"needed=" << needed <<
" actual=" << packetLength <<
std::endl;
437 if ( needed > packetLength || needed + 3 < packetLength )
440 "needed=" +
toString( needed ) +
"packetLength=" +
toString( packetLength ) );
444 for (
unsigned i = needed; i < packetLength; i++ )
446 if (
reinterpret_cast<const char *
>(
this )[i] != 0 )
455 #ifdef E57_MAX_VERBOSE
456 std::cout <<
"getBytestream called, bytestreamNumber=" << bytestreamNumber <<
std::endl;
473 auto bsbLength =
reinterpret_cast<uint16_t *
>( &
payload[0] );
477 unsigned totalPreceeding = 0;
478 for (
unsigned i = 0; i < bytestreamNumber; i++ )
480 totalPreceeding += bsbLength[i];
483 byteCount = bsbLength[bytestreamNumber];
496 return ( &streamBase[totalPreceeding] );
504 return ( byteCount );
517 auto bsbLength =
reinterpret_cast<const uint16_t *
>( &
payload[0] );
523 os <<
space( indent + 4 ) <<
"length: " << bsbLength[i] <<
std::endl;
535 "size=" +
toString( p -
reinterpret_cast<const uint8_t *
>(
this ) ) );
555 unsigned packetLength = packetLogicalLengthMinus1 + 1;
556 if ( packetLength <
sizeof( *
this ) )
562 if ( packetLength % 4 )
567 if ( entryCount == 0 )
573 if ( entryCount > MAX_ENTRIES )
580 if ( indexLevel > 5 )
588 if ( indexLevel > 0 && entryCount < 2 )
591 "indexLevel=" +
toString( indexLevel ) +
" entryCount=" +
toString( entryCount ) );
596 for (
unsigned i = 0; i <
sizeof( reserved1 ); i++ )
598 if ( reserved1[i] != 0 )
605 if ( bufferLength > 0 && packetLength > bufferLength )
608 "packetLength=" +
toString( packetLength ) +
" bufferLength=" +
toString( bufferLength ) );
612 unsigned neededLength = 16 + 8 * entryCount;
613 if ( packetLength < neededLength )
616 "packetLength=" +
toString( packetLength ) +
" neededLength=" +
toString( neededLength ) );
621 const char *p =
reinterpret_cast<const char *
>( this );
622 for (
unsigned i = neededLength; i < packetLength; i++ )
629 for (
unsigned i = 0; i < entryCount; i++ )
632 if ( totalRecordCount > 0 && entries[i].chunkRecordNumber >= totalRecordCount )
635 "i=" +
toString( i ) +
" chunkRecordNumber=" +
toString( entries[i].chunkRecordNumber ) +
636 " totalRecordCount=" +
toString( totalRecordCount ) );
640 if ( i > 0 && entries[i - 1].chunkRecordNumber >= entries[i].chunkRecordNumber )
644 " prevChunkRecordNumber=" +
toString( entries[i - 1].chunkRecordNumber ) +
645 " currentChunkRecordNumber=" +
toString( entries[i].chunkRecordNumber ) );
649 if ( fileSize > 0 && entries[i].chunkPhysicalOffset >= fileSize )
652 toString( entries[i].chunkPhysicalOffset ) +
653 " fileSize=" +
toString( fileSize ) );
657 if ( i > 0 && entries[i - 1].chunkPhysicalOffset >= entries[i].chunkPhysicalOffset )
661 " prevChunkPhysicalOffset=" +
toString( entries[i - 1].chunkPhysicalOffset ) +
662 " currentChunkPhysicalOffset=" +
toString( entries[i].chunkPhysicalOffset ) );
671 os <<
space( indent ) <<
"packetType: " <<
static_cast<unsigned>( packetType ) <<
std::endl;
672 os <<
space( indent ) <<
"packetFlags: " <<
static_cast<unsigned>( packetFlags ) <<
std::endl;
673 os <<
space( indent ) <<
"packetLogicalLengthMinus1: " << packetLogicalLengthMinus1 <<
std::endl;
674 os <<
space( indent ) <<
"entryCount: " << entryCount <<
std::endl;
675 os <<
space( indent ) <<
"indexLevel: " << indexLevel <<
std::endl;
677 for ( i = 0; i < entryCount && i < 10; i++ )
680 os <<
space( indent + 4 ) <<
"chunkRecordNumber: " << entries[i].chunkRecordNumber <<
std::endl;
681 os <<
space( indent + 4 ) <<
"chunkPhysicalOffset: " << entries[i].chunkPhysicalOffset <<
std::endl;
683 if ( i < entryCount )
685 os <<
space( indent ) << entryCount - i <<
"more entries unprinted..." <<
std::endl;
702 unsigned packetLength = packetLogicalLengthMinus1 + 1;
703 if ( packetLength <
sizeof( *
this ) )
709 if ( packetLength % 4 )
713 if ( bufferLength > 0 && packetLength > bufferLength )
716 "packetLength=" +
toString( packetLength ) +
" bufferLength=" +
toString( bufferLength ) );
723 os <<
space( indent ) <<
"packetType: " <<
static_cast<unsigned>( packetType ) <<
std::endl;
724 os <<
space( indent ) <<
"packetLogicalLengthMinus1: " << packetLogicalLengthMinus1 <<
std::endl;
void read(char *buf, size_t nRead, size_t bufSize=0)
void seek(uint64_t offset, OffsetMode omode=Logical)
void verify(unsigned bufferLength=0) const
void dump(int indent=0, std::ostream &os=std::cout) const
char * getBytestream(unsigned bytestreamNumber, unsigned &byteCount)
uint8_t payload[PayloadSize]
unsigned getBytestreamBufferLength(unsigned bytestreamNumber)
std::vector< CacheEntry > entries_
PacketReadCache(CheckedFile *cFile, unsigned packetCount)
friend class PacketLock
Only PacketLock can unlock the cache.
void unlock(unsigned cacheIndex)
void readPacket(unsigned oldestEntry, uint64_t packetLogicalOffset)
void dump(int indent=0, std::ostream &os=std::cout)
std::unique_ptr< PacketLock > lock(uint64_t packetLogicalOffset, char *&pkt)
QTextStream & endl(QTextStream &stream)
@ E57_ERROR_INTERNAL
An unrecoverable inconsistent internal state was detected.
@ E57_ERROR_BAD_CV_PACKET
a CompressedVector binary packet was bad
std::string toString(T x)
constexpr int DATA_PACKET_MAX
maximum size of CompressedVector binary data packet
std::string space(size_t n)
void verify(unsigned bufferLength=0, uint64_t totalRecordCount=0, uint64_t fileSize=0) const
void dump(int indent=0, std::ostream &os=std::cout) const