Beispiel #1
0
/**
 * Set state of TDS connection, with logging and checking.
 * \param tds	  state information for the socket and the TDS protocol
 * \param state	  the new state of the connection, cf. TDS_STATE.
 * \return 	  the new state, which might not be \a state.
 */
TDS_STATE
tds_set_state(TDSSOCKET * tds, TDS_STATE state)
{
	const TDS_STATE prior_state = tds->state;
	static const char state_names[][10] = {
		"IDLE",
	        "QUERYING",
	        "PENDING",
	        "READING",
	        "DEAD"
	};
	assert(state < TDS_VECTOR_SIZE(state_names));
	assert(tds->state < TDS_VECTOR_SIZE(state_names));
	
	if (state == tds->state)
		return state;
	
	switch(state) {
		/* transition to READING are valid only from PENDING */
	case TDS_PENDING:
		if (tds->state != TDS_READING && tds->state != TDS_QUERYING) {
			tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", 
							state_names[prior_state], state_names[state]);
			return tds->state;
		}
		tds->state = state;
		break;
	case TDS_READING:
		if (tds->state != TDS_PENDING) {
			tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", 
							state_names[prior_state], state_names[state]);
			return tds->state;
		}
		tds->state = state;
		break;
	case TDS_IDLE:
		if (tds->state == TDS_DEAD && TDS_IS_SOCKET_INVALID(tds_get_s(tds))) {
			tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n",
				state_names[prior_state], state_names[state]);
			return tds->state;
		}
	case TDS_DEAD:
		tds->state = state;
		break;
	case TDS_QUERYING:
		CHECK_TDS_EXTRA(tds);

		if (tds->state == TDS_DEAD) {
			tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", 
							state_names[prior_state], state_names[state]);
			tdserror(tds_get_ctx(tds), tds, TDSEWRIT, 0);
			break;
		} else if (tds->state != TDS_IDLE) {
			tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", 
							state_names[prior_state], state_names[state]);
			tdserror(tds_get_ctx(tds), tds, TDSERPND, 0);
			break;
		}

		/* TODO check this code, copied from tds_submit_prepare */
		tds_free_all_results(tds);
		tds->rows_affected = TDS_NO_COUNT;
		tds_release_cursor(tds, tds->cur_cursor);
		tds->cur_cursor = NULL;
		tds->internal_sp_called = 0;

		tds->state = state;
		break;
	default:
		assert(0);
		break;
	}
	
	tdsdump_log(TDS_DBG_ERROR, "Changed query state from %s to %s\n", state_names[prior_state], state_names[state]);
	CHECK_TDS_EXTRA(tds);
	
	return tds->state; 
}
Beispiel #2
0
/**
 * Set state of TDS connection, with logging and checking.
 * \param tds	  state information for the socket and the TDS protocol
 * \param state	  the new state of the connection, cf. TDS_STATE.
 * \return 	  the new state, which might not be \a state.
 */
TDS_STATE
tds_set_state(TDSSOCKET * tds, TDS_STATE state)
{
	TDS_STATE prior_state;
	static const char state_names[][8] = {
		"IDLE",
	        "WRITING",
	        "SENDING",
	        "PENDING",
	        "READING",
	        "DEAD"
	};
	assert(state < TDS_VECTOR_SIZE(state_names));
	assert(tds->state < TDS_VECTOR_SIZE(state_names));

	prior_state = tds->state;
	if (state == prior_state)
		return state;

	switch(state) {
	case TDS_PENDING:
		if (prior_state == TDS_READING || prior_state == TDS_WRITING) {
			tds->state = TDS_PENDING;
			tds_mutex_unlock(&tds->wire_mtx);
			break;
		}
		tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n",
						state_names[prior_state], state_names[state]);
		break;
	case TDS_READING:
		/* transition to READING are valid only from PENDING */
		if (tds_mutex_trylock(&tds->wire_mtx))
			return tds->state;
		if (tds->state != TDS_PENDING) {
			tds_mutex_unlock(&tds->wire_mtx);
			tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", 
							state_names[prior_state], state_names[state]);
			break;
		}
		tds->state = state;
		break;
	case TDS_SENDING:
		if (prior_state != TDS_READING && prior_state != TDS_WRITING) {
			tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n",
				state_names[prior_state], state_names[state]);
			break;
		}
		if (tds->state == TDS_READING) {
			/* TODO check this code, copied from tds_submit_prepare */
			tds_free_all_results(tds);
			tds->rows_affected = TDS_NO_COUNT;
			tds_release_cursor(&tds->cur_cursor);
			tds_release_cur_dyn(tds);
			tds->current_op = TDS_OP_NONE;
		}

		tds_mutex_unlock(&tds->wire_mtx);
		tds->state = state;
		break;
	case TDS_IDLE:
		if (prior_state == TDS_DEAD && TDS_IS_SOCKET_INVALID(tds_get_s(tds))) {
			tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n",
				state_names[prior_state], state_names[state]);
			break;
		}
	case TDS_DEAD:
		if (prior_state == TDS_READING || prior_state == TDS_WRITING)
			tds_mutex_unlock(&tds->wire_mtx);
		tds->state = state;
		break;
	case TDS_WRITING:
		CHECK_TDS_EXTRA(tds);

		if (tds_mutex_trylock(&tds->wire_mtx))
			return tds->state;

		if (tds->state == TDS_DEAD) {
			tds_mutex_unlock(&tds->wire_mtx);
			tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", 
							state_names[prior_state], state_names[state]);
			tdserror(tds_get_ctx(tds), tds, TDSEWRIT, 0);
			break;
		} else if (tds->state != TDS_IDLE && tds->state != TDS_SENDING) {
			tds_mutex_unlock(&tds->wire_mtx);
			tdsdump_log(TDS_DBG_ERROR, "logic error: cannot change query state from %s to %s\n", 
							state_names[prior_state], state_names[state]);
			tdserror(tds_get_ctx(tds), tds, TDSERPND, 0);
			break;
		}

		if (tds->state == TDS_IDLE) {
			/* TODO check this code, copied from tds_submit_prepare */
			tds_free_all_results(tds);
			tds->rows_affected = TDS_NO_COUNT;
			tds_release_cursor(&tds->cur_cursor);
			tds_release_cur_dyn(tds);
			tds->current_op = TDS_OP_NONE;
		}

		tds->state = state;
		break;
	default:
		assert(0);
		break;
	}

	state = tds->state;

	tdsdump_log(TDS_DBG_ERROR, "Changed query state from %s to %s\n", state_names[prior_state], state_names[state]);
	CHECK_TDS_EXTRA(tds);

	return state;
}