void CryptoManager::changeCryptState(thread_db* tdbb, const Firebird::string& plugName) { if (plugName.length() > 31) { (Arg::Gds(isc_cp_name_too_long) << Arg::Num(31)).raise(); } bool newCryptState = plugName.hasData(); { // window scope Header hdr(tdbb, LCK_write); // Check header page for flags if (hdr->hdr_flags & Ods::hdr_crypt_process) { (Arg::Gds(isc_cp_process_active)).raise(); } bool headerCryptState = hdr->hdr_flags & Ods::hdr_encrypted; if (headerCryptState == newCryptState) { (Arg::Gds(isc_cp_already_crypted)).raise(); } fb_assert(stateLock); // Take exclusive stateLock bool ret = needLock ? LCK_lock(tdbb, stateLock, LCK_PW, LCK_WAIT) : LCK_convert(tdbb, stateLock, LCK_PW, LCK_WAIT); if (!ret) { fb_assert(tdbb->tdbb_status_vector[1]); ERR_punt(); } fb_utils::init_status(tdbb->tdbb_status_vector); needLock = false; // Load plugin if (newCryptState) { loadPlugin(plugName.c_str()); } crypt = newCryptState; // Write modified header page Ods::header_page* header = hdr.write(); if (crypt) { header->hdr_flags |= Ods::hdr_encrypted; plugName.copyTo(header->hdr_crypt_plugin, sizeof header->hdr_crypt_plugin); } else { header->hdr_flags &= ~Ods::hdr_encrypted; } header->hdr_flags |= Ods::hdr_crypt_process; process = true; } // Trigger lock on ChangeCryptState if (!LCK_convert(tdbb, stateLock, LCK_EX, LCK_WAIT)) { ERR_punt(); } if (!LCK_convert(tdbb, stateLock, LCK_SR, LCK_WAIT)) { ERR_punt(); } fb_utils::init_status(tdbb->tdbb_status_vector); // Now we may set hdr_crypt_page for crypt thread { // window scope Header hdr(tdbb, LCK_write); Ods::header_page* header = hdr.write(); header->hdr_crypt_page = 1; } startCryptThread(tdbb); }
bool GlobalRWLock::lockWrite(thread_db* tdbb, SSHORT wait) { SET_TDBB(tdbb); Database* dbb = tdbb->getDatabase(); { // scope 1 Database::CheckoutLockGuard counterGuard(dbb, counterMutex); COS_TRACE(("(%p)->lockWrite stage 1 readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)", this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical)); ++pendingWriters; while (readers > 0 ) { Database::Checkout checkoutDbb(dbb); noReaders.wait(counterMutex); } COS_TRACE(("(%p)->lockWrite stage 2 readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)", this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical)); while (currentWriter || pendingLock) { Database::Checkout checkoutDbb(dbb); writerFinished.wait(counterMutex); } COS_TRACE(("(%p)->lockWrite stage 3 readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)", this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical)); fb_assert(!readers && !currentWriter); if (cachedLock->lck_physical > LCK_none) { LCK_release(tdbb, cachedLock); // To prevent self deadlock invalidate(tdbb); } ++pendingLock; } COS_TRACE(("(%p)->lockWrite LCK_lock readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d), pendingLock(%d)", this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical, pendingLock)); if (!LCK_lock(tdbb, cachedLock, LCK_write, wait)) { Database::CheckoutLockGuard counterGuard(dbb, counterMutex); --pendingLock; if (--pendingWriters) { if (!currentWriter) writerFinished.notifyAll(); } return false; } { // scope 2 Database::CheckoutLockGuard counterGuard(dbb, counterMutex); --pendingLock; --pendingWriters; fb_assert(!currentWriter); currentWriter = true; COS_TRACE(("(%p)->lockWrite end readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)", this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical)); return fetch(tdbb); } }
INTL_BOOL IntlUtil::utf8WellFormed(charset* cs, ULONG len, const UCHAR* str, ULONG* offendingPos) { fb_assert(cs != NULL); return UnicodeUtil::utf8WellFormed(len, str, offendingPos); }
ULONG CVGB_unicode_to_gb2312(csconvert* obj, ULONG unicode_len, const UCHAR* p_unicode_str, ULONG gb_len, UCHAR* gb_str, USHORT* err_code, ULONG* err_position) { fb_assert(obj != NULL); CsConvertImpl* impl = obj->csconvert_impl; fb_assert(p_unicode_str != NULL || gb_str == NULL); fb_assert(err_code != NULL); fb_assert(err_position != NULL); fb_assert(obj->csconvert_fn_convert == CVGB_unicode_to_gb2312); fb_assert(impl->csconvert_datatable != NULL); fb_assert(impl->csconvert_misc != NULL); const ULONG src_start = unicode_len; *err_code = 0; // See if we're only after a length estimate if (gb_str == NULL) return unicode_len; // worst case - all han character input Firebird::Aligner<USHORT> s(p_unicode_str, unicode_len); const USHORT* unicode_str = s; const UCHAR* const start = gb_str; while (gb_len && unicode_len > 1) { // Convert from UNICODE to GB2312 code const USHORT wide = *unicode_str++; const USHORT gb_ch = ((const USHORT*) impl->csconvert_datatable) [((const USHORT*) impl->csconvert_misc)[(USHORT)wide / 256] + (wide % 256)]; if ((gb_ch == CS_CANT_MAP) && !(wide == CS_CANT_MAP)) { *err_code = CS_CONVERT_ERROR; break; } const int tmp1 = gb_ch / 256; const int tmp2 = gb_ch % 256; if (tmp1 == 0) { // ASCII character fb_assert((UCHAR(tmp2) & 0x80) == 0); *gb_str++ = tmp2; gb_len--; unicode_len -= sizeof(*unicode_str); continue; } if (gb_len < 2) { *err_code = CS_TRUNCATION_ERROR; break; } else { fb_assert(GB1(tmp1)); fb_assert(GB2(tmp2)); *gb_str++ = tmp1; *gb_str++ = tmp2; unicode_len -= sizeof(*unicode_str); gb_len -= 2; } } if (unicode_len && !*err_code) { *err_code = CS_TRUNCATION_ERROR; } *err_position = src_start - unicode_len; return ((gb_str - start) * sizeof(*gb_str)); }
static bool_t xdr_slice(XDR* xdrs, lstring* slice, /*USHORT sdl_length,*/ const UCHAR* sdl) { /************************************** * * x d r _ s l i c e * ************************************** * * Functional description * Move a slice of an array under * **************************************/ if (!xdr_long(xdrs, reinterpret_cast<SLONG*>(&slice->lstr_length))) return FALSE; // Handle operation specific stuff, particularly memory allocation/deallocation switch (xdrs->x_op) { case XDR_ENCODE: break; case XDR_DECODE: if (!slice->lstr_length) return TRUE; if (slice->lstr_length > slice->lstr_allocated && slice->lstr_allocated) { BURP_free(slice->lstr_address); slice->lstr_address = NULL; } if (!slice->lstr_address) { slice->lstr_address = BURP_alloc((SLONG) slice->lstr_length); if (!slice->lstr_address) { return FALSE; } slice->lstr_allocated = slice->lstr_length; } break; case XDR_FREE: if (slice->lstr_allocated) BURP_free(slice->lstr_address); slice->lstr_address = NULL; slice->lstr_allocated = 0; return TRUE; default: fb_assert(FALSE); return FALSE; } // Get descriptor of array element sdl_info info; { Firebird::LocalStatus ls; Firebird::CheckStatusWrapper s(&ls); if (SDL_info(&s, sdl, &info, 0)) return FALSE; } dsc* desc = &info.sdl_info_element; const ULONG n = slice->lstr_length / desc->dsc_length; UCHAR* p = slice->lstr_address; for (UCHAR* const end = p + n * desc->dsc_length; p < end; p += desc->dsc_length) { if (!xdr_datum(xdrs, desc, p)) { return FALSE; } } return TRUE; }
static USHORT LCKSC_string_to_key(texttype* obj, USHORT iInLen, const BYTE* pInChar, USHORT iOutLen, BYTE *pOutChar, USHORT /*key_type*/) { fb_assert(pOutChar != NULL); fb_assert(pInChar != NULL); fb_assert(iInLen <= LANGKSC_MAX_KEY); fb_assert(iOutLen <= LANGKSC_MAX_KEY); fb_assert(iOutLen >= LCKSC_key_length(obj, iInLen)); const BYTE* inbuff = pInChar + iInLen - 1; while ((inbuff >= pInChar) && (*inbuff == ASCII_SPACE)) inbuff--; iInLen = (inbuff - pInChar + 1); BYTE* outbuff = pOutChar; for (USHORT i = 0; i < iInLen && iOutLen; i++, pInChar++) { if (GEN_HAN(*pInChar, *(pInChar + 1))) { // general hangul const int idx = GetGenHanNdx(*pInChar, *(pInChar + 1)); if (idx >= 0) { if (iOutLen < 3) break; *outbuff++ = gen_han[idx][0]; *outbuff++ = gen_han[idx][1]; *outbuff++ = 1; iOutLen -= 3; } else { if (iOutLen < 2) break; *outbuff++ = *pInChar; *outbuff++ = *(pInChar + 1); iOutLen -= 2; } pInChar += 1; i++; } else if (SPE_HAN(*pInChar, *(pInChar + 1))) { // special hangul const int idx = GetSpeHanNdx(*(pInChar + 1)); fb_assert(idx >= 0); if (iOutLen < 3) break; *outbuff++ = gen_han[idx][0]; *outbuff++ = gen_han[idx][1]; *outbuff++ = 2; iOutLen -= 3; pInChar += 1; i++; } else { // ascii or rest -> in case with binary collation *outbuff++ = *pInChar; iOutLen--; fb_assert(KSC1(*pInChar) || (*pInChar < 0x80)); if (KSC1(*pInChar)) { // the rest characters of KSC_5601 table fb_assert(KSC2(*(pInChar + 1))); if (!iOutLen) break; *outbuff++ = *(pInChar + 1); iOutLen--; pInChar += 1; i++; } else // ascii continue; } } return (outbuff - pOutChar); }
static void explain(qli_dbb* db, const UCHAR* explain_buffer) { /************************************** * * e x p l a i n * ************************************** * * Functional description * Print out the access path for a blr * request in pretty-printed form. * **************************************/ int level = 0; SCHAR relation_name[MAX_SQL_IDENTIFIER_SIZE]; // CVC: This function may have the same bugs as the internal function // used in the engine, that received fixes in FB1 & FB1.5. if (*explain_buffer++ != isc_info_access_path) return; int buffer_length = (unsigned int) *explain_buffer++; buffer_length += (unsigned int) (*explain_buffer++) << 8; while (buffer_length > 0) { buffer_length--; switch (*explain_buffer++) { case isc_info_rsb_begin: explain_printf(level, "isc_info_rsb_begin,\n", 0); level++; break; case isc_info_rsb_end: explain_printf(level, "isc_info_rsb_end,\n", 0); level--; break; case isc_info_rsb_relation: { explain_printf(level, "isc_info_rsb_relation, ", 0); buffer_length--; const size_t length = *explain_buffer++; fb_assert(length < MAX_SQL_IDENTIFIER_SIZE); buffer_length -= length; memcpy(relation_name, explain_buffer, length); relation_name[length] = 0; explain_buffer += length; printf("%s,\n", relation_name); } break; case isc_info_rsb_type: buffer_length--; explain_printf(level, "isc_info_rsb_type, ", 0); switch (*explain_buffer++) { case isc_info_rsb_unknown: printf("unknown type\n"); break; case isc_info_rsb_indexed: printf("isc_info_rsb_indexed,\n"); level++; explain_index_tree(db, level, relation_name, &explain_buffer, &buffer_length); level--; break; // for join types, advance past the count byte // of substreams; we don't need it case isc_info_rsb_merge: buffer_length--; printf("isc_info_rsb_merge, %d,\n", *explain_buffer++); break; case isc_info_rsb_cross: buffer_length--; printf("isc_info_rsb_cross, %d,\n", *explain_buffer++); break; case isc_info_rsb_navigate: printf("isc_info_rsb_navigate,\n"); level++; explain_index_tree(db, level, relation_name, &explain_buffer, &buffer_length); level--; break; case isc_info_rsb_sequential: printf("isc_info_rsb_sequential,\n"); break; case isc_info_rsb_sort: printf("isc_info_rsb_sort,\n"); break; case isc_info_rsb_first: printf("isc_info_rsb_first,\n"); break; case isc_info_rsb_boolean: printf("isc_info_rsb_boolean,\n"); break; case isc_info_rsb_union: printf("isc_info_rsb_union,\n"); break; case isc_info_rsb_aggregate: printf("isc_info_rsb_aggregate,\n"); break; case isc_info_rsb_ext_sequential: printf("isc_info_rsb_ext_sequential,\n"); break; case isc_info_rsb_ext_indexed: printf("isc_info_rsb_ext_indexed,\n"); break; case isc_info_rsb_ext_dbkey: printf("isc_info_rsb_ext_dbkey,\n"); break; case isc_info_rsb_left_cross: printf("isc_info_rsb_left_cross,\n"); break; case isc_info_rsb_select: printf("isc_info_rsb_select,\n"); break; case isc_info_rsb_sql_join: printf("isc_info_rsb_sql_join,\n"); break; case isc_info_rsb_simulate: printf("isc_info_rsb_simulate,\n"); break; case isc_info_rsb_sim_cross: printf("isc_info_rsb_sim_cross,\n"); break; case isc_info_rsb_once: printf("isc_info_rsb_once,\n"); break; case isc_info_rsb_procedure: printf("isc_info_rsb_procedure,\n"); break; } break; default: explain_printf(level, "unknown info item\n", 0); break; } } }
bool SyncObject::wait(SyncType type, ThreadSync* thread, Sync* sync, int timeOut) { if (thread->nextWaiting) { mutex.leave(); fatal_exception::raise("single thread deadlock"); } if (waitingThreads) { thread->prevWaiting = waitingThreads->prevWaiting; thread->nextWaiting = waitingThreads; waitingThreads->prevWaiting->nextWaiting = thread; waitingThreads->prevWaiting = thread; } else { thread->prevWaiting = thread->nextWaiting = thread; waitingThreads = thread; } thread->lockType = type; thread->lockGranted = false; thread->lockPending = sync; mutex.leave(); bool wakeup = false; while (timeOut && !thread->lockGranted) { const int wait = timeOut > 10000 ? 10000 : timeOut; wakeup = true; if (timeOut == -1) thread->sleep(); else wakeup = thread->sleep(wait); if (thread->lockGranted) return true; (void) wakeup; //if (!wakeup) // stalled(thread); if (timeOut != -1) timeOut -= wait; } if (thread->lockGranted) return true; MutexLockGuard guard(mutex, "SyncObject::wait"); if (thread->lockGranted) return true; dequeThread(thread); if (type == SYNC_SHARED) --waiters; else waiters -= WRITER_INCR; fb_assert(timeOut >= 0); return false; }
bool SyncObject::lock(Sync* sync, SyncType type, const char* from, int timeOut) { ThreadSync* thread = NULL; if (type == SYNC_SHARED) { // In Vulcan SyncObject locking is not fair. Shared locks have priority // before Exclusive locks. To change this behavior we should replace // loop condition below by: //while (waiters == 0) // activate to make locking fair while (true) { const AtomicCounter::counter_type oldState = lockState; if (oldState < 0) break; const AtomicCounter::counter_type newState = oldState + 1; if (lockState.compareExchange(oldState, newState)) { WaitForFlushCache(); #ifdef DEV_BUILD MutexLockGuard g(mutex, FB_FUNCTION); reason(from); #endif return true; } } if (timeOut == 0) return false; mutex.enter(FB_FUNCTION); ++waiters; //while (!waitingThreads) // activate to make locking fair while (true) { const AtomicCounter::counter_type oldState = lockState; if (oldState < 0) break; const AtomicCounter::counter_type newState = oldState + 1; if (lockState.compareExchange(oldState, newState)) { --waiters; reason(from); mutex.leave(); return true; } } thread = ThreadSync::findThread(); fb_assert(thread); } else { thread = ThreadSync::findThread(); fb_assert(thread); if (thread == exclusiveThread) { ++monitorCount; reason(from); return true; } while (waiters == 0) { const AtomicCounter::counter_type oldState = lockState; if (oldState != 0) break; if (lockState.compareExchange(oldState, -1)) { exclusiveThread = thread; WaitForFlushCache(); #ifdef DEV_BUILD MutexLockGuard g(mutex, FB_FUNCTION); #endif reason(from); return true; } } if (timeOut == 0) return false; mutex.enter(FB_FUNCTION); waiters += WRITER_INCR; while (!waitingThreads) { const AtomicCounter::counter_type oldState = lockState; if (oldState != 0) break; if (lockState.compareExchange(oldState, -1)) { exclusiveThread = thread; waiters -= WRITER_INCR; reason(from); mutex.leave(); return true; } } } return wait(type, thread, sync, timeOut); #ifdef DEV_BUILD MutexLockGuard g(mutex, FB_FUNCTION); reason(from); #endif }
jrd_nod* InAutonomousTransactionNode::execute(thread_db* tdbb, jrd_req* request) { Database* const dbb = tdbb->getDatabase(); Attachment* const attachment = tdbb->getAttachment(); Impure* const impure = (Impure*) ((UCHAR*) request + impureOffset); if (request->req_operation == jrd_req::req_evaluate) { // Force unconditional reschedule. It prevents new transactions being // started after an attachment or a database shutdown has been initiated. JRD_reschedule(tdbb, 0, true); jrd_tra* const org_transaction = request->req_transaction; fb_assert(tdbb->getTransaction() == org_transaction); jrd_tra* const transaction = TRA_start(tdbb, org_transaction->tra_flags, org_transaction->tra_lock_timeout, org_transaction); TRA_attach_request(transaction, request); tdbb->setTransaction(transaction); request->req_auto_trans.push(org_transaction); impure->traNumber = transaction->tra_number; VIO_start_save_point(tdbb, transaction); impure->savNumber = transaction->tra_save_point->sav_number; if (!(attachment->att_flags & ATT_no_db_triggers)) { // run ON TRANSACTION START triggers EXE_execute_db_triggers(tdbb, transaction, jrd_req::req_trigger_trans_start); } return action; } jrd_tra* transaction = request->req_transaction; fb_assert(transaction); fb_assert(transaction != dbb->dbb_sys_trans); if (!impure->traNumber) return node->nod_parent; fb_assert(transaction->tra_number == impure->traNumber); switch (request->req_operation) { case jrd_req::req_return: if (!(attachment->att_flags & ATT_no_db_triggers)) { // run ON TRANSACTION COMMIT triggers EXE_execute_db_triggers(tdbb, transaction, jrd_req::req_trigger_trans_commit); } if (transaction->tra_save_point && !(transaction->tra_save_point->sav_flags & SAV_user) && !transaction->tra_save_point->sav_verb_count) { VIO_verb_cleanup(tdbb, transaction); } { // scope Firebird::AutoSetRestore2<jrd_req*, thread_db> autoNullifyRequest( tdbb, &thread_db::getRequest, &thread_db::setRequest, NULL); TRA_commit(tdbb, transaction, false); } // end scope break; case jrd_req::req_unwind: if (request->req_flags & req_leave) { try { if (!(attachment->att_flags & ATT_no_db_triggers)) { // run ON TRANSACTION COMMIT triggers EXE_execute_db_triggers(tdbb, transaction, jrd_req::req_trigger_trans_commit); } if (transaction->tra_save_point && !(transaction->tra_save_point->sav_flags & SAV_user) && !transaction->tra_save_point->sav_verb_count) { VIO_verb_cleanup(tdbb, transaction); } Firebird::AutoSetRestore2<jrd_req*, thread_db> autoNullifyRequest( tdbb, &thread_db::getRequest, &thread_db::setRequest, NULL); TRA_commit(tdbb, transaction, false); } catch (...) { request->req_flags &= ~req_leave; throw; } } else { ThreadStatusGuard temp_status(tdbb); if (!(attachment->att_flags & ATT_no_db_triggers)) { try { // run ON TRANSACTION ROLLBACK triggers EXE_execute_db_triggers(tdbb, transaction, jrd_req::req_trigger_trans_rollback); } catch (const Firebird::Exception&) { if (dbb->dbb_flags & DBB_bugcheck) throw; } } try { Firebird::AutoSetRestore2<jrd_req*, thread_db> autoNullifyRequest( tdbb, &thread_db::getRequest, &thread_db::setRequest, NULL); // undo all savepoints up to our one for (const Savepoint* save_point = transaction->tra_save_point; save_point && impure->savNumber <= save_point->sav_number; save_point = transaction->tra_save_point) { ++transaction->tra_save_point->sav_verb_count; VIO_verb_cleanup(tdbb, transaction); } TRA_rollback(tdbb, transaction, false, false); } catch (const Firebird::Exception&) { if (dbb->dbb_flags & DBB_bugcheck) throw; } } break; default: fb_assert(false); } impure->traNumber = impure->savNumber = 0; transaction = request->req_auto_trans.pop(); TRA_attach_request(transaction, request); tdbb->setTransaction(transaction); return node->nod_parent; }
RecordBuffer* DbCreatorsList::getList(thread_db* tdbb, jrd_rel* relation) { fb_assert(relation); fb_assert(relation->rel_id == rel_sec_db_creators); RecordBuffer* buffer = getData(relation); if (buffer) { return buffer; } RefPtr<IAttachment> att; RefPtr<ITransaction> tra; const char* dbName = tdbb->getDatabase()->dbb_config->getSecurityDatabase(); if (!openDb(dbName, att, tra)) { // In embedded mode we are not raising any errors - silent return if (MasterInterfacePtr()->serverMode(-1) < 0) return makeBuffer(tdbb); (Arg::Gds(isc_crdb_nodb) << dbName).raise(); } Message gr; Field<ISC_SHORT> uType(gr); Field<Varying> u(gr, MAX_SQL_IDENTIFIER_LEN); FbLocalStatus st; RefPtr<IResultSet> curs(REF_NO_INCR, att->openCursor(&st, tra, 0, "select RDB$USER_TYPE, RDB$USER from RDB$DB_CREATORS", SQL_DIALECT_V6, NULL, NULL, gr.getMetadata(), NULL, 0)); if (st->getState() & IStatus::STATE_ERRORS) { if (!fb_utils::containsErrorCode(st->getErrors(), isc_dsql_relation_err)) check("IAttachment::openCursor", &st); // isc_dsql_relation_err when opening cursor - i.e. table // is missing due to non-FB3 security DB // In embedded mode we are not raising any errors - silent return if (MasterInterfacePtr()->serverMode(-1) < 0) return makeBuffer(tdbb); (Arg::Gds(isc_crdb_notable) << dbName).raise(); } try { buffer = makeBuffer(tdbb); while (curs->fetchNext(&st, gr.getBuffer()) == IStatus::RESULT_OK) { Record* record = buffer->getTempRecord(); record->nullify(); putField(tdbb, record, DumpField(f_sec_crt_user, VALUE_STRING, u->len, u->data)); SINT64 v = uType; putField(tdbb, record, DumpField(f_sec_crt_u_type, VALUE_INTEGER, sizeof(v), &v)); buffer->store(record); } check("IResultSet::fetchNext", &st); } catch (const Exception&) { clearSnapshot(); throw; } return getData(relation); }
dsc* EVAL_value(qli_nod* node) { /************************************** * * E V A L _ v a l u e * ************************************** * * Functional description * Evaluate a value node. * **************************************/ DSC *values[4]; // Start by evaluating sub-expressions (where appropriate) dsc* desc = &node->nod_desc; fb_assert(node->nod_count < 5); qli_nod** ptr = node->nod_arg; const qli_nod* const* const end_ptr = ptr + node->nod_count; for (dsc** value = values; ptr < end_ptr; ptr++, value++) { *value = EVAL_value(*ptr); if (node->nod_flags & nod_partial) break; } switch (node->nod_type) { case nod_edit_blob: return execute_edit(node); case nod_rpt_max: case nod_rpt_min: case nod_rpt_total: case nod_rpt_average: if (!(IPTR) node->nod_arg[e_stt_default]) desc->dsc_missing = DSC_missing; case nod_rpt_count: case nod_constant: return desc; case nod_variable: { qli_fld* field = (qli_fld*) node->nod_arg[e_fld_field]; desc->dsc_missing = (field->fld_flags & FLD_missing) ? DSC_missing : 0; } return desc; case nod_field: return EVAL_value(node->nod_arg[e_fld_reference]); case nod_reference: return EVAL_parameter(node->nod_import); case nod_null: return desc; case nod_add: if ((values[0]->dsc_missing & DSC_missing) || (values[1]->dsc_missing & DSC_missing)) { desc->dsc_missing = DSC_missing; return desc; } desc->dsc_missing = FALSE; if (node->nod_flags & nod_date) { double d1 = MOVQ_date_to_double(values[0]) + MOVQ_get_double(values[1]); MOVQ_double_to_date(d1, (SLONG*) desc->dsc_address); } else if (desc->dsc_dtype == dtype_long) { *((SLONG*) desc->dsc_address) = MOVQ_get_long(values[0], desc->dsc_scale) + MOVQ_get_long(values[1], desc->dsc_scale); } else *((double*) desc->dsc_address) = MOVQ_get_double(values[0]) + MOVQ_get_double(values[1]); return desc; case nod_subtract: if ((values[0]->dsc_missing & DSC_missing) || (values[1]->dsc_missing & DSC_missing)) { desc->dsc_missing = DSC_missing; return desc; } desc->dsc_missing = FALSE; if (node->nod_flags & nod_date) { *((double*) desc->dsc_address) = MOVQ_date_to_double(values[0]) - MOVQ_date_to_double(values[1]); } else if (desc->dsc_dtype == dtype_long) { *((SLONG*) desc->dsc_address) = MOVQ_get_long(values[0], desc->dsc_scale) - MOVQ_get_long(values[1], desc->dsc_scale); } else *((double*) desc->dsc_address) = MOVQ_get_double(values[0]) - MOVQ_get_double(values[1]); return desc; case nod_divide: if ((values[0]->dsc_missing & DSC_missing) || (values[1]->dsc_missing & DSC_missing)) { desc->dsc_missing = DSC_missing; return desc; } desc->dsc_missing = FALSE; *((double*) desc->dsc_address) = MOVQ_get_double(values[0]) / MOVQ_get_double(values[1]); return desc; case nod_multiply: if ((values[0]->dsc_missing & DSC_missing) || (values[1]->dsc_missing & DSC_missing)) { desc->dsc_missing = DSC_missing; return desc; } desc->dsc_missing = FALSE; if (desc->dsc_dtype == dtype_long) { *((SLONG*) desc->dsc_address) = MOVQ_get_long(values[0], values[0]->dsc_scale) * MOVQ_get_long(values[1], values[1]->dsc_scale); } else *((double*) desc->dsc_address) = MOVQ_get_double(values[0]) * MOVQ_get_double(values[1]); return desc; case nod_negate: if (values[0]->dsc_missing & DSC_missing) { desc->dsc_missing = DSC_missing; return desc; } desc->dsc_missing = FALSE; switch (desc->dsc_dtype) { case dtype_short: *((SSHORT*) desc->dsc_address) = -MOVQ_get_long(values[0], desc->dsc_scale); break; case dtype_long: *((SLONG*) desc->dsc_address) = -MOVQ_get_long(values[0], desc->dsc_scale); break; // lets throw arithmetic not supported until fixed //case dtype_int64: // *((SINT64*) desc->dsc_address) = -MOVQ_get_long(values[0], desc->dsc_scale); // break; case dtype_real: *((float*) desc->dsc_address) = -MOVQ_get_double(values[0]); break; case dtype_double: *((double*) desc->dsc_address) = -MOVQ_get_double(values[0]); break; default: IBERROR(30); // Msg30 data type not supported for arithmetic } return desc; case nod_prompt: if (!prompt[0][0]) { ERRQ_msg_get(499, prompt[0], sizeof(prompt[0])); // Msg499 Re-enter ERRQ_msg_get(500, prompt[1], sizeof(prompt[1])); // Msg500 Enter } return execute_prompt(node); case nod_concatenate: return execute_concatenate(node, values[0], values[1]); case nod_function: return execute_function(node); case nod_max: case nod_min: case nod_count: case nod_average: case nod_total: case nod_from: return execute_statistical(node); case nod_running_count: *(SLONG*) (desc->dsc_address) += 1; return desc; case nod_running_total: { dsc* desc2 = EVAL_value(node->nod_arg[e_stt_value]); if (desc2) { if (desc2->dsc_missing & DSC_missing) return desc; if (desc->dsc_dtype == dtype_long) *(SLONG*) desc->dsc_address += MOVQ_get_long(desc2, desc->dsc_scale); else *(double*) desc->dsc_address += MOVQ_get_double(desc2); } } return desc; case nod_format: { UCHAR* p = desc->dsc_address; PIC_edit(values[0], (pics*) node->nod_arg[e_fmt_picture], (TEXT**) &p, desc->dsc_length); desc->dsc_length = p - desc->dsc_address; } return desc; case nod_user_name: IBERROR(31); // Msg31 user name is supported only in RSEs temporarily case nod_parameter: case nod_position: case nod_substr: case nod_via: default: ERRQ_bugcheck(29); // Msg29 EVAL_value: not finished return NULL; } }
void Why::UtilInterface::getPerfCounters(Firebird::CheckStatusWrapper* status, Firebird::IAttachment* att, const char* countersSet, ISC_INT64* counters) { try { // Parse countersSet unsigned cntLink[TOTAL_COUNTERS]; memset(cntLink, 0xFF, sizeof cntLink); Firebird::string dupSet(countersSet); char* set = dupSet.begin(); char* save = NULL; const char* delim = " \t,;"; unsigned typeMask = 0; unsigned n = 0; UCHAR info[TOTAL_COUNTERS]; // will never use all, but do not care about few bytes UCHAR* pinfo = info; #ifdef WIN_NT #define strtok_r strtok_s #endif for (char* nm = strtok_r(set, delim, &save); nm; nm = strtok_r(NULL, delim, &save)) { Firebird::NoCaseString name(nm); for (unsigned i = 0; i < TOTAL_COUNTERS; ++i) { if (name == knownCounters[i].name) { if (cntLink[i] != ~0u) (Firebird::Arg::Gds(isc_random) << "Duplicated name").raise(); //report name & position cntLink[i] = n++; typeMask |= knownCounters[i].type; if (knownCounters[i].type == CNT_DB_INFO) *pinfo++ = knownCounters[i].code; goto found; } } (Firebird::Arg::Gds(isc_random) << "Unknown name").raise(); //report name & position found: ; } #ifdef WIN_NT #undef strtok_r #endif // Force reset counters memset(counters, 0, n * sizeof(ISC_INT64)); // Fill time counters if (typeMask & CNT_TIMER) { SINT64 tr = fb_utils::query_performance_counter() * 1000 / fb_utils::query_performance_frequency(); SINT64 uTime, sTime; fb_utils::get_process_times(uTime, sTime); for (unsigned i = 0; i < TOTAL_COUNTERS; ++i) { if (cntLink[i] == ~0u) continue; if (knownCounters[i].type == CNT_TIMER) { clock_t v = 0; switch(knownCounters[i].code) { case CNT_TIME_REAL: v = tr; break; case CNT_TIME_USER: v = uTime; break; case CNT_TIME_SYSTEM: v = sTime; break; default: fb_assert(false); break; } counters[cntLink[i]] = v; } } } // Fill DB counters if (typeMask & CNT_DB_INFO) { UCHAR buffer[BUFFER_LARGE]; att->getInfo(status, pinfo - info, info, sizeof(buffer), buffer); if (status->getState() & Firebird::IStatus::STATE_ERRORS) return; const UCHAR* p = buffer; while (true) { SINT64 v = 0; UCHAR ipb = *p++; switch (ipb) { case isc_info_reads: case isc_info_writes: case isc_info_marks: case isc_info_fetches: case isc_info_num_buffers: case isc_info_page_size: case isc_info_current_memory: case isc_info_max_memory: v = get_parameter(&p); break; case isc_info_end: goto parsed; case isc_info_error: { const SINT64 temp = isc_portable_integer(p, 2); fb_assert(temp <= MAX_SSHORT); p += temp + 2; continue; } default: (Firebird::Arg::Gds(isc_random) << "Unknown info code").raise(); //report char code } for (unsigned i = 0; i < TOTAL_COUNTERS; ++i) { if (knownCounters[i].type == CNT_DB_INFO && knownCounters[i].code == ipb) { if (cntLink[i] != ~0u) counters[cntLink[i]] = v; break; } } } parsed: ; } } catch (const Firebird::Exception& ex) { ex.stuffException(status); } }
static void perf_get_info(FB_API_HANDLE* handle, P* perf) { /************************************** * * P E R F _ g e t _ i n f o * ************************************** * * Functional description * Acquire timing and performance information. Some info comes * from the system and some from the database. * **************************************/ SSHORT buffer_length, item_length; ISC_STATUS_ARRAY jrd_status; #ifdef HAVE_GETTIMEOFDAY struct timeval tp; #else struct timeb time_buffer; #define LARGE_NUMBER 696600000 // to avoid overflow, get rid of decades) #endif // If there isn't a database, zero everything out if (!*handle) { memset(perf, 0, sizeof(PERF)); } // Get system time times(&perf->perf_times); #ifdef HAVE_GETTIMEOFDAY GETTIMEOFDAY(&tp); perf->perf_elapsed = tp.tv_sec * 100 + tp.tv_usec / 10000; #else ftime(&time_buffer); perf->perf_elapsed = (time_buffer.time - LARGE_NUMBER) * 100 + (time_buffer.millitm / 10); #endif if (!*handle) return; SCHAR buffer[256]; buffer_length = sizeof(buffer); item_length = sizeof(items); isc_database_info(jrd_status, handle, item_length, items, buffer_length, buffer); const char* p = buffer; while (true) switch (*p++) { case isc_info_reads: perf->perf_reads = get_parameter(&p); break; case isc_info_writes: perf->perf_writes = get_parameter(&p); break; case isc_info_marks: perf->perf_marks = get_parameter(&p); break; case isc_info_fetches: perf->perf_fetches = get_parameter(&p); break; case isc_info_num_buffers: perf->perf_buffers = get_parameter(&p); break; case isc_info_page_size: perf->perf_page_size = get_parameter(&p); break; case isc_info_current_memory: perf->perf_current_memory = get_parameter(&p); break; case isc_info_max_memory: perf->perf_max_memory = get_parameter(&p); break; case isc_info_end: return; case isc_info_error: switch (p[2]) { case isc_info_marks: perf->perf_marks = 0; break; case isc_info_current_memory: perf->perf_current_memory = 0; break; case isc_info_max_memory: perf->perf_max_memory = 0; break; } { const SLONG temp = isc_vax_integer(p, 2); fb_assert(temp <= MAX_SSHORT); p += temp + 2; } perf->perf_marks = 0; break; default: return; } }
bool ConfigStorage::getNextSession(TraceSession& session) { ITEM tag = tagID; ULONG len; session.clear(); while (true) { if (!getItemLength(tag, len)) return false; if (tag == tagEnd) { if (session.ses_id != 0) return true; continue; } void* p = NULL; switch (tag) { case tagID: fb_assert(len == sizeof(session.ses_id)); p = &session.ses_id; break; case tagName: if (session.ses_id) p = session.ses_name.getBuffer(len); break; case tagUserName: if (session.ses_id) p = session.ses_user.getBuffer(len); break; case tagFlags: fb_assert(len == sizeof(session.ses_flags)); if (session.ses_id) p = &session.ses_flags; break; case tagConfig: if (session.ses_id) p = session.ses_config.getBuffer(len); break; case tagStartTS: fb_assert(len == sizeof(session.ses_start)); if (session.ses_id) p = &session.ses_start; break; case tagLogFile: if (session.ses_id) p = session.ses_logfile.getBuffer(len); break; default: fb_assert(false); } if (p) { if (::read(m_cfg_file, p, len) != len) checkFileError(m_sharedMemory->getHeader()->cfg_file_name, "read", isc_io_read_err); } else { if (lseek(m_cfg_file, len, SEEK_CUR) < 0) checkFileError(m_sharedMemory->getHeader()->cfg_file_name, "lseek", isc_io_read_err); } } return true; }
void InternalTransaction::doPrepare(FbStatusVector* /*status*/, thread_db* /*tdbb*/, int /*info_len*/, const char* /*info*/) { fb_assert(m_transaction); fb_assert(false); }
void BlrFromMessage::buildBlr(IMessageMetadata* metadata) { if (!metadata) return; LocalStatus st; expectedMessageLength = metadata->getMessageLength(&st); checkStatus(&st); getBlrData().clear(); const unsigned count = metadata->getCount(&st); fb_assert(count < MAX_USHORT / 2); if (count == 0) return; // If there isn't an SQLDA, don't bother with anything else. appendVersion(); appendUChar(blr_begin); appendUChar(blr_message); appendUChar(0); appendUShort(count * 2); unsigned msgLen = 0; for (unsigned i = 0; i < count; ++i) { unsigned dtype = metadata->getType(&st, i) & ~1; checkStatus(&st); unsigned len = metadata->getLength(&st, i); checkStatus(&st); unsigned scale = metadata->getScale(&st, i); checkStatus(&st); unsigned charset = metadata->getCharset(&st, i); checkStatus(&st); switch (dtype) { case SQL_VARYING: appendUChar(blr_varying2); appendUShort(charset); appendUShort(len); dtype = dtype_varying; len += sizeof(USHORT); break; case SQL_TEXT: appendUChar(blr_text2); appendUShort(charset); appendUShort(len); dtype = dtype_text; break; case SQL_DOUBLE: appendUChar(blr_double); dtype = dtype_double; break; case SQL_FLOAT: appendUChar(blr_float); dtype = dtype_real; break; case SQL_D_FLOAT: appendUChar(blr_d_float); dtype = dtype_d_float; break; case SQL_TYPE_DATE: appendUChar(blr_sql_date); dtype = dtype_sql_date; break; case SQL_TYPE_TIME: appendUChar(blr_sql_time); dtype = dtype_sql_time; break; case SQL_TIMESTAMP: appendUChar(blr_timestamp); dtype = dtype_timestamp; break; case SQL_BLOB: appendUChar(blr_blob2); appendUShort(metadata->getSubType(&st, i)); appendUShort(charset); dtype = dtype_blob; break; case SQL_ARRAY: appendUChar(blr_quad); appendUChar(0); dtype = dtype_array; break; case SQL_LONG: appendUChar(blr_long); appendUChar(scale); dtype = dtype_long; break; case SQL_SHORT: appendUChar(blr_short); appendUChar(scale); dtype = dtype_short; break; case SQL_INT64: appendUChar(blr_int64); appendUChar(scale); dtype = dtype_int64; break; case SQL_QUAD: appendUChar(blr_quad); appendUChar(scale); dtype = dtype_quad; break; case SQL_BOOLEAN: appendUChar(blr_bool); dtype = dtype_boolean; break; case SQL_NULL: appendUChar(blr_text); appendUShort(len); dtype = dtype_text; break; default: Arg::Gds(isc_dsql_sqlda_value_err).raise(); break; } appendUChar(blr_short); appendUChar(0); unsigned align = type_alignments[dtype]; if (align) msgLen = FB_ALIGN(msgLen, align); msgLen += len; align = type_alignments[dtype_short]; if (align) msgLen = FB_ALIGN(msgLen, align); msgLen += sizeof(SSHORT); } appendUChar(blr_end); appendUChar(blr_eoc); if (expectedMessageLength && msgLen && (expectedMessageLength != msgLen)) { Arg::Gds(isc_wrong_message_length).raise(); } }
void InternalStatement::doPrepare(thread_db* tdbb, const string& sql) { m_inMetadata->reset(); m_outMetadata->reset(); JAttachment* att = m_intConnection.getJrdAtt(); JTransaction* tran = getIntTransaction()->getJrdTran(); FbLocalStatus status; if (m_request) { doClose(tdbb, true); fb_assert(!m_allocated); } { EngineCallbackGuard guard(tdbb, *this, FB_FUNCTION); CallerName save_caller_name(tran->getHandle()->tra_caller_name); if (m_callerPrivileges) { jrd_req* request = tdbb->getRequest(); JrdStatement* statement = request ? request->getStatement() : NULL; CallerName callerName; const Routine* routine; if (statement && statement->parentStatement) statement = statement->parentStatement; if (statement && statement->triggerName.hasData()) tran->getHandle()->tra_caller_name = CallerName(obj_trigger, statement->triggerName); else if (statement && (routine = statement->getRoutine()) && routine->getName().identifier.hasData()) { if (routine->getName().package.isEmpty()) { tran->getHandle()->tra_caller_name = CallerName(routine->getObjectType(), routine->getName().identifier); } else { tran->getHandle()->tra_caller_name = CallerName(obj_package_header, routine->getName().package); } } else tran->getHandle()->tra_caller_name = CallerName(); } m_request.assignRefNoIncr(att->prepare(&status, tran, sql.length(), sql.c_str(), m_connection.getSqlDialect(), 0)); m_allocated = (m_request != NULL); tran->getHandle()->tra_caller_name = save_caller_name; } if (status->getState() & IStatus::STATE_ERRORS) raise(&status, tdbb, "JAttachment::prepare", &sql); const DsqlCompiledStatement* statement = m_request->getHandle()->getStatement(); if (statement->getSendMsg()) { try { PreparedStatement::parseDsqlMessage(statement->getSendMsg(), m_inDescs, m_inMetadata, m_in_buffer); m_inputs = m_inMetadata->getCount(); } catch (const Exception&) { raise(tdbb->tdbb_status_vector, tdbb, "parse input message", &sql); } } else m_inputs = 0; if (statement->getReceiveMsg()) { try { PreparedStatement::parseDsqlMessage(statement->getReceiveMsg(), m_outDescs, m_outMetadata, m_out_buffer); m_outputs = m_outMetadata->getCount(); } catch (const Exception&) { raise(tdbb->tdbb_status_vector, tdbb, "parse output message", &sql); } } else m_outputs = 0; m_stmt_selectable = false; switch (statement->getType()) { case DsqlCompiledStatement::TYPE_SELECT: case DsqlCompiledStatement::TYPE_SELECT_UPD: case DsqlCompiledStatement::TYPE_SELECT_BLOCK: m_stmt_selectable = true; break; case DsqlCompiledStatement::TYPE_START_TRANS: case DsqlCompiledStatement::TYPE_COMMIT: case DsqlCompiledStatement::TYPE_ROLLBACK: case DsqlCompiledStatement::TYPE_COMMIT_RETAIN: case DsqlCompiledStatement::TYPE_ROLLBACK_RETAIN: case DsqlCompiledStatement::TYPE_CREATE_DB: Arg::Gds(isc_eds_expl_tran_ctrl).copyTo(&status); raise(&status, tdbb, "JAttachment::prepare", &sql); break; case DsqlCompiledStatement::TYPE_INSERT: case DsqlCompiledStatement::TYPE_DELETE: case DsqlCompiledStatement::TYPE_UPDATE: case DsqlCompiledStatement::TYPE_UPDATE_CURSOR: case DsqlCompiledStatement::TYPE_DELETE_CURSOR: case DsqlCompiledStatement::TYPE_DDL: case DsqlCompiledStatement::TYPE_EXEC_PROCEDURE: case DsqlCompiledStatement::TYPE_SET_GENERATOR: case DsqlCompiledStatement::TYPE_SAVEPOINT: case DsqlCompiledStatement::TYPE_EXEC_BLOCK: break; } }
const char* Switches::findNameByTag(const int in_sw) const { const in_sw_tab_t* rc = findByTag(in_sw, NULL, false); fb_assert(rc); return rc->in_sw_name; }
InternalBlob::~InternalBlob() { fb_assert(!m_blob); }
void UnitList::addUnit(Unit *unit) { fb_assert(unit != NULL); unit->setUnitListEntity(new UnitListEntity()); if (impl->tree) { float radius = UNIT_QTREE_RADIUS_HACK; // grow the radius for non-boned units only // (as boned units may have 15m radius or such because of changing animations) if (unit->getUnitType()->getBonesFilename() == NULL) { if (unit->getVisualObject() != NULL && unit->getVisualObject()->getStormModel() != NULL) { float radius2 = unit->getVisualObject()->getStormModel()->GetRadius(); if (radius2 > radius) radius = radius2; } } //Logger::getInstance()->info(int2str(radius)); unit->getUnitListEntity()->entity = impl->tree->insert(unit, unit->getPosition(), radius); unit->setUnitListRadius(radius); } allUnits->append(unit); int own = unit->getOwner(); if (own != NO_UNIT_OWNER) { if (own < 0 || own >= ABS_MAX_PLAYERS) abort(); ownedUnits[own]->append(unit); ownedUnitAmount[own]++; } allUnitAmount++; unit->setIdNumber(unitlist_nextIdNumber); int failsafecount = 0; while (true) { unitlist_nextIdNumber++; if (unitlist_nextIdNumber > UNITID_HIGHEST_POSSIBLE_VALUE) unitlist_nextIdNumber = UNITID_LOWEST_POSSIBLE_VALUE; bool alreadyTaken = false; LinkedListIterator iter(allUnits); while (iter.iterateAvailable()) { Unit *u = (Unit *)iter.iterateNext(); if (u->getIdNumber() == unitlist_nextIdNumber) { alreadyTaken = true; break; } } if (!alreadyTaken) break; failsafecount++; if (failsafecount > (UNITID_HIGHEST_POSSIBLE_VALUE - UNITID_LOWEST_POSSIBLE_VALUE + 1)) { break; } } }
void InstanceControl::registerGdsCleanup(FPTR_VOID cleanup) { fb_assert(!gdsCleanup || !cleanup || gdsCleanup == cleanup); gdsCleanup = cleanup; }
ULONG CVGB_gb2312_to_unicode(csconvert* obj, ULONG src_len, const UCHAR* src_ptr, ULONG dest_len, UCHAR* p_dest_ptr, USHORT* err_code, ULONG* err_position) { fb_assert(obj != NULL); CsConvertImpl* impl = obj->csconvert_impl; fb_assert(src_ptr != NULL || p_dest_ptr == NULL); fb_assert(err_code != NULL); fb_assert(err_position != NULL); fb_assert(obj->csconvert_fn_convert == CVGB_gb2312_to_unicode); fb_assert(impl->csconvert_datatable != NULL); fb_assert(impl->csconvert_misc != NULL); const ULONG src_start = src_len; *err_code = 0; // See if we're only after a length estimate if (p_dest_ptr == NULL) return (src_len * sizeof(USHORT)); Firebird::OutAligner<USHORT> d(p_dest_ptr, dest_len); USHORT* dest_ptr = d; USHORT wide; USHORT this_len; const USHORT* const start = dest_ptr; while (src_len && dest_len > 1) { if (*src_ptr & 0x80) { const UCHAR c1 = *src_ptr++; if (GB1(c1)) { // first byte is GB2312 if (src_len == 1) { *err_code = CS_BAD_INPUT; break; } const UCHAR c2 = *src_ptr++; if (!(GB2(c2))) { // Bad second byte *err_code = CS_BAD_INPUT; break; } wide = (c1 << 8) + c2; this_len = 2; } else { *err_code = CS_BAD_INPUT; break; } } else { // it is ASCII wide = *src_ptr++; this_len = 1; } // Convert from GB2312 to UNICODE const USHORT ch = ((const USHORT*) impl->csconvert_datatable) [((const USHORT*) impl->csconvert_misc)[(USHORT) wide / 256] + (wide % 256)]; if ((ch == CS_CANT_MAP) && !(wide == CS_CANT_MAP)) { *err_code = CS_CONVERT_ERROR; break; } *dest_ptr++ = ch; dest_len -= sizeof(*dest_ptr); src_len -= this_len; } if (src_len && !*err_code) { *err_code = CS_TRUNCATION_ERROR; } *err_position = src_start - src_len; return ((dest_ptr - start) * sizeof(*dest_ptr)); }
void InstanceControl::registerShutdown(FPTR_VOID shutdown) { fb_assert(!gdsShutdown || !shutdown); gdsShutdown = shutdown; }
ULONG CAN_encode_decode(burp_rel* relation, lstring* buffer, UCHAR* data, bool_t direction) { /************************************** * * C A N _ e n c o d e _ d e c o d e * ************************************** * * Functional description * encode and decode canonical backup. * **************************************/ const burp_fld* field; SSHORT n; XDR xdr; XDR* xdrs = &xdr; xdr_init(xdrs, buffer, direction ? XDR_ENCODE : XDR_DECODE); RCRD_OFFSET offset = 0; for (field = relation->rel_fields; field; field = field->fld_next) { if (field->fld_flags & FLD_computed) continue; UCHAR* p = data + field->fld_offset; const bool array_fld = ((field->fld_flags & FLD_array) != 0); const FLD_LENGTH length = array_fld ? 8 : field->fld_length; if (field->fld_offset >= offset) offset = field->fld_offset + length; if (field->fld_type == blr_varying && !array_fld) offset += sizeof(SSHORT); SSHORT dtype; if (field->fld_type == blr_blob || array_fld) dtype = dtype_blob; else dtype = (SSHORT) gds_cvt_blr_dtype[field->fld_type]; switch (dtype) { case dtype_text: if (!xdr_opaque(xdrs, reinterpret_cast<char*>(p), length)) { return FALSE; } break; case dtype_varying: { vary* pVary = reinterpret_cast<vary*>(p); if (!xdr_short(xdrs, reinterpret_cast<SSHORT*>(&pVary->vary_length))) { return FALSE; } if (!xdr_opaque(xdrs, reinterpret_cast<SCHAR*>(pVary->vary_string), MIN(pVary->vary_length, length))) { return FALSE; } } break; case dtype_cstring: if (xdrs->x_op == XDR_ENCODE) n = static_cast<SSHORT>(MIN(strlen(reinterpret_cast<const char*>(p)), length)); if (!xdr_short(xdrs, &n)) return FALSE; if (!xdr_opaque(xdrs, reinterpret_cast<SCHAR*>(p), n)) return FALSE; if (xdrs->x_op == XDR_DECODE) p[n] = 0; break; case dtype_short: if (!xdr_short(xdrs, (SSHORT *) p)) return FALSE; break; case dtype_long: case dtype_sql_time: case dtype_sql_date: if (!xdr_long(xdrs, (SLONG *) p)) return FALSE; break; case dtype_real: if (!xdr_float(xdrs, (float *) p)) return FALSE; break; case dtype_double: if (!xdr_double(xdrs, (double *) p)) return FALSE; break; case dtype_timestamp: if (!xdr_long(xdrs, &((SLONG*) p)[0])) return FALSE; if (!xdr_long(xdrs, &((SLONG*) p)[1])) return FALSE; break; case dtype_quad: case dtype_blob: if (!xdr_quad(xdrs, (SQUAD*) p)) return FALSE; break; case dtype_int64: if (!xdr_hyper(xdrs, (SINT64*) p)) return FALSE; break; case dtype_boolean: if (!xdr_opaque(xdrs, (SCHAR*) p, length)) return FALSE; break; default: fb_assert(FALSE); return FALSE; } } // Next, get null flags for (field = relation->rel_fields; field; field = field->fld_next) { if (field->fld_flags & FLD_computed) continue; offset = FB_ALIGN(offset, sizeof(SSHORT)); UCHAR* p = data + offset; if (!xdr_short(xdrs, (SSHORT*) p)) return FALSE; offset += sizeof(SSHORT); } return (xdrs->x_private - xdrs->x_base); }
static int read_and_write_for_join(FILE_DESC output_fl_desc, const TEXT* file_name, UCHAR* io_buffer, SLONG cnt, SLONG* total_int) { /******************************************************************** ** ** r e a d _ a n d _ w r i t e _ f o r _ j o i n ** ********************************************************************* ** ** Functional description: ** ** Reads data from backup files and writes to standard ** output file. ** ********************************************************************* */ TEXT num_arr[5], total_arr[5]; header_rec hdr_rec; FILE_DESC input_fl_desc = open_platf(file_name, mode_read); if (input_fl_desc == INVALID_HANDLE_VALUE) { fprintf(stderr, "can not open input file %s\n", file_name); return FB_FAILURE; } int read_cnt = read_platf(input_fl_desc, io_buffer, header_rec_len); if (read_cnt != static_cast<int>(header_rec_len)) { close_platf(input_fl_desc); fprintf(stderr, "progam fails to read gsplit header record in back-up file%s\n", file_name); return FB_FAILURE; } const TEXT* char_ptr1 = reinterpret_cast<char*>(io_buffer); SLONG ret_cd = strncmp(char_ptr1, header_rec_name, sizeof(hdr_rec.name) - 1); if (ret_cd != 0) { close_platf(input_fl_desc); fprintf(stderr, "gsplit: expected GSPLIT description record\n"); fprintf(stderr, "gsplit: Exiting before completion due to errors\n"); return FB_FAILURE; } SLONG skip_to_num = sizeof(hdr_rec.name) + sizeof(hdr_rec.date_time) + sizeof(hdr_rec.text1); SLONG skip_to_total = skip_to_num + sizeof(hdr_rec.num) + sizeof(hdr_rec.text2); char_ptr1 = reinterpret_cast<char*>(io_buffer + skip_to_num); const TEXT* char_ptr2 = reinterpret_cast<char*>(io_buffer + skip_to_total); size_t indx; for (indx = 0; indx < sizeof(hdr_rec.num); indx++) { num_arr[indx] = *char_ptr1; char_ptr1++; if (cnt == 1) { total_arr[indx] = *char_ptr2; char_ptr2++; } } num_arr[indx] = '\0'; const SLONG num_int = atoi(num_arr); if (cnt == 1) { total_arr[indx] = '\0'; *total_int = atoi(total_arr); } if ((num_int != cnt) || (num_int > *total_int)) { close_platf(input_fl_desc); fprintf(stderr, "gsplit: join backup file is out of sequence\n"); fprintf(stderr, "gsplit: Exiting before completion due to errors\n"); return FB_FAILURE; } read_cnt = read_platf(input_fl_desc, io_buffer, IO_BUFFER_SIZE); while (true) { switch (read_cnt) { case 0: // no more data to be read close_platf(input_fl_desc); return FB_SUCCESS; case -1: // read failed close_platf(input_fl_desc); return FB_FAILURE; default: // this is the last read break; } SLONG write_cnt = write_platf(output_fl_desc, io_buffer, read_cnt); switch (write_cnt) { case -1: // write failed close_platf(input_fl_desc); return FB_FAILURE; default: fb_assert(write_cnt == read_cnt); break; } read_cnt = read_platf(input_fl_desc, io_buffer, IO_BUFFER_SIZE); } // end of while (true) loop }
bool GlobalRWLock::lockRead(thread_db* tdbb, SSHORT wait, const bool queueJump) { SET_TDBB(tdbb); Database* dbb = tdbb->getDatabase(); bool needFetch; { // scope 1 Database::CheckoutLockGuard counterGuard(dbb, counterMutex); COS_TRACE(("(%p)->lockRead stage 1 readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)", this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical)); while (true) { if (readers > 0 && queueJump) { COS_TRACE(("(%p)->lockRead queueJump", this)); readers++; return true; } while (pendingWriters > 0 || currentWriter) { Database::Checkout checkoutDbb(dbb); writerFinished.wait(counterMutex); } COS_TRACE(("(%p)->lockRead stage 3 readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)", this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical)); if (!pendingLock) break; counterMutex.leave(); Database::Checkout checkoutDbb(dbb); counterMutex.enter(); } needFetch = cachedLock->lck_physical < LCK_read; if (!needFetch) { ++readers; return true; } ++pendingLock; fb_assert(cachedLock->lck_physical == LCK_none); } if (!LCK_lock(tdbb, cachedLock, LCK_read, wait)) { Database::CheckoutLockGuard counterGuard(dbb, counterMutex); --pendingLock; return false; } { // scope 2 Database::CheckoutLockGuard counterGuard(dbb, counterMutex); --pendingLock; ++readers; COS_TRACE(("(%p)->lockRead end readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)", this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical)); return fetch(tdbb); } }
void ConfigStorage::checkFile() { if (m_cfg_file >= 0) return; char* cfg_file_name = m_sharedMemory->getHeader()->cfg_file_name; if (!(*cfg_file_name)) { fb_assert(m_sharedMemory->getHeader()->cnt_uses == 0); char dir[MAXPATHLEN]; iscPrefixLock(dir, "", true); PathName filename = TempFile::create("fb_trace_", dir); filename.copyTo(cfg_file_name, sizeof(m_sharedMemory->getHeader()->cfg_file_name)); m_cfg_file = os_utils::openCreateSharedFile(cfg_file_name, O_BINARY); } else { m_cfg_file = ::open(cfg_file_name, O_RDWR | O_BINARY); if (m_cfg_file < 0) checkFileError(cfg_file_name, "open", isc_io_open_err); } // put default (audit) trace file contents into storage if (m_sharedMemory->getHeader()->change_number == 0) { FILE* cfgFile = NULL; try { PathName configFileName(Config::getAuditTraceConfigFile()); // remove quotes around path if present { // scope const FB_SIZE_T pathLen = configFileName.length(); if (pathLen > 1 && configFileName[0] == '"' && configFileName[pathLen - 1] == '"') { configFileName.erase(0, 1); configFileName.erase(pathLen - 2, 1); } } if (configFileName.empty()) return; if (PathUtils::isRelative(configFileName)) { PathName root(Config::getRootDirectory()); PathUtils::ensureSeparator(root); configFileName.insert(0, root); } cfgFile = fopen(configFileName.c_str(), "rb"); if (!cfgFile) { checkFileError(configFileName.c_str(), "fopen", isc_io_open_err); } TraceSession session(*getDefaultMemoryPool()); fseek(cfgFile, 0, SEEK_END); const long len = ftell(cfgFile); if (len) { fseek(cfgFile, 0, SEEK_SET); char* p = session.ses_config.getBuffer(len + 1); if (fread(p, 1, len, cfgFile) != size_t(len)) { checkFileError(configFileName.c_str(), "fread", isc_io_read_err); } p[len] = 0; } else { gds__log("Audit configuration file \"%s\" is empty", configFileName.c_str()); } session.ses_user = SYSDBA_USER_NAME; session.ses_name = "Firebird Audit"; session.ses_flags = trs_admin | trs_system; addSession(session); } catch(const Exception& ex) { ISC_STATUS_ARRAY temp; ex.stuff_exception(temp); iscLogStatus("Cannot open audit configuration file", temp); } if (cfgFile) { fclose(cfgFile); } } }
static SSHORT unicodeCompare(texttype* tt, ULONG len1, const UCHAR* str1, ULONG len2, const UCHAR* str2, INTL_BOOL* errorFlag) { TextTypeImpl* impl = static_cast<TextTypeImpl*>(tt->texttype_impl); try { *errorFlag = false; charset* cs = impl->cs; HalfStaticArray<UCHAR, BUFFER_SMALL> utf16Str1; HalfStaticArray<UCHAR, BUFFER_SMALL> utf16Str2; USHORT errorCode; ULONG offendingPos; utf16Str1.getBuffer( cs->charset_to_unicode.csconvert_fn_convert( &cs->charset_to_unicode, len1, str1, 0, NULL, &errorCode, &offendingPos)); const ULONG utf16Len1 = cs->charset_to_unicode.csconvert_fn_convert( &cs->charset_to_unicode, len1, str1, utf16Str1.getCapacity(), utf16Str1.begin(), &errorCode, &offendingPos); utf16Str2.getBuffer( cs->charset_to_unicode.csconvert_fn_convert( &cs->charset_to_unicode, len2, str2, 0, NULL, &errorCode, &offendingPos)); const ULONG utf16Len2 = cs->charset_to_unicode.csconvert_fn_convert( &cs->charset_to_unicode, len2, str2, utf16Str2.getCapacity(), utf16Str2.begin(), &errorCode, &offendingPos); return impl->collation->compare(utf16Len1, (USHORT*)utf16Str1.begin(), utf16Len2, (USHORT*)utf16Str2.begin(), errorFlag); } catch (const BadAlloc&) { fb_assert(false); return 0; } }
dsc& ResultSet::getDesc(unsigned param) { fb_assert(param > 0); return stmt->outValues[(param - 1) * 2]; }