src/dbfs/link.c
branchnew-evsql
changeset 50 881de320e483
parent 49 bb2ff0d2d343
equal deleted inserted replaced
49:bb2ff0d2d343 50:881de320e483
    62     struct dbfs *ctx = fuse_req_userdata(req);
    62     struct dbfs *ctx = fuse_req_userdata(req);
    63     struct evsql_query *query;
    63     struct evsql_query *query;
    64     int err;
    64     int err;
    65 
    65 
    66     INFO("[dbfs.lookup] parent=%lu name=%s", parent, name);
    66     INFO("[dbfs.lookup] parent=%lu name=%s", parent, name);
    67     
    67 
    68     // query and params
    68     // query info
    69     const char *sql = 
    69     static struct evsql_query_info query_info = {
    70         "SELECT"
    70         .sql    =   "SELECT"
    71         " inodes.ino, " DBFS_STAT_COLS
    71                     " inodes.ino, " DBFS_STAT_COLS
    72         " FROM file_tree INNER JOIN inodes ON (file_tree.ino = inodes.ino)"
    72                     " FROM file_tree INNER JOIN inodes ON (file_tree.ino = inodes.ino)"
    73         " WHERE file_tree.parent = $1::int4 AND file_tree.name = $2::varchar";
    73                     " WHERE file_tree.parent = $1::int4 AND file_tree.name = $2::varchar",
    74     
    74         
    75     static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
    75         .params =   {
    76         EVSQL_PARAM ( UINT32 ),
    76             EVSQL_TYPE ( UINT32 ),
    77         EVSQL_PARAM ( STRING ),
    77             EVSQL_TYPE ( STRING ),
    78 
    78 
    79         EVSQL_PARAMS_END
    79             EVSQL_TYPE_END
    80     };
    80         }
    81     
    81     };
    82     // build params
    82 
    83     if (0
    83     // query
    84         ||  evsql_param_uint32(&params, 0, parent)
    84     if ((query = evsql_query_exec(ctx->db, NULL, &query_info, dbfs_entry_res, req,
    85         ||  evsql_param_string(&params, 1, name)
    85         (uint32_t) parent,
    86     )
    86         (const char *) name
    87         EERROR(err = EIO, "evsql_param_*");
    87     )) == NULL)
    88 
       
    89     // query
       
    90     if ((query = evsql_query_params(ctx->db, NULL, sql, &params, dbfs_entry_res, req)) == NULL)
       
    91         EERROR(err = EIO, "evsql_query_params");
    88         EERROR(err = EIO, "evsql_query_params");
    92 
    89 
    93     // handle interrupts
    90     // handle interrupts
    94     fuse_req_interrupt_func(req, dbfs_interrupt_query, query);
    91     fuse_req_interrupt_func(req, dbfs_interrupt_query, query);
    95     
    92     
    99 error:
    96 error:
   100     if ((err = -fuse_reply_err(req, err)))
    97     if ((err = -fuse_reply_err(req, err)))
   101         EWARNING(err, "fuse_reply_err");
    98         EWARNING(err, "fuse_reply_err");
   102 }
    99 }
   103 
   100 
   104 void _dbfs_readlink_res (struct evsql_result *res, void *arg) {
   101 void dbfs_readlink_res (struct evsql_result *res, void *arg) {
   105     struct fuse_req *req = arg;
   102     struct fuse_req *req = arg;
   106     int err = 0;
   103     int err = 0;
   107     
   104     
   108     uint32_t ino;
   105     uint32_t ino;
   109     const char *type, *link;
   106     const char *type, *link;
   110 
   107 
   111     // check the results
   108     // result info
   112     if ((err = _dbfs_check_res(res, 1, 3)))
   109     static struct evsql_result_info result_info = {
   113         SERROR(err = (err ==  1 ? ENOENT : EIO));
   110         0, {
   114         
   111             EVSQL_TYPE ( UINT32 ),
   115     // get our data
   112             EVSQL_TYPE ( STRING ),
   116     if (0
   113             EVSQL_TYPE ( STRING ),
   117         ||  evsql_result_uint32(res, 0, 0, &ino,        0 ) // inodes.ino
   114 
   118         ||  evsql_result_string(res, 0, 1, &type,       0 ) // inodes.type
   115             EVSQL_TYPE_END
   119         ||  evsql_result_string(res, 0, 2, &link,       1 ) // inodes.link_path
   116         }
   120     )
   117     };
   121         EERROR(err = EIO, "invalid db data");
   118 
       
   119     // begin
       
   120     if ((err = evsql_result_begin(&result_info, res)))
       
   121         EERROR(err, "evsql_result_begin");
       
   122 
       
   123     // get the row of data
       
   124     if ((err = evsql_result_next(res,
       
   125         &ino, &type, &link
       
   126     )) <= 0)
       
   127         SERROR(err = err || ENOENT);
   122     
   128     
   123     // is it a symlink?
   129     // is it a symlink?
   124     if (_dbfs_mode(type) != S_IFLNK)
   130     if (_dbfs_mode(type) != S_IFLNK)
   125         EERROR(err = EINVAL, "wrong type: %s", type);
   131         EERROR(err = EINVAL, "wrong type: %s", type);
   126     
   132     
   142     struct dbfs *ctx = fuse_req_userdata(req);
   148     struct dbfs *ctx = fuse_req_userdata(req);
   143     struct evsql_query *query;
   149     struct evsql_query *query;
   144     int err;
   150     int err;
   145     
   151     
   146     INFO("[dbfs.readlink %p] ino=%lu", req, ino);
   152     INFO("[dbfs.readlink %p] ino=%lu", req, ino);
   147 
   153     
   148     const char *sql =
   154     // query info
   149         "SELECT"
   155     static struct evsql_query_info query_info = {
   150         " inodes.ino, inodes.type, inodes.link_path"
   156         .sql    =   "SELECT"
   151         " FROM inodes"
   157                     " inodes.ino, inodes.type, inodes.link_path"
   152         " WHERE inodes.ino = $1::int4";
   158                     " FROM inodes"
   153 
   159                     " WHERE inodes.ino = $1::int4",
   154     static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
   160 
   155         EVSQL_PARAM ( UINT32 ),
   161         .params =   {
   156 
   162             EVSQL_TYPE ( UINT32 ),
   157         EVSQL_PARAMS_END
   163 
   158     };
   164             EVSQL_TYPE_END
   159 
   165         }
   160     // build params
   166     };
   161     if (0
   167 
   162         ||  evsql_param_uint32(&params, 0, ino)
   168     // query
   163     )
   169     if ((query = evsql_query_exec(ctx->db, NULL, &query_info, dbfs_readlink_res, req,
       
   170         (uint32_t) ino
       
   171     )) == NULL)
   164         SERROR(err = EIO);
   172         SERROR(err = EIO);
   165         
   173 
   166     // query
   174     // handle interrupts
   167     if ((query = evsql_query_params(ctx->db, NULL, sql, &params, _dbfs_readlink_res, req)) == NULL)
   175     fuse_req_interrupt_func(req, dbfs_interrupt_query, query);
   168         SERROR(err = EIO);
   176     
   169 
   177     // wait
   170     // handle interrupts
   178     return;
   171     fuse_req_interrupt_func(req, dbfs_interrupt_query, query);
   179 
   172     
   180 error:
   173     // wait
   181     if ((err = -fuse_reply_err(req, err)))
   174     return;
   182         EWARNING(err, "fuse_reply_err");
   175 
   183 
   176 error:
   184 }
   177     if ((err = -fuse_reply_err(req, err)))
       
   178         EWARNING(err, "fuse_reply_err");
       
   179 
       
   180 }
       
   181 
       
   182 #define SETERR(err_var, err_val, bool_val) ((err_var) = bool_val ? (err_val) : 0)
       
   183 
   185 
   184 void dbfs_unlink_res (struct evsql_result *res, void *arg) {
   186 void dbfs_unlink_res (struct evsql_result *res, void *arg) {
   185     struct fuse_req *req = arg;
   187     struct fuse_req *req = arg;
   186     int err = 0;
   188     int err = 0;
   187     
   189 
   188     // check the results
   190     // check
   189     // XXX: reply with ENOTEMPTY if it fails due to this inode being a dir
   191     if ((err = evsql_result_check(res)))
   190     if ((err = dbfs_check_result(res, 1, 0)))
   192         ERROR("evsql_result_check: %s", evsql_result_error(res));
   191         goto error;
   193     
   192         
       
   193     INFO("\t[dbfs.unlink %p] -> OK", req);
   194     INFO("\t[dbfs.unlink %p] -> OK", req);
   194     
   195     
   195     // reply
   196     // reply
   196     if ((err = -fuse_reply_err(req, 0)))
   197     if ((err = -fuse_reply_err(req, 0)))
   197         EERROR(err, "fuse_reply_err");
   198         EERROR(err, "fuse_reply_err");
   208     struct dbfs *ctx = fuse_req_userdata(req);
   209     struct dbfs *ctx = fuse_req_userdata(req);
   209     struct evsql_query *query;
   210     struct evsql_query *query;
   210     int err;
   211     int err;
   211     
   212     
   212     INFO("[dbfs.unlink %p] parent=%lu, name=%s", req, parent, name);
   213     INFO("[dbfs.unlink %p] parent=%lu, name=%s", req, parent, name);
   213 
   214     
   214     const char *sql =
   215     // query info
   215         "DELETE"
   216     static struct evsql_query_info query_info = {
   216         " FROM file_tree"
   217         .sql    =   "DELETE"
   217         " WHERE parent = $1::int4 AND name = $2::varchar";
   218                     " FROM file_tree"
   218 
   219                     " WHERE parent = $1::int4 AND name = $2::varchar",
   219     static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
   220         
   220         EVSQL_PARAM ( UINT32 ),
   221         .params =   {
   221         EVSQL_PARAM ( STRING ),
   222             EVSQL_TYPE ( UINT32 ),
   222 
   223             EVSQL_TYPE ( STRING ),
   223         EVSQL_PARAMS_END
   224 
   224     };
   225             EVSQL_TYPE_END
   225 
   226         }
   226     // build params
   227     };
   227     if (0
   228 
   228         ||  evsql_param_uint32(&params, 0, parent)
   229     // query
   229         ||  evsql_param_string(&params, 1, name)
   230     if ((query = evsql_query_exec(ctx->db, NULL, &query_info, dbfs_unlink_res, req,
   230     )
   231         (uint32_t) parent,
       
   232         (const char *) name
       
   233     )) == NULL)
   231         SERROR(err = EIO);
   234         SERROR(err = EIO);
   232         
   235 
   233     // query
   236     // handle interrupts
   234     if ((query = evsql_query_params(ctx->db, NULL, sql, &params, dbfs_unlink_res, req)) == NULL)
   237     fuse_req_interrupt_func(req, dbfs_interrupt_query, query);
       
   238     
       
   239     // wait
       
   240     return;
       
   241 
       
   242 error:
       
   243     if ((err = -fuse_reply_err(req, err)))
       
   244         EWARNING(err, "fuse_reply_err");
       
   245 }
       
   246 
       
   247 void dbfs_link (struct fuse_req *req, fuse_ino_t ino, fuse_ino_t newparent, const char *newname) {
       
   248     struct dbfs *ctx = fuse_req_userdata(req);
       
   249     struct evsql_query *query;
       
   250     int err;
       
   251     
       
   252     INFO("[dbfs.link %p] ino=%lu, newparent=%lu, newname=%s", req, ino, newparent, newname);
       
   253 
       
   254     // query info
       
   255     static struct evsql_query_info query_info = {
       
   256         .sql    =   "SELECT ino, type, mode, size, nlink FROM dbfs_link($1::int4, $2::int4, $3::varchar)",
       
   257 
       
   258         .params =   {
       
   259             EVSQL_TYPE ( UINT32 ),
       
   260             EVSQL_TYPE ( UINT32 ),
       
   261             EVSQL_TYPE ( STRING ),
       
   262 
       
   263             EVSQL_TYPE_END
       
   264         }
       
   265     };
       
   266 
       
   267     // query
       
   268     if ((query = evsql_query_exec(ctx->db, NULL, &query_info, dbfs_entry_res, req,
       
   269         (uint32_t) ino,
       
   270         (uint32_t) newparent,
       
   271         (const char *) newname
       
   272     )) == NULL)
   235         SERROR(err = EIO);
   273         SERROR(err = EIO);
   236 
   274 
   237     // handle interrupts
   275     // handle interrupts
   238     fuse_req_interrupt_func(req, dbfs_interrupt_query, query);
   276     fuse_req_interrupt_func(req, dbfs_interrupt_query, query);
   239     
   277     
   240     // wait
   278     // wait
   241     return;
   279     return;
   242 
   280 
   243 error:
   281 error:
   244     if ((err = -fuse_reply_err(req, err)))
   282     if ((err = -fuse_reply_err(req, err)))
   245         EWARNING(err, "fuse_reply_err");
       
   246 }
       
   247 
       
   248 void dbfs_link (struct fuse_req *req, fuse_ino_t ino, fuse_ino_t newparent, const char *newname) {
       
   249     struct dbfs *ctx = fuse_req_userdata(req);
       
   250     struct evsql_query *query;
       
   251     int err;
       
   252     
       
   253     INFO("[dbfs.link %p] ino=%lu, newparent=%lu, newname=%s", req, ino, newparent, newname);
       
   254 
       
   255     const char *sql =
       
   256         "SELECT ino, type, mode, size, nlink FROM dbfs_link($1::int4, $2::int4, $3::varchar)";
       
   257 
       
   258     static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
       
   259         EVSQL_PARAM ( UINT32 ),
       
   260         EVSQL_PARAM ( UINT32 ),
       
   261         EVSQL_PARAM ( STRING ),
       
   262 
       
   263         EVSQL_PARAMS_END
       
   264     };
       
   265 
       
   266     // build params
       
   267     if (0
       
   268         ||  evsql_param_uint32(&params, 0, ino)
       
   269         ||  evsql_param_uint32(&params, 1, newparent)
       
   270         ||  evsql_param_string(&params, 2, newname)
       
   271     )
       
   272         SERROR(err = EIO);
       
   273         
       
   274     // query
       
   275     if ((query = evsql_query_params(ctx->db, NULL, sql, &params, dbfs_entry_res, req)) == NULL)
       
   276         SERROR(err = EIO);
       
   277 
       
   278     // handle interrupts
       
   279     fuse_req_interrupt_func(req, dbfs_interrupt_query, query);
       
   280     
       
   281     // wait
       
   282     return;
       
   283 
       
   284 error:
       
   285     if ((err = -fuse_reply_err(req, err)))
       
   286         EWARNING(err, "fuse_reply_err");   
   283         EWARNING(err, "fuse_reply_err");   
   287 }
   284 }
       
   285