terom@31: #include terom@30: #include terom@30: #include terom@31: #include terom@30: terom@31: #include "../cache.h" terom@31: #include "cache.h" terom@30: #include "op.h" terom@31: #include "req.h" terom@31: #include "engine.h" terom@30: #include "../common.h" terom@30: terom@33: void _cache_op_free (struct cache_op *op) { terom@33: // check we have no reqs listed terom@33: assert(op->req_list.lh_first == NULL); terom@33: terom@33: // remove it from the engine op_list terom@33: LIST_REMOVE(op, node); terom@33: terom@33: // tell the engine to close/free the op terom@33: if (op->cache->engine->fn_op_close(op)) terom@33: WARNING("fn_op_close failed"); terom@33: } terom@33: terom@36: int _cache_op_init (struct cache_op *op, struct cache *cache, struct cache_key *key) { terom@30: op->cache = cache; terom@30: op->key = key; terom@30: op->state = OP_STATE_INVALID; terom@30: terom@30: LIST_INIT(&op->req_list); terom@31: terom@31: // add this to the cache's list of ops terom@31: LIST_INSERT_HEAD(&cache->op_list, op, node); terom@31: terom@31: return 0; terom@30: } terom@30: terom@30: struct cache_op *cache_op_find (struct cache *cache, struct cache_key *key) { terom@30: struct cache_op *op; terom@30: terom@31: for (op = cache->op_list.lh_first; op != NULL; op = op->node.le_next) { terom@31: if (op->key->length == key->length && memcmp(op->key->buf, key->buf, key->length) == 0) terom@30: break; terom@30: } terom@30: terom@30: return op; terom@30: } terom@30: terom@30: int cache_op_register (struct cache_op *op, struct cache_req *req) { terom@30: LIST_INSERT_HEAD(&op->req_list, req, node); terom@31: terom@31: return 0; terom@30: } terom@30: terom@33: int cache_op_deregister (struct cache_op *op, struct cache_req *req) { terom@33: // XXX: check that the req is in our list of ops? terom@33: terom@33: LIST_REMOVE(req, node); terom@33: terom@33: if (op->req_list.lh_first == NULL) { terom@33: // the op is now unused terom@33: _cache_op_free(op); terom@33: } terom@33: terom@33: return 0; terom@33: } terom@33: terom@30: static int _cache_op_notify (struct cache_op *op) { terom@30: struct cache_req *req; terom@30: terom@31: for (req = op->req_list.lh_first; req != NULL; req = req->node.le_next) { terom@30: if (cache_req_notify(req)) terom@30: goto error; terom@30: } terom@30: terom@30: return 0; terom@30: terom@30: error: terom@30: return -1; terom@30: } terom@30: terom@33: int cache_op_available (struct cache_op *op, size_t *size, size_t *offset) { terom@33: return op->cache->engine->fn_op_available(op, size, offset); terom@33: } terom@33: terom@36: int cache_op_begin_read (struct cache_op *op) { terom@36: assert(op->state == OP_STATE_HIT); terom@36: terom@36: op->state = OP_STATE_OPEN_READ; terom@36: terom@36: return op->cache->engine->fn_op_begin_read(op); terom@36: } terom@36: terom@31: int cache_op_begin_write (struct cache_op *op, size_t size_hint) { terom@36: assert(op->state == OP_STATE_MISS); terom@36: terom@36: op->state = OP_STATE_OPEN_WRITE; terom@36: terom@31: return op->cache->engine->fn_op_begin_write(op, size_hint); terom@31: } terom@31: terom@31: int cache_op_push (struct cache_op *op, int fd, size_t *size) { terom@36: assert(op->state == OP_STATE_WRITE); terom@36: terom@31: return op->cache->engine->fn_op_push(op, fd, size); terom@31: } terom@31: terom@37: int cache_op_pull (struct cache_op *op, int fd, size_t *offset, size_t *size) { terom@37: assert(op->state == OP_STATE_READ || op->state == OP_STATE_WRITE); terom@37: terom@37: return op->cache->engine->fn_op_pull(op, fd, offset, size); terom@37: } terom@37: terom@33: int cache_op_done (struct cache_op *op) { terom@36: assert(op->state == OP_STATE_WRITE); terom@36: terom@33: return op->cache->engine->fn_op_done(op); terom@33: } terom@33: terom@36: int _cache_op_lookup_done (struct cache_op *op, int found) { terom@30: // modify state terom@30: op->state = found ? OP_STATE_HIT : OP_STATE_MISS; terom@30: terom@30: // notify waiting reqs terom@30: return _cache_op_notify(op); terom@30: } terom@30: terom@37: int _cache_op_read_ready (struct cache_op *op) { terom@37: // modify state terom@37: op->state = OP_STATE_READ; terom@37: terom@37: // notify waiting reqs terom@37: return _cache_op_notify(op); terom@37: } terom@37: terom@36: int _cache_op_write_ready (struct cache_op *op) { terom@31: // modify state terom@31: op->state = OP_STATE_WRITE; terom@31: terom@31: // notify waiting reqs terom@31: return _cache_op_notify(op); terom@31: } terom@31: terom@36: int _cache_op_data_available (struct cache_op *op) { terom@31: // notify waiting reqs terom@31: return _cache_op_notify(op); terom@31: } terom@31: terom@36: int _cache_op_write_done (struct cache_op *op) { terom@33: op->state = OP_STATE_READ; terom@31: terom@31: // notify waiting reqs terom@31: return _cache_op_notify(op); terom@31: } terom@31: