8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 20:03:02 +01:00

Slightly reworked exception handling in the sorter.

This commit is contained in:
dimitr 2009-08-21 10:16:01 +00:00
parent 817d0be282
commit 3d5f752edb

View File

@ -123,9 +123,6 @@ static sort_record* get_merge(merge_control*, sort_context*);
#endif #endif
static ULONG allocate_memory(sort_context*, ULONG, ULONG, bool); static ULONG allocate_memory(sort_context*, ULONG, ULONG, bool);
static void error_memory(sort_context*);
static inline FB_UINT64 find_file_space(sort_context*, ULONG);
static inline void free_file_space(sort_context*, FB_UINT64, ULONG);
static void init(sort_context*); static void init(sort_context*);
static bool local_fini(sort_context*, Attachment*); static bool local_fini(sort_context*, Attachment*);
static void merge_runs(sort_context*, USHORT); static void merge_runs(sort_context*, USHORT);
@ -638,9 +635,12 @@ void SORT_get(thread_db* tdbb,
scb->scb_status_vector = tdbb->tdbb_status_vector; scb->scb_status_vector = tdbb->tdbb_status_vector;
try
{
// If there weren't any runs, everything fit in memory. Just return stuff. // If there weren't any runs, everything fit in memory. Just return stuff.
if (!scb->scb_merge) if (!scb->scb_merge)
{
while (true) while (true)
{ {
if (scb->scb_records == 0) if (scb->scb_records == 0)
@ -652,17 +652,32 @@ void SORT_get(thread_db* tdbb,
if ( (record = *scb->scb_next_pointer++) ) if ( (record = *scb->scb_next_pointer++) )
break; break;
} }
}
else else
{
record = get_merge(scb->scb_merge, scb); record = get_merge(scb->scb_merge, scb);
}
*record_address = (ULONG*) record; *record_address = (ULONG*) record;
if (record) { if (record)
{
diddle_key((UCHAR*) record->sort_record_key, scb, false); diddle_key((UCHAR*) record->sort_record_key, scb, false);
} }
tdbb->bumpStats(RuntimeStatistics::SORT_GETS); tdbb->bumpStats(RuntimeStatistics::SORT_GETS);
} }
catch (const BadAlloc&)
{
Firebird::Arg::Gds(isc_sort_mem_err).raise();
}
catch (const status_exception& ex)
{
Firebird::Arg::Gds status(isc_sort_err);
status.append(Firebird::Arg::StatusVector(ex.value()));
status.raise();
}
}
#endif #endif
@ -701,8 +716,8 @@ sort_context* SORT_init(thread_db* tdbb,
ISC_STATUS* status_vector = tdbb->tdbb_status_vector; ISC_STATUS* status_vector = tdbb->tdbb_status_vector;
sort_context* scb = NULL; sort_context* scb = NULL;
try { try
{
// Allocate and setup a sort context block, including copying the // Allocate and setup a sort context block, including copying the
// key description vector. Round the record length up to the next // key description vector. Round the record length up to the next
// longword, and add a longword to a pointer back to the pointer slot. // longword, and add a longword to a pointer back to the pointer slot.
@ -750,17 +765,19 @@ sort_context* SORT_init(thread_db* tdbb,
scb->scb_size_memory >= MIN_SORT_BUFFER_SIZE; scb->scb_size_memory >= MIN_SORT_BUFFER_SIZE;
scb->scb_size_memory -= SORT_BUFFER_CHUNK_SIZE) scb->scb_size_memory -= SORT_BUFFER_CHUNK_SIZE)
{ {
try { try
{
scb->scb_memory = (SORTP*) scb->scb_pool->allocate(scb->scb_size_memory); scb->scb_memory = (SORTP*) scb->scb_pool->allocate(scb->scb_size_memory);
break; break;
} }
catch (const Firebird::BadAlloc&) { catch (const BadAlloc&)
// not enough memory, let's allocate smaller buffer {} // not enough memory, let's allocate smaller buffer
}
} }
if (scb->scb_size_memory < MIN_SORT_BUFFER_SIZE) if (scb->scb_size_memory < MIN_SORT_BUFFER_SIZE)
Firebird::BadAlloc::raise(); {
BadAlloc::raise();
}
#endif // DEBUG_MERGE #endif // DEBUG_MERGE
scb->scb_end_memory = (SORTP*) ((BLOB_PTR*) scb->scb_memory + scb->scb_size_memory); scb->scb_end_memory = (SORTP*) ((BLOB_PTR*) scb->scb_memory + scb->scb_size_memory);
@ -783,18 +800,21 @@ sort_context* SORT_init(thread_db* tdbb,
att->att_active_sorts = scb; att->att_active_sorts = scb;
scb->scb_attachment = att; scb->scb_attachment = att;
} }
}
catch (const BadAlloc&)
{
delete scb;
Firebird::Arg::Gds(isc_sort_mem_err).raise();
}
catch (const status_exception& ex)
{
delete scb;
Firebird::Arg::Gds status(isc_sort_err);
status.append(Firebird::Arg::StatusVector(ex.value()));
status.raise();
}
return scb; return scb;
}
catch (const Firebird::BadAlloc&)
{
Arg::Gds(isc_sort_mem_err).copyTo(status_vector);
delete scb;
ERR_punt();
}
return NULL;
} }
@ -818,6 +838,8 @@ void SORT_put(thread_db* tdbb, sort_context* scb, ULONG** record_address)
**************************************/ **************************************/
scb->scb_status_vector = tdbb->tdbb_status_vector; scb->scb_status_vector = tdbb->tdbb_status_vector;
try
{
// Find the last record passed in, and zap the keys something comparable // Find the last record passed in, and zap the keys something comparable
// by unsigned longword compares // by unsigned longword compares
@ -873,6 +895,17 @@ void SORT_put(thread_db* tdbb, sort_context* scb, ULONG** record_address)
tdbb->bumpStats(RuntimeStatistics::SORT_PUTS); tdbb->bumpStats(RuntimeStatistics::SORT_PUTS);
} }
catch (const BadAlloc&)
{
Firebird::Arg::Gds(isc_sort_mem_err).raise();
}
catch (const status_exception& ex)
{
Firebird::Arg::Gds status(isc_sort_err);
status.append(Firebird::Arg::StatusVector(ex.value()));
status.raise();
}
}
#ifdef SCROLLABLE_CURSORS #ifdef SCROLLABLE_CURSORS
@ -896,18 +929,10 @@ FB_UINT64 SORT_read_block(
* Read a block of stuff from a scratch file. * Read a block of stuff from a scratch file.
* *
**************************************/ **************************************/
try {
const size_t bytes = tmp_space->read(seek, address, length); const size_t bytes = tmp_space->read(seek, address, length);
fb_assert(bytes == length); fb_assert(bytes == length);
seek += bytes;
}
catch (const Firebird::status_exception& ex)
{
Firebird::stuff_exception(status_vector, ex);
ERR_post(Arg::Gds(isc_sort_err));
}
#ifndef SCROLLABLE_CURSORS #ifndef SCROLLABLE_CURSORS
return seek; return seek + bytes;
#endif #endif
} }
@ -959,8 +984,8 @@ void SORT_sort(thread_db* tdbb, sort_context* scb)
scb->scb_status_vector = tdbb->tdbb_status_vector; scb->scb_status_vector = tdbb->tdbb_status_vector;
try { try
{
if (scb->scb_last_record != (SR*) scb->scb_end_memory) if (scb->scb_last_record != (SR*) scb->scb_end_memory)
{ {
#ifdef SCROLLABLE_CURSORS #ifdef SCROLLABLE_CURSORS
@ -1038,13 +1063,14 @@ void SORT_sort(thread_db* tdbb, sort_context* scb)
if (count > 1) if (count > 1)
{ {
fb_assert(!scb->scb_merge_pool); // shouldn't have a pool fb_assert(!scb->scb_merge_pool); // shouldn't have a pool
try { try
{
scb->scb_merge_pool = scb->scb_merge_pool =
(merge_control*) scb->scb_pool->allocate((count - 1) * sizeof(merge_control)); (merge_control*) scb->scb_pool->allocate((count - 1) * sizeof(merge_control));
merge_pool = scb->scb_merge_pool; merge_pool = scb->scb_merge_pool;
memset(merge_pool, 0, (count - 1) * sizeof(merge_control)); memset(merge_pool, 0, (count - 1) * sizeof(merge_control));
} }
catch (const Firebird::BadAlloc&) catch (const BadAlloc&)
{ {
delete streams; delete streams;
throw; throw;
@ -1123,10 +1149,11 @@ void SORT_sort(thread_db* tdbb, sort_context* scb)
{ {
int mem_size = MIN(allocSize / rec_size, run->run_records) * rec_size; int mem_size = MIN(allocSize / rec_size, run->run_records) * rec_size;
char* mem = NULL; char* mem = NULL;
try { try
{
mem = (char*) scb->scb_pool->allocate(mem_size); mem = (char*) scb->scb_pool->allocate(mem_size);
} }
catch (const Firebird::BadAlloc&) catch (const BadAlloc&)
{ {
mem_size = (mem_size / (2 * rec_size)) * rec_size; mem_size = (mem_size / (2 * rec_size)) * rec_size;
if (!mem_size) if (!mem_size)
@ -1148,10 +1175,16 @@ void SORT_sort(thread_db* tdbb, sort_context* scb)
scb->scb_flags |= scb_sorted; scb->scb_flags |= scb_sorted;
tdbb->bumpStats(RuntimeStatistics::SORTS); tdbb->bumpStats(RuntimeStatistics::SORTS);
} }
catch (const Firebird::BadAlloc&) { catch (const BadAlloc&)
error_memory(scb); {
Firebird::Arg::Gds(isc_sort_mem_err).raise();
}
catch (const status_exception& ex)
{
Firebird::Arg::Gds status(isc_sort_err);
status.append(Firebird::Arg::StatusVector(ex.value()));
status.raise();
} }
} }
@ -1172,18 +1205,9 @@ FB_UINT64 SORT_write_block(ISC_STATUS* status_vector,
* Write a block of stuff to the scratch file. * Write a block of stuff to the scratch file.
* *
**************************************/ **************************************/
try {
const size_t bytes = tmp_space->write(seek, address, length); const size_t bytes = tmp_space->write(seek, address, length);
fb_assert(bytes == length); fb_assert(bytes == length);
seek += bytes; return seek + bytes;
}
catch (const Firebird::status_exception& ex)
{
Firebird::stuff_exception(status_vector, ex);
ERR_post(Arg::Gds(isc_sort_err));
}
return seek;
} }
@ -1539,69 +1563,6 @@ static void diddle_key(UCHAR* record, sort_context* scb, bool direction)
#endif #endif
static void error_memory(sort_context* scb)
{
/**************************************
*
* e r r o r _ m e m o r y
*
**************************************
*
* Functional description
* Report fatal out of memory error.
*
**************************************/
ISC_STATUS* status_vector = scb->scb_status_vector;
fb_assert(status_vector);
Arg::Gds(isc_sort_mem_err).copyTo(status_vector);
ERR_punt();
}
static inline FB_UINT64 find_file_space(sort_context* scb, ULONG size)
{
/**************************************
*
* f i n d _ f i l e _ s p a c e
*
**************************************
*
* Functional description
* Find space of input size in one of the
* open sort files. If a free block is not
* available, allocate space at the end.
*
**************************************/
return scb->scb_space->allocateSpace(size);
}
static inline void free_file_space(sort_context* scb, FB_UINT64 position, ULONG size)
{
/**************************************
*
* f r e e _ f i l e _ s p a c e
*
**************************************
*
* Functional description
* Release a segment of work file.
*
**************************************/
try
{
scb->scb_space->releaseSpace(position, size);
}
catch (const Firebird::BadAlloc&) {
error_memory(scb);
}
}
static sort_record* get_merge(merge_control* merge, sort_context* scb static sort_record* get_merge(merge_control* merge, sort_context* scb
#ifdef SCROLLABLE_CURSORS #ifdef SCROLLABLE_CURSORS
, rse_get_mode mode , rse_get_mode mode
@ -1886,14 +1847,8 @@ static void init(sort_context* scb)
if (scb->scb_size_memory <= MAX_SORT_BUFFER_SIZE && scb->scb_runs && if (scb->scb_size_memory <= MAX_SORT_BUFFER_SIZE && scb->scb_runs &&
scb->scb_runs->run_depth == MAX_MERGE_LEVEL) scb->scb_runs->run_depth == MAX_MERGE_LEVEL)
{ {
void* mem = NULL;
const ULONG mem_size = MAX_SORT_BUFFER_SIZE * RUN_GROUP; const ULONG mem_size = MAX_SORT_BUFFER_SIZE * RUN_GROUP;
try { void* const mem = scb->scb_pool->allocate_nothrow(mem_size);
mem = scb->scb_pool->allocate(mem_size);
}
catch (const Firebird::BadAlloc&) {
// do nothing
}
if (mem) if (mem)
{ {
@ -2246,7 +2201,7 @@ static void merge_runs(sort_context* scb, USHORT n)
CHECK_FILE(scb); CHECK_FILE(scb);
sort_record* q = reinterpret_cast<sort_record*>(temp_run.run_buffer); sort_record* q = reinterpret_cast<sort_record*>(temp_run.run_buffer);
FB_UINT64 seek = temp_run.run_seek = find_file_space(scb, temp_run.run_size); FB_UINT64 seek = temp_run.run_seek = scb->scb_space->allocateSpace(temp_run.run_size);
temp_run.run_records = 0; temp_run.run_records = 0;
CHECK_FILE2(scb, &temp_run); CHECK_FILE2(scb, &temp_run);
@ -2286,7 +2241,7 @@ static void merge_runs(sort_context* scb, USHORT n)
if (seek - temp_run.run_seek < temp_run.run_size) if (seek - temp_run.run_seek < temp_run.run_size)
{ {
free_file_space(scb, seek, temp_run.run_seek + temp_run.run_size - seek); scb->scb_space->releaseSpace(seek, temp_run.run_seek + temp_run.run_size - seek);
temp_run.run_size = seek - temp_run.run_seek; temp_run.run_size = seek - temp_run.run_seek;
} }
@ -2304,11 +2259,11 @@ static void merge_runs(sort_context* scb, USHORT n)
#endif #endif
// Free the sort file space associated with the run // Free the sort file space associated with the run
free_file_space(scb, seek, run->run_size); scb->scb_space->releaseSpace(seek, run->run_size);
if (run->run_mem_size) if (run->run_mem_size)
{ {
free_file_space(scb, run->run_mem_seek, run->run_mem_size); scb->scb_space->releaseSpace(run->run_mem_seek, run->run_mem_size);
run->run_mem_seek = run->run_mem_size = 0; run->run_mem_seek = run->run_mem_size = 0;
} }
@ -2516,7 +2471,7 @@ static ULONG order(sort_context* scb)
sort_record* output = reinterpret_cast<sort_record*>(scb->scb_last_record); sort_record* output = reinterpret_cast<sort_record*>(scb->scb_last_record);
sort_ptr_t* lower_limit = reinterpret_cast<sort_ptr_t*>(output); sort_ptr_t* lower_limit = reinterpret_cast<sort_ptr_t*>(output);
Firebird::HalfStaticArray<ULONG, 1024> record_buffer(*scb->scb_pool); HalfStaticArray<ULONG, 1024> record_buffer(*scb->scb_pool);
SORTP* buffer = record_buffer.getBuffer(scb->scb_longs); SORTP* buffer = record_buffer.getBuffer(scb->scb_longs);
// Length of the key part of the record // Length of the key part of the record
@ -2621,7 +2576,7 @@ static void order_and_save(sort_context* scb)
const ULONG key_length = (scb->scb_longs - SIZEOF_SR_BCKPTR_IN_LONGS) * sizeof(ULONG); const ULONG key_length = (scb->scb_longs - SIZEOF_SR_BCKPTR_IN_LONGS) * sizeof(ULONG);
run->run_size = run->run_records * key_length; run->run_size = run->run_records * key_length;
run->run_seek = find_file_space(scb, run->run_size); run->run_seek = scb->scb_space->allocateSpace(run->run_size);
char* mem = scb->scb_space->inMemory(run->run_seek, run->run_size); char* mem = scb->scb_space->inMemory(run->run_seek, run->run_size);
@ -2668,8 +2623,6 @@ static void put_run(sort_context* scb)
* were sorted. * were sorted.
* *
**************************************/ **************************************/
try {
run_control* run = scb->scb_free_runs; run_control* run = scb->scb_free_runs;
if (run) { if (run) {
@ -2701,17 +2654,13 @@ static void put_run(sort_context* scb)
// written, etc. // written, etc.
run->run_size = run->run_records * (scb->scb_longs - SIZEOF_SR_BCKPTR_IN_LONGS) * sizeof(ULONG); run->run_size = run->run_records * (scb->scb_longs - SIZEOF_SR_BCKPTR_IN_LONGS) * sizeof(ULONG);
run->run_seek = find_file_space(scb, run->run_size); run->run_seek = scb->scb_space->allocateSpace(run->run_size);
SORT_write_block(scb->scb_status_vector, scb->scb_space, SORT_write_block(scb->scb_status_vector, scb->scb_space,
run->run_seek, (UCHAR*) scb->scb_last_record, run->run_size); run->run_seek, (UCHAR*) scb->scb_last_record, run->run_size);
#else #else
order_and_save(scb); order_and_save(scb);
#endif #endif
} }
catch (const Firebird::BadAlloc&) {
error_memory(scb);
}
}
static void sort(sort_context* scb) static void sort(sort_context* scb)
@ -2851,8 +2800,7 @@ static void sort_runs_by_seek(sort_context* scb, int n)
* *
**************************************/ **************************************/
Firebird::SortedArray<RunSort, Firebird::InlineStorage<RunSort, RUN_GROUP>, FB_UINT64, RunSort> SortedArray<RunSort, InlineStorage<RunSort, RUN_GROUP>, FB_UINT64, RunSort> runs(*scb->scb_pool, n);
runs(*scb->scb_pool, n);
run_control* run; run_control* run;
for (run = scb->scb_runs; run && n; run = run->run_next, n--) { for (run = scb->scb_runs; run && n; run = run->run_next, n--) {