Bruce Momjian 4f70680177 Make ecpg thread safe.
Lee Kindness
2003-06-15 04:07:58 +00:00

238 lines
4.1 KiB
C

/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.3 2003/06/15 04:07:58 momjian Exp $ */
#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"
#include <unistd.h>
#ifdef USE_THREADS
#include <pthread.h>
#endif
#include "ecpgtype.h"
#include "ecpglib.h"
#include "ecpgerrno.h"
#include "extern.h"
#include "sqlca.h"
static struct sqlca_t sqlca_init =
{
{
'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
},
sizeof(struct sqlca_t),
0,
{
0,
{
0
}
},
{
'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '
},
{
0, 0, 0, 0, 0, 0
},
{
0, 0, 0, 0, 0, 0, 0, 0
},
{
0, 0, 0, 0, 0, 0, 0, 0
}
};
#ifdef USE_THREADS
static pthread_key_t sqlca_key;
static pthread_once_t sqlca_key_once = PTHREAD_ONCE_INIT;
#else
static struct sqlca_t sqlca =
{
{
'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
},
sizeof(struct sqlca_t),
0,
{
0,
{
0
}
},
{
'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '
},
{
0, 0, 0, 0, 0, 0
},
{
0, 0, 0, 0, 0, 0, 0, 0
},
{
0, 0, 0, 0, 0, 0, 0, 0
}
};
#endif
#ifdef USE_THREADS
static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
static int simple_debug = 0;
static FILE *debugstream = NULL;
void ECPGinit_sqlca(struct sqlca_t *sqlca)
{
memcpy((char *)sqlca, (char *)&sqlca_init, sizeof(struct sqlca_t));
}
bool
ECPGinit(const struct connection * con, const char *connection_name, const int lineno)
{
struct sqlca_t *sqlca = ECPGget_sqlca();
ECPGinit_sqlca(sqlca);
if (con == NULL)
{
ECPGraise(lineno, ECPG_NO_CONN, connection_name ? connection_name : "NULL");
return (false);
}
return (true);
}
#ifdef USE_THREADS
static void ecpg_sqlca_key_init(void)
{
pthread_key_create(&sqlca_key, NULL);
}
#endif
struct sqlca_t *ECPGget_sqlca(void)
{
#ifdef USE_THREADS
struct sqlca_t *sqlca;
pthread_once(&sqlca_key_once, ecpg_sqlca_key_init);
sqlca = pthread_getspecific(&sqlca_key);
if( sqlca == NULL )
{
sqlca = malloc(sizeof(struct sqlca_t));
ECPGinit_sqlca(sqlca);
pthread_setspecific(&sqlca_key, sqlca);
}
return( sqlca );
#else
return( &sqlca );
#endif
}
bool
ECPGstatus(int lineno, const char *connection_name)
{
struct connection *con = ECPGget_connection(connection_name);
if (!ECPGinit(con, connection_name, lineno))
return (false);
/* are we connected? */
if (con->connection == NULL)
{
ECPGraise(lineno, ECPG_NOT_CONN, con->name);
return false;
}
return (true);
}
bool
ECPGtrans(int lineno, const char *connection_name, const char *transaction)
{
PGresult *res;
struct connection *con = ECPGget_connection(connection_name);
if (!ECPGinit(con, connection_name, lineno))
return (false);
ECPGlog("ECPGtrans line %d action = %s connection = %s\n", lineno, transaction, con->name);
/* if we have no connection we just simulate the command */
if (con && con->connection)
{
/*
* if we are not in autocommit mode, already have committed the
* transaction and get another commit, just ignore it
*/
if (!con->committed || con->autocommit)
{
if ((res = PQexec(con->connection, transaction)) == NULL)
{
ECPGraise(lineno, ECPG_TRANS, NULL);
return FALSE;
}
PQclear(res);
}
}
if (strcmp(transaction, "commit") == 0 || strcmp(transaction, "rollback") == 0)
{
con->committed = true;
#if 0
/* deallocate all prepared statements */
if (!ECPGdeallocate_all(lineno))
return false;
#endif
}
return true;
}
void
ECPGdebug(int n, FILE *dbgs)
{
#ifdef USE_THREADS
pthread_mutex_lock(&debug_mutex);
#endif
simple_debug = n;
debugstream = dbgs;
ECPGlog("ECPGdebug: set to %d\n", simple_debug);
#ifdef USE_THREADS
pthread_mutex_unlock(&debug_mutex);
#endif
}
void
ECPGlog(const char *format,...)
{
va_list ap;
#ifdef USE_THREADS
pthread_mutex_lock(&debug_mutex);
#endif
if( simple_debug )
{
char *f = (char *)malloc(strlen(format) + 100);
if( f == NULL )
{
#ifdef USE_THREADS
pthread_mutex_unlock(&debug_mutex);
#endif
return;
}
sprintf(f, "[%d]: %s", (int) getpid(), format);
va_start(ap, format);
vfprintf(debugstream, f, ap);
va_end(ap);
ECPGfree(f);
}
#ifdef USE_THREADS
pthread_mutex_unlock(&debug_mutex);
#endif
}