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 <afs/param.h>
16 #include <netinet/in.h>
18 #include <sys/resource.h>
22 #include <sys/types.h>
33 #include <afs/cellconfig.h>
37 #include "budb_errs.h"
39 #include "error_macros.h"
41 #include "afs/audit.h"
44 /* dump ubik database - interface routines */
47 * no checking for now.
59 * decode the arguments passed via LWP and dump the database.
67 code = InitRPC(&dumpSyncPtr->ut, LOCKREAD, 1);
71 code = writeDatabase(dumpSyncPtr->ut, writeFid);
73 LogError(code, "writeDatabase failed\n");
75 code = close(writeFid);
77 LogError(code, "pipe writer close failed\n");
79 LogDebug(5, "writeDatabase complete\n");
82 if ( dumpSyncPtr->ut )
83 ubik_EndTrans(dumpSyncPtr->ut);
88 afs_int32 DumpDB(), RestoreDbHeader();
89 afs_int32 BUDB_DumpDB (call, firstcall, maxLength, charListPtr, done)
93 charListT *charListPtr;
98 code = DumpDB (call, firstcall, maxLength, charListPtr, done);
99 osi_auditU (call, BUDB_DmpDBEvent, code, AUD_END);
103 afs_int32 DumpDB (call, firstcall, maxLength, charListPtr, done)
104 struct rx_call *call;
105 int firstcall; /* 1 - init. 0 - no init */
107 charListT *charListPtr;
110 PROCESS dumperPid, watcherPid;
113 extern dumpWatcher();
115 if ( callPermitted(call) == 0 )
116 ERROR(BUDB_NOTPERMITTED);
118 ObtainWriteLock(&dumpSyncPtr->ds_lock);
120 /* If asking for zero bytes, then this is a call to reset the timeToLive
121 * timer. Reset it if there is a dump in progress.
125 charListPtr->charListT_val = (char *)0;
126 charListPtr->charListT_len = 0;
128 *done = ((dumpSyncPtr->statusFlags == 0) ? 1 : 0);
130 /* reset the clock on dump timeout */
131 dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC;
135 if (dumpSyncPtr->statusFlags == 0)
137 if (!firstcall) ERROR(BUDB_DUMPFAILED);
139 LogDebug(5, "Setup dump\n");
141 /* no dump in progress - setup and retake lock */
142 bzero(dumpSyncPtr, sizeof(*dumpSyncPtr));
143 /* ObtainWriteLock(&dumpSyncPtr->ds_lock); */
145 /* mark dump in progress */
146 dumpSyncPtr->statusFlags = 1;
148 code = pipe(dumpSyncPtr->pipeFid);
149 if (code) ERROR(errno);
151 code = LWP_CreateProcess(setupDbDump, 16384, 1, dumpSyncPtr->pipeFid[1],
152 "Database Dumper", &dumperPid);
153 if (code) goto error_exit;
155 dumpSyncPtr->dumperPid = dumperPid;
156 dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC;
158 /* now create the watcher thread */
159 code = LWP_CreateProcess(dumpWatcher, 16384, 1, 0,
160 "Database Dump Watchdog", &watcherPid);
165 /* now read the database and feed it to the rpc connection */
168 while ( dumpSyncPtr->ds_bytes == 0 )
170 /* if no more data */
171 if ( (dumpSyncPtr->ds_writerStatus == DS_DONE ) ||
172 (dumpSyncPtr->ds_writerStatus == DS_DONE_ERROR) )
177 if ( dumpSyncPtr->ds_writerStatus == DS_WAITING )
179 LogDebug(6, "wakup writer\n");
180 dumpSyncPtr->ds_writerStatus = 0;
181 code = LWP_SignalProcess(&dumpSyncPtr->ds_writerStatus);
183 LogError(code, "BUDB_DumpDB: signal delivery failed\n");
185 LogDebug(6, "wait for writer\n");
186 dumpSyncPtr->ds_readerStatus = DS_WAITING;
187 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
188 LWP_WaitProcess(&dumpSyncPtr->ds_readerStatus);
189 ObtainWriteLock(&dumpSyncPtr->ds_lock);
192 charListPtr->charListT_val = (char *) malloc(maxLength);
193 readSize = read(dumpSyncPtr->pipeFid[0], charListPtr->charListT_val, maxLength);
195 /* reset the clock on dump timeout */
196 dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC;
198 LogDebug(4, "read of len %d returned %d\n", maxLength, readSize);
200 charListPtr->charListT_len = readSize;
202 if ( readSize == 0 ) /* last chunk */
205 close(dumpSyncPtr->pipeFid[0]);
206 dumpSyncPtr->statusFlags = 0;
211 dumpSyncPtr->ds_bytes -= readSize;
212 if ( dumpSyncPtr->ds_writerStatus == DS_WAITING )
214 dumpSyncPtr->ds_writerStatus = 0;
215 code = LWP_SignalProcess(&dumpSyncPtr->ds_writerStatus);
217 LogError(code, "BUDB_DumpDB: signal delivery failed\n");
221 if ( !code && (dumpSyncPtr->ds_writerStatus == DS_DONE_ERROR) ) code = -1;
222 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
226 afs_int32 BUDB_RestoreDbHeader (call, header)
227 struct rx_call *call;
228 struct DbHeader *header;
232 code = RestoreDbHeader (call, header);
233 osi_auditU (call, BUDB_RstDBHEvent, code, AUD_END);
237 afs_int32 RestoreDbHeader (call, header)
238 struct rx_call *call;
239 struct DbHeader *header;
241 struct ubik_trans *ut = 0;
244 extern struct memoryDB db;
246 if ( callPermitted(call) == 0 )
247 ERROR(BUDB_NOTPERMITTED);
249 code = InitRPC(&ut, LOCKWRITE, 1);
253 if ( header->dbversion != ntohl(db.h.version) )
254 ERROR(BUDB_VERSIONMISMATCH);
256 /* merge rather than replace the header information */
257 if ( db.h.lastDumpId < htonl(header->lastDumpId))
258 db.h.lastDumpId = htonl(header->lastDumpId);
260 if ( db.h.lastTapeId < htonl(header->lastTapeId))
261 db.h.lastTapeId = htonl(header->lastTapeId);
263 if ( db.h.lastInstanceId < htonl(header->lastInstanceId))
264 db.h.lastInstanceId = htonl(header->lastInstanceId);
266 code = dbwrite(ut, 0, (char *) &db.h, sizeof(db.h));
277 * monitors the state of a database dump. If the dump calls do not
278 * reset the time to live value, the dump times out. In that case,
279 * we kill the database traversal thread and clean up all the other
280 * state. Most importantly, the database is unlocked so that other
281 * transactions can proceed.
291 /* printf("dumpWatcher\n"); */
292 ObtainWriteLock(&dumpSyncPtr->ds_lock);
294 if ( dumpSyncPtr->statusFlags == 0 )
296 /* dump has finished */
300 /* check time to live */
301 if ( time(0) > dumpSyncPtr->timeToLive )
303 /* dump has exceeded the allocated time - terminate it */
304 LogError(0, "Database dump timeout exceeded: %s", ctime(&dumpSyncPtr->timeToLive));
305 LogError(0, "Terminating database dump\n");
307 close(dumpSyncPtr->pipeFid[0]);
308 close(dumpSyncPtr->pipeFid[1]);
310 code = LWP_DestroyProcess(dumpSyncPtr->dumperPid);
311 if (code) LogError(code, "dumpWatcher: failed to kill dump thread\n");
313 if ( dumpSyncPtr->ut )
315 code = ubik_AbortTrans(dumpSyncPtr->ut);
316 if (code) LogError(code, "Aborting dump transaction\n");
319 bzero(dumpSyncPtr, sizeof(*dumpSyncPtr));
323 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
328 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
329 /* printf("dumpWatcher exit\n"); */