summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pgfuse.c35
-rw-r--r--pgsql.c28
-rw-r--r--pgsql.h1
-rw-r--r--schema.sql2
4 files changed, 47 insertions, 19 deletions
diff --git a/pgfuse.c b/pgfuse.c
index 5b025a9..bb809d2 100644
--- a/pgfuse.c
+++ b/pgfuse.c
@@ -296,6 +296,7 @@ static int pgfuse_create( const char *path, mode_t mode, struct fuse_file_info *
meta.ctime = now( );
meta.mtime = meta.ctime;
meta.atime = meta.ctime;
+ meta.ref_count = 1;
res = psql_create_file( data->conn, parent_id, path, new_file, meta );
if( res < 0 ) {
@@ -303,11 +304,6 @@ static int pgfuse_create( const char *path, mode_t mode, struct fuse_file_info *
return res;
}
- /* get id and store it, remember it in the hash of open files
- * the hash function is currently the inode (i.e. the serial
- * in the 'id' field module hashtable size, avoiding a much
- * more complicated implementation for no good here
- */
id = psql_get_meta( data->conn, path, &meta );
if( id < 0 ) {
free( copy_path );
@@ -332,6 +328,7 @@ static int pgfuse_open( const char *path, struct fuse_file_info *fi )
PgFuseData *data = (PgFuseData *)fuse_get_context( )->private_data;
PgMeta meta;
int id;
+ int res;
if( data->verbose ) {
char *s = flags_to_string( fi->flags );
@@ -345,6 +342,11 @@ static int pgfuse_open( const char *path, struct fuse_file_info *fi )
return id;
}
+ /* currently don't allow parallel access */
+ if( meta.ref_count > 0 ) {
+ return -ETXTBSY;
+ }
+
if( data->verbose ) {
syslog( LOG_DEBUG, "Id for file '%s' to open is %d, thread #%d",
path, id, fuse_get_context( )->uid );
@@ -362,7 +364,14 @@ static int pgfuse_open( const char *path, struct fuse_file_info *fi )
if( meta.size > MAX_FILE_SIZE ) {
return -EFBIG;
- }
+ }
+
+ meta.ref_count = 1;
+
+ res = psql_write_meta( data->conn, id, path, meta );
+ if( res < 0 ) {
+ return res;
+ }
fi->fh = id;
@@ -579,6 +588,9 @@ static int pgfuse_fsync( const char *path, int isdatasync, struct fuse_file_info
static int pgfuse_release( const char *path, struct fuse_file_info *fi )
{
PgFuseData *data = (PgFuseData *)fuse_get_context( )->private_data;
+ int id;
+ int res;
+ PgMeta meta;
if( data->verbose ) {
syslog( LOG_INFO, "Releasing '%s' on '%s', thread #%d",
@@ -592,8 +604,17 @@ static int pgfuse_release( const char *path, struct fuse_file_info *fi )
if( data->read_only ) {
return 0;
}
+
+ id = psql_get_meta( data->conn, path, &meta );
+ if( id < 0 ) {
+ return id;
+ }
+
+ meta.ref_count = 0;
+
+ res = psql_write_meta( data->conn, id, path, meta );
- return 0;
+ return res;
}
static int pgfuse_write( const char *path, const char *buf, size_t size,
diff --git a/pgsql.c b/pgsql.c
index 9f7cc71..f529ea7 100644
--- a/pgsql.c
+++ b/pgsql.c
@@ -99,7 +99,7 @@ int psql_get_meta( PGconn *conn, const char *path, PgMeta *meta )
int lengths[1] = { strlen( path ) };
int binary[1] = { 1 };
- res = PQexecParams( conn, "SELECT id, size, mode, uid, gid, ctime, mtime, atime FROM dir WHERE path = $1::varchar",
+ res = PQexecParams( conn, "SELECT id, size, mode, uid, gid, ctime, mtime, atime, ref_count FROM dir WHERE path = $1::varchar",
1, NULL, values, lengths, binary, 1 );
if( PQresultStatus( res ) != PGRES_TUPLES_OK ) {
@@ -150,6 +150,10 @@ int psql_get_meta( PGconn *conn, const char *path, PgMeta *meta )
idx = PQfnumber( res, "atime" );
data = PQgetvalue( res, 0, idx );
meta->atime = convert_from_timestamp( *( (uint64_t *)data ) );
+
+ idx = PQfnumber( res, "ref_count" );
+ data = PQgetvalue( res, 0, idx );
+ meta->ref_count = ntohl( *( (uint32_t *)data ) );
PQclear( res );
@@ -166,13 +170,14 @@ int psql_write_meta( PGconn *conn, const int id, const char *path, PgMeta meta )
uint64_t param6 = convert_to_timestamp( meta.ctime );
uint64_t param7 = convert_to_timestamp( meta.mtime );
uint64_t param8 = convert_to_timestamp( meta.atime );
- const char *values[8] = { (const char *)&param1, (const char *)&param2, (const char *)&param3, (const char *)&param4, (const char *)&param5, (const char *)&param6, (const char *)&param7, (const char *)&param8 };
- int lengths[8] = { sizeof( param1 ), sizeof( param2 ), sizeof( param3 ), sizeof( param4 ), sizeof( param5 ), sizeof( param6 ), sizeof( param7 ), sizeof( param8 ) };
- int binary[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
+ int param9 = htonl( meta.ref_count );
+ const char *values[9] = { (const char *)&param1, (const char *)&param2, (const char *)&param3, (const char *)&param4, (const char *)&param5, (const char *)&param6, (const char *)&param7, (const char *)&param8, (const char *)&param9 };
+ int lengths[9] = { sizeof( param1 ), sizeof( param2 ), sizeof( param3 ), sizeof( param4 ), sizeof( param5 ), sizeof( param6 ), sizeof( param7 ), sizeof( param8 ), sizeof( param9 ) };
+ int binary[9] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
PGresult *res;
- res = PQexecParams( conn, "UPDATE dir SET size=$2::int4, mode=$3::int4, uid=$4::int4, gid=$5::int4, ctime=$6::timestamp, mtime=$7::timestamp, atime=$8::timestamp WHERE id=$1::int4",
- 8, NULL, values, lengths, binary, 1 );
+ res = PQexecParams( conn, "UPDATE dir SET size=$2::int4, mode=$3::int4, uid=$4::int4, gid=$5::int4, ctime=$6::timestamp, mtime=$7::timestamp, atime=$8::timestamp, ref_count=$9::int4 WHERE id=$1::int4",
+ 9, NULL, values, lengths, binary, 1 );
if( PQresultStatus( res ) != PGRES_COMMAND_OK ) {
syslog( LOG_ERR, "Error in psql_write_meta for file '%s': %s", path, PQerrorMessage( conn ) );
@@ -195,13 +200,14 @@ int psql_create_file( PGconn *conn, const int parent_id, const char *path, const
uint64_t param6 = convert_to_timestamp( meta.ctime );
uint64_t param7 = convert_to_timestamp( meta.mtime );
uint64_t param8 = convert_to_timestamp( meta.atime );
- const char *values[10] = { (const char *)&param1, new_file, path, (const char *)&param2, (const char *)&param3, (const char *)&param4, (const char *)&param5, (const char *)&param6, (const char *)&param7, (const char *)&param8 };
- int lengths[10] = { sizeof( param1 ), strlen( new_file ), strlen( path ), sizeof( param2 ), sizeof( param3 ), sizeof( param4 ), sizeof( param5 ), sizeof( param6 ), sizeof( param7 ), sizeof( param8 ) };
- int binary[10] = { 1, 0, 0, 1, 1, 1, 1, 1, 1, 1 };
+ int param9 = htonl( meta.ref_count );
+ const char *values[11] = { (const char *)&param1, new_file, path, (const char *)&param2, (const char *)&param3, (const char *)&param4, (const char *)&param5, (const char *)&param6, (const char *)&param7, (const char *)&param8, (const char *)&param9 };
+ int lengths[11] = { sizeof( param1 ), strlen( new_file ), strlen( path ), sizeof( param2 ), sizeof( param3 ), sizeof( param4 ), sizeof( param5 ), sizeof( param6 ), sizeof( param7 ), sizeof( param8 ), sizeof( param9 ) };
+ int binary[11] = { 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 };
PGresult *res;
- res = PQexecParams( conn, "INSERT INTO dir( parent_id, name, path, size, mode, uid, gid, ctime, mtime, atime ) VALUES ($1::int4, $2::varchar, $3::varchar, $4::int4, $5::int4, $6::int4, $7::int4, $8::timestamp, $9::timestamp, $10::timestamp )",
- 10, NULL, values, lengths, binary, 1 );
+ res = PQexecParams( conn, "INSERT INTO dir( parent_id, name, path, size, mode, uid, gid, ctime, mtime, atime, ref_count ) VALUES ($1::int4, $2::varchar, $3::varchar, $4::int4, $5::int4, $6::int4, $7::int4, $8::timestamp, $9::timestamp, $10::timestamp, $11::int4 )",
+ 11, NULL, values, lengths, binary, 1 );
if( PQresultStatus( res ) != PGRES_COMMAND_OK ) {
syslog( LOG_ERR, "Error in psql_create_file for path '%s': %s",
diff --git a/pgsql.h b/pgsql.h
index 04e9376..c2ad54a 100644
--- a/pgsql.h
+++ b/pgsql.h
@@ -34,6 +34,7 @@ typedef struct PgMeta {
struct timespec ctime; /* last status change time */
struct timespec mtime; /* last modification time */
struct timespec atime; /* last access time */
+ int ref_count; /* how many open file handles exist for this file */
} PgMeta;
int psql_get_meta( PGconn *conn, const char *path, PgMeta *meta );
diff --git a/schema.sql b/schema.sql
index 48afd0e..0550656 100644
--- a/schema.sql
+++ b/schema.sql
@@ -9,7 +9,7 @@ CREATE TABLE dir (
mode INTEGER NOT NULL DEFAULT 0,
uid INTEGER NOT NULL DEFAULT 0,
gid INTEGER NOT NULL DEFAULT 0,
- inuse BOOL DEFAULT false,
+ ref_count INTEGER NOT NULL DEFAULT 0,
ctime TIMESTAMP,
mtime TIMESTAMP,
atime TIMESTAMP