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>
41 #include "budb_errs.h"
43 #include "error_macros.h"
45 #include "afs/audit.h"
48 /* dump ubik database - interface routines */
51 * no checking for now.
63 * decode the arguments passed via LWP and dump the database.
71 code = InitRPC(&dumpSyncPtr->ut, LOCKREAD, 1);
75 code = writeDatabase(dumpSyncPtr->ut, writeFid);
77 LogError(code, "writeDatabase failed\n");
79 code = close(writeFid);
81 LogError(code, "pipe writer close failed\n");
83 LogDebug(5, "writeDatabase complete\n");
87 ubik_EndTrans(dumpSyncPtr->ut);
92 afs_int32 DumpDB(), RestoreDbHeader();
94 SBUDB_DumpDB(call, firstcall, maxLength, charListPtr, done)
98 charListT *charListPtr;
103 code = DumpDB(call, firstcall, maxLength, charListPtr, done);
104 osi_auditU(call, BUDB_DmpDBEvent, code, AUD_END);
109 DumpDB(call, firstcall, maxLength, charListPtr, done)
110 struct rx_call *call;
111 int firstcall; /* 1 - init. 0 - no init */
113 charListT *charListPtr;
116 PROCESS dumperPid, watcherPid;
119 extern dumpWatcher();
121 if (callPermitted(call) == 0)
122 ERROR(BUDB_NOTPERMITTED);
124 ObtainWriteLock(&dumpSyncPtr->ds_lock);
126 /* If asking for zero bytes, then this is a call to reset the timeToLive
127 * timer. Reset it if there is a dump in progress.
129 if (maxLength == 0) {
130 charListPtr->charListT_val = NULL;
131 charListPtr->charListT_len = 0;
133 *done = ((dumpSyncPtr->statusFlags == 0) ? 1 : 0);
135 /* reset the clock on dump timeout */
136 dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC;
140 if (dumpSyncPtr->statusFlags == 0) {
142 ERROR(BUDB_DUMPFAILED);
144 LogDebug(5, "Setup dump\n");
146 /* no dump in progress - setup and retake lock */
147 memset(dumpSyncPtr, 0, sizeof(*dumpSyncPtr));
148 /* ObtainWriteLock(&dumpSyncPtr->ds_lock); */
150 /* mark dump in progress */
151 dumpSyncPtr->statusFlags = 1;
153 code = pipe(dumpSyncPtr->pipeFid);
158 LWP_CreateProcess(setupDbDump, 16384, 1,
159 (void *)dumpSyncPtr->pipeFid[1],
160 "Database Dumper", &dumperPid);
164 dumpSyncPtr->dumperPid = dumperPid;
165 dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC;
167 /* now create the watcher thread */
169 LWP_CreateProcess(dumpWatcher, 16384, 1, 0,
170 "Database Dump Watchdog", &watcherPid);
171 } else if (firstcall)
174 /* now read the database and feed it to the rpc connection */
177 while (dumpSyncPtr->ds_bytes == 0) {
178 /* if no more data */
179 if ((dumpSyncPtr->ds_writerStatus == DS_DONE)
180 || (dumpSyncPtr->ds_writerStatus == DS_DONE_ERROR)) {
184 if (dumpSyncPtr->ds_writerStatus == DS_WAITING) {
185 LogDebug(6, "wakup writer\n");
186 dumpSyncPtr->ds_writerStatus = 0;
187 code = LWP_SignalProcess(&dumpSyncPtr->ds_writerStatus);
189 LogError(code, "BUDB_DumpDB: signal delivery failed\n");
191 LogDebug(6, "wait for writer\n");
192 dumpSyncPtr->ds_readerStatus = DS_WAITING;
193 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
194 LWP_WaitProcess(&dumpSyncPtr->ds_readerStatus);
195 ObtainWriteLock(&dumpSyncPtr->ds_lock);
198 charListPtr->charListT_val = (char *)malloc(maxLength);
200 read(dumpSyncPtr->pipeFid[0], charListPtr->charListT_val, maxLength);
202 /* reset the clock on dump timeout */
203 dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC;
205 LogDebug(4, "read of len %d returned %d\n", maxLength, readSize);
207 charListPtr->charListT_len = readSize;
209 if (readSize == 0) { /* last chunk */
211 close(dumpSyncPtr->pipeFid[0]);
212 dumpSyncPtr->statusFlags = 0;
216 dumpSyncPtr->ds_bytes -= readSize;
217 if (dumpSyncPtr->ds_writerStatus == DS_WAITING) {
218 dumpSyncPtr->ds_writerStatus = 0;
219 code = LWP_SignalProcess(&dumpSyncPtr->ds_writerStatus);
221 LogError(code, "BUDB_DumpDB: signal delivery failed\n");
225 if (!code && (dumpSyncPtr->ds_writerStatus == DS_DONE_ERROR))
227 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
232 SBUDB_RestoreDbHeader(call, header)
233 struct rx_call *call;
234 struct DbHeader *header;
238 code = RestoreDbHeader(call, header);
239 osi_auditU(call, BUDB_RstDBHEvent, code, AUD_END);
244 RestoreDbHeader(call, header)
245 struct rx_call *call;
246 struct DbHeader *header;
248 struct ubik_trans *ut = 0;
251 extern struct memoryDB db;
253 if (callPermitted(call) == 0)
254 ERROR(BUDB_NOTPERMITTED);
256 code = InitRPC(&ut, LOCKWRITE, 1);
260 if (header->dbversion != ntohl(db.h.version))
261 ERROR(BUDB_VERSIONMISMATCH);
263 /* merge rather than replace the header information */
264 if (db.h.lastDumpId < htonl(header->lastDumpId))
265 db.h.lastDumpId = htonl(header->lastDumpId);
267 if (db.h.lastTapeId < htonl(header->lastTapeId))
268 db.h.lastTapeId = htonl(header->lastTapeId);
270 if (db.h.lastInstanceId < htonl(header->lastInstanceId))
271 db.h.lastInstanceId = htonl(header->lastInstanceId);
273 code = dbwrite(ut, 0, (char *)&db.h, sizeof(db.h));
284 * monitors the state of a database dump. If the dump calls do not
285 * reset the time to live value, the dump times out. In that case,
286 * we kill the database traversal thread and clean up all the other
287 * state. Most importantly, the database is unlocked so that other
288 * transactions can proceed.
297 /* printf("dumpWatcher\n"); */
298 ObtainWriteLock(&dumpSyncPtr->ds_lock);
300 if (dumpSyncPtr->statusFlags == 0) {
301 /* dump has finished */
305 /* check time to live */
306 if (time(0) > dumpSyncPtr->timeToLive) { /*i */
307 /* dump has exceeded the allocated time - terminate it */
308 LogError(0, "Database dump timeout exceeded: %s",
309 ctime(&dumpSyncPtr->timeToLive));
310 LogError(0, "Terminating database dump\n");
312 close(dumpSyncPtr->pipeFid[0]);
313 close(dumpSyncPtr->pipeFid[1]);
315 code = LWP_DestroyProcess(dumpSyncPtr->dumperPid);
317 LogError(code, "dumpWatcher: failed to kill dump thread\n");
319 if (dumpSyncPtr->ut) {
320 code = ubik_AbortTrans(dumpSyncPtr->ut);
322 LogError(code, "Aborting dump transaction\n");
325 memset(dumpSyncPtr, 0, sizeof(*dumpSyncPtr));
329 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
334 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
335 /* printf("dumpWatcher exit\n"); */