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);
	}
}
Exemple #3
0
INTL_BOOL IntlUtil::utf8WellFormed(charset* cs, ULONG len, const UCHAR* str, ULONG* offendingPos)
{
	fb_assert(cs != NULL);
	return UnicodeUtil::utf8WellFormed(len, str, offendingPos);
}
Exemple #4
0
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));
}
Exemple #5
0
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;
}
Exemple #6
0
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);
}
Exemple #7
0
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
}
Exemple #10
0
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;
}
Exemple #11
0
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);
}
Exemple #12
0
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;
	}
}
Exemple #13
0
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);
	}
}
Exemple #14
0
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;
}
Exemple #16
0
void InternalTransaction::doPrepare(FbStatusVector* /*status*/, thread_db* /*tdbb*/,
		int /*info_len*/, const char* /*info*/)
{
	fb_assert(m_transaction);
	fb_assert(false);
}
Exemple #17
0
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();
	}
}
Exemple #18
0
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;
	}
}
Exemple #19
0
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;
}
Exemple #20
0
InternalBlob::~InternalBlob()
{
	fb_assert(!m_blob);
}
Exemple #21
0
	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;
			}
		}
	}
Exemple #22
0
	void InstanceControl::registerGdsCleanup(FPTR_VOID cleanup)
	{
		fb_assert(!gdsCleanup || !cleanup || gdsCleanup == cleanup);
		gdsCleanup = cleanup;
	}
Exemple #23
0
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));
}
Exemple #24
0
	void InstanceControl::registerShutdown(FPTR_VOID shutdown)
	{
		fb_assert(!gdsShutdown || !shutdown);
		gdsShutdown = shutdown;
	}
Exemple #25
0
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);
}
Exemple #26
0
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
}
Exemple #27
0
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);
		}
	}
}
Exemple #29
0
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;
	}
}
Exemple #30
0
dsc& ResultSet::getDesc(unsigned param)
{
	fb_assert(param > 0);
	return stmt->outValues[(param - 1) * 2];
}