110 |
110 |
111 // Get resource |
111 // Get resource |
112 // params: $1: resource_id |
112 // params: $1: resource_id |
113 static const char *sql_get_resource = "select resource_id, nodename, iscollection, lastmodified, creationdate, contentlength from Resource where resource_id = $1;"; |
113 static const char *sql_get_resource = "select resource_id, nodename, iscollection, lastmodified, creationdate, contentlength from Resource where resource_id = $1;"; |
114 |
114 |
|
115 // Create resource |
|
116 // params: $1: parent_id |
|
117 // $2: node name |
|
118 static const char *sql_create_resource = |
|
119 "insert into Resource (parent_id, nodename, iscollection, lastmodified, creationdate, contentlength, resoid) values\n\ |
|
120 ($1, $2, false, now(), now(), 0, lo_creat(-1))\n\ |
|
121 returning resource_id, resoid, lastmodified, creationdate;"; |
|
122 |
115 VFS* pg_vfs_create(Session *sn, Request *rq, pblock *pb) { |
123 VFS* pg_vfs_create(Session *sn, Request *rq, pblock *pb) { |
116 // resourcepool is required |
124 // resourcepool is required |
117 char *resource_pool = pblock_findval("resourcepool", pb); |
125 char *resource_pool = pblock_findval("resourcepool", pb); |
118 if(!resource_pool) { |
126 if(!resource_pool) { |
119 log_ereport(LOG_MISCONFIG, "pg_vfs_create: missing resourcepool parameter"); |
127 log_ereport(LOG_MISCONFIG, "pg_vfs_create: missing resourcepool parameter"); |
268 s->st_size = len; |
276 s->st_size = len; |
269 } |
277 } |
270 } |
278 } |
271 } |
279 } |
272 |
280 |
|
281 int pg_create_file( |
|
282 VFSContext *ctx, |
|
283 PgVFS *pg, |
|
284 const char *path, |
|
285 int64_t *new_resource_id, |
|
286 int64_t *res_parent_id, |
|
287 Oid *oid, |
|
288 const char **resource_name, |
|
289 struct stat *s) |
|
290 { |
|
291 char *parent_path = util_parent_path(path); |
|
292 if(!parent_path) return 1; |
|
293 |
|
294 const char *nodename = util_resource_name(path); |
|
295 |
|
296 // resolve the parent path |
|
297 // if the parent path can't be resolved, we are done |
|
298 const char *resname; |
|
299 int64_t resource_id, parent_id; |
|
300 resource_id = -1; |
|
301 parent_id = -1; |
|
302 WSBool iscollection; |
|
303 Oid unused_oid = 0; |
|
304 |
|
305 int err = pg_resolve_path(ctx, parent_path, &parent_id, &resource_id, &unused_oid, &resname, &iscollection, NULL); |
|
306 FREE(parent_path); |
|
307 if(err) { |
|
308 return 1; |
|
309 } |
|
310 |
|
311 // parent path exists, check if it is a collection |
|
312 if(!iscollection) { |
|
313 return 1; |
|
314 } |
|
315 |
|
316 // create new Resource |
|
317 char resid_str[32]; |
|
318 snprintf(resid_str, 32, "%" PRId64, resource_id); // convert parent resource_id to string |
|
319 |
|
320 const char* params[2] = { resid_str, nodename }; |
|
321 PGresult *result = PQexecParams( |
|
322 pg->connection, |
|
323 sql_create_resource, |
|
324 2, // number of parameters |
|
325 NULL, |
|
326 params, // parameter value |
|
327 NULL, |
|
328 NULL, |
|
329 0); // 0: result in text format |
|
330 |
|
331 if(!result) return 1; |
|
332 |
|
333 int ret = 1; |
|
334 if(PQntuples(result) == 1) { |
|
335 // sql insert succesful |
|
336 ret = 0; |
|
337 |
|
338 char *id_str = PQgetvalue(result, 0, 0); |
|
339 char *oid_str = PQgetvalue(result, 0, 1); |
|
340 char *lastmodified = PQgetvalue(result, 0, 2); |
|
341 char *creationdate = PQgetvalue(result, 0, 3); |
|
342 |
|
343 if(new_resource_id) { |
|
344 if(!id_str || !util_strtoint(id_str, new_resource_id)) { |
|
345 ret = 1; // shouldn't happen |
|
346 log_ereport(LOG_FAILURE, "Postgresql VFS: sql_create_resource: Could not convert resource_id to int"); |
|
347 } |
|
348 } |
|
349 if(res_parent_id) { |
|
350 // resource_id is still the id of the parent from previous pg_resolve_path call |
|
351 *res_parent_id = resource_id; |
|
352 } |
|
353 if(oid) { |
|
354 int64_t i; |
|
355 if(!oid_str || !util_strtoint(oid_str, &i)) { |
|
356 ret = 1; // shouldn't happen |
|
357 log_ereport(LOG_FAILURE, "Postgresql VFS: sql_create_resource: Could not convert oid to int"); |
|
358 } else { |
|
359 *oid = i; |
|
360 } |
|
361 } |
|
362 if(resource_name) { |
|
363 *resource_name = nodename; |
|
364 } |
|
365 if(s) { |
|
366 pg_set_stat(s, 0, lastmodified, creationdate, NULL); |
|
367 } |
|
368 } |
|
369 |
|
370 PQclear(result); |
|
371 |
|
372 return ret; |
|
373 } |
|
374 |
273 /* -------------------------- VFS functions -------------------------- */ |
375 /* -------------------------- VFS functions -------------------------- */ |
274 |
376 |
275 SYS_FILE pg_vfs_open(VFSContext *ctx, const char *path, int oflags) { |
377 SYS_FILE pg_vfs_open(VFSContext *ctx, const char *path, int oflags) { |
276 VFS *vfs = ctx->vfs; |
378 VFS *vfs = ctx->vfs; |
277 PgVFS *pg = vfs->instance; |
379 PgVFS *pg = vfs->instance; |
282 parent_id = -1; |
384 parent_id = -1; |
283 WSBool iscollection; |
385 WSBool iscollection; |
284 struct stat s; |
386 struct stat s; |
285 Oid oid = 0; |
387 Oid oid = 0; |
286 if(pg_resolve_path(ctx, path, &parent_id, &resource_id, &oid, &resname, &iscollection, &s)) { |
388 if(pg_resolve_path(ctx, path, &parent_id, &resource_id, &oid, &resname, &iscollection, &s)) { |
287 return NULL; |
389 if((oflags & O_CREAT) == O_CREAT) { |
|
390 if(pg_create_file(ctx, pg, path, &resource_id, &parent_id, &oid, &resname, &s)) { |
|
391 return NULL; |
|
392 } |
|
393 iscollection = 0; |
|
394 } else { |
|
395 return NULL; |
|
396 } |
288 } |
397 } |
289 |
398 |
290 VFSFile *file = pool_malloc(ctx->pool, sizeof(VFSFile)); |
399 VFSFile *file = pool_malloc(ctx->pool, sizeof(VFSFile)); |
291 if(!file) { |
400 if(!file) { |
292 return NULL; |
401 return NULL; |