mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 21:23:03 +01:00
307 lines
8.7 KiB
C++
307 lines
8.7 KiB
C++
/*
|
|
* PROGRAM: JRD Sort
|
|
* MODULE: sort.h
|
|
* DESCRIPTION: Sort package 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): ______________________________________.
|
|
*/
|
|
|
|
#ifndef JRD_SORT_H
|
|
#define JRD_SORT_H
|
|
|
|
#include "../jrd/common.h"
|
|
#include "../jrd/fil.h"
|
|
|
|
#include "../include/fb_blk.h"
|
|
#include "../jrd/TempSpace.h"
|
|
|
|
namespace Jrd {
|
|
|
|
// Forward declaration
|
|
struct sort_work_file;
|
|
class Attachment;
|
|
struct irsb_sort;
|
|
struct merge_control;
|
|
class SortOwner;
|
|
|
|
// SORTP is used throughout sort.c as a pointer into arrays of
|
|
// longwords(32 bits).
|
|
// Use this definition whenever doing pointer arithmetic, as
|
|
// Firebird variables (eg. scb->scb_longs) are in 32 - bit longwords.
|
|
|
|
typedef ULONG SORTP;
|
|
|
|
// since the first part of the record contains a back_pointer, whose
|
|
// size depends on the platform (ie 16, 32 or 64 bits.).
|
|
// This pointer data_type is defined by platform specific sort_ptr_t.
|
|
|
|
typedef IPTR sort_ptr_t;
|
|
|
|
#define PREV_RUN_RECORD(record) (((SORTP*) record - scb->scb_longs))
|
|
#define NEXT_RUN_RECORD(record) (((SORTP*) record + scb->scb_longs))
|
|
|
|
// a macro to goto the key_id part of a particular record.
|
|
// Pls. refer to the SR structure in sort.h for an explanation of the record structure.
|
|
|
|
#define KEYOF(record) ((SORTP*)(((SR*)record)->sr_sort_record.sort_record_key))
|
|
|
|
// macro to point to the next/previous record for sorting.
|
|
// still using scb_longs as we cannot do record++ *
|
|
//#define PREV_RECORD(record) ((SR*)((SORTP*) record + scb->scb_longs))
|
|
#define NEXT_RECORD(record) ((SR*)((SORTP*) record - scb->scb_longs))
|
|
|
|
// structure containing the key and data part of the sort record,
|
|
// the back pointer is not written to the disk, this is how the records
|
|
// look in the run files.
|
|
|
|
struct sort_record
|
|
{
|
|
ULONG sort_record_key[1];
|
|
/* Sorting key. Mangled by diddle_key to
|
|
compare using ULONG word compares (size
|
|
is rounded upwards if necessary).
|
|
Min length of 1 ULONG, max indeterminate
|
|
For current sort, length is stored as
|
|
scb_key_length.
|
|
Keys are created by BTR_* routines as
|
|
sequences of ULONG - this representation
|
|
cannot be easily changed. */
|
|
|
|
/* sort_record_data is here to explain the sort record.
|
|
To get to the data part of a record add scb->scb_key_length to a pointer
|
|
pointing to the start of the sort_record_key.
|
|
|
|
ULONG sort_record_data [1];
|
|
Data values, not part of key,
|
|
that are pumped through sort.
|
|
Min length of 0, max indeterminate,
|
|
byte data, but starts on ULONG boundary and
|
|
rounded up to ULONG size
|
|
Sizeof sr_data array would be
|
|
(scb_longs - scb_key_length)*sizeof(ULONG) -
|
|
sizeof(sr_bckptr)
|
|
*/
|
|
|
|
};
|
|
|
|
const ULONG MAX_SORT_RECORD = 65535; // bytes
|
|
|
|
// the record struct actually contains the keyids etc, and the back_pointer
|
|
// which points to the sort_record structure.
|
|
typedef struct sr
|
|
{
|
|
sort_record** sr_bckptr; // Pointer back to sort list entry
|
|
union {
|
|
sort_record sr_sort_record;
|
|
FB_UINT64 dummy_alignment_force;
|
|
};
|
|
} SR;
|
|
|
|
// scb_longs includes the size of sr_bckptr.
|
|
|
|
/* The sort memory pool is laid out as follows during sorting:
|
|
|
|
struct sort_memory
|
|
{
|
|
struct sr *records [X1];
|
|
ULONG empty [X2];
|
|
struct sr data [X1];
|
|
};
|
|
|
|
We pack items into sort_memory, inserting the first pointer into
|
|
records [0], and the first data value into data[X1-1]; Continuing
|
|
until we are out of records to sort or memory.
|
|
(eg: X1*(sizeof(struct sr*) + scb->scb_longs) + X2*sizeof(ULONG) == MAX_MEMORY
|
|
*/
|
|
|
|
|
|
// Sort key definition block
|
|
|
|
struct sort_key_def
|
|
{
|
|
UCHAR skd_dtype; // Data type
|
|
UCHAR skd_flags; // Flags
|
|
USHORT skd_length; // Length if string
|
|
USHORT skd_offset; // Offset from beginning
|
|
USHORT skd_vary_offset; // Offset to varying/cstring length
|
|
};
|
|
|
|
|
|
// skd_dtype
|
|
|
|
const int SKD_long = 1;
|
|
const int SKD_ulong = 2;
|
|
const int SKD_short = 3;
|
|
const int SKD_ushort = 4;
|
|
const int SKD_text = 5;
|
|
const int SKD_float = 6;
|
|
const int SKD_double = 7;
|
|
const int SKD_quad = 8;
|
|
const int SKD_timestamp1 = 9; // Timestamp as Float
|
|
const int SKD_bytes = 10;
|
|
const int SKD_d_float = 11;
|
|
const int SKD_varying = 12; // non-international
|
|
const int SKD_cstring = 13; // non-international
|
|
|
|
const int SKD_sql_time = 14;
|
|
const int SKD_sql_date = 15;
|
|
const int SKD_timestamp2 = 16; // Timestamp as Quad
|
|
|
|
const int SKD_int64 = 17;
|
|
|
|
// Historical alias for pre V6 code
|
|
const int SKD_date = SKD_timestamp1;
|
|
|
|
// skd_flags
|
|
|
|
const UCHAR SKD_ascending = 0; // default initializer
|
|
const UCHAR SKD_descending = 1;
|
|
const UCHAR SKD_binary = 2;
|
|
|
|
|
|
// Run/merge common block header
|
|
|
|
struct run_merge_hdr
|
|
{
|
|
SSHORT rmh_type;
|
|
merge_control* rmh_parent;
|
|
};
|
|
|
|
// rmh_type
|
|
|
|
const int RMH_TYPE_RUN = 0;
|
|
const int RMH_TYPE_MRG = 1;
|
|
|
|
|
|
// Run control block
|
|
|
|
struct run_control
|
|
{
|
|
run_merge_hdr run_header;
|
|
run_control* run_next; // Next (actually last) run
|
|
ULONG run_records; // Records (remaining) in run
|
|
USHORT run_depth; // Number of "elementary" runs
|
|
FB_UINT64 run_seek; // Offset in file of run
|
|
FB_UINT64 run_size; // Length of run in work file
|
|
sort_record* run_record; // Next record in run
|
|
SORTP* run_buffer; // Run buffer
|
|
SORTP* run_end_buffer; // End of buffer
|
|
bool run_buff_alloc; // Allocated buffer flag
|
|
bool run_buff_cache; // run buffer is already in cache
|
|
FB_UINT64 run_mem_seek; // position of run's buffer in in-memory part of sort file
|
|
ULONG run_mem_size; // size of run's buffer in in-memory part of sort file
|
|
};
|
|
|
|
// Merge control block
|
|
|
|
struct merge_control
|
|
{
|
|
run_merge_hdr mrg_header;
|
|
sort_record* mrg_record_a;
|
|
run_merge_hdr* mrg_stream_a;
|
|
sort_record* mrg_record_b;
|
|
run_merge_hdr* mrg_stream_b;
|
|
};
|
|
|
|
|
|
// Sort Context Block
|
|
// Context or Control???
|
|
|
|
// Used by SORT_init
|
|
typedef bool (*FPTR_REJECT_DUP_CALLBACK)(const UCHAR*, const UCHAR*, void*);
|
|
|
|
struct sort_context
|
|
{
|
|
Database* scb_dbb; // Database
|
|
SortOwner* scb_owner; // Sort owner
|
|
SORTP* scb_memory; // ALLOC: Memory for sort
|
|
SORTP* scb_end_memory; // End of memory
|
|
ULONG scb_size_memory; // Bytes allocated
|
|
SR* scb_last_record; // Address of last record
|
|
sort_record** scb_first_pointer; // Memory for sort
|
|
sort_record** scb_next_pointer; // Address for next pointer
|
|
//USHORT scb_length; // Record length. Unused.
|
|
USHORT scb_longs; // Length of record in longwords
|
|
ULONG scb_keys; // Number of keys
|
|
ULONG scb_key_length; // Key length
|
|
ULONG scb_unique_length; // Unique key length, used when duplicates eliminated
|
|
ULONG scb_records; // Number of records
|
|
//FB_UINT64 scb_max_records; // Maximum number of records to store. Unused.
|
|
TempSpace* scb_space; // temporary space for scratch file
|
|
run_control* scb_runs; // ALLOC: Run on scratch file, if any
|
|
merge_control* scb_merge; // Top level merge block
|
|
run_control* scb_free_runs; // ALLOC: Currently unused run blocks
|
|
SORTP* scb_merge_space; // ALLOC: memory space to do merging
|
|
ULONG scb_flags; // see flag bits below
|
|
FPTR_REJECT_DUP_CALLBACK scb_dup_callback; // Duplicate handling callback
|
|
void* scb_dup_callback_arg; // Duplicate handling callback arg
|
|
merge_control* scb_merge_pool; // ALLOC: pool of merge_control blocks
|
|
sort_key_def scb_description[1];
|
|
};
|
|
|
|
// flags as set in scb_flags
|
|
|
|
const int scb_initialized = 1;
|
|
const int scb_sorted = 2; // stream has been sorted
|
|
|
|
#define SCB_LEN(n_k) (sizeof (sort_context) + (SLONG)(n_k) * sizeof (sort_key_def))
|
|
|
|
class SortOwner
|
|
{
|
|
public:
|
|
explicit SortOwner(MemoryPool& p)
|
|
: pool(p), sorts(p)
|
|
{}
|
|
|
|
~SortOwner();
|
|
|
|
void linkSort(sort_context* scb)
|
|
{
|
|
fb_assert(scb);
|
|
|
|
if (!sorts.exist(scb))
|
|
{
|
|
sorts.add(scb);
|
|
}
|
|
}
|
|
|
|
void unlinkSort(sort_context* scb)
|
|
{
|
|
fb_assert(scb);
|
|
|
|
size_t pos;
|
|
if (sorts.find(scb, pos))
|
|
{
|
|
sorts.remove(pos);
|
|
}
|
|
}
|
|
|
|
MemoryPool& getPool() const
|
|
{
|
|
return pool;
|
|
}
|
|
|
|
private:
|
|
MemoryPool& pool;
|
|
Firebird::SortedArray<sort_context*> sorts;
|
|
};
|
|
|
|
} //namespace Jrd
|
|
|
|
#endif // JRD_SORT_H
|