dpm.epp (Firebird-3.0.2.32703-0.tar.bz2) | : | dpm.epp (Firebird-3.0.4.33054-0.tar.bz2) | ||
---|---|---|---|---|
skipping to change at line 150 | skipping to change at line 150 | |||
* Functional description | * Functional description | |||
* Backout a record where the record and previous version are on | * Backout a record where the record and previous version are on | |||
* the same page. | * the same page. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
CHECK_DBB(dbb); | CHECK_DBB(dbb); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = rpb->rpb_relation; | ||||
VIO_trace(DEBUG_WRITES, | VIO_trace(DEBUG_WRITES, | |||
"DPM_backout (record_param %" QUADFORMAT"d)\n", rpb->rpb_number.g | "DPM_backout (rel_id %u, record_param %" QUADFORMAT"d)\n", | |||
etValue()); | relation->rel_id, rpb->rpb_number.getValue()); | |||
VIO_trace(DEBUG_WRITES_INFO, | VIO_trace(DEBUG_WRITES_INFO, | |||
" record %" ULONGFORMAT":%d transaction %" ULONGFORMAT" back %" | " record %" ULONGFORMAT":%d transaction %" ULONGFORMAT" back %" | |||
ULONGFORMAT":%d fragment %" ULONGFORMAT":%d flags %d\n", | ULONGFORMAT":%d fragment %" ULONGFORMAT":%d flags %d\n", | |||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, | rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, | |||
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, | rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, | |||
rpb->rpb_f_line, rpb->rpb_flags); | rpb->rpb_f_line, rpb->rpb_flags); | |||
#endif | #endif | |||
CCH_MARK(tdbb, &rpb->getWindow(tdbb)); | CCH_MARK(tdbb, &rpb->getWindow(tdbb)); | |||
skipping to change at line 231 | skipping to change at line 233 | |||
* | * | |||
* D P M _ c a r d i n a l i t y | * D P M _ c a r d i n a l i t y | |||
* | * | |||
************************************** | ************************************** | |||
* | * | |||
* Functional description | * Functional description | |||
* Estimate cardinality for the given relation. | * Estimate cardinality for the given relation. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* const dbb = tdbb->getDatabase(); | |||
// Estimated number of total records for this relation, | ||||
// we assume that the records are compressed to 50% | ||||
// Every record has also a header and a jump section (13 + 4) | ||||
USHORT minRecordSize = static_cast<USHORT>(sizeof(Ods::data_page::dpg_rep | ||||
eat) + RHD_SIZE); | ||||
if (!(dbb->dbb_flags & DBB_no_reserve)) { | ||||
minRecordSize += RHDF_SIZE; | ||||
} | ||||
// Get the number of data-pages for this relation | // Get the number of data pages for this relation | |||
const ULONG dataPages = DPM_data_pages(tdbb, relation); | const ULONG dataPages = DPM_data_pages(tdbb, relation); | |||
// AB: If we have only 1 data-page then the cardinality calculation | // Calculate record count and total compressed record length | |||
// is to worse to be useful, therefore rely on the record count | // on the first data page | |||
// from the data-page. | ||||
if (dataPages == 1) | ULONG recordCount = 0, recordLength = 0; | |||
const RelationPages* const relPages = relation->getPages(tdbb); | ||||
const vcl* const vector = relPages->rel_pages; | ||||
if (vector) | ||||
{ | { | |||
RelationPages* relPages = relation->getPages(tdbb); | WIN window(relPages->rel_pg_space_id, (*vector)[0]); | |||
vcl* vector = relPages->rel_pages; | ||||
if (vector) | Ods::pointer_page* ppage = | |||
{ | (Ods::pointer_page*) CCH_FETCH(tdbb, &window, LCK_read, p | |||
WIN window(relPages->rel_pg_space_id, (*vector)[0]); | ag_pointer); | |||
Ods::pointer_page* ppage = | if (!ppage) | |||
(Ods::pointer_page*) CCH_FETCH(tdbb, &window, LCK | { | |||
_read, pag_pointer); | BUGCHECK(243); | |||
USHORT recordCount = 0; | // msg 243 missing pointer page in DPM_data_pages | |||
const ULONG* page = ppage->ppg_page; | } | |||
const ULONG* page = ppage->ppg_page; | ||||
const ULONG* const end_page = page + ppage->ppg_count; | ||||
while (page < end_page) | ||||
{ | ||||
if (*page) | if (*page) | |||
{ | { | |||
Ods::data_page* dpage = | Ods::data_page* dpage = | |||
(Ods::data_page*) CCH_HANDOFF(tdbb, &wind ow, *page, LCK_read, pag_data); | (Ods::data_page*) CCH_HANDOFF(tdbb, &wind ow, *page, LCK_read, pag_data); | |||
recordCount = dpage->dpg_count; | ||||
const data_page::dpg_repeat* index = dpage->dpg_r | ||||
pt; | ||||
const data_page::dpg_repeat* const end = index + | ||||
dpage->dpg_count; | ||||
for (; index < end; index++) | ||||
{ | ||||
if (index->dpg_offset) | ||||
{ | ||||
recordCount++; | ||||
recordLength += index->dpg_length | ||||
- RHD_SIZE; | ||||
} | ||||
} | ||||
break; | ||||
} | } | |||
CCH_RELEASE(tdbb, &window); | page++; | |||
return (double) recordCount; | ||||
} | } | |||
CCH_RELEASE(tdbb, &window); | ||||
} | } | |||
// AB: If we have only 1 data-page then the cardinality calculation | ||||
// is too imprecise to be useful, therefore rely on the record count | ||||
// from the data-page. | ||||
if (dataPages == 1) | ||||
return (double) recordCount; | ||||
// Estimate total number of records for this relation | ||||
if (!format) | if (!format) | |||
format = relation->rel_current_format; | format = MET_current(tdbb, relation); | |||
static const double DEFAULT_COMPRESSION_RATIO = 0.5; | ||||
const ULONG compressedSize = | ||||
recordCount ? recordLength / recordCount : | ||||
format->fmt_length * DEFAULT_COMPRESSION_RATIO; | ||||
const ULONG recordSize = sizeof(Ods::data_page::dpg_repeat) + | ||||
ROUNDUP(compressedSize + RHD_SIZE, ODS_ALIGNMENT) + | ||||
((dbb->dbb_flags & DBB_no_reserve) ? 0 : SPACE_FUDGE); | ||||
return (double) dataPages * (dbb->dbb_page_size - DPG_SIZE) / | return (double) dataPages * (dbb->dbb_page_size - DPG_SIZE) / recordSize; | |||
(minRecordSize + (format->fmt_length * 0.5)); | ||||
} | } | |||
bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb) | bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb) | |||
{ | { | |||
/************************************** | /************************************** | |||
* | * | |||
* D P M _ c h a i n | * D P M _ c h a i n | |||
* | * | |||
************************************** | ************************************** | |||
* | * | |||
skipping to change at line 307 | skipping to change at line 339 | |||
* that record number. The caller has to check the results to | * that record number. The caller has to check the results to | |||
* see what failed if false is returned. At the moment, there is | * see what failed if false is returned. At the moment, there is | |||
* only one caller, VIO_erase. | * only one caller, VIO_erase. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
CHECK_DBB(dbb); | CHECK_DBB(dbb); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = org_rpb->rpb_relation; | ||||
VIO_trace(DEBUG_WRITES, | VIO_trace(DEBUG_WRITES, | |||
"DPM_chain (org_rpb %" QUADFORMAT"d, new_rpb %" | "DPM_chain (rel_id %u, org_rpb %" QUADFORMAT"d, new_rpb %" QUADFO | |||
QUADFORMAT"d)\n", org_rpb->rpb_number.getValue(), | RMAT"d)\n", | |||
relation->rel_id, org_rpb->rpb_number.getValue(), | ||||
new_rpb ? new_rpb->rpb_number.getValue() : 0); | new_rpb ? new_rpb->rpb_number.getValue() : 0); | |||
VIO_trace(DEBUG_WRITES_INFO, | VIO_trace(DEBUG_WRITES_INFO, | |||
" org record %" ULONGFORMAT":%d transaction %" ULONGFORMAT | " org record %" ULONGFORMAT":%d transaction %" ULONGFORMAT | |||
" back %" ULONGFORMAT":%d fragment %" ULONGFORMAT":%d flags %d\n" , | " back %" ULONGFORMAT":%d fragment %" ULONGFORMAT":%d flags %d\n" , | |||
org_rpb->rpb_page, org_rpb->rpb_line, org_rpb->rpb_transaction_nr , | org_rpb->rpb_page, org_rpb->rpb_line, org_rpb->rpb_transaction_nr , | |||
org_rpb->rpb_b_page, org_rpb->rpb_b_line, org_rpb->rpb_f_page, | org_rpb->rpb_b_page, org_rpb->rpb_b_line, org_rpb->rpb_f_page, | |||
org_rpb->rpb_f_line, org_rpb->rpb_flags); | org_rpb->rpb_f_line, org_rpb->rpb_flags); | |||
if (new_rpb) | if (new_rpb) | |||
skipping to change at line 477 | skipping to change at line 510 | |||
header->rhd_b_page = new_rpb->rpb_b_page; | header->rhd_b_page = new_rpb->rpb_b_page; | |||
header->rhd_b_line = new_rpb->rpb_b_line; | header->rhd_b_line = new_rpb->rpb_b_line; | |||
UCHAR* const data = (UCHAR*) header + header_size; | UCHAR* const data = (UCHAR*) header + header_size; | |||
dcc.pack(new_rpb->rpb_address, data); | dcc.pack(new_rpb->rpb_address, data); | |||
if (fill) | if (fill) | |||
memset(data + size, 0, fill); | memset(data + size, 0, fill); | |||
#ifdef VIO_DEBUG | ||||
VIO_trace(DEBUG_WRITES_INFO, | ||||
" new record %" ULONGFORMAT":%d transaction %" ULONGFORMAT | ||||
" back %" ULONGFORMAT":%d fragment %" ULONGFORMAT":%d flags %d\n" | ||||
, | ||||
new_rpb->rpb_page, new_rpb->rpb_line, new_rpb->rpb_transaction_nr | ||||
, | ||||
new_rpb->rpb_b_page, new_rpb->rpb_b_line, new_rpb->rpb_f_page, | ||||
new_rpb->rpb_f_line, new_rpb->rpb_flags); | ||||
#endif | ||||
if (page->dpg_header.pag_flags & dpg_swept) | if (page->dpg_header.pag_flags & dpg_swept) | |||
{ | { | |||
page->dpg_header.pag_flags &= ~dpg_swept; | page->dpg_header.pag_flags &= ~dpg_swept; | |||
mark_full(tdbb, org_rpb); | mark_full(tdbb, org_rpb); | |||
} | } | |||
else | else | |||
CCH_RELEASE(tdbb, &org_rpb->getWindow(tdbb)); | CCH_RELEASE(tdbb, &org_rpb->getWindow(tdbb)); | |||
return true; | return true; | |||
} | } | |||
skipping to change at line 614 | skipping to change at line 656 | |||
while (page < end_page) | while (page < end_page) | |||
{ | { | |||
if (*page++) | if (*page++) | |||
pages++; | pages++; | |||
} | } | |||
if (ppage->ppg_header.pag_flags & ppg_eof) | if (ppage->ppg_header.pag_flags & ppg_eof) | |||
break; | break; | |||
CCH_RELEASE(tdbb, &window); | CCH_RELEASE(tdbb, &window); | |||
tdbb->checkCancelState(true); | ||||
} | } | |||
CCH_RELEASE(tdbb, &window); | CCH_RELEASE(tdbb, &window); | |||
relPages->rel_data_pages = pages; | relPages->rel_data_pages = pages; | |||
} | } | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
VIO_trace(DEBUG_TRACE_ALL, | VIO_trace(DEBUG_TRACE_ALL, | |||
" returned pages: %" ULONGFORMAT"\n", pages); | " returned pages: %" ULONGFORMAT"\n", pages); | |||
#endif | #endif | |||
skipping to change at line 649 | skipping to change at line 693 | |||
* record header into the record parameter block before deleting | * record header into the record parameter block before deleting | |||
* it. If the record goes empty, release the page. Release the | * it. If the record goes empty, release the page. Release the | |||
* page when we're done. | * page when we're done. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
CHECK_DBB(dbb); | CHECK_DBB(dbb); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = rpb->rpb_relation; | ||||
VIO_trace(DEBUG_WRITES, | VIO_trace(DEBUG_WRITES, | |||
"DPM_delete (record_param %" QUADFORMAT", prior_page %" ULONGFORM AT")\n", | "DPM_delete (record_param %" QUADFORMAT", prior_page %" ULONGFORM AT")\n", | |||
rpb->rpb_number.getValue(), prior_page); | rpb->rpb_number.getValue(), prior_page); | |||
VIO_trace(DEBUG_WRITES_INFO, | VIO_trace(DEBUG_WRITES_INFO, | |||
" record %" ULONGFORMAT":%d transaction %" ULONGFORMAT" back %" | " record %" ULONGFORMAT":%d transaction %" ULONGFORMAT" back %" | |||
ULONGFORMAT":%d fragment %" ULONGFORMAT":%d flags %d\n", | ULONGFORMAT":%d fragment %" ULONGFORMAT":%d flags %d\n", | |||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, | rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, | |||
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, | rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, | |||
rpb->rpb_f_line, rpb->rpb_flags); | rpb->rpb_f_line, rpb->rpb_flags); | |||
skipping to change at line 899 | skipping to change at line 944 | |||
// Make sure that the pointer page is written after the data page. | // Make sure that the pointer page is written after the data page. | |||
// The resulting 'must-be-written-after' graph is: | // The resulting 'must-be-written-after' graph is: | |||
// pip --> pp --> deallocated page --> prior_page | // pip --> pp --> deallocated page --> prior_page | |||
for (i = 0; i < pages.getCount(); i++, s++) | for (i = 0; i < pages.getCount(); i++, s++) | |||
CCH_precedence(tdbb, &pwindow, pages[i]); | CCH_precedence(tdbb, &pwindow, pages[i]); | |||
CCH_MARK(tdbb, &pwindow); | CCH_MARK(tdbb, &pwindow); | |||
const ULONG dpSequence = ppage->ppg_sequence * dbb->dbb_dp_per_pp; | ||||
s = extent ? firstSlot : slot; | s = extent ? firstSlot : slot; | |||
for (i = 0; i < pages.getCount(); i++, s++) | for (i = 0; i < pages.getCount(); i++, s++) | |||
{ | ||||
ppage->ppg_page[s] = 0; | ppage->ppg_page[s] = 0; | |||
if (relPages->rel_last_free_pri_dp == pages[i]) | ||||
relPages->rel_last_free_pri_dp = 0; | ||||
relPages->setDPNumber(dpSequence + s, 0); | ||||
} | ||||
if (relPages->rel_data_pages) | if (relPages->rel_data_pages) | |||
relPages->rel_data_pages -= pages.getCount(); | relPages->rel_data_pages -= pages.getCount(); | |||
const ULONG* ptr; | const ULONG* ptr; | |||
for (ptr = &ppage->ppg_page[ppage->ppg_count]; ptr > ppage->ppg_page; --p tr) | for (ptr = &ppage->ppg_page[ppage->ppg_count]; ptr > ppage->ppg_page; --p tr) | |||
{ | { | |||
if (ptr[-1]) | if (ptr[-1]) | |||
break; | break; | |||
} | } | |||
skipping to change at line 975 | skipping to change at line 1028 | |||
Jrd::RelationPages* relPages) | Jrd::RelationPages* relPages) | |||
{ | { | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
WIN window(relPages->rel_pg_space_id, -1), data_window(relPages->rel_pg_s pace_id, -1); | WIN window(relPages->rel_pg_space_id, -1), data_window(relPages->rel_pg_s pace_id, -1); | |||
window.win_flags = data_window.win_flags = WIN_large_scan; | window.win_flags = data_window.win_flags = WIN_large_scan; | |||
window.win_scans = data_window.win_scans = 1; | window.win_scans = data_window.win_scans = 1; | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
VIO_trace(DEBUG_TRACE_ALL, | VIO_trace(DEBUG_TRACE_ALL, | |||
"DPM_delete_relation (relation %d)\n", relation->rel_id); | "DPM_delete_relation_pages (relation %d, instance %" SQUADFORMAT" | |||
)\n", | ||||
relation->rel_id, relPages->rel_instance_id); | ||||
#endif | #endif | |||
// Delete all data and pointer pages | // Delete all data and pointer pages | |||
SortedArray<ULONG, InlineStorage<ULONG, 256> > pages(*relation->rel_pool) ; | SortedArray<ULONG, InlineStorage<ULONG, 256> > pages(*relation->rel_pool) ; | |||
for (ULONG sequence = 0; true; sequence++) | for (ULONG sequence = 0; true; sequence++) | |||
{ | { | |||
const pointer_page* ppage = | const pointer_page* ppage = | |||
get_pointer_page(tdbb, relation, relPages, &window, seque nce, LCK_read); | get_pointer_page(tdbb, relation, relPages, &window, seque nce, LCK_read); | |||
skipping to change at line 1067 | skipping to change at line 1121 | |||
* Fetch a particular record fragment from page and line numbers. | * Fetch a particular record fragment from page and line numbers. | |||
* Get various header stuff, but don't change the record number. | * Get various header stuff, but don't change the record number. | |||
* | * | |||
* return: true if the fragment is returned. | * return: true if the fragment is returned. | |||
* false if the fragment is not found. | * false if the fragment is not found. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = rpb->rpb_relation; | ||||
VIO_trace(DEBUG_READS, | VIO_trace(DEBUG_READS, | |||
"DPM_fetch (record_param %" QUADFORMAT"d, lock %d)\n", | "DPM_fetch (rel_id %u, record_param %" QUADFORMAT"d, lock %d)\n", | |||
rpb->rpb_number.getValue(), lock); | relation->rel_id, rpb->rpb_number.getValue(), lock); | |||
VIO_trace(DEBUG_READS_INFO, | VIO_trace(DEBUG_READS_INFO, | |||
" record %" ULONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line); | " record %" ULONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line); | |||
#endif | #endif | |||
const RecordNumber number = rpb->rpb_number; | const RecordNumber number = rpb->rpb_number; | |||
RelationPages* relPages = rpb->rpb_relation->getPages(tdbb); | RelationPages* relPages = rpb->rpb_relation->getPages(tdbb); | |||
rpb->getWindow(tdbb).win_page = PageNumber(relPages->rel_pg_space_id, rpb ->rpb_page); | rpb->getWindow(tdbb).win_page = PageNumber(relPages->rel_pg_space_id, rpb ->rpb_page); | |||
CCH_FETCH(tdbb, &rpb->getWindow(tdbb), lock, pag_data); | CCH_FETCH(tdbb, &rpb->getWindow(tdbb), lock, pag_data); | |||
skipping to change at line 1128 | skipping to change at line 1183 | |||
* true: fetch back was successful. | * true: fetch back was successful. | |||
* false: unsuccessful (only possible is latch_wait <> 1), | * false: unsuccessful (only possible is latch_wait <> 1), | |||
* The latch timed out. | * The latch timed out. | |||
* The latch on the fetched page is downgraded to shared. | * The latch on the fetched page is downgraded to shared. | |||
* The fetched page is unmarked. | * The fetched page is unmarked. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = rpb->rpb_relation; | ||||
VIO_trace(DEBUG_READS, | VIO_trace(DEBUG_READS, | |||
"DPM_fetch_back (record_param %" QUADFORMAT"d, lock %d)\n", | "DPM_fetch_back (rel_id %u, record_param %" QUADFORMAT"d, lock %d | |||
rpb->rpb_number.getValue(), lock); | )\n", | |||
relation->rel_id, rpb->rpb_number.getValue(), lock); | ||||
VIO_trace(DEBUG_READS_INFO, | VIO_trace(DEBUG_READS_INFO, | |||
" record %" ULONGFORMAT":%d transaction %" ULONGFORMAT | " record %" ULONGFORMAT":%d transaction %" ULONGFORMAT | |||
" back %" ULONGFORMAT":%d\n", | " back %" ULONGFORMAT":%d\n", | |||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, | rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, | |||
rpb->rpb_b_page, rpb->rpb_b_line); | rpb->rpb_b_page, rpb->rpb_b_line); | |||
#endif | #endif | |||
// Possibly allow a latch timeout to occur. Return error if that is the case. | // Possibly allow a latch timeout to occur. Return error if that is the case. | |||
skipping to change at line 1190 | skipping to change at line 1246 | |||
* | * | |||
************************************** | ************************************** | |||
* | * | |||
* Functional description | * Functional description | |||
* Chase a fragment pointer with a handoff. | * Chase a fragment pointer with a handoff. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = rpb->rpb_relation; | ||||
VIO_trace(DEBUG_READS, | VIO_trace(DEBUG_READS, | |||
"DPM_fetch_fragment (record_param %" QUADFORMAT"d, lock %d)\n", | "DPM_fetch_fragment (rel_id %u, record_param %" QUADFORMAT"d, loc | |||
rpb->rpb_number.getValue(), lock); | k %d)\n", | |||
relation->rel_id, rpb->rpb_number.getValue(), lock); | ||||
VIO_trace(DEBUG_READS_INFO, | VIO_trace(DEBUG_READS_INFO, | |||
" record %" ULONGFORMAT":%d transaction %" ULONGFORMAT | " record %" ULONGFORMAT":%d transaction %" ULONGFORMAT | |||
" back %" ULONGFORMAT":%d\n", | " back %" ULONGFORMAT":%d\n", | |||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, | rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, | |||
rpb->rpb_b_page, rpb->rpb_b_line); | rpb->rpb_b_page, rpb->rpb_b_line); | |||
#endif | #endif | |||
const RecordNumber number = rpb->rpb_number; | const RecordNumber number = rpb->rpb_number; | |||
rpb->rpb_page = rpb->rpb_f_page; | rpb->rpb_page = rpb->rpb_f_page; | |||
skipping to change at line 1302 | skipping to change at line 1359 | |||
const SSHORT lock_mode = dbb->readOnly() ? LCK_read : LCK_write; | const SSHORT lock_mode = dbb->readOnly() ? LCK_read : LCK_write; | |||
generator_page* const page = (generator_page*) CCH_FETCH(tdbb, &window, l ock_mode, pag_ids); | generator_page* const page = (generator_page*) CCH_FETCH(tdbb, &window, l ock_mode, pag_ids); | |||
/* If we are in ODS >= 10, then we have a pointer to an int64 value in t he | /* If we are in ODS >= 10, then we have a pointer to an int64 value in t he | |||
* generator page: if earlier than 10, it's a pointer to a long value. | * generator page: if earlier than 10, it's a pointer to a long value. | |||
* Pick up the right kind of pointer, based on the ODS version. | * Pick up the right kind of pointer, based on the ODS version. | |||
* The conditions were commented out 1999-05-14 by ChrisJ, because we | * The conditions were commented out 1999-05-14 by ChrisJ, because we | |||
* decided that the V6 engine would only access an ODS-10 database. | * decided that the V6 engine would only access an ODS-10 database. | |||
* (and uncommented 2000-05-05, also by ChrisJ, when minds changed.) | * (and uncommented 2000-05-05, also by ChrisJ, when minds changed.) | |||
* | ||||
* ODS12.1 - take into account ODS 12.0 which may have wrong offset | ||||
(see CORE-5791) | ||||
*/ | */ | |||
SINT64* const ptr = ((SINT64*) (page->gpg_values)) + offset; | SINT64* ptr = Ods::getGpgValues(page, dbb->dbb_implementation, dbb->dbb_m | |||
inor_version); | ||||
fb_assert(ptr); | ||||
ptr += offset; | ||||
if (val || initialize) | if (val || initialize) | |||
{ | { | |||
if (dbb->readOnly()) | if (dbb->readOnly()) | |||
{ | { | |||
CCH_RELEASE(tdbb, &window); | CCH_RELEASE(tdbb, &window); | |||
ERR_post(Arg::Gds(isc_read_only_database)); | ERR_post(Arg::Gds(isc_read_only_database)); | |||
} | } | |||
CCH_MARK_SYSTEM(tdbb, &window); | CCH_MARK_SYSTEM(tdbb, &window); | |||
skipping to change at line 1349 | skipping to change at line 1410 | |||
* Functional description | * Functional description | |||
* Get a specific record in a relation. If it doesn't exit, | * Get a specific record in a relation. If it doesn't exit, | |||
* just return false. | * just return false. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
CHECK_DBB(dbb); | CHECK_DBB(dbb); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = rpb->rpb_relation; | ||||
VIO_trace(DEBUG_READS, | VIO_trace(DEBUG_READS, | |||
"DPM_get (record_param %" QUADFORMAT"d, lock type %d)\n", | "DPM_get (rel_id %u, record_param %" QUADFORMAT"d, lock type %d)\ | |||
rpb->rpb_number.getValue(), lock_type); | n", | |||
relation->rel_id, rpb->rpb_number.getValue(), lock_type); | ||||
#endif | #endif | |||
WIN* window = &rpb->getWindow(tdbb); | WIN* window = &rpb->getWindow(tdbb); | |||
rpb->rpb_prior = NULL; | rpb->rpb_prior = NULL; | |||
// Find starting point | // Find starting point | |||
ULONG pp_sequence; | ULONG pp_sequence; | |||
USHORT slot, line; | USHORT slot, line; | |||
rpb->rpb_number.decompose(dbb->dbb_max_records, dbb->dbb_dp_per_pp, line, slot, pp_sequence); | rpb->rpb_number.decompose(dbb->dbb_max_records, dbb->dbb_dp_per_pp, line, slot, pp_sequence); | |||
skipping to change at line 1451 | skipping to change at line 1513 | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
CHECK_DBB(dbb); | CHECK_DBB(dbb); | |||
record_param rpb; | record_param rpb; | |||
rpb.rpb_relation = blob->blb_relation; | rpb.rpb_relation = blob->blb_relation; | |||
rpb.getWindow(tdbb).win_flags = WIN_secondary; | rpb.getWindow(tdbb).win_flags = WIN_secondary; | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = blob->blb_relation; | ||||
VIO_trace(DEBUG_READS, | VIO_trace(DEBUG_READS, | |||
"DPM_get_blob (blob, record_number %" QUADFORMAT | "DPM_get_blob (rel_id %u, blob, record_number %" QUADFORMAT | |||
"d, delete_flag %d, prior_page %" ULONGFORMAT")\n", | "d, delete_flag %d, prior_page %" ULONGFORMAT")\n", | |||
record_number.getValue(), (int) delete_flag, prior_page); | relation->rel_id, record_number.getValue(), (int)delete_flag, pri or_page); | |||
#endif | #endif | |||
// Find starting point | // Find starting point | |||
ULONG pp_sequence; | ULONG pp_sequence; | |||
USHORT slot, line; | USHORT slot, line; | |||
record_number.decompose(dbb->dbb_max_records, dbb->dbb_dp_per_pp, line, s lot, pp_sequence); | record_number.decompose(dbb->dbb_max_records, dbb->dbb_dp_per_pp, line, s lot, pp_sequence); | |||
// Find the next pointer page, data page, and record. If the page or | // Find the next pointer page, data page, and record. If the page or | |||
// record doesn't exist, or the record isn't a blob, give up and | // record doesn't exist, or the record isn't a blob, give up and | |||
skipping to change at line 1569 | skipping to change at line 1632 | |||
* | * | |||
* Functional description | * Functional description | |||
* Get the next record in a stream. | * Get the next record in a stream. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
CHECK_DBB(dbb); | CHECK_DBB(dbb); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = rpb->rpb_relation; | ||||
VIO_trace(DEBUG_READS, | VIO_trace(DEBUG_READS, | |||
"DPM_next (record_param %" QUADFORMAT"d)\n", rpb->rpb_number.getV | "DPM_next (rel_id %u, record_param %" QUADFORMAT"d)\n", | |||
alue()); | relation->rel_id, rpb->rpb_number.getValue()); | |||
#endif | #endif | |||
WIN* window = &rpb->getWindow(tdbb); | WIN* window = &rpb->getWindow(tdbb); | |||
RelationPages* relPages = rpb->rpb_relation->getPages(tdbb); | RelationPages* relPages = rpb->rpb_relation->getPages(tdbb); | |||
if (window->win_flags & WIN_large_scan) | if (window->win_flags & WIN_large_scan) | |||
{ | { | |||
// Try to account for staggered execution of large sequential sca ns. | // Try to account for staggered execution of large sequential sca ns. | |||
window->win_scans = rpb->rpb_relation->rel_scan_count - rpb->rpb_ org_scans; | window->win_scans = rpb->rpb_relation->rel_scan_count - rpb->rpb_ org_scans; | |||
skipping to change at line 1597 | skipping to change at line 1662 | |||
// Find starting point | // Find starting point | |||
rpb->rpb_number.increment(); | rpb->rpb_number.increment(); | |||
USHORT slot, line; | USHORT slot, line; | |||
ULONG pp_sequence; | ULONG pp_sequence; | |||
rpb->rpb_number.decompose(dbb->dbb_max_records, dbb->dbb_dp_per_pp, line, slot, pp_sequence); | rpb->rpb_number.decompose(dbb->dbb_max_records, dbb->dbb_dp_per_pp, line, slot, pp_sequence); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
VIO_trace(DEBUG_READS_INFO, | VIO_trace(DEBUG_READS_INFO, | |||
" pointer, slot, and line %d:%d%d\n", pp_sequence, slot, line ); | " sequence, slot, and line %" ULONGFORMAT" %" ULONGFORMAT":%d\ n", pp_sequence, slot, line); | |||
#endif | #endif | |||
// If I'm a sweeper I don't need to look at swept pages. Also I should | // If I'm a sweeper I don't need to look at swept pages. Also I should | |||
// check processed pages if they were swept. | // check processed pages if they were swept. | |||
const bool sweeper = (rpb->rpb_stream_flags & RPB_s_sweeper); | const bool sweeper = (rpb->rpb_stream_flags & RPB_s_sweeper); | |||
jrd_tra* transaction = tdbb->getTransaction(); | jrd_tra* transaction = tdbb->getTransaction(); | |||
const TraNumber oldest = transaction ? transaction->tra_oldest : 0; | const TraNumber oldest = transaction ? transaction->tra_oldest : 0; | |||
if (sweeper && (pp_sequence || slot) && !line) | if (sweeper && (pp_sequence || slot) && !line) | |||
skipping to change at line 1782 | skipping to change at line 1847 | |||
slot = 0; | slot = 0; | |||
line = 0; | line = 0; | |||
if (window->win_flags & WIN_large_scan) | if (window->win_flags & WIN_large_scan) | |||
CCH_RELEASE_TAIL(tdbb, window); | CCH_RELEASE_TAIL(tdbb, window); | |||
else | else | |||
CCH_RELEASE(tdbb, window); | CCH_RELEASE(tdbb, window); | |||
if (flags & ppg_eof || onepage) | if (flags & ppg_eof || onepage) | |||
return false; | return false; | |||
if (sweeper) | ||||
tdbb->checkCancelState(true); | ||||
} | } | |||
} | } | |||
void DPM_pages(thread_db* tdbb, SSHORT rel_id, int type, ULONG sequence, ULONG p age) | void DPM_pages(thread_db* tdbb, SSHORT rel_id, int type, ULONG sequence, ULONG p age) | |||
{ | { | |||
/************************************** | /************************************** | |||
* | * | |||
* D P M _ p a g e s | * D P M _ p a g e s | |||
* | * | |||
************************************** | ************************************** | |||
skipping to change at line 1979 | skipping to change at line 2047 | |||
* Functional description | * Functional description | |||
* Store a new record in a relation. If we can put it on a | * Store a new record in a relation. If we can put it on a | |||
* specific page, so much the better. | * specific page, so much the better. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
CHECK_DBB(dbb); | CHECK_DBB(dbb); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = rpb->rpb_relation; | ||||
VIO_trace(DEBUG_WRITES, | VIO_trace(DEBUG_WRITES, | |||
"DPM_store (record_param %" QUADFORMAT"d, stack, type %d)\n", | "DPM_store (rel_id %u, record_param %" QUADFORMAT"d, stack, type | |||
rpb->rpb_number.getValue(), type); | %d)\n", | |||
relation->rel_id, rpb->rpb_number.getValue(), type); | ||||
VIO_trace(DEBUG_WRITES_INFO, | VIO_trace(DEBUG_WRITES_INFO, | |||
" record to store %" ULONGFORMAT":%d transaction %" ULONGFORMA T | " record to store %" ULONGFORMAT":%d transaction %" ULONGFORMA T | |||
" back %" ULONGFORMAT":%d fragment %" ULONGFORMAT":%d flags %d\n" , | " back %" ULONGFORMAT":%d fragment %" ULONGFORMAT":%d flags %d\n" , | |||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, | rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, | |||
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, | rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, | |||
rpb->rpb_f_line, rpb->rpb_flags); | rpb->rpb_f_line, rpb->rpb_flags); | |||
#endif | #endif | |||
const Compressor dcc(*tdbb->getDefaultPool(), rpb->rpb_length, rpb->rpb_a ddress); | const Compressor dcc(*tdbb->getDefaultPool(), rpb->rpb_length, rpb->rpb_a ddress); | |||
skipping to change at line 2063 | skipping to change at line 2132 | |||
* | * | |||
* Functional description | * Functional description | |||
* Store a blob on a data page. Not so hard, all in all. | * Store a blob on a data page. Not so hard, all in all. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
CHECK_DBB(dbb); | CHECK_DBB(dbb); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = blob->blb_relation; | ||||
VIO_trace(DEBUG_WRITES, | VIO_trace(DEBUG_WRITES, | |||
"DPM_store_blob (blob, record)\n"); | "DPM_store_blob (rel_id %u, blob, record)\n", | |||
relation->rel_id); | ||||
#endif | #endif | |||
// Figure out length of blob on page. Remember that blob can either | // Figure out length of blob on page. Remember that blob can either | |||
// be a clump of data or a vector of page pointers. | // be a clump of data or a vector of page pointers. | |||
USHORT length; | USHORT length; | |||
const UCHAR* q; | const UCHAR* q; | |||
PageStack stack; | PageStack stack; | |||
Firebird::Array<UCHAR> buffer; | Firebird::Array<UCHAR> buffer; | |||
blob->storeToPage(&length, buffer, &q, &stack); | blob->storeToPage(&length, buffer, &q, &stack); | |||
skipping to change at line 2130 | skipping to change at line 2201 | |||
* Functional description | * Functional description | |||
* Re-write benign fields in record header. This is mostly used | * Re-write benign fields in record header. This is mostly used | |||
* to purge out old versions. | * to purge out old versions. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
CHECK_DBB(dbb); | CHECK_DBB(dbb); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = rpb->rpb_relation; | ||||
VIO_trace(DEBUG_WRITES, | VIO_trace(DEBUG_WRITES, | |||
"DPM_rewrite_header (record_param %" QUADFORMAT"d)\n", rpb->rpb_n | "DPM_rewrite_header (rel_id %u, record_param %" QUADFORMAT"d)\n", | |||
umber.getValue()); | relation->rel_id, rpb->rpb_number.getValue()); | |||
VIO_trace(DEBUG_WRITES_INFO, | VIO_trace(DEBUG_WRITES_INFO, | |||
" record %" ULONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line) ; | " record %" ULONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line) ; | |||
#endif | #endif | |||
WIN* window = &rpb->getWindow(tdbb); | WIN* window = &rpb->getWindow(tdbb); | |||
data_page* page = (data_page*) window->win_buffer; | data_page* page = (data_page*) window->win_buffer; | |||
rhd* header = (rhd*) ((SCHAR *) page + page->dpg_rpt[rpb->rpb_line].dpg_o ffset); | rhd* header = (rhd*) ((SCHAR *) page + page->dpg_rpt[rpb->rpb_line].dpg_o ffset); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
skipping to change at line 2182 | skipping to change at line 2255 | |||
* | * | |||
* Functional description | * Functional description | |||
* Replace an existing record. | * Replace an existing record. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
CHECK_DBB(dbb); | CHECK_DBB(dbb); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = rpb->rpb_relation; | ||||
VIO_trace(DEBUG_WRITES, | VIO_trace(DEBUG_WRITES, | |||
"DPM_update (record_param %" QUADFORMAT"d, stack, transaction %" | "DPM_update (rel_id %u, record_param %" QUADFORMAT"d, stack, tran | |||
ULONGFORMAT")\n", | saction %" ULONGFORMAT")\n", | |||
rpb->rpb_number.getValue(), transaction ? transaction->tra_number | relation->rel_id, rpb->rpb_number.getValue(), transaction ? trans | |||
: 0); | action->tra_number : 0); | |||
VIO_trace(DEBUG_WRITES_INFO, | VIO_trace(DEBUG_WRITES_INFO, | |||
" record %" ULONGFORMAT":%d transaction %" ULONGFORMAT" back % " | " record %" ULONGFORMAT":%d transaction %" ULONGFORMAT" back % " | |||
ULONGFORMAT":%d fragment %" ULONGFORMAT":%d flags %d\n", | ULONGFORMAT":%d fragment %" ULONGFORMAT":%d flags %d\n", | |||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, | rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, | |||
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, | rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, | |||
rpb->rpb_f_line, rpb->rpb_flags); | rpb->rpb_f_line, rpb->rpb_flags); | |||
#endif | #endif | |||
// Mark the page as modified, then figure out the compressed length of th e | // Mark the page as modified, then figure out the compressed length of th e | |||
skipping to change at line 2470 | skipping to change at line 2544 | |||
const ULONG* page1 = blob->blh_page; | const ULONG* page1 = blob->blh_page; | |||
const ULONG* const end1 = page1 + (length - BLH_SIZE) / sizeof(ULONG); | const ULONG* const end1 = page1 + (length - BLH_SIZE) / sizeof(ULONG); | |||
for (; page1 < end1; page1++) | for (; page1 < end1; page1++) | |||
{ | { | |||
if (blob->blh_level == 2) | if (blob->blh_level == 2) | |||
{ | { | |||
window.win_page = *page1; | window.win_page = *page1; | |||
blob_page* bpage = (blob_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_blob); | blob_page* bpage = (blob_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_blob); | |||
ULONG* page2 = bpage->blp_page; | ULONG* page2 = bpage->blp_page; | |||
const ULONG* const end2 = page2 + ((bpage->blp_length - B LP_SIZE) / sizeof(ULONG)); | const ULONG* const end2 = page2 + ((bpage->blp_length) / sizeof(ULONG)); | |||
while (page2 < end2) | while (page2 < end2) | |||
PAG_release_page(tdbb, PageNumber(page_space, *pa ge2++), ZERO_PAGE_NUMBER); | PAG_release_page(tdbb, PageNumber(page_space, *pa ge2++), ZERO_PAGE_NUMBER); | |||
CCH_RELEASE_TAIL(tdbb, &window); | CCH_RELEASE_TAIL(tdbb, &window); | |||
} | } | |||
PAG_release_page(tdbb, PageNumber(page_space, *page1), ZERO_PAGE_ NUMBER); | PAG_release_page(tdbb, PageNumber(page_space, *page1), ZERO_PAGE_ NUMBER); | |||
} | } | |||
} | } | |||
skipping to change at line 2549 | skipping to change at line 2623 | |||
* In all cases, once the tail is written and safe, we come back to | * In all cases, once the tail is written and safe, we come back to | |||
* the head, store the remaining data, fix up the record header and | * the head, store the remaining data, fix up the record header and | |||
* everything is done. | * everything is done. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
CHECK_DBB(dbb); | CHECK_DBB(dbb); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = rpb->rpb_relation; | ||||
VIO_trace(DEBUG_WRITES, | VIO_trace(DEBUG_WRITES, | |||
"fragment (record_param %" QUADFORMAT | "fragment (rel_id %u, record_param %" QUADFORMAT | |||
"d, available_space %d, dcc, length %d, transaction %" ULONGFORMA T")\n", | "d, available_space %d, dcc, length %d, transaction %" ULONGFORMA T")\n", | |||
rpb->rpb_number.getValue(), available_space, length, | relation->rel_id, rpb->rpb_number.getValue(), available_space, le ngth, | |||
transaction ? transaction->tra_number : 0); | transaction ? transaction->tra_number : 0); | |||
VIO_trace(DEBUG_WRITES_INFO, | VIO_trace(DEBUG_WRITES_INFO, | |||
" record %" ULONGFORMAT":%d transaction %" ULONGFORMAT" back % " | " record %" ULONGFORMAT":%d transaction %" ULONGFORMAT" back % " | |||
ULONGFORMAT":%d fragment %" ULONGFORMAT":%d flags %d\n", | ULONGFORMAT":%d fragment %" ULONGFORMAT":%d flags %d\n", | |||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, | rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr, | |||
rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, | rpb->rpb_b_page, rpb->rpb_b_line, rpb->rpb_f_page, | |||
rpb->rpb_f_line, rpb->rpb_flags); | rpb->rpb_f_line, rpb->rpb_flags); | |||
#endif | #endif | |||
skipping to change at line 2723 | skipping to change at line 2798 | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
CHECK_DBB(dbb); | CHECK_DBB(dbb); | |||
RelationPages* relPages = relation->getPages(tdbb); | RelationPages* relPages = relation->getPages(tdbb); | |||
WIN pp_window(relPages->rel_pg_space_id, -1); | WIN pp_window(relPages->rel_pg_space_id, -1); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
VIO_trace(DEBUG_WRITES_INFO, | VIO_trace(DEBUG_WRITES_INFO, | |||
" extend_relation (relation %d, window)\n", relation->rel_id) | " extend_relation (relation %d, instance %" SQUADFORMAT", win | |||
; | dow)\n", | |||
relation->rel_id, relPages->rel_instance_id); | ||||
#endif | #endif | |||
// Search pointer pages for an empty slot. | // Search pointer pages for an empty slot. | |||
// If we run out of pointer pages, allocate another one. Note that the code below | // If we run out of pointer pages, allocate another one. Note that the code below | |||
// is not careful in preventing deadlocks when it allocates a new pointe r page: | // is not careful in preventing deadlocks when it allocates a new pointe r page: | |||
// - the last already-existing pointer page is fetched with an exclusiv e latch, | // - the last already-existing pointer page is fetched with an exclusiv e latch, | |||
// - allocation of a new pointer page requires the fetching of the PIP page with | // - allocation of a new pointer page requires the fetching of the PIP page with | |||
// an exlusive latch. | // an exlusive latch. | |||
pointer_page* ppage = NULL; | pointer_page* ppage = NULL; | |||
skipping to change at line 3038 | skipping to change at line 3114 | |||
rpb->rpb_page = window->win_page.getPageNum(); | rpb->rpb_page = window->win_page.getPageNum(); | |||
rpb->rpb_line = line; | rpb->rpb_line = line; | |||
rpb->rpb_flags = header->rhdf_flags; | rpb->rpb_flags = header->rhdf_flags; | |||
if (!(rpb->rpb_flags & rpb_fragment)) | if (!(rpb->rpb_flags & rpb_fragment)) | |||
{ | { | |||
rpb->rpb_b_page = header->rhdf_b_page; | rpb->rpb_b_page = header->rhdf_b_page; | |||
rpb->rpb_b_line = header->rhdf_b_line; | rpb->rpb_b_line = header->rhdf_b_line; | |||
rpb->rpb_transaction_nr = Ods::getTraNum(header); | rpb->rpb_transaction_nr = Ods::getTraNum(header); | |||
rpb->rpb_format_number = header->rhdf_format; | rpb->rpb_format_number = header->rhdf_format; | |||
if (rpb->rpb_relation->rel_id == 0 /*i.e.RDB$PAGES*/ && rpb->rpb_ | ||||
transaction_nr != 0) | ||||
{ | ||||
// RDB$PAGES relation should be modified only by system t | ||||
ransaction | ||||
thread_db* tdbb = JRD_get_thread_data(); | ||||
CCH_unwind(tdbb, false); | ||||
ERR_post(Arg::Gds(isc_bad_db_format) << Arg::Str(tdbb->ge | ||||
tAttachment()->att_filename) << | ||||
Arg::Gds(isc_random) << "RDB$PAGES written by non | ||||
-system transaction, DB appears damaged"); | ||||
} | ||||
} | } | |||
FB_SIZE_T header_size; | FB_SIZE_T header_size; | |||
if (rpb->rpb_flags & rpb_incomplete) | if (rpb->rpb_flags & rpb_incomplete) | |||
{ | { | |||
rpb->rpb_f_page = header->rhdf_f_page; | rpb->rpb_f_page = header->rhdf_f_page; | |||
rpb->rpb_f_line = header->rhdf_f_line; | rpb->rpb_f_line = header->rhdf_f_line; | |||
header_size = RHDF_SIZE; | header_size = RHDF_SIZE; | |||
} | } | |||
skipping to change at line 3358 | skipping to change at line 3443 | |||
* | * | |||
* Functional description | * Functional description | |||
* Mark a fetched page and its pointer page to indicate the page | * Mark a fetched page and its pointer page to indicate the page | |||
* is full. | * is full. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
CHECK_DBB(dbb); | CHECK_DBB(dbb); | |||
jrd_rel* relation = rpb->rpb_relation; | ||||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
VIO_trace(DEBUG_TRACE_ALL, | VIO_trace(DEBUG_TRACE_ALL, | |||
"mark_full ()\n"); | "mark_full (rel_id %u)\n", relation->rel_id); | |||
#endif | #endif | |||
// We need to access the pointer page for write. To avoid deadlocks, | // We need to access the pointer page for write. To avoid deadlocks, | |||
// we need to release the data page, fetch the pointer page for write, | // we need to release the data page, fetch the pointer page for write, | |||
// and re-fetch the data page. If the data page is still empty, set | // and re-fetch the data page. If the data page is still empty, set | |||
// it's "full" bit on the pointer page. | // it's "full" bit on the pointer page. | |||
data_page* dpage = (data_page*) rpb->getWindow(tdbb).win_buffer; | data_page* dpage = (data_page*) rpb->getWindow(tdbb).win_buffer; | |||
const ULONG sequence = dpage->dpg_sequence; | const ULONG sequence = dpage->dpg_sequence; | |||
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb)); | CCH_RELEASE(tdbb, &rpb->getWindow(tdbb)); | |||
jrd_rel* relation = rpb->rpb_relation; | ||||
RelationPages* relPages = relation->getPages(tdbb); | RelationPages* relPages = relation->getPages(tdbb); | |||
WIN pp_window(relPages->rel_pg_space_id, -1); | WIN pp_window(relPages->rel_pg_space_id, -1); | |||
USHORT slot; | USHORT slot; | |||
ULONG pp_sequence; | ULONG pp_sequence; | |||
DECOMPOSE(sequence, dbb->dbb_dp_per_pp, pp_sequence, slot); | DECOMPOSE(sequence, dbb->dbb_dp_per_pp, pp_sequence, slot); | |||
// Fetch the pointer page, then the data page. Since this is a case of | // Fetch the pointer page, then the data page. Since this is a case of | |||
// fetching a second page after having fetched the first page with an | // fetching a second page after having fetched the first page with an | |||
// exclusive latch, care has to be taken to prevent a deadlock. This | // exclusive latch, care has to be taken to prevent a deadlock. This | |||
skipping to change at line 3516 | skipping to change at line 3601 | |||
* | * | |||
* Functional description | * Functional description | |||
* Store a new record in a relation. | * Store a new record in a relation. | |||
* | * | |||
**************************************/ | **************************************/ | |||
SET_TDBB(tdbb); | SET_TDBB(tdbb); | |||
Database* dbb = tdbb->getDatabase(); | Database* dbb = tdbb->getDatabase(); | |||
CHECK_DBB(dbb); | CHECK_DBB(dbb); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
jrd_rel* relation = rpb->rpb_relation; | ||||
VIO_trace(DEBUG_TRACE_ALL, | VIO_trace(DEBUG_TRACE_ALL, | |||
"store_big_record ()\n"); | "store_big_record (rel_id %u, record %" SQUADFORMAT")\n", | |||
relation->rel_id, rpb->rpb_number.getValue()); | ||||
#endif | #endif | |||
// Start compression from the end. | // Start compression from the end. | |||
const UCHAR* in = rpb->rpb_address + rpb->rpb_length; | const UCHAR* in = rpb->rpb_address + rpb->rpb_length; | |||
RelationPages* relPages = rpb->rpb_relation->getPages(tdbb); | RelationPages* relPages = rpb->rpb_relation->getPages(tdbb); | |||
PageNumber prior(relPages->rel_pg_space_id, 0); | PageNumber prior(relPages->rel_pg_space_id, 0); | |||
signed char count = 0; | signed char count = 0; | |||
const USHORT max_data = dbb->dbb_page_size - (static_cast<USHORT>(sizeof( data_page)) + RHDF_SIZE); | const USHORT max_data = dbb->dbb_page_size - (static_cast<USHORT>(sizeof( data_page)) + RHDF_SIZE); | |||
skipping to change at line 3593 | skipping to change at line 3680 | |||
++size; | ++size; | |||
if (prior.getPageNum()) | if (prior.getPageNum()) | |||
CCH_precedence(tdbb, &rpb->getWindow(tdbb), prior); | CCH_precedence(tdbb, &rpb->getWindow(tdbb), prior); | |||
#ifdef VIO_DEBUG | #ifdef VIO_DEBUG | |||
VIO_trace(DEBUG_WRITES_INFO, | VIO_trace(DEBUG_WRITES_INFO, | |||
" back portion\n"); | " back portion\n"); | |||
VIO_trace(DEBUG_WRITES_INFO, | VIO_trace(DEBUG_WRITES_INFO, | |||
" getWindow(tdbb) page %" ULONGFORMAT | " window page %" ULONGFORMAT | |||
", max_data %d, \n\trhdf_flags %d, prior %" ULONGFORMAT"\ n", | ", max_data %d, \n\trhdf_flags %d, prior %" ULONGFORMAT"\ n", | |||
rpb->getWindow(tdbb).win_page.getPageNum(), max_data, hea der->rhdf_flags, | rpb->getWindow(tdbb).win_page.getPageNum(), max_data, hea der->rhdf_flags, | |||
prior.getPageNum()); | prior.getPageNum()); | |||
#endif | #endif | |||
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb)); | CCH_RELEASE(tdbb, &rpb->getWindow(tdbb)); | |||
prior = rpb->getWindow(tdbb).win_page; | prior = rpb->getWindow(tdbb).win_page; | |||
} | } | |||
// What's left fits on a page. Luckily, we don't have to store it oursel ves. | // What's left fits on a page. Luckily, we don't have to store it oursel ves. | |||
End of changes. 59 change blocks. | ||||
69 lines changed or deleted | 169 lines changed or added |