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,
156 (void *) dumpSyncPtr->pipeFid[1],
157 "Database Dumper", &dumperPid);
158 if (code) goto error_exit;
160 dumpSyncPtr->dumperPid = dumperPid;
161 dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC;
163 /* now create the watcher thread */
164 code = LWP_CreateProcess(dumpWatcher, 16384, 1, 0,
165 "Database Dump Watchdog", &watcherPid);
170 /* now read the database and feed it to the rpc connection */
173 while ( dumpSyncPtr->ds_bytes == 0 )
175 /* if no more data */
176 if ( (dumpSyncPtr->ds_writerStatus == DS_DONE ) ||
177 (dumpSyncPtr->ds_writerStatus == DS_DONE_ERROR) )
182 if ( dumpSyncPtr->ds_writerStatus == DS_WAITING )
184 LogDebug(6, "wakup writer\n");
185 dumpSyncPtr->ds_writerStatus = 0;
186 code = LWP_SignalProcess(&dumpSyncPtr->ds_writerStatus);
188 LogError(code, "BUDB_DumpDB: signal delivery failed\n");
190 LogDebug(6, "wait for writer\n");
191 dumpSyncPtr->ds_readerStatus = DS_WAITING;
192 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
193 LWP_WaitProcess(&dumpSyncPtr->ds_readerStatus);
194 ObtainWriteLock(&dumpSyncPtr->ds_lock);
197 charListPtr->charListT_val = (char *) malloc(maxLength);
198 readSize = read(dumpSyncPtr->pipeFid[0], charListPtr->charListT_val, maxLength);
200 /* reset the clock on dump timeout */
201 dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC;
203 LogDebug(4, "read of len %d returned %d\n", maxLength, readSize);
205 charListPtr->charListT_len = readSize;
207 if ( readSize == 0 ) /* last chunk */
210 close(dumpSyncPtr->pipeFid[0]);
211 dumpSyncPtr->statusFlags = 0;
216 dumpSyncPtr->ds_bytes -= readSize;
217 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) ) code = -1;
227 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
231 afs_int32 SBUDB_RestoreDbHeader (call, header)
232 struct rx_call *call;
233 struct DbHeader *header;
237 code = RestoreDbHeader (call, header);
238 osi_auditU (call, BUDB_RstDBHEvent, code, AUD_END);
242 afs_int32 RestoreDbHeader (call, header)
243 struct rx_call *call;
244 struct DbHeader *header;
246 struct ubik_trans *ut = 0;
249 extern struct memoryDB db;
251 if ( callPermitted(call) == 0 )
252 ERROR(BUDB_NOTPERMITTED);
254 code = InitRPC(&ut, LOCKWRITE, 1);
258 if ( header->dbversion != ntohl(db.h.version) )
259 ERROR(BUDB_VERSIONMISMATCH);
261 /* merge rather than replace the header information */
262 if ( db.h.lastDumpId < htonl(header->lastDumpId))
263 db.h.lastDumpId = htonl(header->lastDumpId);
265 if ( db.h.lastTapeId < htonl(header->lastTapeId))
266 db.h.lastTapeId = htonl(header->lastTapeId);
268 if ( db.h.lastInstanceId < htonl(header->lastInstanceId))
269 db.h.lastInstanceId = htonl(header->lastInstanceId);
271 code = dbwrite(ut, 0, (char *) &db.h, sizeof(db.h));
282 * monitors the state of a database dump. If the dump calls do not
283 * reset the time to live value, the dump times out. In that case,
284 * we kill the database traversal thread and clean up all the other
285 * state. Most importantly, the database is unlocked so that other
286 * transactions can proceed.
296 /* printf("dumpWatcher\n"); */
297 ObtainWriteLock(&dumpSyncPtr->ds_lock);
299 if ( dumpSyncPtr->statusFlags == 0 )
301 /* dump has finished */
305 /* check time to live */
306 if ( time(0) > dumpSyncPtr->timeToLive )
308 /* dump has exceeded the allocated time - terminate it */
309 LogError(0, "Database dump timeout exceeded: %s", 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);
316 if (code) LogError(code, "dumpWatcher: failed to kill dump thread\n");
318 if ( dumpSyncPtr->ut )
320 code = ubik_AbortTrans(dumpSyncPtr->ut);
321 if (code) LogError(code, "Aborting dump transaction\n");
324 memset(dumpSyncPtr, 0, sizeof(*dumpSyncPtr));
328 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
333 ReleaseWriteLock(&dumpSyncPtr->ds_lock);
334 /* printf("dumpWatcher exit\n"); */