terom@29: #ifndef DBFS_OP_BASE_H terom@29: #define DBFS_OP_BASE_H terom@29: terom@29: #include "dbfs.h" terom@29: terom@29: // forward-declaration for callbacks terom@29: struct dbfs_op; terom@29: terom@29: /* terom@29: * Called by dbfs_op_free to release any resources when the op is free'd (i.e. not open anymore). terom@29: */ terom@29: typedef void (*dbfs_op_free_cb) (struct dbfs_op *op_base); terom@29: terom@29: /* terom@29: * Called after the transaction has been opened, and before reply_open. terom@29: * terom@29: * You can do any at-open initialization here. terom@29: */ terom@29: typedef void (*dbfs_op_open_cb) (struct dbfs_op *op_base); terom@29: terom@29: // the base op state terom@29: struct dbfs_op { terom@29: struct fuse_file_info fi; terom@29: struct fuse_req *req; terom@29: terom@29: struct evsql_trans *trans; terom@29: terom@29: // op target inode terom@29: uint32_t ino; terom@29: terom@29: // open has returned and release hasn't been called yet terom@29: int open; terom@29: terom@29: // callbacks terom@29: dbfs_op_free_cb free_fn; terom@29: dbfs_op_open_cb open_fn; terom@29: }; terom@29: terom@29: /* terom@29: * This will handle failures during requests. terom@29: * terom@29: * 1) if we have a trans, abort it terom@29: * 2) fail the req (mandatory) with the given err terom@29: * terom@29: * If the op is open, then we don't release it, but if it's not open, then the op will be free'd completely. terom@29: * terom@29: */ terom@29: void dbfs_op_fail (struct dbfs_op *op, int err); terom@29: terom@29: /* terom@29: * Open the op, that is, store all the initial state, and open a new transaction. terom@29: * terom@29: * The op must be pre-allocated and zero-initialized. terom@29: * terom@29: * This will always set op->req, so op is safe for dbfs_op_fail after this. terom@29: * terom@29: * This does not fail the dirop, handle error replies yourself. terom@29: * terom@29: * Returns zero on success, err on failure. terom@29: */ terom@29: int dbfs_op_open (struct dbfs *ctx, struct dbfs_op *op, struct fuse_req *req, fuse_ino_t ino, struct fuse_file_info *fi, dbfs_op_free_cb free_fn, dbfs_op_open_cb ready_fn); terom@29: terom@29: /* terom@29: * Should be called from open_fn to send the fuse_reply_open with fi and mark the op as open. terom@29: * terom@29: * If the op has failed earlier or fuse_reply_open fails, this will return nonzero. Fail the op yourself. terom@29: */ terom@29: int dbfs_op_open_reply (struct dbfs_op *op); terom@29: terom@29: /* terom@29: * Start handling a normal op requests. terom@29: * terom@29: * Lookup the op for the given fi, validate params, and assign the new req. terom@29: * terom@29: * In case the op failed previously, this will error the req and return NULL, indicating that the req has been handled. terom@30: * terom@30: * Repeat, if this returns NULL, consider req invalid. terom@29: */ terom@29: struct dbfs_op *dbfs_op_req (struct fuse_req *req, fuse_ino_t ino, struct fuse_file_info *fi); terom@29: terom@29: /* terom@29: * Done handling a request, adjust state accordingly. terom@29: * terom@29: * req *must* have been replied to. terom@29: */ terom@29: int dbfs_op_req_done (struct dbfs_op *op); terom@29: terom@29: /* terom@29: * Handle the op release. terom@29: * terom@29: * This will take care of committing the transaction, sending any reply/error, closing the op and freeing it. terom@29: */ terom@29: void dbfs_op_release (struct fuse_req *req, fuse_ino_t, struct fuse_file_info *fi); terom@29: terom@29: terom@29: #endif /* DBFS_OP_BASE_H */