Saves, in a DBPROCESS structure, a pointer to user-allocated data.
void dbsetuserdata ( PDBPROCESS dbproc, LPVOID ptr );
where
The dbsetuserdata function lets an application associate user data with a particular DBPROCESS, eliminating the need for global variables. This function is especially useful when an application has more than one DBPROCESS.
Make sure each application allocates the data that ptr points to. DB-Library never manipulates this data; it merely saves the pointer so the application can use it later.
The following example shows how dbsetuserdata handles deadlock, an occasional occurrence in high-volume applications. For more information about deadlock, see the Microsoft SQL Server Administrator's Companion.
This program fragment sends updates to the SQL Server and reruns the transaction when its message handler detects deadlock:
// Deadlock detection: // In the DBPROCESS structure, save a pointer to a DBBOOL variable. // The message handler sets the variable when deadlock occurs. // The result processing logic checks the variable and resends the // transaction in case of deadlock. // Allocate the space for the DBBOOL variable and save it in // the DBPROCESS structure. dbsetuserdata(dbproc, malloc(sizeof(DBBOOL))); // Initialize the variable to FALSE. *((DBBOOL *) dbgetuserdata(dbproc)) = FALSE; // Run queries and check for deadlock. deadlock: // Did the application get here via deadlock? // If so, the server has already canceled the transaction. // Start the application again. In a real application, // the deadlock handling may need to be somewhat more // sophisticated. For instance, you may want to keep a // counter and retry the transaction a fixed number // of times. if (*((DBBOOL *) dbgetuserdata(dbproc)) == TRUE) { // Reset the variable to FALSE. *((DBBOOL *) dbgetuserdata(dbproc)) = FALSE; } // Start the transaction. dbcmd(dbproc, "begin transaction "); // Run the first UPDATE command. dbcmd(dbproc, "update ......"); dbsqlexec(dbproc); while (dbresults(dbproc) ! = NO_MORE_RESULTS) { // application code } // Did the application deadlock? if (*(DBBOOL *) dbgetuserdata(dbproc)) == TRUE) goto deadlock; // Run the second UPDATE command. dbcmd(dbproc, "update ......"); dbsqlexec(dbproc); while (dbresults(dbproc) ! = NO_MORE_RESULTS { // application code } // Did the application deadlock? if (*((DBBOOL *) dbgetuserdata(dbproc)) == TRUE) goto deadlock; // No deadlock -- Commit the transaction. dbcmd(dbproc, "commit transaction"); dbsqlexec(dbproc); dbresults(dbproc); // SERVERMSGS // This is the server message handler. Assume that the dbmsghandle // function installed it earlier in the application. servermsgs(dbproc, msgno, msgstate, severity, msgtext, srvname, procname, line) DBPROCESS *dbproc; DBINT msgno; int msgstate; int severity; char *msgtext; char srvname; char *procname; DBUSMALLINT line; { // Is this a deadlock message? if (msgno = 1205) { // Set the deadlock indicator. * ((DBBOOL *) dbgetuserdata(dbproc)) = TRUE; return (O); } // Normal message handling code here. }