diff --git a/src/dsql/DsqlBatch.cpp b/src/dsql/DsqlBatch.cpp index 95bbfecbbe..66e47c24d1 100644 --- a/src/dsql/DsqlBatch.cpp +++ b/src/dsql/DsqlBatch.cpp @@ -255,7 +255,7 @@ void DsqlBatch::add(thread_db* tdbb, ULONG count, const void* inBuffer) return; m_messages.align(m_alignment); m_messages.put(inBuffer, (count - 1) * m_alignedMessage + m_messageSize); - DEB_BATCH(fprintf(stderr, "Put to batch %d messages\n", count)); + //DEB_BATCH(fprintf(stderr, "Put to batch %d messages\n", count)); } void DsqlBatch::blobCheckMeta() @@ -298,6 +298,7 @@ void DsqlBatch::blobSetSize() m_blobs.put3(&blobSize, sizeof(blobSize), m_lastBlob + sizeof(ISC_QUAD)); m_setBlobSize = false; } + DEB_BATCH(fprintf(stderr, "blobSetSize %u\n", blobSize)); } void DsqlBatch::blobPrepare() @@ -347,6 +348,8 @@ void DsqlBatch::addBlob(thread_db* tdbb, ULONG length, const void* inBuffer, ISC ULONG fullLength = length + parLength; m_blobs.put(&fullLength, sizeof(ULONG)); m_blobs.put(&parLength, sizeof(ULONG)); + DEB_BATCH(fprintf(stderr, "addBlob %08x.%08x par %u full %u ", + blobId->gds_quad_high, blobId->gds_quad_low, parLength, fullLength)); // Store BPB if (parLength) @@ -383,8 +386,11 @@ void DsqlBatch::putSegment(ULONG length, const void* inBuffer) m_blobs.align(IBatch::BLOB_SEGHDR_ALIGN); m_blobs.put(&l, sizeof(l)); m_setBlobSize = true; + + DEB_BATCH(fprintf(stderr, "segment header, ")); } m_blobs.put(inBuffer, length); + DEB_BATCH(fprintf(stderr, "segment data %u ", length)); } void DsqlBatch::addBlobStream(thread_db* tdbb, unsigned length, const void* inBuffer) @@ -529,6 +535,10 @@ private: ISC_QUAD batchBlobId = *reinterpret_cast(flow.data); ULONG* blobSize = reinterpret_cast(flow.data + sizeof(ISC_QUAD)); ULONG* bpbSize = reinterpret_cast(flow.data + sizeof(ISC_QUAD) + sizeof(ULONG)); + + DEB_BATCH(fprintf(stderr, "B-ID: %08x.%08x full=%u par=%u\n", batchBlobId.gds_quad_high, batchBlobId.gds_quad_low, + *blobSize, *bpbSize)); + flow.newHdr(*blobSize); ULONG currentBpbSize = *bpbSize; @@ -579,7 +589,6 @@ private: blob = blb::create2(tdbb, transaction, &engineBlobId, bpb->getCount(), bpb->begin(), true); - //DEB_BATCH(fprintf(stderr, "B-ID: (%x,%x)\n", batchBlobId.gds_quad_high, batchBlobId.gds_quad_low)); registerBlob(reinterpret_cast(&engineBlobId), &batchBlobId); } } @@ -598,6 +607,8 @@ private: flow.move(sizeof(USHORT)); dataSize = *segSize; + + DEB_BATCH(fprintf(stderr, " Seg: %u\n", dataSize)); if (dataSize > flow.currentBlobSize) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << @@ -795,8 +806,6 @@ void DsqlBatch::DataCache::setBuf(ULONG size, ULONG cacheCapacity) void DsqlBatch::DataCache::put3(const void* data, ULONG dataSize, ULONG offset) { - // This assertion guarantees that data always fits as a whole into m_cache or m_space, - // never placed half in one storage, half - in another. fb_assert((DsqlBatch::RAM_BATCH % dataSize == 0) && (offset % dataSize == 0)); if (offset >= m_used) @@ -809,6 +818,13 @@ void DsqlBatch::DataCache::put3(const void* data, ULONG dataSize, ULONG offset) } else { + if (offset + dataSize > m_used) + { + // what a pity - data appears partilly divided between cache & tempspace + fb_assert(offset + dataSize <= getSize()); + flush(); + } + const FB_UINT64 writtenBytes = m_space->write(offset, data, dataSize); fb_assert(writtenBytes == dataSize); } @@ -841,13 +857,7 @@ void DsqlBatch::DataCache::put(const void* d, ULONG dataSize) } // swap ram cache to tempspace - if (!m_space) - m_space = FB_NEW_POOL(getPool()) TempSpace(getPool(), TEMP_NAME); - - const FB_UINT64 writtenBytes = m_space->write(m_used, m_cache.begin(), m_cache.getCount()); - fb_assert(writtenBytes == m_cache.getCount()); - m_used += m_cache.getCount(); - m_cache.clear(); + flush(); // in a case of huge buffer write directly to tempspace if (dataSize > m_cacheCapacity / K) @@ -862,6 +872,17 @@ void DsqlBatch::DataCache::put(const void* d, ULONG dataSize) m_cache.append(data, dataSize); } +void DsqlBatch::DataCache::flush() +{ + if (!m_space) + m_space = FB_NEW_POOL(getPool()) TempSpace(getPool(), TEMP_NAME); + + const FB_UINT64 writtenBytes = m_space->write(m_used, m_cache.begin(), m_cache.getCount()); + fb_assert(writtenBytes == m_cache.getCount()); + m_used += m_cache.getCount(); + m_cache.clear(); +} + void DsqlBatch::DataCache::align(ULONG alignment) { ULONG a = getSize() % alignment; diff --git a/src/dsql/DsqlBatch.h b/src/dsql/DsqlBatch.h index 5d9d048a6c..495d12a868 100644 --- a/src/dsql/DsqlBatch.h +++ b/src/dsql/DsqlBatch.h @@ -125,6 +125,7 @@ private: ULONG getSize() const; ULONG getCapacity() const; void clear(); + void flush(); private: typedef Firebird::Array Cache;