# HG changeset patch # User Olaf Wintermann # Date 1650271993 -7200 # Node ID 277a5896a2ec3a7bb2552c7638b6453f66a81ab4 # Parent d3899857a81d4f3aa5d74529f71202973de7b4bc implement pg unlink diff -r d3899857a81d -r 277a5896a2ec src/server/plugins/postgresql/pgtest.c --- a/src/server/plugins/postgresql/pgtest.c Sun Apr 17 12:04:41 2022 +0200 +++ b/src/server/plugins/postgresql/pgtest.c Mon Apr 18 10:53:13 2022 +0200 @@ -64,6 +64,8 @@ ucx_test_register(suite, test_pg_vfs_open); ucx_test_register(suite, test_pg_vfs_io); ucx_test_register(suite, test_pg_vfs_stat); + ucx_test_register(suite, test_pg_vfs_mkdir); + ucx_test_register(suite, test_pg_vfs_unlink); PGresult *result = PQexec(test_connection, "BEGIN"); PQclear(result); @@ -113,6 +115,8 @@ vfs_close(file); UCX_TEST_END; + + testutil_destroy_session(sn); } UCX_TEST(test_pg_vfs_io) { @@ -161,6 +165,7 @@ UCX_TEST_END; + testutil_destroy_session(sn); } UCX_TEST(test_pg_vfs_stat) { @@ -201,8 +206,44 @@ UCX_TEST_ASSERT(testfail != 0, "stat 3 should fail"); UCX_TEST_END; + + testutil_destroy_session(sn); } UCX_TEST(test_pg_vfs_mkdir) { } + +UCX_TEST(test_pg_vfs_unlink) { + Session *sn = testutil_session(); + Request *rq = testutil_request(sn->pool, "PUT", "/"); + rq->vfs = create_test_pgvfs(sn, rq); + VFSContext *vfs = vfs_request_context(sn, rq); + + UCX_TEST_BEGIN; + + SYS_FILE f1 = vfs_open(vfs, "/test_unlink1", O_WRONLY|O_CREAT); + UCX_TEST_ASSERT(f1, "cannot create test file"); + system_fwrite(f1, "test", 4); + + PgFile *pgfile = f1->data; + Oid oid = pgfile->oid; + + vfs_close(f1); + + int r = vfs_unlink(vfs, "/test_unlink1"); + UCX_TEST_ASSERT(r == 0, "unlink failed"); + + f1 = vfs_open(vfs, "/test_unlink1", O_RDONLY); + UCX_TEST_ASSERT(f1 == NULL, "test file not deleted"); + + int pgfd = lo_open(test_connection, oid, INV_READ); + UCX_TEST_ASSERT(pgfd < 0, "large object not deleted"); + + r = vfs_unlink(vfs, "/test_unlink1"); + UCX_TEST_ASSERT(r, "unlink should fail"); + + UCX_TEST_END; + + testutil_destroy_session(sn); +} diff -r d3899857a81d -r 277a5896a2ec src/server/plugins/postgresql/pgtest.h --- a/src/server/plugins/postgresql/pgtest.h Sun Apr 17 12:04:41 2022 +0200 +++ b/src/server/plugins/postgresql/pgtest.h Mon Apr 18 10:53:13 2022 +0200 @@ -26,6 +26,7 @@ UCX_TEST(test_pg_vfs_io); UCX_TEST(test_pg_vfs_stat); UCX_TEST(test_pg_vfs_mkdir); +UCX_TEST(test_pg_vfs_unlink); #ifdef __cplusplus } diff -r d3899857a81d -r 277a5896a2ec src/server/plugins/postgresql/vfs.c --- a/src/server/plugins/postgresql/vfs.c Sun Apr 17 12:04:41 2022 +0200 +++ b/src/server/plugins/postgresql/vfs.c Mon Apr 18 10:53:13 2022 +0200 @@ -133,6 +133,10 @@ // $2: contentlength static const char *sql_update_resource = "update Resource set contentlength = $2, lastmodified = now() where resource_id = $1;"; +// Delete a resource +// params: $1: resource_id +static const char *sql_delete_res = "delete from Resource where resource_id = $1;"; + VFS* pg_vfs_create(Session *sn, Request *rq, pblock *pb) { // resourcepool is required char *resource_pool = pblock_findval("resourcepool", pb); @@ -460,6 +464,37 @@ return ret; } +int pg_remove_file( + VFSContext *ctx, + PgVFS *pg, + int64_t resource_id, + Oid oid) +{ + if(oid > 0) { + if(lo_unlink(pg->connection, oid) != 1) { + return 1; // error + } + } + + char resid_str[32]; + snprintf(resid_str, 32, "%" PRId64, resource_id); + + const char* params[1] = { resid_str }; + PGresult *result = PQexecParams( + pg->connection, + sql_delete_res, + 1, // number of parameters + NULL, + params, // parameter value + NULL, + NULL, + 0); // 0: result in text format + + int ret = PQresultStatus(result) == PGRES_COMMAND_OK ? 0 : 1; + PQclear(result); + return ret; +} + int pg_update_resource(PgVFS *pg, int64_t resource_id, int64_t contentlength) { char resid_str[32]; char ctlen_str[32]; @@ -622,7 +657,26 @@ } int pg_vfs_unlink(VFSContext *ctx, const char *path) { - return 1; + VFS *vfs = ctx->vfs; + PgVFS *pg = vfs->instance; + + const char *resname; + int64_t resource_id, parent_id; + resource_id = -1; + parent_id = -1; + WSBool iscollection; + Oid oid = 0; + if(pg_resolve_path(ctx, path, &parent_id, &resource_id, &oid, &resname, &iscollection, NULL)) { + ctx->vfs_errno = ENOENT; + return 1; + } + + if(iscollection) { + ctx->vfs_errno = EISDIR; + return 1; + } + + return pg_remove_file(ctx, pg, resource_id, oid); } int pg_vfs_rmdir(VFSContext *Ctx, const char *path) { diff -r d3899857a81d -r 277a5896a2ec src/server/plugins/postgresql/vfs.h --- a/src/server/plugins/postgresql/vfs.h Sun Apr 17 12:04:41 2022 +0200 +++ b/src/server/plugins/postgresql/vfs.h Mon Apr 18 10:53:13 2022 +0200 @@ -102,6 +102,12 @@ struct stat *s, WSBool collection); +int pg_remove_file( + VFSContext *ctx, + PgVFS *pg, + int64_t resource_id, + Oid oid); + int pg_update_resource(PgVFS *pg, int64_t resource_id, int64_t contentlength); SYS_FILE pg_vfs_open(VFSContext *ctx, const char *path, int oflags);