2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: JRD Access Method
|
|
|
|
* MODULE: blb.h
|
|
|
|
* DESCRIPTION: Blob handling definitions
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Interbase Public
|
|
|
|
* License Version 1.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy
|
|
|
|
* of the License at http://www.Inprise.com/IPL.html
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an
|
|
|
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
|
|
|
* or implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code was created by Inprise Corporation
|
|
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
|
|
* Copyright (C) Inprise Corporation.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
2002-10-29 04:17:45 +01:00
|
|
|
*
|
|
|
|
* 2002.10.28 Sean Leyne - Code cleanup, removed obsolete "DecOSF" port
|
|
|
|
*
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
|
|
|
|
2001-12-24 03:51:06 +01:00
|
|
|
#ifndef JRD_BLB_H
|
|
|
|
#define JRD_BLB_H
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-09-28 08:28:38 +02:00
|
|
|
#include "../jrd/RecordNumber.h"
|
2008-01-16 09:16:36 +01:00
|
|
|
#include "../common/classes/array.h"
|
|
|
|
#include "../common/classes/File.h"
|
2004-09-28 08:28:38 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
namespace Jrd {
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
/* Blob id. A blob has two states -- temporary and permanent. In each
|
|
|
|
case, the blob id is 8 bytes (2 longwords) long. In the case of a
|
|
|
|
temporary blob, the first word is NULL and the second word points to
|
|
|
|
an internal blob block. In the case of a permanent blob, the first
|
|
|
|
word contains the relation id of the blob and the second the record
|
|
|
|
number of the first segment-clump. The two types of blobs can be
|
|
|
|
reliably distinguished by a zero or non-zero relation id. */
|
2004-03-19 07:14:53 +01:00
|
|
|
|
2006-10-30 21:58:06 +01:00
|
|
|
class Attachment;
|
2004-03-19 07:14:53 +01:00
|
|
|
class BlobControl;
|
2006-10-30 21:58:06 +01:00
|
|
|
class jrd_rel;
|
2004-03-19 07:14:53 +01:00
|
|
|
class jrd_req;
|
|
|
|
class jrd_tra;
|
2006-10-30 21:58:06 +01:00
|
|
|
class vcl;
|
2004-03-20 15:57:40 +01:00
|
|
|
|
2004-09-28 08:28:38 +02:00
|
|
|
// This structure must occupy 8 bytes
|
2004-09-30 19:45:09 +02:00
|
|
|
struct bid {
|
2004-09-28 08:28:38 +02:00
|
|
|
union {
|
2004-09-30 19:45:09 +02:00
|
|
|
// Internal decomposition of the structure
|
2007-03-25 18:09:00 +02:00
|
|
|
RecordNumber::Packed bid_internal;
|
2004-09-30 19:45:09 +02:00
|
|
|
|
|
|
|
// This is how bid structure represented in public API.
|
|
|
|
// Must be present to enforce alignment rules when structure is declared on stack
|
2004-09-28 08:28:38 +02:00
|
|
|
struct {
|
2004-09-30 19:45:09 +02:00
|
|
|
ULONG bid_quad_high;
|
|
|
|
ULONG bid_quad_low;
|
|
|
|
} bid_quad;
|
2004-09-28 08:28:38 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
ULONG& bid_temp_id() {
|
2004-09-30 19:45:09 +02:00
|
|
|
// Make sure that compiler packed structure like we wanted
|
|
|
|
fb_assert(sizeof(*this) == 8);
|
|
|
|
|
2007-03-25 18:09:00 +02:00
|
|
|
return bid_internal.bid_temp_id();
|
2004-09-28 08:28:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ULONG bid_temp_id() const {
|
2004-09-30 19:45:09 +02:00
|
|
|
// Make sure that compiler packed structure like we wanted
|
|
|
|
fb_assert(sizeof(*this) == 8);
|
|
|
|
|
2007-03-25 18:09:00 +02:00
|
|
|
return bid_internal.bid_temp_id();
|
2004-09-28 08:28:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool isEmpty() const {
|
2004-09-30 19:45:09 +02:00
|
|
|
// Make sure that compiler packed structure like we wanted
|
|
|
|
fb_assert(sizeof(*this) == 8);
|
|
|
|
|
|
|
|
return bid_quad.bid_quad_high == 0 && bid_quad.bid_quad_low == 0;
|
2004-09-28 08:28:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void clear() {
|
2004-09-30 19:45:09 +02:00
|
|
|
// Make sure that compiler packed structure like we wanted
|
|
|
|
fb_assert(sizeof(*this) == 8);
|
|
|
|
|
|
|
|
bid_quad.bid_quad_high = 0;
|
|
|
|
bid_quad.bid_quad_low = 0;
|
2004-09-28 08:28:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void set_temporary(ULONG temp_id) {
|
2004-09-30 19:45:09 +02:00
|
|
|
// Make sure that compiler packed structure like we wanted
|
|
|
|
fb_assert(sizeof(*this) == 8);
|
|
|
|
|
2004-09-28 08:28:38 +02:00
|
|
|
clear();
|
|
|
|
bid_temp_id() = temp_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_permanent(USHORT relation_id, RecordNumber num) {
|
2004-09-30 19:45:09 +02:00
|
|
|
// Make sure that compiler packed structure like we wanted
|
|
|
|
fb_assert(sizeof(*this) == 8);
|
|
|
|
|
2004-09-28 08:28:38 +02:00
|
|
|
clear();
|
2004-09-30 19:45:09 +02:00
|
|
|
bid_internal.bid_relation_id = relation_id;
|
2007-03-25 18:09:00 +02:00
|
|
|
num.bid_encode(&bid_internal);
|
2004-09-28 08:28:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
RecordNumber get_permanent_number() const {
|
2004-09-30 19:45:09 +02:00
|
|
|
// Make sure that compiler packed structure like we wanted
|
|
|
|
fb_assert(sizeof(*this) == 8);
|
|
|
|
|
2004-09-28 08:28:38 +02:00
|
|
|
RecordNumber temp;
|
2007-03-25 18:09:00 +02:00
|
|
|
temp.bid_decode(&bid_internal);
|
2004-09-28 08:28:38 +02:00
|
|
|
return temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator == (const bid& other) const {
|
2004-09-30 19:45:09 +02:00
|
|
|
// Make sure that compiler packed structure like we wanted
|
|
|
|
fb_assert(sizeof(*this) == 8);
|
|
|
|
|
|
|
|
return bid_quad.bid_quad_high == other.bid_quad.bid_quad_high &&
|
|
|
|
bid_quad.bid_quad_low == other.bid_quad.bid_quad_low;
|
2004-09-28 08:28:38 +02:00
|
|
|
}
|
2004-02-20 07:43:27 +01:00
|
|
|
};
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* Your basic blob block. */
|
|
|
|
|
2008-01-16 09:16:36 +01:00
|
|
|
class blb : public pool_alloc<type_blb>
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
2008-01-16 09:16:36 +01:00
|
|
|
public:
|
|
|
|
blb(MemoryPool& pool, USHORT page_size)
|
|
|
|
: blb_buffer(pool, page_size / sizeof(SLONG)),
|
|
|
|
blb_has_buffer(true)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2004-03-18 06:56:06 +01:00
|
|
|
Attachment* blb_attachment; /* database attachment */
|
2004-03-19 07:14:53 +01:00
|
|
|
jrd_rel* blb_relation; /* Relation, if known */
|
|
|
|
jrd_tra* blb_transaction; /* Parent transaction block */
|
|
|
|
blb* blb_next; /* Next blob in transaction */
|
|
|
|
UCHAR* blb_segment; /* Next segment to be addressed */
|
|
|
|
BlobControl* blb_filter; /* Blob filter control block, if any */
|
|
|
|
bid blb_blob_id; /* Id of materialized blob */
|
|
|
|
vcl* blb_pages; /* Vector of pages */
|
2001-05-23 15:26:42 +02:00
|
|
|
USHORT blb_pointers; /* Max pointer on a page */
|
|
|
|
USHORT blb_level; /* Storage type */
|
|
|
|
USHORT blb_max_segment; /* Longest segment */
|
|
|
|
USHORT blb_flags; /* Interesting stuff (see below) */
|
|
|
|
USHORT blb_clump_size; /* Size of data clump */
|
|
|
|
USHORT blb_space_remaining; /* Data space left */
|
|
|
|
USHORT blb_max_pages; /* Max pages in vector */
|
|
|
|
USHORT blb_fragment_size; /* Residual fragment size */
|
|
|
|
USHORT blb_source_interp; /* source interp (for writing) */
|
|
|
|
USHORT blb_target_interp; /* destination interp (for reading) */
|
|
|
|
SSHORT blb_sub_type; /* Blob's declared sub-type */
|
2007-05-22 04:14:20 +02:00
|
|
|
UCHAR blb_charset; // Blob's charset
|
2006-05-22 00:07:35 +02:00
|
|
|
USHORT blb_pg_space_id; // page space
|
2001-05-23 15:26:42 +02:00
|
|
|
ULONG blb_sequence; /* Blob page sequence */
|
|
|
|
ULONG blb_max_sequence; /* Number of data pages */
|
|
|
|
ULONG blb_count; /* Number of segments */
|
|
|
|
ULONG blb_length; /* Total length of data sans segments */
|
|
|
|
ULONG blb_lead_page; /* First page number */
|
|
|
|
ULONG blb_seek; /* Seek location */
|
2004-01-21 08:18:30 +01:00
|
|
|
ULONG blb_temp_id; // ID of newly created blob in transaction
|
2008-01-16 09:16:36 +01:00
|
|
|
size_t blb_temp_size; // size stored in transaction temp space
|
|
|
|
offset_t blb_temp_offset; // offset in transaction temp space
|
|
|
|
|
|
|
|
private:
|
|
|
|
Firebird::Array<SLONG> blb_buffer; // buffer used in opened blobs - must be longword aligned
|
|
|
|
bool blb_has_buffer;
|
|
|
|
|
|
|
|
public:
|
|
|
|
bool hasBuffer() const
|
|
|
|
{
|
|
|
|
return blb_has_buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
UCHAR* getBuffer()
|
|
|
|
{
|
|
|
|
fb_assert(blb_has_buffer);
|
|
|
|
return (UCHAR*) blb_buffer.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
void freeBuffer()
|
|
|
|
{
|
|
|
|
fb_assert(blb_has_buffer);
|
|
|
|
blb_buffer.free();
|
|
|
|
blb_has_buffer = false;
|
|
|
|
}
|
2001-12-24 03:51:06 +01:00
|
|
|
};
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-04-29 16:51:02 +02:00
|
|
|
const int BLB_temporary = 1; /* Newly created blob */
|
|
|
|
const int BLB_eof = 2; /* This blob is exhausted */
|
|
|
|
const int BLB_stream = 4; /* Stream style blob */
|
|
|
|
const int BLB_closed = 8; /* Temporary blob has been closed */
|
|
|
|
const int BLB_damaged = 16; /* Blob is busted */
|
|
|
|
const int BLB_seek = 32; /* Seek is pending */
|
|
|
|
const int BLB_user_def = 64; /* Blob is user created */
|
|
|
|
const int BLB_large_scan = 128; /* Blob is larger than page buffer cache */
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
/* Blob levels are:
|
|
|
|
|
|
|
|
0 small blob -- blob "record" is actual data
|
|
|
|
1 medium blob -- blob "record" is pointer to pages
|
|
|
|
2 large blob -- blob "record" is pointer to pages of pointers
|
|
|
|
*/
|
|
|
|
|
2004-02-20 07:43:27 +01:00
|
|
|
// mapping blob ids for REPLAY
|
|
|
|
// Useful only with REPLAY_OSRI_API_CALLS_SUBSYSTEM defined.
|
|
|
|
class blb_map : public pool_alloc<type_map>
|
2001-12-24 03:51:06 +01:00
|
|
|
{
|
|
|
|
public:
|
2004-02-20 07:43:27 +01:00
|
|
|
blb_map* map_next;
|
|
|
|
blb* map_old_blob;
|
|
|
|
blb* map_new_blob;
|
2001-12-24 03:51:06 +01:00
|
|
|
};
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-20 15:57:40 +01:00
|
|
|
} //namespace Jrd
|
|
|
|
|
2004-02-20 07:43:27 +01:00
|
|
|
#endif // JRD_BLB_H
|
2003-10-29 11:53:47 +01:00
|
|
|
|