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>
20 #include <netinet/in.h>
22 #include <sys/resource.h>
26 #include <sys/types.h>
37 #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");
86 if ( dumpSyncPtr->ut )
87 ubik_EndTrans(dumpSyncPtr->ut);
92 afs_int32 DumpDB(), RestoreDbHeader();
93 afs_int32 SBUDB_DumpDB (call, firstcall, maxLength, charListPtr, done)
97 charListT *charListPtr;
102 code = DumpDB (call, firstcall, maxLength, charListPtr, done);
103 osi_auditU (call, BUDB_DmpDBEvent, code, AUD_END);
107 afs_int32 DumpDB (call, firstcall, maxLength, charListPtr, done)
108 struct rx_call *call;
109 int firstcall; /* 1 - init. 0 - no init */
111 charListT *charListPtr;
114 PROCESS dumperPid, watcherPid;
117 extern dumpWatcher();
119 if ( callPermitted(call) == 0 )
120 ERROR(BUDB_NOTPERMITTED);
122 ObtainWriteLock(&dumpSyncPtr->ds_lock);
124 /* If asking for zero bytes, then this is a call to reset the timeToLive
125 * timer. Reset it if there is a dump in progress.
129 charListPtr->charListT_val = NULL;
130 charListPtr->charListT_len = 0;
132 *done = ((dumpSyncPtr->statusFlags == 0) ? 1 : 0);
134 /* reset the clock on dump timeout */
135 dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC;
139 if (dumpSyncPtr->statusFlags == 0)
141 if (!firstcall) ERROR(BUDB_DUMPFAILED);
143 LogDebug(5, "Setup dump\n");
145 /* no dump in progress - setup and retake lock */
146 memset(dumpSyncPtr, 0, sizeof(*dumpSyncPtr));
147 /* ObtainWriteLock(&dumpSyncPtr->ds_lock); */
149 /* mark dump in progress */
150 dumpSyncPtr->statusFlags = 1;
152 code = pipe(dumpSyncPtr->pipeFid);
153 if (code) ERROR(errno);
155 code = LWP_CreateProcess(setupDbDump, 16384, 1, dumpSyncPtr->pipeFid[1],
156 "Database Dumper", &dumperPid);
157 if (code) goto error_exit;
159 dumpSyncPtr->dumperPid = dumperPid;
160 dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC;
162 /* now create the watcher thread */
163 code = LWP_CreateProcess(dumpWatcher, 16384, 1, 0,
164 "Database Dump Watchdog", &watcherPid);
169 /* now read the database and feed it to the rpc connection */
172 while ( dumpSyncPtr->ds_bytes == 0 )
174 /* if no more data */
175 if ( (dumpSyncPtr->ds_writerStatus == DS_DONE ) ||
176 (dumpSyncPtr->ds_writerStatus == DS_DONE_ERROR) )
181 if ( dumpSyncPtr->ds_writerStatus == DS_WAITING )
183 LogDebug(6, "wakup writer\n");
184 dumpSyncPtr->ds_writerStatus = 0;
185 code = LWP_SignalProcess(&dumpSyncPtr->ds_writerStatus);
187 LogError(code, "BUDB_DumpDB: signal delivery failed\n");
189 LogDebug(6, "wait for writer\n");
190 dumpSyncPtr->ds_readerStatus = DS_WAITING;
191 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
192 LWP_WaitProcess(&dumpSyncPtr->ds_readerStatus);
193 ObtainWriteLock(&dumpSyncPtr->ds_lock);
196 charListPtr->charListT_val = (char *) malloc(maxLength);
197 readSize = read(dumpSyncPtr->pipeFid[0], charListPtr->charListT_val, maxLength);
199 /* reset the clock on dump timeout */
200 dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC;
202 LogDebug(4, "read of len %d returned %d\n", maxLength, readSize);
204 charListPtr->charListT_len = readSize;
206 if ( readSize == 0 ) /* last chunk */
209 close(dumpSyncPtr->pipeFid[0]);
210 dumpSyncPtr->statusFlags = 0;
215 dumpSyncPtr->ds_bytes -= readSize;
216 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) ) code = -1;
226 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
230 afs_int32 SBUDB_RestoreDbHeader (call, header)
231 struct rx_call *call;
232 struct DbHeader *header;
236 code = RestoreDbHeader (call, header);
237 osi_auditU (call, BUDB_RstDBHEvent, code, AUD_END);
241 afs_int32 RestoreDbHeader (call, header)
242 struct rx_call *call;
243 struct DbHeader *header;
245 struct ubik_trans *ut = 0;
248 extern struct memoryDB db;
250 if ( callPermitted(call) == 0 )
251 ERROR(BUDB_NOTPERMITTED);
253 code = InitRPC(&ut, LOCKWRITE, 1);
257 if ( header->dbversion != ntohl(db.h.version) )
258 ERROR(BUDB_VERSIONMISMATCH);
260 /* merge rather than replace the header information */
261 if ( db.h.lastDumpId < htonl(header->lastDumpId))
262 db.h.lastDumpId = htonl(header->lastDumpId);
264 if ( db.h.lastTapeId < htonl(header->lastTapeId))
265 db.h.lastTapeId = htonl(header->lastTapeId);
267 if ( db.h.lastInstanceId < htonl(header->lastInstanceId))
268 db.h.lastInstanceId = htonl(header->lastInstanceId);
270 code = dbwrite(ut, 0, (char *) &db.h, sizeof(db.h));
281 * monitors the state of a database dump. If the dump calls do not
282 * reset the time to live value, the dump times out. In that case,
283 * we kill the database traversal thread and clean up all the other
284 * state. Most importantly, the database is unlocked so that other
285 * transactions can proceed.
295 /* printf("dumpWatcher\n"); */
296 ObtainWriteLock(&dumpSyncPtr->ds_lock);
298 if ( dumpSyncPtr->statusFlags == 0 )
300 /* dump has finished */
304 /* check time to live */
305 if ( time(0) > dumpSyncPtr->timeToLive )
307 /* dump has exceeded the allocated time - terminate it */
308 LogError(0, "Database dump timeout exceeded: %s", ctime(&dumpSyncPtr->timeToLive));
309 LogError(0, "Terminating database dump\n");
311 close(dumpSyncPtr->pipeFid[0]);
312 close(dumpSyncPtr->pipeFid[1]);
314 code = LWP_DestroyProcess(dumpSyncPtr->dumperPid);
315 if (code) LogError(code, "dumpWatcher: failed to kill dump thread\n");
317 if ( dumpSyncPtr->ut )
319 code = ubik_AbortTrans(dumpSyncPtr->ut);
320 if (code) LogError(code, "Aborting dump transaction\n");
323 memset(dumpSyncPtr, 0, sizeof(*dumpSyncPtr));
327 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
332 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
333 /* printf("dumpWatcher exit\n"); */