1 |
|
2 #include "dbfs.h" |
|
3 |
|
4 void _dbfs_interrupt_reply (evutil_socket_t _unused1, short _unused2, void *req_ptr) { |
|
5 struct fuse_req *req = req_ptr; |
|
6 err_t err; |
|
7 |
|
8 // error the req |
|
9 if ((err = -fuse_reply_err(req, EINTR))) |
|
10 EWARNING(err, "fuse_reply_err"); |
|
11 } |
|
12 |
|
13 void dbfs_interrupt_query (struct fuse_req *req, void *query_ptr) { |
|
14 struct dbfs *ctx = fuse_req_userdata(req); |
|
15 struct evsql_query *query = query_ptr; |
|
16 struct timeval tv; |
|
17 err_t err; |
|
18 |
|
19 // abort query |
|
20 evsql_query_abort(NULL, query); |
|
21 |
|
22 /* |
|
23 * Due to a locking bug in libfuse (at least 2.7.4), we can't call fuse_reply_err from the interrupt function, so we must |
|
24 * schedule after this function returns. |
|
25 */ |
|
26 tv.tv_sec = 0; |
|
27 tv.tv_usec = 0; |
|
28 if (event_base_once(ctx->ev_base, -1, EV_TIMEOUT, _dbfs_interrupt_reply, req, &tv)) |
|
29 PWARNING("event_base_once failed, dropping req reply: %p", req); |
|
30 } |
|
31 |
|
32 void _dbfs_interrupt_ctx (struct fuse_req *req, void *ctx_ptr) { |
|
33 // dereference ctx |
|
34 struct dbfs_interrupt_ctx *ctx = ctx_ptr; |
|
35 |
|
36 // just cancel query if pending |
|
37 if (ctx->query) { |
|
38 evsql_query_abort(NULL, ctx->query); |
|
39 ctx->query = NULL; |
|
40 } |
|
41 |
|
42 // mark as interrupted |
|
43 ctx->interrupted = 1; |
|
44 } |
|
45 |
|
46 int dbfs_interrupt_register (struct fuse_req *req, struct dbfs_interrupt_ctx *ctx) { |
|
47 // initialize |
|
48 ctx->query = NULL; |
|
49 ctx->interrupted = 0; |
|
50 |
|
51 // just pass over to fuse_req_interrupt_func |
|
52 fuse_req_interrupt_func(req, _dbfs_interrupt_ctx, ctx); |
|
53 } |
|