1 #include "tdb1-external-agent.h"
2 #include "tdb1-lock-tracking.h"
13 #include <ccan/tdb2/tdb1_private.h>
14 #include <ccan/tap/tap.h>
18 static struct tdb_context
*tdb
;
20 static enum agent_return
do_operation(enum operation op
, const char *name
)
23 enum agent_return ret
;
26 if (op
!= OPEN
&& !tdb
) {
27 diag("external: No tdb open!");
31 k
.dptr
= (void *)name
;
32 k
.dsize
= strlen(name
);
34 locking_would_block1
= 0;
38 diag("Already have tdb %s open", tdb
->name
);
41 tdb
= tdb_open(name
, TDB_VERSION1
, O_RDWR
, 0, &tap_log_attr
);
43 if (!locking_would_block1
)
44 diag("Opening tdb gave %s", strerror(errno
));
49 case TRANSACTION_START
:
50 ret
= tdb_transaction_start(tdb
) == TDB_SUCCESS
? SUCCESS
: OTHER_FAILURE
;
53 if (tdb_fetch(tdb
, k
, &data
) != TDB_SUCCESS
) {
54 if (tdb
->last_error
== TDB_ERR_NOEXIST
)
58 } else if (data
.dsize
!= k
.dsize
59 || memcmp(data
.dptr
, k
.dptr
, k
.dsize
) != 0) {
67 if (tdb_store(tdb
, k
, k
, 0) == TDB_SUCCESS
)
72 case TRANSACTION_COMMIT
:
73 ret
= tdb_transaction_commit(tdb
) == TDB_SUCCESS
? SUCCESS
: OTHER_FAILURE
;
76 ret
= tdb_check(tdb
, NULL
, NULL
) == TDB_SUCCESS
? SUCCESS
: OTHER_FAILURE
;
79 ret
= tdb1_needs_recovery(tdb
) ? SUCCESS
: FAILED
;
82 ret
= tdb_close(tdb
) == 0 ? SUCCESS
: OTHER_FAILURE
;
89 if (locking_would_block1
)
90 ret
= WOULD_HAVE_BLOCKED
;
96 int cmdfd
, responsefd
;
99 /* Do this before doing any tdb stuff. Return handle, or NULL. */
100 struct agent
*prepare_external_agent1(void)
103 int command
[2], response
[2];
104 char name
[1+PATH_MAX
];
106 if (pipe(command
) != 0 || pipe(response
) != 0)
114 struct agent
*agent
= malloc(sizeof(*agent
));
118 agent
->cmdfd
= command
[1];
119 agent
->responsefd
= response
[0];
126 /* We want to fail, not block. */
127 nonblocking_locks1
= true;
128 log_prefix
= "external: ";
129 while ((ret
= read(command
[0], name
, sizeof(name
))) > 0) {
130 enum agent_return result
;
132 result
= do_operation(name
[0], name
+1);
133 if (write(response
[1], &result
, sizeof(result
))
135 err(1, "Writing response");
140 /* Ask the external agent to try to do an operation. */
141 enum agent_return
external_agent_operation1(struct agent
*agent
,
145 enum agent_return res
;
151 len
= 1 + strlen(name
) + 1;
152 string
= malloc(len
);
155 strcpy(string
+1, name
);
157 if (write(agent
->cmdfd
, string
, len
) != len
158 || read(agent
->responsefd
, &res
, sizeof(res
)) != sizeof(res
))
165 const char *agent_return_name1(enum agent_return ret
)
167 return ret
== SUCCESS
? "SUCCESS"
168 : ret
== WOULD_HAVE_BLOCKED
? "WOULD_HAVE_BLOCKED"
169 : ret
== AGENT_DIED
? "AGENT_DIED"
170 : ret
== FAILED
? "FAILED"
171 : ret
== OTHER_FAILURE
? "OTHER_FAILURE"
175 const char *operation_name1(enum operation op
)
178 case OPEN
: return "OPEN";
179 case TRANSACTION_START
: return "TRANSACTION_START";
180 case FETCH
: return "FETCH";
181 case STORE
: return "STORE";
182 case TRANSACTION_COMMIT
: return "TRANSACTION_COMMIT";
183 case CHECK
: return "CHECK";
184 case NEEDS_RECOVERY
: return "NEEDS_RECOVERY";
185 case CLOSE
: return "CLOSE";
187 return "**INVALID**";