|
1 #include <stdlib.h> |
|
2 #include <string.h> |
|
3 #include <assert.h> |
1 |
4 |
2 #include "../cache.h" |
5 #include "../cache.h" |
|
6 #include "cache.h" |
3 #include "req.h" |
7 #include "req.h" |
4 #include "op.h" |
8 #include "op.h" |
5 #include "common.h" |
9 #include "engine.h" |
|
10 #include "../common.h" |
6 |
11 |
7 struct cache_req *cache_request (struct cache *cache, struct cache_key *key, cache_callback cb_func, void *cb_data) { |
12 void _cache_req_free (struct cache_req *req) { |
|
13 free(req->key_copy.buf); |
|
14 free(req); |
|
15 } |
|
16 |
|
17 struct cache_req *cache_req (struct cache *cache, const struct cache_key *key, cache_callback cb_func, void *cb_data) { |
8 struct cache_req *req = NULL; |
18 struct cache_req *req = NULL; |
9 |
19 |
10 // calloc the req info |
20 // calloc the req info |
11 if ((req = calloc(1, sizeof(*req))) == NULL) |
21 if ((req = calloc(1, sizeof(*req))) == NULL) |
12 ERROR("calloc"); |
22 ERROR("calloc"); |
13 |
23 |
14 // set up basic state |
24 // set up basic state |
15 req->key = key; |
|
16 req->cb_func = cb_func; |
25 req->cb_func = cb_func; |
17 req->cb_data = cb_data; |
26 req->cb_data = cb_data; |
18 req->is_write = 0; |
27 req->is_write = 0; |
19 |
28 |
|
29 // copy the key |
|
30 if (key->length == 0) |
|
31 req->key_copy.length = strlen(key->buf) + 1; |
|
32 else |
|
33 req->key_copy.length = key->length; |
|
34 |
|
35 if (req->key_copy.length == 0) |
|
36 ERROR("zero-length key"); |
|
37 |
|
38 if ((req->key_copy.buf = malloc(req->key_copy.length)) == NULL) |
|
39 ERROR("malloc"); |
|
40 |
|
41 memcpy(req->key_copy.buf, key->buf, req->key_copy.length); |
|
42 |
|
43 req->key = &req->key_copy; |
|
44 |
20 // look for an existing cache_op for this key |
45 // look for an existing cache_op for this key |
21 if ((req->op = cache_op_find(cache, key)) == NULL) { |
46 if ((req->op = cache_op_find(cache, req->key)) == NULL) { |
22 |
47 |
23 // none available, start a new cache op |
48 // none available, start a new cache op |
24 if (cache->engine->fn_op_start(cache, &req->op, key)) |
49 if (cache->engine->fn_op_start(cache, &req->op, req->key)) |
25 goto error; |
50 goto error; |
26 |
51 |
27 // since we were the one that created it, we take care of writing it |
52 // since we were the one that created it, we take care of writing it |
28 req->is_write = 1; |
53 req->is_write = 1; |
29 |
54 |
30 } else { |
55 } else { |
31 // we found an existing cache_op, we can just use that |
56 // we found an existing cache_op, we can just use that |
32 |
57 |
33 } |
58 } |
34 |
59 |
|
60 // engine may forget to update the op_ptr |
|
61 assert(req->op); |
|
62 |
35 // register |
63 // register |
36 if (cache_op_reigster(req->op, req)) |
64 if (cache_op_register(req->op, req)) |
37 goto error; |
65 goto error; |
38 |
66 |
39 // hurray, we now have an active cache_op \o/ |
67 // hurray, we now have an active cache_op \o/ |
40 return 0; |
68 return req; |
41 |
69 |
42 error: |
70 error: |
43 free(req); |
71 _cache_req_free(req); |
44 |
72 |
45 return -1; |
73 return NULL; |
46 } |
74 } |
47 |
75 |
48 int _cache_req_notify (struct cache_req *req, enum cache_req_event event) { |
76 /*int _cache_req_notify (struct cache_req *req, enum cache_req_event event) { */ |
49 if (req->cb_func(req, event, req->cb_arg)) { |
77 int _cache_req_notify (struct cache_req *req) { |
|
78 if (req->cb_func(req, req->cb_data)) { |
50 // XXX: handle errors |
79 // XXX: handle errors |
51 assert(0); |
80 assert(0); |
52 } |
81 } |
53 |
82 |
54 return 0; |
83 return 0; |
55 } |
84 } |
56 |
85 |
57 int cache_req_notify (struct cache_req *req) { |
86 int cache_req_notify (struct cache_req *req) { |
|
87 /* |
58 switch (req->op->state) { |
88 switch (req->op->state) { |
59 case OP_STATE_INVALID: |
89 case OP_STATE_INVALID: |
60 case OP_STATE_LOOKUP: |
90 case OP_STATE_LOOKUP: |
61 assert(0); |
91 assert(0); |
62 |
92 |
72 if (_cache_req_notify(req, CACHE_EVENT_MISS)) |
102 if (_cache_req_notify(req, CACHE_EVENT_MISS)) |
73 goto error; |
103 goto error; |
74 |
104 |
75 break; |
105 break; |
76 |
106 |
|
107 case OP_STATE_WRITE: |
|
108 if (_cache_req_notify(req, req->is_write ? CACHE_EVENT_BEGIN_WRITE : CACHE_EVENT_BEGIN_READ)) |
|
109 goto error; |
|
110 |
|
111 break; |
|
112 |
77 default: |
113 default: |
78 assert(0); |
114 assert(0); |
79 |
115 |
80 break; |
116 break; |
81 } |
117 } |
82 |
118 |
83 return 0; |
119 return 0; |
84 |
120 |
85 error: |
121 error: |
86 return -1; |
122 return -1; |
|
123 */ |
|
124 |
|
125 return _cache_req_notify(req); |
87 } |
126 } |
88 |
127 |
89 enum cache_req_state cache_request_state (struct cache_req *req) { |
128 enum cache_req_state cache_req_state (struct cache_req *req) { |
90 switch (req->op->state) { |
129 switch (req->op->state) { |
91 case OP_STATE_INVALID: |
130 case OP_STATE_INVALID: |
92 return CACHE_STATE_INVALID; |
131 return CACHE_STATE_INVALID; |
93 |
132 |
94 case OP_STATE_LOOKUP: |
133 case OP_STATE_LOOKUP: |
95 return CACHE_STATE_LOOKUP; |
134 return CACHE_STATE_LOOKUP; |
96 |
135 |
97 case OP_STATE_HIT: |
136 case OP_STATE_HIT: |
|
137 return CACHE_STATE_READ_BEGIN; |
|
138 |
98 case OP_STATE_MISS: |
139 case OP_STATE_MISS: |
99 return CACHE_STATE_OPEN; |
140 return req->is_write ? CACHE_STATE_WRITE_BEGIN : CACHE_STATE_READ_BEGIN; |
100 |
141 |
|
142 case OP_STATE_WRITE: |
|
143 return req->is_write ? CACHE_STATE_WRITE : CACHE_STATE_READ; |
|
144 |
101 default: |
145 default: |
102 assert(0); |
146 assert(0); |
103 } |
147 } |
104 } |
148 } |
105 |
149 |
|
150 const struct cache_key *cache_req_key (struct cache_req *req) { |
|
151 return req->key; |
|
152 } |
|
153 |
|
154 int cache_req_begin_write(struct cache_req *req, size_t hint) { |
|
155 if (req->op->state != OP_STATE_MISS || !req->is_write) |
|
156 ERROR("req not in pre-write mode"); |
|
157 |
|
158 return cache_op_begin_write(req->op, hint); |
|
159 |
|
160 error: |
|
161 return -1; |
|
162 } |
|
163 |
|
164 int cache_req_push (struct cache_req *req, int fd, size_t *size) { |
|
165 if (req->op->state != OP_STATE_WRITE || !req->is_write) |
|
166 ERROR("req not in write mode"); |
|
167 |
|
168 return cache_op_push(req->op, fd, size); |
|
169 |
|
170 error: |
|
171 return -1; |
|
172 } |
|
173 |