diff -r 82cfdb6680d1 -r 99a41f48e29b src/dbfs.c --- a/src/dbfs.c Sun Oct 12 14:57:06 2008 +0300 +++ b/src/dbfs.c Sun Oct 12 20:10:47 2008 +0300 @@ -56,51 +56,98 @@ } +/* + * Check the result set. + * + * Returns; + * -1 if the query failed, the columns do not match, or there are too many/few rows + * 0 the results match + * 1 there were no results + */ +int _dbfs_check_res (const struct evsql_result_info *res, size_t rows, size_t cols) { + int err = 0; + + // check if it failed + if (res->error) + NERROR(evsql_result_error(res)); + + // not found? + if (evsql_result_rows(res) == 0) + SERROR(err = 1); + + // duplicate rows? + if (evsql_result_rows(res) != rows) + ERROR("multiple rows returned"); + + // correct number of columns + if (evsql_result_cols(res) != 5) + ERROR("wrong number of columns: %zu", evsql_result_cols(res)); + + // good + return 0; + +error: + if (!err) + err = -1; + + return err; +} + +int _dbfs_stat_info (struct stat *st, const struct evsql_result_info *res, size_t row, size_t col_offset) { + int err = 0; + + uint16_t mode; + uint64_t size, nlink; + const char *type; + + // extract the data + if (0 + || evsql_result_string(res, row, col_offset + 0, &type, 0 ) // inodes.type + || evsql_result_uint16(res, row, col_offset + 1, &mode, 0 ) // inodes.mode + || evsql_result_uint64(res, row, col_offset + 2, &size, 0 ) // inodes.size + || evsql_result_uint64(res, row, col_offset + 3, &nlink, 0 ) // count(*) + ) + EERROR(err = EIO, "invalid db data"); + + INFO("\tst_mode=S_IF%s | %ho, st_nlink=%llu, st_size=%llu", type, mode, (long long unsigned int) nlink, (long long unsigned int) size); + + // convert and store + st->st_mode = _dbfs_mode(type) | mode; + st->st_nlink = nlink; + st->st_size = size; + + // good + return 0; + +error: + return -1; +} + void _dbfs_lookup_result (const struct evsql_result_info *res, void *arg) { struct fuse_req *req = arg; struct fuse_entry_param e; ZINIT(e); int err = 0; - uint16_t mode; uint32_t ino; - uint64_t size, nlink; - const char *type; - // check if it failed - if (res->error && (err = EIO)) - NERROR(evsql_result_error(res)); - - // duplicate rows? - if (evsql_result_rows(res) > 1) - EERROR(err = EIO, "multiple rows returned"); - - // not found? - if (evsql_result_rows(res) == 0) - SERROR(err = ENOENT); - - // correct number of columns - if (evsql_result_cols(res) != 5) - EERROR(err = EIO, "wrong number of columns: %zu", evsql_result_cols(res)); + // check the results + if ((err = _dbfs_check_res(res, 1, 5))) + SERROR(err = (err == 1 ? ENOENT : EIO)); // get the data if (0 || evsql_result_uint32(res, 0, 0, &ino, 0 ) // inodes.ino - || evsql_result_string(res, 0, 1, &type, 0 ) // inodes.type - || evsql_result_uint16(res, 0, 2, &mode, 0 ) // inodes.mode - || evsql_result_uint64(res, 0, 3, &size, 0 ) // inodes.size - || evsql_result_uint64(res, 0, 4, &nlink, 0 ) // count(*) ) EERROR(err = EIO, "invalid db data"); + + INFO("[dbfs.lookup] -> ion=%u", ino); - INFO("[dbfs.look] -> ino=%u, st_mode=S_IF%s | %ho, st_nlink=%llu, st_size=%llu", ino, type, mode, (long long unsigned int) nlink, (long long unsigned int) size); + // stat attrs + if (_dbfs_stat_info(&e.attr, res, 0, 1)) + goto error; - // convert and store + // other attrs e.ino = e.attr.st_ino = ino; - e.attr.st_mode = _dbfs_mode(type) | mode; - e.attr.st_nlink = nlink; - e.attr.st_size = size; - - // XXX: timeouts e.attr_timeout = CACHE_TIMEOUT; e.entry_timeout = CACHE_TIMEOUT; @@ -127,7 +174,7 @@ "SELECT" " inodes.ino, inodes.type, inodes.mode, inodes.size, count(*)" " FROM file_tree INNER JOIN inodes ON (file_tree.inode = inodes.ino)" - " WHERE file_tree.parent = $1::int AND file_tree.name = $2::varchar" + " WHERE file_tree.parent = $1::int4 AND file_tree.name = $2::varchar" " GROUP BY inodes.ino, inodes.type, inodes.mode, inodes.size"; static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) { @@ -145,7 +192,7 @@ EERROR(err = EIO, "evsql_param_*"); // query - if (evsql_query_params(ctx->db, sql, ¶ms, _dbfs_lookup_result, req) == NULL) + if (evsql_query_params(ctx->db, NULL, sql, ¶ms, _dbfs_lookup_result, req) == NULL) EERROR(err = EIO, "evsql_query_params"); // XXX: handle interrupts @@ -158,11 +205,85 @@ EWARNING(err, "fuse_reply_err"); } +void _dbfs_getattr_result (const struct evsql_result_info *res, void *arg) { + struct fuse_req *req = arg; + struct stat st; ZINIT(st); + int err = 0; + + // check the results + if ((err = _dbfs_check_res(res, 1, 4))) + SERROR(err = (err == 1 ? ENOENT : EIO)); + + INFO("[dbfs.getattr %p] -> (stat follows)", req); + + // stat attrs + if (_dbfs_stat_info(&st, res, 0, 0)) + goto error; + + // XXX: we don't have the ino + st.st_ino = 0; + + // reply + if ((err = fuse_reply_attr(req, &st, CACHE_TIMEOUT))) + EERROR(err, "fuse_reply_entry"); + +error: + if (err && (err = fuse_reply_err(req, err))) + EWARNING(err, "fuse_reply_err"); + + // free + evsql_result_free(res); +} + +static void dbfs_getattr (struct fuse_req *req, fuse_ino_t ino, struct fuse_file_info *fi) { + struct dbfs *ctx = fuse_req_userdata(req); + int err; + + (void) fi; + + INFO("[dbfs.getattr %p] ino=%lu", req, ino); + + const char *sql = + "SELECT" + " inodes.type, inodes.mode, inodes.size, count(*)" + " FROM inodes" + " WHERE inodes.ino = ‰1::int4" + " GROUP BY inodes.type, inodes.mode, inodes.size"; + + static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) { + EVSQL_PARAM ( UINT32 ), + + EVSQL_PARAMS_END + }; + + // build params + if (0 + || evsql_param_uint32(¶ms, 0, ino) + ) + SERROR(err = EIO); + + // query + if (evsql_query_params(ctx->db, NULL, sql, ¶ms, _dbfs_getattr_result, req) == NULL) + SERROR(err = EIO); + + // XXX: handle interrupts + + // wait + return; + +error: + if ((err = fuse_reply_err(req, err))) + EWARNING(err, "fuse_reply_err"); +} + struct fuse_lowlevel_ops dbfs_llops = { + .init = dbfs_init, .destroy = dbfs_destroy, .lookup = dbfs_lookup, + + .getattr = dbfs_getattr, }; void dbfs_sql_error (struct evsql *evsql, void *arg) {