2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
21 #include <netinet/in.h>
23 #include <sys/resource.h>
27 #include <sys/types.h>
38 #include <afs/cellconfig.h>
42 #include "budb_errs.h"
44 #include "error_macros.h"
46 #include "afs/audit.h"
49 /* dump ubik database - interface routines */
52 * no checking for now.
64 * decode the arguments passed via LWP and dump the database.
72 code = InitRPC(&dumpSyncPtr->ut, LOCKREAD, 1);
76 code = writeDatabase(dumpSyncPtr->ut, writeFid);
78 LogError(code, "writeDatabase failed\n");
80 code = close(writeFid);
82 LogError(code, "pipe writer close failed\n");
84 LogDebug(5, "writeDatabase complete\n");
88 ubik_EndTrans(dumpSyncPtr->ut);
93 afs_int32 DumpDB(), RestoreDbHeader();
95 SBUDB_DumpDB(call, firstcall, maxLength, charListPtr, done)
99 charListT *charListPtr;
104 code = DumpDB(call, firstcall, maxLength, charListPtr, done);
105 osi_auditU(call, BUDB_DmpDBEvent, code, AUD_END);
110 DumpDB(call, firstcall, maxLength, charListPtr, done)
111 struct rx_call *call;
112 int firstcall; /* 1 - init. 0 - no init */
114 charListT *charListPtr;
117 PROCESS dumperPid, watcherPid;
120 extern dumpWatcher();
122 if (callPermitted(call) == 0)
123 ERROR(BUDB_NOTPERMITTED);
125 ObtainWriteLock(&dumpSyncPtr->ds_lock);
127 /* If asking for zero bytes, then this is a call to reset the timeToLive
128 * timer. Reset it if there is a dump in progress.
130 if (maxLength == 0) {
131 charListPtr->charListT_val = NULL;
132 charListPtr->charListT_len = 0;
134 *done = ((dumpSyncPtr->statusFlags == 0) ? 1 : 0);
136 /* reset the clock on dump timeout */
137 dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC;
141 if (dumpSyncPtr->statusFlags == 0) {
143 ERROR(BUDB_DUMPFAILED);
145 LogDebug(5, "Setup dump\n");
147 /* no dump in progress - setup and retake lock */
148 memset(dumpSyncPtr, 0, sizeof(*dumpSyncPtr));
149 /* ObtainWriteLock(&dumpSyncPtr->ds_lock); */
151 /* mark dump in progress */
152 dumpSyncPtr->statusFlags = 1;
154 code = pipe(dumpSyncPtr->pipeFid);
159 LWP_CreateProcess(setupDbDump, 16384, 1,
160 (void *)dumpSyncPtr->pipeFid[1],
161 "Database Dumper", &dumperPid);
165 dumpSyncPtr->dumperPid = dumperPid;
166 dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC;
168 /* now create the watcher thread */
170 LWP_CreateProcess(dumpWatcher, 16384, 1, 0,
171 "Database Dump Watchdog", &watcherPid);
172 } else if (firstcall)
175 /* now read the database and feed it to the rpc connection */
178 while (dumpSyncPtr->ds_bytes == 0) {
179 /* if no more data */
180 if ((dumpSyncPtr->ds_writerStatus == DS_DONE)
181 || (dumpSyncPtr->ds_writerStatus == DS_DONE_ERROR)) {
185 if (dumpSyncPtr->ds_writerStatus == DS_WAITING) {
186 LogDebug(6, "wakup writer\n");
187 dumpSyncPtr->ds_writerStatus = 0;
188 code = LWP_SignalProcess(&dumpSyncPtr->ds_writerStatus);
190 LogError(code, "BUDB_DumpDB: signal delivery failed\n");
192 LogDebug(6, "wait for writer\n");
193 dumpSyncPtr->ds_readerStatus = DS_WAITING;
194 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
195 LWP_WaitProcess(&dumpSyncPtr->ds_readerStatus);
196 ObtainWriteLock(&dumpSyncPtr->ds_lock);
199 charListPtr->charListT_val = (char *)malloc(maxLength);
201 read(dumpSyncPtr->pipeFid[0], charListPtr->charListT_val, maxLength);
203 /* reset the clock on dump timeout */
204 dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC;
206 LogDebug(4, "read of len %d returned %d\n", maxLength, readSize);
208 charListPtr->charListT_len = readSize;
210 if (readSize == 0) { /* last chunk */
212 close(dumpSyncPtr->pipeFid[0]);
213 dumpSyncPtr->statusFlags = 0;
217 dumpSyncPtr->ds_bytes -= readSize;
218 if (dumpSyncPtr->ds_writerStatus == DS_WAITING) {
219 dumpSyncPtr->ds_writerStatus = 0;
220 code = LWP_SignalProcess(&dumpSyncPtr->ds_writerStatus);
222 LogError(code, "BUDB_DumpDB: signal delivery failed\n");
226 if (!code && (dumpSyncPtr->ds_writerStatus == DS_DONE_ERROR))
228 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
233 SBUDB_RestoreDbHeader(call, header)
234 struct rx_call *call;
235 struct DbHeader *header;
239 code = RestoreDbHeader(call, header);
240 osi_auditU(call, BUDB_RstDBHEvent, code, AUD_END);
245 RestoreDbHeader(call, header)
246 struct rx_call *call;
247 struct DbHeader *header;
249 struct ubik_trans *ut = 0;
252 extern struct memoryDB db;
254 if (callPermitted(call) == 0)
255 ERROR(BUDB_NOTPERMITTED);
257 code = InitRPC(&ut, LOCKWRITE, 1);
261 if (header->dbversion != ntohl(db.h.version))
262 ERROR(BUDB_VERSIONMISMATCH);
264 /* merge rather than replace the header information */
265 if (db.h.lastDumpId < htonl(header->lastDumpId))
266 db.h.lastDumpId = htonl(header->lastDumpId);
268 if (db.h.lastTapeId < htonl(header->lastTapeId))
269 db.h.lastTapeId = htonl(header->lastTapeId);
271 if (db.h.lastInstanceId < htonl(header->lastInstanceId))
272 db.h.lastInstanceId = htonl(header->lastInstanceId);
274 code = dbwrite(ut, 0, (char *)&db.h, sizeof(db.h));
285 * monitors the state of a database dump. If the dump calls do not
286 * reset the time to live value, the dump times out. In that case,
287 * we kill the database traversal thread and clean up all the other
288 * state. Most importantly, the database is unlocked so that other
289 * transactions can proceed.
298 /* printf("dumpWatcher\n"); */
299 ObtainWriteLock(&dumpSyncPtr->ds_lock);
301 if (dumpSyncPtr->statusFlags == 0) {
302 /* dump has finished */
306 /* check time to live */
307 if (time(0) > dumpSyncPtr->timeToLive) { /*i */
308 /* dump has exceeded the allocated time - terminate it */
309 LogError(0, "Database dump timeout exceeded: %s",
310 ctime(&dumpSyncPtr->timeToLive));
311 LogError(0, "Terminating database dump\n");
313 close(dumpSyncPtr->pipeFid[0]);
314 close(dumpSyncPtr->pipeFid[1]);
316 code = LWP_DestroyProcess(dumpSyncPtr->dumperPid);
318 LogError(code, "dumpWatcher: failed to kill dump thread\n");
320 if (dumpSyncPtr->ut) {
321 code = ubik_AbortTrans(dumpSyncPtr->ut);
323 LogError(code, "Aborting dump transaction\n");
326 memset(dumpSyncPtr, 0, sizeof(*dumpSyncPtr));
330 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
335 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
336 /* printf("dumpWatcher exit\n"); */