Esempio n. 1
0
/**
 * gda_xa_transaction_begin:
 * @xa_trans: a #GdaXaTransaction object
 * @error: (nullable): a place to store errors, or %NULL
 *
 * Begins a distributed transaction (managed by @xa_trans). Please note that this phase may fail
 * for some connections if a (normal) transaction is already started (this depends on the database
 * provider being used), so it's better to avoid starting any (normal) transaction on any of the
 * connections registered with @xa_trans.
 *
 * Returns: TRUE if no error occurred
 */
gboolean
gda_xa_transaction_begin  (GdaXaTransaction *xa_trans, GError **error)
{
	GList *list;
	g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE);
	GdaXaTransactionPrivate *priv = gda_xa_transaction_get_instance_private (xa_trans);
	
	for (list = priv->cnc_list; list; list = list->next) {
		GdaConnection *cnc;
		GdaServerProvider *prov;
		
		cnc = GDA_CONNECTION (list->data);
		prov = gda_connection_get_provider (cnc);
		if (cnc != priv->non_xa_cnc) {
			GdaBinary *branch;
			branch = g_hash_table_lookup (priv->cnc_hash, cnc);
			memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */
				gda_binary_get_data (branch), gda_binary_get_size (branch));
			if (! _gda_server_provider_xa_start (prov, cnc, &(priv->xid), error))
				break;
		}
		else {
			/* do a simple BEGIN */
			if (! gda_connection_begin_transaction (cnc, NULL, GDA_TRANSACTION_ISOLATION_UNKNOWN,
								error))
				break;
		}
	}

	if (list) {
		/* something went wrong */
		for (; list; list = list->prev) {
			GdaConnection *cnc;
			GdaServerProvider *prov;
			
			cnc = GDA_CONNECTION (list->data);
			prov = gda_connection_get_provider (cnc);
			if (cnc != priv->non_xa_cnc) {
				GdaBinary *branch;
				branch = g_hash_table_lookup (priv->cnc_hash, cnc);
				memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */
					gda_binary_get_data (branch), gda_binary_get_size (branch));
				_gda_server_provider_xa_rollback (prov, cnc, &(priv->xid), NULL);
			}
			else {
				/* do a simple ROLLBACK */
				gda_connection_rollback_transaction (cnc, NULL, NULL);
			}
		}
		return FALSE;
	}
	return TRUE;
}
/**
 * gda_xa_transaction_rollback:
 * @xa_trans: a #GdaXaTransaction object
 * @error: (allow-none): a place to store errors, or %NULL
 *
 * Cancels a distributed transaction (managed by @xa_trans). 
 *
 * Returns: %TRUE if no error occurred
 */
gboolean
gda_xa_transaction_rollback (GdaXaTransaction *xa_trans, GError **error)
{
	GList *list;
	g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE);
	
	for (list = xa_trans->priv->cnc_list; list; list = list->next) {
		GdaConnection *cnc;
		GdaServerProvider *prov;

		cnc = GDA_CONNECTION (list->data);
		prov = gda_connection_get_provider (cnc);
		
		if (cnc == xa_trans->priv->non_xa_cnc) 
			gda_connection_rollback_transaction (cnc, NULL, NULL);
		else {
			const GdaBinary *branch;
			branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc);
			memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */
				branch->data, branch->binary_length);
			if (!PROV_CLASS (prov)->xa_funcs->xa_rollback) 
				g_warning (_("Provider error: %s method not implemented for provider %s"),
					   "xa_prepare()", gda_server_provider_get_name (prov));
			else
				PROV_CLASS (prov)->xa_funcs->xa_rollback (prov, cnc, &(xa_trans->priv->xid), error);
		}
	}
	return TRUE;
}
Esempio n. 3
0
/**
 * gda_xa_transaction_rollback:
 * @xa_trans: a #GdaXaTransaction object
 * @error: (nullable): a place to store errors, or %NULL
 *
 * Cancels a distributed transaction (managed by @xa_trans). 
 *
 * Returns: %TRUE if no error occurred
 */
gboolean
gda_xa_transaction_rollback (GdaXaTransaction *xa_trans, GError **error)
{
	GList *list;
	g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE);
	GdaXaTransactionPrivate *priv = gda_xa_transaction_get_instance_private (xa_trans);
	
	for (list = priv->cnc_list; list; list = list->next) {
		GdaConnection *cnc;
		GdaServerProvider *prov;

		cnc = GDA_CONNECTION (list->data);
		prov = gda_connection_get_provider (cnc);
		
		if (cnc == priv->non_xa_cnc)
			gda_connection_rollback_transaction (cnc, NULL, NULL);
		else {
			GdaBinary *branch;
			branch = g_hash_table_lookup (priv->cnc_hash, cnc);
			memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */
				gda_binary_get_data (branch), gda_binary_get_size (branch));
			GError *lerror = NULL;
			_gda_server_provider_xa_rollback (prov, cnc, &(priv->xid), &lerror);
			if (error && !*error)
				g_propagate_error (error, lerror);
			else
				g_clear_error (&lerror);
		}
	}
	return TRUE;
}
/**
 * gda_xa_transaction_commit_recovered:
 * @xa_trans: a #GdaXaTransaction object
 * @cnc_to_recover: (allow-none) (element-type Gda.Connection) (out callee-allocates): a place to store the list of connections for which the there were data to recover and which failed to be actually committed, or %NULL
 * @error: (allow-none): a place to store errors, or %NULL
 *
 * Tries to commit the data prepared but which failed to commit (see gda_xa_transaction_commit()). This
 * method allows one to terminate a distributed transaction which succeeded but for which some
 * connections needed to be recovered.
 *
 * Returns: %TRUE if all the data which was still uncommitted has been committed
 */
gboolean
gda_xa_transaction_commit_recovered (GdaXaTransaction *xa_trans, GSList **cnc_to_recover, GError **error)
{
	GList *list;
	gboolean retval = TRUE;
	
	if (cnc_to_recover)
		*cnc_to_recover = NULL;
	g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE);
	
	for (list = xa_trans->priv->cnc_list; list; list = list->next) {
		GdaConnection *cnc;
		GdaServerProvider *prov;

		cnc = GDA_CONNECTION (list->data);
		prov = gda_connection_get_provider (cnc);
		
		if (cnc == xa_trans->priv->non_xa_cnc) 
			continue;
		else {
			GList *recov_xid_list;
			

			if (!PROV_CLASS (prov)->xa_funcs->xa_recover) 
				g_warning (_("Provider error: %s method not implemented for provider %s"),
					   "xa_recover()", gda_server_provider_get_name (prov));
			else {
				const GdaBinary *branch;
				GList *xlist;
				gboolean commit_needed = FALSE;
				
				recov_xid_list = PROV_CLASS (prov)->xa_funcs->xa_recover (prov, cnc, error);
				if (!recov_xid_list)
					continue;

				branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc);
				memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */
					branch->data, branch->binary_length);
				for (xlist = recov_xid_list; xlist; xlist = xlist->next) {
					GdaXaTransactionId *xid = (GdaXaTransactionId*) xlist->data;
					if (!xid)
						/* ignore unknown XID format */
						continue;

					if (!commit_needed &&
					    (xid->format == xa_trans->priv->xid.format) &&
					    (xid->gtrid_length == xa_trans->priv->xid.gtrid_length) &&
					    (xid->bqual_length == xa_trans->priv->xid.bqual_length) &&
					    ! memcmp (xa_trans->priv->xid.data, xid->data, xid->bqual_length + xid->bqual_length)) 
						/* found a transaction to commit */
						commit_needed = TRUE;
						
					g_free (xid);
				}
				g_list_free (recov_xid_list);

				if (commit_needed) {
					if (!PROV_CLASS (prov)->xa_funcs->xa_commit) {
						g_warning (_("Provider error: %s method not implemented for provider %s"),
							   "xa_commit()", gda_server_provider_get_name (prov));
						retval = FALSE;
					}
					else {
						retval = PROV_CLASS (prov)->xa_funcs->xa_commit (prov, cnc, 
												 &(xa_trans->priv->xid), 
												 error);
						if (!retval)
							if (cnc_to_recover)
								*cnc_to_recover = g_slist_prepend (*cnc_to_recover, cnc);
					}
				}
			}
		}
	}
	return retval;	
}
/**
 * gda_xa_transaction_commit:
 * @xa_trans: a #GdaXaTransaction object
 * @cnc_to_recover: (allow-none) (element-type Gda.Connection) (out callee-allocates): a place to store the list of connections for which the commit phase failed, or %NULL
 * @error: a place to store errors, or %NULL
 *
 * Commits a distributed transaction (managed by @xa_trans). The commit is composed of two phases:
 * <itemizedlist>
 *   <listitem><para>a PREPARE phase where all the connections are required to store their transaction data to a 
 *     permanent place (to be able to complete the commit should a problem occur afterwards)</para></listitem>
 *   <listitem><para>a COMMIT phase where the transaction data is actually written to the database</para></listitem>
 * </itemizedlist>
 *
 * If the PREPARE phase fails for any of the connection registered with @xa_trans, then the distributed commit
 * fails and FALSE is returned. During the COMMIT phase, some commit may actually fail but the transaction can
 * still be completed because the PREPARE phase succeeded (through the recover method).
 *
 * Returns: TRUE if no error occurred (there may be some connections to recover, though)
 */
gboolean
gda_xa_transaction_commit (GdaXaTransaction *xa_trans, GSList **cnc_to_recover, GError **error)
{
	GList *list;
	if (cnc_to_recover)
		*cnc_to_recover = NULL;

	g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE);
	
	/* 
	 * PREPARE phase 
	 */
	for (list = xa_trans->priv->cnc_list; list; list = list->next) {
		GdaConnection *cnc = NULL;
		GdaServerProvider *prov;
		const GdaBinary *branch;
		
		if (cnc == xa_trans->priv->non_xa_cnc)
			continue;

		cnc = GDA_CONNECTION (list->data);
		prov = gda_connection_get_provider (cnc);

		branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc);
		memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */
			branch->data, branch->binary_length);

		if (PROV_CLASS (prov)->xa_funcs->xa_end && 
		    !PROV_CLASS (prov)->xa_funcs->xa_end (prov, cnc, &(xa_trans->priv->xid), error))
			break;

		if (!PROV_CLASS (prov)->xa_funcs->xa_prepare) {
			g_warning (_("Provider error: %s method not implemented for provider %s"),
				   "xa_prepare()", gda_server_provider_get_name (prov));
			break;
		}
		if (!PROV_CLASS (prov)->xa_funcs->xa_commit) {
			g_warning (_("Provider error: %s method not implemented for provider %s"),
				   "xa_commit()", gda_server_provider_get_name (prov));
			break;
		}

		if (!PROV_CLASS (prov)->xa_funcs->xa_prepare (prov, cnc, &(xa_trans->priv->xid), error))
			break;
	}
	if (list) {
		/* something went wrong during the PREPARE phase => rollback everything */
		for (; list; list = list->prev) {
			GdaConnection *cnc = NULL;
			GdaServerProvider *prov;
			
			if (cnc == xa_trans->priv->non_xa_cnc) 
				gda_connection_rollback_transaction (cnc, NULL, NULL);
			else {
				const GdaBinary *branch;
				cnc = GDA_CONNECTION (list->data);
				prov = gda_connection_get_provider (cnc);
				branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc);
				memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */
					branch->data, branch->binary_length);

				if (PROV_CLASS (prov)->xa_funcs->xa_rollback)
					PROV_CLASS (prov)->xa_funcs->xa_rollback (prov, cnc, &(xa_trans->priv->xid), NULL);
				else
					g_warning (_("Provider error: %s method not implemented for provider %s"),
						   "xa_rollback()", gda_server_provider_get_name (prov));
			}
		}
		return FALSE;
	}

	/*
	 * COMMIT phase 
	 */
	if (xa_trans->priv->non_xa_cnc &&
	    ! gda_connection_commit_transaction (xa_trans->priv->non_xa_cnc, NULL, error)) {
		/* something went wrong => rollback everything */
		for (list = xa_trans->priv->cnc_list; list; list = list->next) {
			GdaConnection *cnc = NULL;
			GdaServerProvider *prov;
			
			if (cnc == xa_trans->priv->non_xa_cnc)
				gda_connection_rollback_transaction (cnc, NULL, NULL);
			else {
				const GdaBinary *branch;
				cnc = GDA_CONNECTION (list->data);
				prov = gda_connection_get_provider (cnc);
				branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc);
				memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */
					branch->data, branch->binary_length);

				if (PROV_CLASS (prov)->xa_funcs->xa_rollback)
					PROV_CLASS (prov)->xa_funcs->xa_rollback (prov, cnc, &(xa_trans->priv->xid), NULL);
				else
					g_warning (_("Provider error: %s method not implemented for provider %s"),
						   "xa_rollback()", gda_server_provider_get_name (prov));
			}
		}
		return FALSE;
	}

	for (list = xa_trans->priv->cnc_list; list; list = list->next) {
		GdaConnection *cnc = NULL;
		GdaServerProvider *prov;
		const GdaBinary *branch;
		
		if (cnc == xa_trans->priv->non_xa_cnc)
			continue;

		cnc = GDA_CONNECTION (list->data);
		prov = gda_connection_get_provider (cnc);
		branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc);
		memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */
			branch->data, branch->binary_length);
		if (!PROV_CLASS (prov)->xa_funcs->xa_commit (prov, cnc, &(xa_trans->priv->xid), error) &&
		    cnc_to_recover)
			*cnc_to_recover = g_slist_prepend (*cnc_to_recover, cnc);
	}
	
	return TRUE;
}
/**
 * gda_xa_transaction_begin:
 * @xa_trans: a #GdaXaTransaction object
 * @error: (allow-none): a place to store errors, or %NULL
 *
 * Begins a distributed transaction (managed by @xa_trans). Please note that this phase may fail
 * for some connections if a (normal) transaction is already started (this depends on the database
 * provider being used), so it's better to avoid starting any (normal) transaction on any of the
 * connections registered with @xa_trans.
 *
 * Returns: TRUE if no error occurred
 */
gboolean
gda_xa_transaction_begin  (GdaXaTransaction *xa_trans, GError **error)
{
	GList *list;
	g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE);
	
	for (list = xa_trans->priv->cnc_list; list; list = list->next) {
		GdaConnection *cnc;
		GdaServerProvider *prov;
		
		cnc = GDA_CONNECTION (list->data);
		prov = gda_connection_get_provider (cnc);
		if (cnc != xa_trans->priv->non_xa_cnc) {
			if (!PROV_CLASS (prov)->xa_funcs->xa_start) {
				g_warning (_("Provider error: %s method not implemented for provider %s"),
					   "xa_start()", gda_server_provider_get_name (prov));
				break;
			}
			else {
				const GdaBinary *branch;
				branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc);
				memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */
					branch->data, branch->binary_length);
				if (!PROV_CLASS (prov)->xa_funcs->xa_start (prov, cnc, &(xa_trans->priv->xid), error))
					break;
			}
		}
		else {
			/* do a simple BEGIN */
			if (! gda_connection_begin_transaction (cnc, NULL, GDA_TRANSACTION_ISOLATION_UNKNOWN,
								error))
				break;
		}
	}

	if (list) {
		/* something went wrong */
		for (; list; list = list->prev) {
			GdaConnection *cnc;
			GdaServerProvider *prov;
			
			cnc = GDA_CONNECTION (list->data);
			prov = gda_connection_get_provider (cnc);
			if (cnc != xa_trans->priv->non_xa_cnc) {
				if (!PROV_CLASS (prov)->xa_funcs->xa_rollback) 
					g_warning (_("Provider error: %s method not implemented for provider %s"),
						   "xa_rollback()", gda_server_provider_get_name (prov));
				else {
					const GdaBinary *branch;
					branch = g_hash_table_lookup (xa_trans->priv->cnc_hash, cnc);
					memcpy (xa_trans->priv->xid.data + xa_trans->priv->xid.gtrid_length, /* Flawfinder: ignore */
						branch->data, branch->binary_length);
					PROV_CLASS (prov)->xa_funcs->xa_rollback (prov, cnc, &(xa_trans->priv->xid), NULL);
				}
			}
			else {
				/* do a simple ROLLBACK */
				gda_connection_rollback_transaction (cnc, NULL, NULL);
			}
		}
		return FALSE;
	}
	return TRUE;
}
Esempio n. 7
0
/**
 * gda_xa_transaction_commit_recovered:
 * @xa_trans: a #GdaXaTransaction object
 * @cnc_to_recover: (nullable) (element-type Gda.Connection) (out callee-allocates): a place to store the list of connections for which the there were data to recover and which failed to be actually committed, or %NULL
 * @error: (nullable): a place to store errors, or %NULL
 *
 * Tries to commit the data prepared but which failed to commit (see gda_xa_transaction_commit()). This
 * method allows one to terminate a distributed transaction which succeeded but for which some
 * connections needed to be recovered.
 *
 * Returns: %TRUE if all the data which was still uncommitted has been committed
 */
gboolean
gda_xa_transaction_commit_recovered (GdaXaTransaction *xa_trans, GSList **cnc_to_recover, GError **error)
{
	GList *list;
	gboolean retval = TRUE;
	
	if (cnc_to_recover)
		*cnc_to_recover = NULL;
	g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE);
	GdaXaTransactionPrivate *priv = gda_xa_transaction_get_instance_private (xa_trans);
	
	for (list = priv->cnc_list; list; list = list->next) {
		GdaConnection *cnc;
		GdaServerProvider *prov;

		cnc = GDA_CONNECTION (list->data);
		prov = gda_connection_get_provider (cnc);
		
		if (cnc == priv->non_xa_cnc)
			continue;
		else {
			GList *recov_xid_list;
			
			GdaBinary *branch;
			GList *xlist;
			gboolean commit_needed = FALSE;
				
			recov_xid_list = _gda_server_provider_xa_recover (prov, cnc, error);
			if (!recov_xid_list)
				continue;

			branch = g_hash_table_lookup (priv->cnc_hash, cnc);
			memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */
				gda_binary_get_data (branch), gda_binary_get_size (branch));
			for (xlist = recov_xid_list; xlist; xlist = xlist->next) {
				GdaXaTransactionId *xid = (GdaXaTransactionId*) xlist->data;
				if (!xid)
					/* ignore unknown XID format */
					continue;

				if (!commit_needed &&
				    (xid->format == priv->xid.format) &&
				    (xid->gtrid_length == priv->xid.gtrid_length) &&
				    (xid->bqual_length == priv->xid.bqual_length) &&
				    ! memcmp (priv->xid.data, xid->data, xid->bqual_length + xid->bqual_length))
					/* found a transaction to commit */
					commit_needed = TRUE;
				
				g_free (xid);
			}
			g_list_free (recov_xid_list);

			if (commit_needed) {
				retval = _gda_server_provider_xa_commit (prov, cnc, &(priv->xid), error);
				if (!retval)
					if (cnc_to_recover)
						*cnc_to_recover = g_slist_prepend (*cnc_to_recover, cnc);
			}
		}
	}
	return retval;	
}
Esempio n. 8
0
/**
 * gda_xa_transaction_commit:
 * @xa_trans: a #GdaXaTransaction object
 * @cnc_to_recover: (nullable) (element-type Gda.Connection) (out callee-allocates): a place to store the list of connections for which the commit phase failed, or %NULL
 * @error: a place to store errors, or %NULL
 *
 * Commits a distributed transaction (managed by @xa_trans). The commit is composed of two phases:
 * <itemizedlist>
 *   <listitem><para>a PREPARE phase where all the connections are required to store their transaction data to a 
 *     permanent place (to be able to complete the commit should a problem occur afterwards)</para></listitem>
 *   <listitem><para>a COMMIT phase where the transaction data is actually written to the database</para></listitem>
 * </itemizedlist>
 *
 * If the PREPARE phase fails for any of the connection registered with @xa_trans, then the distributed commit
 * fails and FALSE is returned. During the COMMIT phase, some commit may actually fail but the transaction can
 * still be completed because the PREPARE phase succeeded (through the recover method).
 *
 * Returns: TRUE if no error occurred (there may be some connections to recover, though)
 */
gboolean
gda_xa_transaction_commit (GdaXaTransaction *xa_trans, GSList **cnc_to_recover, GError **error)
{
	GList *list;
	if (cnc_to_recover)
		*cnc_to_recover = NULL;

	g_return_val_if_fail (GDA_IS_XA_TRANSACTION (xa_trans), FALSE);
	GdaXaTransactionPrivate *priv = gda_xa_transaction_get_instance_private (xa_trans);
	
	/* 
	 * PREPARE phase 
	 */
	for (list = priv->cnc_list; list; list = list->next) {
		GdaConnection *cnc = NULL;
		GdaServerProvider *prov;
		GdaBinary *branch;
		
		if (cnc == priv->non_xa_cnc)
			continue;

		cnc = GDA_CONNECTION (list->data);
		prov = gda_connection_get_provider (cnc);

		branch = g_hash_table_lookup (priv->cnc_hash, cnc);
		memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */
			gda_binary_get_data (branch), gda_binary_get_size (branch));

		if (!_gda_server_provider_xa_end (prov, cnc, &(priv->xid), error))
			break;

		if (!_gda_server_provider_xa_prepare (prov, cnc, &(priv->xid), error))
			break;
	}
	if (list) {
		/* something went wrong during the PREPARE phase => rollback everything */
		for (; list; list = list->prev) {
			GdaConnection *cnc = NULL;
			GdaServerProvider *prov;
			
			if (cnc == priv->non_xa_cnc)
				gda_connection_rollback_transaction (cnc, NULL, NULL);
			else {
				GdaBinary *branch;
				cnc = GDA_CONNECTION (list->data);
				prov = gda_connection_get_provider (cnc);
				branch = g_hash_table_lookup (priv->cnc_hash, cnc);
				memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */
					gda_binary_get_data (branch), gda_binary_get_size (branch));
				_gda_server_provider_xa_rollback (prov, cnc, &(priv->xid), NULL);
			}
		}
		return FALSE;
	}

	/*
	 * COMMIT phase 
	 */
	if (priv->non_xa_cnc &&
	    ! gda_connection_commit_transaction (priv->non_xa_cnc, NULL, error)) {
		/* something went wrong => rollback everything */
		for (list = priv->cnc_list; list; list = list->next) {
			GdaConnection *cnc = NULL;
			GdaServerProvider *prov;
			
			if (cnc == priv->non_xa_cnc)
				gda_connection_rollback_transaction (cnc, NULL, NULL);
			else {
				GdaBinary *branch;
				cnc = GDA_CONNECTION (list->data);
				prov = gda_connection_get_provider (cnc);
				branch = g_hash_table_lookup (priv->cnc_hash, cnc);
				memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */
					gda_binary_get_data (branch), gda_binary_get_size (branch));
				_gda_server_provider_xa_rollback (prov, cnc, &(priv->xid), NULL);
			}
		}
		return FALSE;
	}

	for (list = priv->cnc_list; list; list = list->next) {
		GdaConnection *cnc = NULL;
		GdaServerProvider *prov;
		GdaBinary *branch;
		
		if (cnc == priv->non_xa_cnc)
			continue;

		cnc = GDA_CONNECTION (list->data);
		prov = gda_connection_get_provider (cnc);
		branch = g_hash_table_lookup (priv->cnc_hash, cnc);
		memcpy (priv->xid.data + priv->xid.gtrid_length, /* Flawfinder: ignore */
			gda_binary_get_data (branch), gda_binary_get_size (branch));
		if (! _gda_server_provider_xa_commit (prov, cnc, &(priv->xid), error) &&
		    cnc_to_recover)
			*cnc_to_recover = g_slist_prepend (*cnc_to_recover, cnc);
	}
	
	return TRUE;
}
Esempio n. 9
0
int
main (int argc, char *argv[])
{
	GOptionContext *context;
	GError *error = NULL;
	int exit_status = EXIT_SUCCESS;
	GSList *list, *cnc_list = NULL;

	context = g_option_context_new ("[DSN|connection string]...");
	g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
        if (!g_option_context_parse (context, &argc, &argv, &error)) {
                g_print ("Can't parse arguments: %s\n", error->message);
		exit_status = EXIT_FAILURE;
		goto cleanup;
        }
        g_option_context_free (context);
        gda_init ();
	ask_pass = !ask_pass;

	config = g_new0 (HtmlConfig, 1);
	html_init_config (HTML_CONFIG (config));
	config->index = html_file_new (HTML_CONFIG (config), 
				       "index.html", "Providers status");
	config->dir = g_strdup (".");

	/* parse command line arguments for connections */
	if (argc > 1) {
		gint i;
		for (i = 1; i < argc; i++) {
			/* open connection */
			GdaConnection *cnc;
			cnc = open_connection (argv[i], &error);
			if (!cnc) {
				g_print ("Can't open connection to '%s': %s\n", argv[i],
					 error && error->message ? error->message : "No detail");
				exit_status = EXIT_FAILURE;
				goto cleanup;
			}
			cnc_list = g_slist_append (cnc_list, cnc);
		}
	}
	else {
		if (getenv ("GDA_SQL_CNC")) {
			GdaConnection *cnc;
			cnc = open_connection (getenv ("GDA_SQL_CNC"), &error);
			if (!cnc) {
				g_print ("Can't open connection defined by GDA_SQL_CNC: %s\n",
					 error && error->message ? error->message : "No detail");
				exit_status = EXIT_FAILURE;
				goto cleanup;
			}
			cnc_list = g_slist_append (cnc_list, cnc);
		}
		else {
			/* report status for all providers */
			GdaDataModel *providers;
			gint i, nb;
			
			providers = gda_config_list_providers ();
			nb = gda_data_model_get_n_rows (providers);
			for (i = 0; i < nb; i++) {
				GdaServerProvider *prov = NULL;
				const gchar *pname;
				const GValue *cvalue;

				cvalue = gda_data_model_get_value_at (providers, 0, i, &error);
				if (!cvalue) 
					g_error ("Can't load next provider: %s\n",
						 error && error->message ? error->message : "No detail");
				pname = g_value_get_string (cvalue);
				prov = gda_config_get_provider (pname, &error);
				if (!prov) 
					g_error ("Can't load the '%s' provider: %s\n", pname,
						 error && error->message ? error->message : "No detail");
				if (!report_provider_status (prov, NULL)) {
					exit_status = EXIT_FAILURE;
					goto cleanup;
				}
			}
			g_object_unref (providers);
		}
	}
	
	/* report provider's status for all the connections */
	for (list = cnc_list; list; list = list->next) {
		if (!report_provider_status (NULL, GDA_CONNECTION (list->data))) {
			exit_status = EXIT_FAILURE;
			goto cleanup;

		}
	}

	g_slist_foreach (HTML_CONFIG (config)->all_files, (GFunc) html_file_write, config);
	
	/* cleanups */
 cleanup:
	g_slist_foreach (cnc_list, (GFunc) g_object_unref, NULL);
	g_slist_free (cnc_list);

	return exit_status;
}