From d9a54c3f6cbf068a1e1553eac9adcf9127b007f5 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 3 Aug 2023 10:37:12 +0200 Subject: fixing for platforms, where pthread_t is not numeric (as for musl, where it is a pointer, POSIX sadly did away with the requirement that pthread_t must be a numeric): - printing thread ids as pointers with '%p' instead of converting them to unsigned int and printing them with '%u' - using separate 'avail' and 'thread' arrays in pools to record status of pooled database connections --- pgfuse.c | 80 ++++++++++++++++++++++++++++++++-------------------------------- pool.c | 46 +++++++++++++++++++++++++------------ pool.h | 3 ++- 3 files changed, 74 insertions(+), 55 deletions(-) diff --git a/pgfuse.c b/pgfuse.c index e99fc7f..572fd31 100644 --- a/pgfuse.c +++ b/pgfuse.c @@ -107,7 +107,7 @@ static int psql_release( PgFuseData *data, PGconn *conn ) #define RELEASE( C ) \ if( psql_release( data, C ) < 0 ) return -EIO; -#define THREAD_ID (unsigned int)pthread_self( ) +#define THREAD_ID pthread_self( ) /* --- other helpers --- */ @@ -149,7 +149,7 @@ static void *pgfuse_init( struct fuse_conn_info *conn ) { PgFuseData *data = (PgFuseData *)fuse_get_context( )->private_data; - syslog( LOG_INFO, "Mounting file system on '%s' ('%s', %s, %s), thread #%u", + syslog( LOG_INFO, "Mounting file system on '%s' ('%s', %s, %s), thread %p", data->mountpoint, data->conninfo, data->read_only ? "read-only" : "read-write", data->noatime ? "noatime" : "atime", @@ -181,7 +181,7 @@ static void pgfuse_destroy( void *userdata ) { PgFuseData *data = (PgFuseData *)userdata; - syslog( LOG_INFO, "Unmounting file system on '%s' (%s), thread #%u", + syslog( LOG_INFO, "Unmounting file system on '%s' (%s), thread %p", data->mountpoint, data->conninfo, THREAD_ID ); if( !data->multi_threaded ) { @@ -217,7 +217,7 @@ static int pgfuse_fgetattr( const char *path, struct stat *stbuf, struct fuse_fi PGconn *conn; if( data->verbose ) { - syslog( LOG_INFO, "FgetAttrs '%s' on '%s', thread #%u", + syslog( LOG_INFO, "FgetAttrs '%s' on '%s', thread %p", path, data->mountpoint, THREAD_ID ); } @@ -233,7 +233,7 @@ static int pgfuse_fgetattr( const char *path, struct stat *stbuf, struct fuse_fi } if( data->verbose ) { - syslog( LOG_DEBUG, "Id for %s '%s' is %"PRIi64", thread #%u", + syslog( LOG_DEBUG, "Id for %s '%s' is %"PRIi64", thread %p", S_ISDIR( meta.mode ) ? "dir" : "file", path, id, THREAD_ID ); } @@ -253,7 +253,7 @@ static int pgfuse_getattr( const char *path, struct stat *stbuf ) PGconn *conn; if( data->verbose ) { - syslog( LOG_INFO, "GetAttrs '%s' on '%s', thread #%u", + syslog( LOG_INFO, "GetAttrs '%s' on '%s', thread %p", path, data->mountpoint, THREAD_ID ); } @@ -269,7 +269,7 @@ static int pgfuse_getattr( const char *path, struct stat *stbuf ) } if( data->verbose ) { - syslog( LOG_DEBUG, "Id for %s '%s' is %"PRIi64", thread #%u", + syslog( LOG_DEBUG, "Id for %s '%s' is %"PRIi64", thread %p", S_ISDIR( meta.mode ) ? "dir" : "file", path, id, THREAD_ID ); } @@ -286,7 +286,7 @@ static int pgfuse_access( const char *path, int mode ) PgFuseData *data = (PgFuseData *)fuse_get_context( )->private_data; if( data->verbose ) { - syslog( LOG_INFO, "Access on '%s' and mode '%o, thread #%u", + syslog( LOG_INFO, "Access on '%s' and mode '%o, thread %p", path, (unsigned int)mode, THREAD_ID ); } @@ -350,7 +350,7 @@ static int pgfuse_create( const char *path, mode_t mode, struct fuse_file_info * if( data->verbose ) { char *s = flags_to_string( fi->flags ); - syslog( LOG_INFO, "Create '%s' in mode '%o' on '%s' with flags '%s', thread #%u", + syslog( LOG_INFO, "Create '%s' in mode '%o' on '%s' with flags '%s', thread %p", path, mode, data->mountpoint, s, THREAD_ID ); if( *s != '<' ) free( s ); } @@ -371,7 +371,7 @@ static int pgfuse_create( const char *path, mode_t mode, struct fuse_file_info * if( id >= 0 ) { if( data->verbose ) { - syslog( LOG_DEBUG, "Id for dir '%s' is %"PRIi64", thread #%u", + syslog( LOG_DEBUG, "Id for dir '%s' is %"PRIi64", thread %p", path, id, THREAD_ID ); } @@ -420,7 +420,7 @@ static int pgfuse_create( const char *path, mode_t mode, struct fuse_file_info * } if( data->verbose ) { - syslog( LOG_DEBUG, "Parent_id for new file '%s' in dir '%s' is %"PRIi64", thread #%u", + syslog( LOG_DEBUG, "Parent_id for new file '%s' in dir '%s' is %"PRIi64", thread %p", path, parent_path, parent_id, THREAD_ID ); } @@ -458,7 +458,7 @@ static int pgfuse_create( const char *path, mode_t mode, struct fuse_file_info * } if( data->verbose ) { - syslog( LOG_DEBUG, "Id for new file '%s' is %"PRIi64", thread #%u", + syslog( LOG_DEBUG, "Id for new file '%s' is %"PRIi64", thread %p", path, id, THREAD_ID ); } @@ -482,7 +482,7 @@ static int pgfuse_open( const char *path, struct fuse_file_info *fi ) if( data->verbose ) { char *s = flags_to_string( fi->flags ); - syslog( LOG_INFO, "Open '%s' on '%s' with flags '%s', thread #%u", + syslog( LOG_INFO, "Open '%s' on '%s' with flags '%s', thread %p", path, data->mountpoint, s, THREAD_ID ); if( *s != '<' ) free( s ); } @@ -497,7 +497,7 @@ static int pgfuse_open( const char *path, struct fuse_file_info *fi ) } if( data->verbose ) { - syslog( LOG_DEBUG, "Id for file '%s' to open is %"PRIi64", thread #%u", + syslog( LOG_DEBUG, "Id for file '%s' to open is %"PRIi64", thread %p", path, id, THREAD_ID ); } @@ -546,7 +546,7 @@ static int pgfuse_readdir( const char *path, void *buf, fuse_fill_dir_t filler, PGconn *conn; if( data->verbose ) { - syslog( LOG_INFO, "Readdir '%s' on '%s', thread #%u", + syslog( LOG_INFO, "Readdir '%s' on '%s', thread %p", path, data->mountpoint, THREAD_ID ); } @@ -606,7 +606,7 @@ static int pgfuse_mkdir( const char *path, mode_t mode ) PGconn *conn; if( data->verbose ) { - syslog( LOG_INFO, "Mkdir '%s' in mode '%o' on '%s', thread #%u", + syslog( LOG_INFO, "Mkdir '%s' in mode '%o' on '%s', thread %p", path, (unsigned int)mode, data->mountpoint, THREAD_ID ); } @@ -639,7 +639,7 @@ static int pgfuse_mkdir( const char *path, mode_t mode ) } if( data->verbose ) { - syslog( LOG_DEBUG, "Parent_id for new dir '%s' is %"PRIi64", thread #%u", + syslog( LOG_DEBUG, "Parent_id for new dir '%s' is %"PRIi64", thread %p", path, parent_id, THREAD_ID ); } @@ -685,7 +685,7 @@ static int pgfuse_rmdir( const char *path ) PGconn *conn; if( data->verbose ) { - syslog( LOG_INFO, "Rmdir '%s' on '%s', thread #%u", + syslog( LOG_INFO, "Rmdir '%s' on '%s', thread %p", path, data->mountpoint, THREAD_ID ); } @@ -703,7 +703,7 @@ static int pgfuse_rmdir( const char *path ) } if( data->verbose ) { - syslog( LOG_DEBUG, "Id of dir '%s' to be removed is %"PRIi64", thread #%u", + syslog( LOG_DEBUG, "Id of dir '%s' to be removed is %"PRIi64", thread %p", path, id, THREAD_ID ); } @@ -735,7 +735,7 @@ static int pgfuse_unlink( const char *path ) PGconn *conn; if( data->verbose ) { - syslog( LOG_INFO, "Remove file '%s' on '%s', thread #%u", + syslog( LOG_INFO, "Remove file '%s' on '%s', thread %p", path, data->mountpoint, THREAD_ID ); } @@ -753,7 +753,7 @@ static int pgfuse_unlink( const char *path ) } if( data->verbose ) { - syslog( LOG_DEBUG, "Id of file '%s' to be removed is %"PRIi64", thread #%u", + syslog( LOG_DEBUG, "Id of file '%s' to be removed is %"PRIi64", thread %p", path, id, THREAD_ID ); } @@ -788,7 +788,7 @@ static int pgfuse_fsync( const char *path, int isdatasync, struct fuse_file_info PgFuseData *data = (PgFuseData *)fuse_get_context( )->private_data; if( data->verbose ) { - syslog( LOG_INFO, "%s on file '%s' on '%s', thread #%u", + syslog( LOG_INFO, "%s on file '%s' on '%s', thread %p", isdatasync ? "FDataSync" : "FSync", path, data->mountpoint, THREAD_ID ); } @@ -815,7 +815,7 @@ static int pgfuse_release( const char *path, struct fuse_file_info *fi ) /* nothing to do given the simple transaction model */ if( data->verbose ) { - syslog( LOG_INFO, "Releasing '%s' on '%s', thread #%u", + syslog( LOG_INFO, "Releasing '%s' on '%s', thread %p", path, data->mountpoint, THREAD_ID ); } @@ -858,7 +858,7 @@ static int pgfuse_write( const char *path, const char *buf, size_t size, PGconn *conn; if( data->verbose ) { - syslog( LOG_INFO, "Write to '%s' from offset %jd, size %zu on '%s', thread #%u", + syslog( LOG_INFO, "Write to '%s' from offset %jd, size %zu on '%s', thread %p", path, offset, size, data->mountpoint, THREAD_ID ); } @@ -921,7 +921,7 @@ static int pgfuse_read( const char *path, char *buf, size_t size, PgMeta meta; if( data->verbose ) { - syslog( LOG_INFO, "Read to '%s' from offset %jd, size %zu on '%s', thread #%u", + syslog( LOG_INFO, "Read to '%s' from offset %jd, size %zu on '%s', thread %p", path, offset, size, data->mountpoint, THREAD_ID ); } @@ -971,7 +971,7 @@ static int pgfuse_truncate( const char* path, off_t offset ) PGconn *conn; if( data->verbose ) { - syslog( LOG_INFO, "Truncate of '%s' to size '%jd' on '%s', thread #%u", + syslog( LOG_INFO, "Truncate of '%s' to size '%jd' on '%s', thread %p", path, offset, data->mountpoint, THREAD_ID ); } @@ -990,7 +990,7 @@ static int pgfuse_truncate( const char* path, off_t offset ) } if( data->verbose ) { - syslog( LOG_DEBUG, "Id of file '%s' to be truncated is %"PRIi64", thread #%u", + syslog( LOG_DEBUG, "Id of file '%s' to be truncated is %"PRIi64", thread %p", path, id, THREAD_ID ); } @@ -1029,7 +1029,7 @@ static int pgfuse_ftruncate( const char *path, off_t offset, struct fuse_file_in PGconn *conn; if( data->verbose ) { - syslog( LOG_INFO, "Truncate of '%s' to size '%jd' on '%s', thread #%u", + syslog( LOG_INFO, "Truncate of '%s' to size '%jd' on '%s', thread %p", path, offset, data->mountpoint, THREAD_ID ); } @@ -1092,7 +1092,7 @@ static int pgfuse_statfs( const char *path, struct statvfs *buf ) int prefix_len; if( data->verbose ) { - syslog( LOG_INFO, "Statfs called on '%s', thread #%u", + syslog( LOG_INFO, "Statfs called on '%s', thread %p", data->mountpoint, THREAD_ID ); } @@ -1115,7 +1115,7 @@ static int pgfuse_statfs( const char *path, struct statvfs *buf ) char *new_path = realpath( old_path, NULL ); if( new_path == NULL ) { /* do nothing, most likely a permission problem */ - syslog( LOG_ERR, "realpath for '%s' failed: %s, pgfuse mount point '%s', thread #%u", + syslog( LOG_ERR, "realpath for '%s' failed: %s, pgfuse mount point '%s', thread %p", old_path, strerror( errno ), data->mountpoint, THREAD_ID ); } else { location[i] = new_path; @@ -1152,13 +1152,13 @@ static int pgfuse_statfs( const char *path, struct statvfs *buf ) /* get data of file system */ res = statfs( prefix, &fs ); if( res < 0 ) { - syslog( LOG_ERR, "statfs on '%s' failed: %s, pgfuse mount point '%s', thread #%u", + syslog( LOG_ERR, "statfs on '%s' failed: %s, pgfuse mount point '%s', thread %p", prefix, strerror( errno ), data->mountpoint, THREAD_ID ); return res; } if( data->verbose ) { - syslog( LOG_DEBUG, "Checking mount point '%s' for free disk space, now %jd, was %jd, pgfuse mount point '%s', thread #%u", + syslog( LOG_DEBUG, "Checking mount point '%s' for free disk space, now %jd, was %jd, pgfuse mount point '%s', thread %p", prefix, fs.f_bfree, blocks_free, data->mountpoint, THREAD_ID ); } @@ -1206,7 +1206,7 @@ static int pgfuse_statfs( const char *path, struct statvfs *buf ) if( data->verbose ) { syslog( LOG_DEBUG, "Stats for '%s' are (%jd blocks total, %jd used, %jd free, " - "%"PRId64" inodes total, %"PRId64" inodes used, %"PRId64" inodes free, thread #%u", + "%"PRId64" inodes total, %"PRId64" inodes used, %"PRId64" inodes free, thread %p", data->mountpoint, blocks_total, blocks_used, blocks_free, files_total, files_used, files_free, @@ -1245,7 +1245,7 @@ static int pgfuse_chmod( const char *path, mode_t mode ) PGconn *conn; if( data->verbose ) { - syslog( LOG_INFO, "Chmod on '%s' to mode '%o' on '%s', thread #%u", + syslog( LOG_INFO, "Chmod on '%s' to mode '%o' on '%s', thread %p", path, (unsigned int)mode, data->mountpoint, THREAD_ID ); } @@ -1287,7 +1287,7 @@ static int pgfuse_chown( const char *path, uid_t uid, gid_t gid ) PGconn *conn; if( data->verbose ) { - syslog( LOG_INFO, "Chown on '%s' to uid '%d' and gid '%d' on '%s', thread #%u", + syslog( LOG_INFO, "Chown on '%s' to uid '%d' and gid '%d' on '%s', thread %p", path, (unsigned int)uid, (unsigned int)gid, data->mountpoint, THREAD_ID ); } @@ -1334,7 +1334,7 @@ static int pgfuse_symlink( const char *from, const char *to ) PGconn *conn; if( data->verbose ) { - syslog( LOG_INFO, "Symlink from '%s' to '%s' on '%s', thread #%u", + syslog( LOG_INFO, "Symlink from '%s' to '%s' on '%s', thread %p", from, to, data->mountpoint, THREAD_ID ); } @@ -1361,7 +1361,7 @@ static int pgfuse_symlink( const char *from, const char *to ) } if( data->verbose ) { - syslog( LOG_DEBUG, "Parent_id for symlink '%s' is %"PRIi64", thread #%u", + syslog( LOG_DEBUG, "Parent_id for symlink '%s' is %"PRIi64", thread %p", to, parent_id, THREAD_ID ); } @@ -1446,7 +1446,7 @@ static int pgfuse_rename( const char *from, const char *to ) char *rename_to; if( data->verbose ) { - syslog( LOG_INFO, "Renaming '%s' to '%s' on '%s', thread #%u", + syslog( LOG_INFO, "Renaming '%s' to '%s' on '%s', thread %p", from, to, data->mountpoint, THREAD_ID ); } @@ -1553,7 +1553,7 @@ static int pgfuse_readlink( const char *path, char *buf, size_t size ) PGconn *conn; if( data->verbose ) { - syslog( LOG_INFO, "Dereferencing symlink '%s' on '%s', thread #%u", + syslog( LOG_INFO, "Dereferencing symlink '%s' on '%s', thread %p", path, data->mountpoint, THREAD_ID ); } @@ -1597,7 +1597,7 @@ static int pgfuse_utimens( const char *path, const struct timespec tv[2] ) PGconn *conn; if( data->verbose ) { - syslog( LOG_INFO, "Utimens on '%s' to access time '%d' and modification time '%d' on '%s', thread #%u", + syslog( LOG_INFO, "Utimens on '%s' to access time '%d' and modification time '%d' on '%s', thread %p", path, (unsigned int)tv[0].tv_sec, (unsigned int)tv[1].tv_sec, data->mountpoint, THREAD_ID ); } diff --git a/pool.c b/pool.c index 11a0f1f..82b0644 100644 --- a/pool.c +++ b/pool.c @@ -22,8 +22,9 @@ #include /* for malloc */ #include /* for syslog */ -#define AVAILABLE -1 -#define ERROR -2 +#define USED 1 +#define AVAILABLE 0 +#define ERROR 3 int psql_pool_init( PgConnPool *pool, const char *conninfo, const size_t max_connections ) { @@ -35,16 +36,24 @@ int psql_pool_init( PgConnPool *pool, const char *conninfo, const size_t max_con return -ENOMEM; } - pool->avail = (pthread_t *)malloc( sizeof( pthread_t ) * max_connections ); + pool->avail = (unsigned int *)malloc( sizeof( unsigned int ) * max_connections ); if( pool->avail == NULL ) { free( pool->conns ); return -ENOMEM; } + + pool->thread = (pthread_t *)malloc( sizeof( pthread_t ) * max_connections ); + if( pool->thread == NULL ) { + free( pool->avail ); + free( pool->conns ); + return -ENOMEM; + } pool->size = max_connections; res = pthread_mutex_init( &pool->lock, NULL ); if( res < 0 ) { + free( pool->thread ); free( pool->avail ); free( pool->conns ); return res; @@ -53,6 +62,7 @@ int psql_pool_init( PgConnPool *pool, const char *conninfo, const size_t max_con res = pthread_cond_init( &pool->cond, NULL ); if( res < 0 ) { (void)pthread_mutex_destroy( &pool->lock ); + free( pool->thread ); free( pool->avail ); free( pool->conns ); return res; @@ -80,17 +90,24 @@ int psql_pool_destroy( PgConnPool *pool ) int res2; for( i = 0; i < pool->size; i++ ) { - if( pool->avail[i] == AVAILABLE ) { - PQfinish( pool->conns[i] ); - } else if( pool->avail[i] > 0 ) { - syslog( LOG_ERR, "Destroying pool connection to thread '%u' which is still in use", - (unsigned int)pool->avail[i] ); - PQfinish( pool->conns[i] ); + switch( pool->avail[i] ) { + case AVAILABLE: + PQfinish( pool->conns[i] ); + break; + case USED: + syslog( LOG_ERR, "Destroying pool connection to thread %p which is still in use", + pool->thread[i] ); + PQfinish( pool->conns[i] ); + break; + case ERROR: + // ignoring threads in error, asusming PQfinish will fail anyway + break; } } free( pool->conns ); free( pool->avail ); + free( pool->thread ); res1 = pthread_cond_destroy( &pool->cond ); res2 = pthread_mutex_destroy( &pool->lock ); @@ -106,8 +123,8 @@ PGconn *psql_pool_acquire( PgConnPool *pool ) for( ;; ) { res = pthread_mutex_lock( &pool->lock ); if( res < 0 ) { - syslog( LOG_ERR, "Locking mutex failed for thread '%u': %d", - (unsigned int)pthread_self( ), res ); + syslog( LOG_ERR, "Locking mutex failed for thread %p: %d", + pthread_self( ), res ); return NULL; } @@ -115,7 +132,8 @@ PGconn *psql_pool_acquire( PgConnPool *pool ) for( i = 0; i < pool->size; i++ ) { if( pool->avail[i] == AVAILABLE ) { if( PQstatus( pool->conns[i] ) == CONNECTION_OK ) { - pool->avail[i] = pthread_self( ); + pool->avail[i] = USED; + pool->thread[i] = pthread_self( ); (void)pthread_mutex_unlock( &pool->lock ); return pool->conns[i]; } else { @@ -127,8 +145,8 @@ PGconn *psql_pool_acquire( PgConnPool *pool ) /* wait on conditional till a free connection is signalled */ res = pthread_cond_wait( &pool->cond, &pool->lock ); if( res < 0 ) { - syslog( LOG_ERR, "Error waiting for free condition in thread '%u': %d", - (unsigned int)pthread_self( ), res ); + syslog( LOG_ERR, "Error waiting for free condition in thread %p: %d", + pthread_self( ), res ); (void)pthread_mutex_unlock( &pool->lock ); return NULL; } diff --git a/pool.h b/pool.h index c8b5036..3dbc7f7 100644 --- a/pool.h +++ b/pool.h @@ -27,7 +27,8 @@ typedef struct PgConnPool { PGconn **conns; /* array of connections */ size_t size; /* max number of connections */ - pthread_t *avail; /* slots of allocated/available connections per thread */ + unsigned int *avail; /* status of slots */ + pthread_t *thread; /* slots of allocated/available connections per thread */ pthread_mutex_t lock; /* monitor lock */ pthread_cond_t cond; /* condition signalling a free connection */ } PgConnPool; -- cgit v1.2.3-54-g00ecf