Skip to content

Commit 51b7217

Browse files
committed
Don't rely on wrong assumption that stream blob always have maximum possible segment size.
1 parent f5c7e57 commit 51b7217

File tree

1 file changed

+54
-30
lines changed

1 file changed

+54
-30
lines changed

src/remote/client/interface.cpp

+54-30
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ class Blob final : public RefCntIface<IBlobImpl<Blob, CheckStatusWrapper> >
215215
void freeClientData(CheckStatusWrapper* status, bool force = false);
216216
void internalCancel(CheckStatusWrapper* status);
217217
void internalClose(CheckStatusWrapper* status);
218+
// seek in cached blob
219+
int seekCached(int mode, int offset);
218220

219221
Rbl* blob;
220222
};
@@ -6863,36 +6865,7 @@ int Blob::seek(CheckStatusWrapper* status, int mode, int offset)
68636865
CHECK_HANDLE(blob, isc_bad_segstr_handle);
68646866

68656867
if (blob->isCached())
6866-
{
6867-
// Segmented blobs does not support seek
6868-
if (blob->rbl_info.blob_type == 0)
6869-
Arg::Gds(isc_bad_segstr_type).raise();
6870-
6871-
if (mode == 1) // seek from current position
6872-
offset += blob->rbl_offset;
6873-
else if (mode == 2) // seek from end of blob
6874-
offset = blob->rbl_info.total_length + offset;
6875-
6876-
if (offset < 0)
6877-
offset = 0;
6878-
6879-
if (offset > blob->rbl_info.total_length)
6880-
offset = blob->rbl_info.total_length;
6881-
6882-
// Assume stream blob with single segment in buffer
6883-
fb_assert(blob->rbl_info.num_segments <= 1);
6884-
fb_assert(blob->rbl_info.total_length <= MAX_USHORT);
6885-
6886-
blob->rbl_offset = offset;
6887-
if (!blob->rbl_data.isEmpty())
6888-
{
6889-
blob->rbl_ptr = blob->rbl_buffer + offset + 2;
6890-
blob->rbl_length = blob->rbl_data.end() - blob->rbl_ptr;
6891-
blob->rbl_fragment_length = blob->rbl_length;
6892-
}
6893-
blob->rbl_flags &= ~(Rbl::EOF_SET | Rbl::SEGMENT);
6894-
return blob->rbl_offset;
6895-
}
6868+
return seekCached(mode, offset);
68966869

68976870
Rdb* rdb = blob->rbl_rdb;
68986871
CHECK_HANDLE(rdb, isc_bad_db_handle);
@@ -6929,6 +6902,57 @@ int Blob::seek(CheckStatusWrapper* status, int mode, int offset)
69296902
}
69306903

69316904

6905+
int Blob::seekCached(int mode, int offset)
6906+
{
6907+
// Segmented blobs does not support seek
6908+
if (blob->rbl_info.blob_type == 0)
6909+
Arg::Gds(isc_bad_segstr_type).raise();
6910+
6911+
if (mode == 1) // seek from current position
6912+
offset += blob->rbl_offset;
6913+
else if (mode == 2) // seek from end of blob
6914+
offset = blob->rbl_info.total_length + offset;
6915+
6916+
if (offset < 0)
6917+
offset = 0;
6918+
6919+
// Engine allows to set seek position to the total length of the blob,
6920+
// but it's not documented and seems to be wrong. See blb::BLB_lseek().
6921+
// Here this behavior is supported for compatibility with the engine.
6922+
if (offset > blob->rbl_info.total_length)
6923+
offset = blob->rbl_info.total_length;
6924+
6925+
fb_assert(blob->rbl_info.total_length <= MAX_USHORT);
6926+
6927+
blob->rbl_offset = offset;
6928+
if (!blob->rbl_data.isEmpty())
6929+
{
6930+
if (offset == blob->rbl_info.total_length)
6931+
{
6932+
blob->rbl_ptr = blob->rbl_data.end();
6933+
blob->rbl_fragment_length = blob->rbl_length = 0;
6934+
}
6935+
else
6936+
{
6937+
const auto seg = offset / blob->rbl_info.max_segment + 1;
6938+
fb_assert(seg <= blob->rbl_info.num_segments);
6939+
6940+
blob->rbl_ptr = blob->rbl_buffer + offset + 2 * seg;
6941+
fb_assert(blob->rbl_ptr < blob->rbl_data.end());
6942+
6943+
blob->rbl_length = blob->rbl_data.end() - blob->rbl_ptr;
6944+
6945+
if (seg < blob->rbl_info.num_segments)
6946+
blob->rbl_fragment_length = blob->rbl_info.max_segment - offset % blob->rbl_info.max_segment;
6947+
else
6948+
blob->rbl_fragment_length = blob->rbl_length;
6949+
}
6950+
}
6951+
6952+
blob->rbl_flags &= ~(Rbl::EOF_SET | Rbl::SEGMENT);
6953+
return blob->rbl_offset;
6954+
}
6955+
69326956
void Request::send(CheckStatusWrapper* status, int level, unsigned int msg_type,
69336957
unsigned int /*length*/, const void* msg)
69346958
{

0 commit comments

Comments
 (0)