--- 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) {