void PIO_get_unique_file_id(const Jrd::jrd_file* file, UCharBuffer& id) { /************************************** * * P I O _ g e t _ u n i q u e _ f i l e _ i d * ************************************** * * Functional description * Return a binary string that uniquely identifies the file. * **************************************/ struct stat statistics; if (fstat(file->fil_desc, &statistics) != 0) { unix_error("fstat", file, isc_io_access_err); } const size_t len1 = sizeof(statistics.st_dev); const size_t len2 = sizeof(statistics.st_ino); UCHAR* p = id.getBuffer(len1 + len2); memcpy(p, &statistics.st_dev, len1); p += len1; memcpy(p, &statistics.st_ino, len2); }
static void makeUniqueFileId(const struct stat& statistics, UCharBuffer& id) { const size_t len1 = sizeof(statistics.st_dev); const size_t len2 = sizeof(statistics.st_ino); UCHAR* p = id.getBuffer(len1 + len2); memcpy(p, &statistics.st_dev, len1); p += len1; memcpy(p, &statistics.st_ino, len2); }
// Parse routine BLR. void Routine::parseBlr(thread_db* tdbb, CompilerScratch* csb, bid* blob_id) { Jrd::Attachment* attachment = tdbb->getAttachment(); UCharBuffer tmp; if (blob_id) { blb* blob = blb::open(tdbb, attachment->getSysTransaction(), blob_id); ULONG length = blob->blb_length + 10; UCHAR* temp = tmp.getBuffer(length); length = blob->BLB_get_data(tdbb, temp, length); tmp.resize(length); } parseMessages(tdbb, csb, BlrReader(tmp.begin(), (unsigned) tmp.getCount())); JrdStatement* statement = getStatement(); PAR_blr(tdbb, NULL, tmp.begin(), (ULONG) tmp.getCount(), NULL, &csb, &statement, false, 0); setStatement(statement); if (!blob_id) setImplemented(false); }
bool MergeJoin::getRecord(thread_db* tdbb) const { if (--tdbb->tdbb_quantum < 0) JRD_reschedule(tdbb, 0, true); jrd_req* const request = tdbb->getRequest(); Impure* const impure = request->getImpure<Impure>(m_impure); if (!(impure->irsb_flags & irsb_open)) return false; // If there is a record group already formed, fetch the next combination if (fetchRecord(tdbb, m_args.getCount() - 1)) return true; // Assuming we are done with the current value group, advance each // stream one record. If any comes up dry, we're done. const NestConst<SortedStream>* highest_ptr = m_args.begin(); FB_SIZE_T highest_index = 0; for (FB_SIZE_T i = 0; i < m_args.getCount(); i++) { const NestConst<SortedStream>* const ptr = &m_args[i]; const SortedStream* const sort_rsb = *ptr; const NestValueArray* const sort_key = m_keys[i]; Impure::irsb_mrg_repeat* const tail = &impure->irsb_mrg_rpt[i]; MergeFile* const mfb = &tail->irsb_mrg_file; // reset equality group record positions tail->irsb_mrg_equal = 0; tail->irsb_mrg_equal_current = 0; tail->irsb_mrg_equal_end = 0; // If there is a record waiting, use it. Otherwise get another. SLONG record = tail->irsb_mrg_last_fetched; if (record >= 0) { tail->irsb_mrg_last_fetched = -1; const UCHAR* const last_data = getData(tdbb, mfb, record); mfb->mfb_current_block = 0; UCHAR* const first_data = getData(tdbb, mfb, 0); if (first_data != last_data) memcpy(first_data, last_data, sort_rsb->getLength()); mfb->mfb_equal_records = 1; record = 0; } else { mfb->mfb_current_block = 0; mfb->mfb_equal_records = 0; if ((record = getRecord(tdbb, i)) < 0) return false; } // map data into target records and do comparison sort_rsb->mapData(tdbb, request, getData(tdbb, mfb, record)); if (ptr != highest_ptr && compare(tdbb, m_keys[highest_index], sort_key) < 0) { highest_ptr = ptr; highest_index = i; } } // Loop thru the streams advancing each up to the target value. // If any exceeds the target value, start over. while (true) { bool recycle = false; for (FB_SIZE_T i = 0; i < m_args.getCount(); i++) { const NestConst<SortedStream>* const ptr = &m_args[i]; const SortedStream* const sort_rsb = *ptr; const NestValueArray* const sort_key = m_keys[i]; Impure::irsb_mrg_repeat* const tail = &impure->irsb_mrg_rpt[i]; if (highest_ptr != ptr) { int result; while ( (result = compare(tdbb, m_keys[highest_index], sort_key)) ) { if (result < 0) { highest_ptr = ptr; highest_index = i; recycle = true; break; } MergeFile* const mfb = &tail->irsb_mrg_file; mfb->mfb_current_block = 0; mfb->mfb_equal_records = 0; const SLONG record = getRecord(tdbb, i); if (record < 0) return false; sort_rsb->mapData(tdbb, request, getData(tdbb, mfb, record)); } if (recycle) break; } } if (!recycle) break; } // finally compute equality group for each stream in sort/merge for (FB_SIZE_T i = 0; i < m_args.getCount(); i++) { const SortedStream* const sort_rsb = m_args[i]; Impure::irsb_mrg_repeat* const tail = &impure->irsb_mrg_rpt[i]; MergeFile* const mfb = &tail->irsb_mrg_file; UCharBuffer key; const ULONG key_length = sort_rsb->getKeyLength(); UCHAR* const first_data = key.getBuffer(key_length); memcpy(first_data, getData(tdbb, mfb, 0), key_length); SLONG record; while ((record = getRecord(tdbb, i)) >= 0) { const UCHAR* p = first_data; const UCHAR* q = getData(tdbb, mfb, record); if (!sort_rsb->compareKeys(p, q)) { tail->irsb_mrg_last_fetched = record; break; } tail->irsb_mrg_equal_end = record; } if (mfb->mfb_current_block) { if (!mfb->mfb_space) { MemoryPool& pool = *getDefaultMemoryPool(); mfb->mfb_space = FB_NEW_POOL(pool) TempSpace(pool, SCRATCH, false); } Sort::writeBlock(mfb->mfb_space, mfb->mfb_block_size * mfb->mfb_current_block, mfb->mfb_block_data, mfb->mfb_block_size); } } // Optimize cross product of equivalence groups by ordering the streams // from left (outermost) to right (innermost) by descending cardinality // of merge blocks. This ordering will vary for each set of equivalence // groups and cannot be statically assigned by the optimizer. typedef Stack<Impure::irsb_mrg_repeat*> ImrStack; ImrStack best_tails; Impure::irsb_mrg_repeat* tail = impure->irsb_mrg_rpt; for (const Impure::irsb_mrg_repeat* const tail_end = tail + m_args.getCount(); tail < tail_end; tail++) { Impure::irsb_mrg_repeat* best_tail = NULL; ULONG most_blocks = 0; for (Impure::irsb_mrg_repeat* tail2 = impure->irsb_mrg_rpt; tail2 < tail_end; tail2++) { ImrStack::iterator stack(best_tails); for (; stack.hasData(); ++stack) { if (stack.object() == tail2) break; } if (stack.hasData()) continue; MergeFile* const mfb = &tail2->irsb_mrg_file; ULONG blocks = mfb->mfb_equal_records / mfb->mfb_blocking_factor; if (++blocks > most_blocks) { most_blocks = blocks; best_tail = tail2; } } best_tails.push(best_tail); tail->irsb_mrg_order = best_tail - impure->irsb_mrg_rpt; } return true; }