static bool packet_send( rem_port* port, const SCHAR* buffer, SSHORT buffer_length) { /************************************** * * p a c k e t _ s e n d * ************************************** * * Functional description * Send some data on it's way. * **************************************/ const SCHAR* data = buffer; const DWORD length = buffer_length; // encrypt HalfStaticArray<char, BUFFER_TINY> b; if (port->port_crypt_plugin && port->port_crypt_complete) { LocalStatus ls; CheckStatusWrapper st(&ls); char* d = b.getBuffer(buffer_length); port->port_crypt_plugin->encrypt(&st, buffer_length, data, d); if (st.getState() & IStatus::STATE_ERRORS) { status_exception::raise(&st); } data = d; } OVERLAPPED ovrl = {0}; ovrl.hEvent = port->port_event; DWORD n; BOOL status = WriteFile(port->port_pipe, data, length, &n, &ovrl); DWORD dwError = GetLastError(); if (!status && dwError == ERROR_IO_PENDING) { status = GetOverlappedResult(port->port_pipe, &ovrl, &n, TRUE); dwError = GetLastError(); } if (!status) return wnet_error(port, "WriteFile", isc_net_write_err, dwError); if (n != length) return wnet_error(port, "WriteFile truncated", isc_net_write_err, dwError); #if defined(DEBUG) && defined(WNET_trace) packet_print("send", reinterpret_cast<const UCHAR*>(buffer), buffer_length); #endif port->port_snd_packets++; port->port_snd_bytes += buffer_length; return true; }
void IntlUtil::toUpper(Jrd::CharSet* cs, string& s) { HalfStaticArray<UCHAR, BUFFER_SMALL> buffer; FB_SIZE_T len = s.length(); ULONG count = toUpper(cs, len, (const UCHAR*) s.c_str(), len * 4, buffer.getBuffer(len * 4), NULL); if (count != INTL_BAD_STR_LENGTH) s.assign(buffer.begin(), count); else fb_assert(false); }
void DBG_parse_debug_info(thread_db* tdbb, bid* blob_id, DbgInfo& dbgInfo) { Jrd::Attachment* attachment = tdbb->getAttachment(); blb* blob = blb::open(tdbb, attachment->getSysTransaction(), blob_id); const ULONG length = blob->blb_length; HalfStaticArray<UCHAR, 128> tmp; UCHAR* temp = tmp.getBuffer(length); blob->BLB_get_data(tdbb, temp, length); DBG_parse_debug_info(length, temp, dbgInfo); }
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(); size_t highest_index = 0; for (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 (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 (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; HalfStaticArray<ULONG, 64> key; const USHORT smb_key_length = sort_rsb->getKeyLength(); ULONG* const first_data = key.getBuffer(smb_key_length); const ULONG key_length = smb_key_length * sizeof(ULONG); memcpy(first_data, getData(tdbb, mfb, 0), key_length); SLONG record; while ((record = getRecord(tdbb, i)) >= 0) { const SLONG* p = (SLONG*) first_data; const SLONG* q = (SLONG*) getData(tdbb, mfb, record); bool equal = true; for (USHORT count = smb_key_length; count; p++, q++, count--) { if (*p != *q) { tail->irsb_mrg_last_fetched = record; equal = false; break; } } if (!equal) 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) 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; }
int INTL_compare(thread_db* tdbb, const dsc* pText1, const dsc* pText2, ErrorFunction err) { /************************************** * * I N T L _ c o m p a r e * ************************************** * * Functional description * Compare two pieces of international text. * **************************************/ SET_TDBB(tdbb); fb_assert(pText1 != NULL); fb_assert(pText2 != NULL); fb_assert(IS_TEXT(pText1) && IS_TEXT(pText2)); fb_assert(INTL_data_or_binary(pText1) || INTL_data_or_binary(pText2)); fb_assert(err); // normal compare routine from CVT_compare // trailing spaces in strings are ignored for comparision UCHAR* p1; USHORT t1; ULONG length1 = CVT_get_string_ptr(pText1, &t1, &p1, NULL, 0, err); UCHAR* p2; USHORT t2; ULONG length2 = CVT_get_string_ptr(pText2, &t2, &p2, NULL, 0, err); // YYY - by SQL II compare_type must be explicit in the // SQL statement if there is any doubt USHORT compare_type = MAX(t1, t2); // YYY HalfStaticArray<UCHAR, BUFFER_XLARGE> buffer; if (t1 != t2) { CHARSET_ID cs1 = INTL_charset(tdbb, t1); CHARSET_ID cs2 = INTL_charset(tdbb, t2); if (cs1 != cs2) { if (compare_type != t2) { // convert pText2 to pText1's type, if possible /* YYY - should failure to convert really return an error here? Support joining a 437 & Latin1 Column, and we pick the compare_type as 437, still only want the equal values.... But then, what about < operations, which make no sense if the string cannot be expressed... */ UCHAR* p = buffer.getBuffer(INTL_convert_bytes(tdbb, cs1, NULL, 0, cs2, p2, length2, err)); length2 = INTL_convert_bytes(tdbb, cs1, p, (ULONG) buffer.getCount(), cs2, p2, length2, err); p2 = p; } else { // convert pText1 to pText2's type, if possible UCHAR* p = buffer.getBuffer(INTL_convert_bytes(tdbb, cs2, NULL, 0, cs1, p1, length1, err)); length1 = INTL_convert_bytes(tdbb, cs2, p, (ULONG) buffer.getCount(), cs1, p1, length1, err); p1 = p; } } } TextType* obj = INTL_texttype_lookup(tdbb, compare_type); return obj->compare(length1, p1, length2, p2); }