1 |
1 #include <stdlib.h> |
2 #include <sys/queue.h> |
2 #include <sys/queue.h> |
3 #include <string.h> |
3 #include <string.h> |
|
4 #include <assert.h> |
4 |
5 |
|
6 #include "../cache.h" |
|
7 #include "cache.h" |
5 #include "op.h" |
8 #include "op.h" |
|
9 #include "req.h" |
|
10 #include "engine.h" |
6 #include "../common.h" |
11 #include "../common.h" |
7 |
12 |
8 int cache_op_init(struct cache_op *op, struct cache *cache, struct cache_key *key) { |
13 int cache_op_init(struct cache_op *op, struct cache *cache, struct cache_key *key) { |
9 op->cache = cache; |
14 op->cache = cache; |
10 op->key = key; |
15 op->key = key; |
11 op->state = OP_STATE_INVALID; |
16 op->state = OP_STATE_INVALID; |
12 |
17 |
13 LIST_INIT(&op->req_list); |
18 LIST_INIT(&op->req_list); |
|
19 |
|
20 // add this to the cache's list of ops |
|
21 LIST_INSERT_HEAD(&cache->op_list, op, node); |
|
22 |
|
23 return 0; |
14 } |
24 } |
15 |
25 |
16 struct cache_op *cache_op_find (struct cache *cache, struct cache_key *key) { |
26 struct cache_op *cache_op_find (struct cache *cache, struct cache_key *key) { |
17 struct cache_op *op; |
27 struct cache_op *op; |
18 |
28 |
19 for (op = cache->op_list.lh_first, op != NULL; op = op->node.le_next) { |
29 for (op = cache->op_list.lh_first; op != NULL; op = op->node.le_next) { |
20 if (op->key->length == key->length && memcmp(op->key->buf, key->buf, key->length)) |
30 if (op->key->length == key->length && memcmp(op->key->buf, key->buf, key->length) == 0) |
21 break; |
31 break; |
22 } |
32 } |
23 |
|
24 if (op) |
|
25 cache_op_incref(op); |
|
26 |
33 |
27 return op; |
34 return op; |
28 } |
35 } |
29 |
36 |
30 int cache_op_register (struct cache_op *op, struct cache_req *req) { |
37 int cache_op_register (struct cache_op *op, struct cache_req *req) { |
31 LIST_INSERT_HEAD(&op->req_list, req, node); |
38 LIST_INSERT_HEAD(&op->req_list, req, node); |
|
39 |
|
40 return 0; |
32 } |
41 } |
33 |
42 |
34 static int _cache_op_notify (struct cache_op *op) { |
43 static int _cache_op_notify (struct cache_op *op) { |
35 struct cache_req *req; |
44 struct cache_req *req; |
36 |
45 |
37 for (req = op->req_list.lh_first, req != NULL; req = req->node.le_next) { |
46 for (req = op->req_list.lh_first; req != NULL; req = req->node.le_next) { |
38 if (cache_req_notify(req)) |
47 if (cache_req_notify(req)) |
39 goto error; |
48 goto error; |
40 } |
49 } |
41 |
50 |
42 return 0; |
51 return 0; |
43 |
52 |
44 error: |
53 error: |
45 return -1; |
54 return -1; |
46 } |
55 } |
47 |
56 |
|
57 int cache_op_begin_write (struct cache_op *op, size_t size_hint) { |
|
58 return op->cache->engine->fn_op_begin_write(op, size_hint); |
|
59 } |
|
60 |
|
61 int cache_op_push (struct cache_op *op, int fd, size_t *size) { |
|
62 return op->cache->engine->fn_op_push(op, fd, size); |
|
63 } |
|
64 |
48 int cache_op_lookup_done (struct cache_op *op, int found) { |
65 int cache_op_lookup_done (struct cache_op *op, int found) { |
49 // modify state |
66 // modify state |
50 op->state = found ? OP_STATE_HIT : OP_STATE_MISS; |
67 op->state = found ? OP_STATE_HIT : OP_STATE_MISS; |
51 |
68 |
52 // notify waiting reqs |
69 // notify waiting reqs |
53 return _cache_op_notify(op); |
70 return _cache_op_notify(op); |
54 } |
71 } |
55 |
72 |
|
73 int cache_op_write_ready (struct cache_op *op) { |
|
74 // modify state |
|
75 op->state = OP_STATE_WRITE; |
|
76 |
|
77 // notify waiting reqs |
|
78 return _cache_op_notify(op); |
|
79 } |
|
80 |
|
81 int cache_op_data_available (struct cache_op *op) { |
|
82 // notify waiting reqs |
|
83 return _cache_op_notify(op); |
|
84 } |
|
85 |
|
86 int cache_op_write_done (struct cache_op *op) { |
|
87 op->state = OP_STATE_DONE; |
|
88 |
|
89 // notify waiting reqs |
|
90 return _cache_op_notify(op); |
|
91 } |
|
92 |