afs_int32 FreeLock(struct rx_call *call, afs_uint32 lockHandle) { db_lockP lockPtr = 0; struct ubik_trans *ut; afs_int32 code; if (callPermitted(call) == 0) return (BUDB_NOTPERMITTED); code = InitRPC(&ut, LOCKWRITE, 1); if (code) return (code); if (checkLockHandle(ut, lockHandle) == 0) ABORT(BUDB_BADARGUMENT); lockPtr = &db.h.textLocks[lockHandle - 1]; lockPtr->lockState = 0; /* unlock it */ lockPtr->lockTime = 0; lockPtr->expires = 0; lockPtr->instanceId = 0; dbwrite(ut, DBH_POS(lockPtr), (char *)lockPtr, sizeof(db_lockT)); code = ubik_EndTrans(ut); return (code); abort_exit: ubik_AbortTrans(ut); return (code); }
afs_int32 FreeAllLocks(struct rx_call *call, afs_uint32 instanceId) { db_lockP startPtr, endPtr; struct ubik_trans *ut; afs_int32 code; if (callPermitted(call) == 0) return (BUDB_NOTPERMITTED); code = InitRPC(&ut, LOCKWRITE, 1); if (code) return (code); startPtr = &db.h.textLocks[0]; endPtr = &db.h.textLocks[TB_NUM - 1]; while (startPtr <= endPtr) { if ((ntohl(startPtr->lockState) == 1) && (ntohl(startPtr->instanceId) == instanceId) ) { /* release the lock */ startPtr->lockState = 0; /* unlock it */ startPtr->lockTime = 0; startPtr->expires = 0; startPtr->instanceId = 0; dbwrite(ut, DBH_POS(startPtr), (char *)startPtr, sizeof(db_lockT)); } startPtr++; } code = ubik_EndTrans(ut); return (code); }
afs_int32 STC_TCInfo(struct rx_call *acid, struct tc_tcInfo *tciptr) { if (callPermitted(acid) == 0) return (TC_NOTPERMITTED); tciptr->tcVersion = CUR_BUTC_VERSION; return (0); }
afs_int32 GetLock(struct rx_call *call, afs_uint32 instanceId, afs_int32 lockName, afs_int32 expiration, afs_uint32 *lockHandle) { struct timeval tv; db_lockP lockPtr; struct ubik_trans *ut; afs_int32 code; if (callPermitted(call) == 0) return (BUDB_NOTPERMITTED); if ((lockName < 0) || (lockName >= TB_NUM)) return (BUDB_BADARGUMENT); /* get the current time */ gettimeofday(&tv, 0); code = InitRPC(&ut, LOCKWRITE, 1); if (code) return (code); lockPtr = &db.h.textLocks[lockName]; if ((ntohl(lockPtr->lockState) != 0) /* lock set */ &&(ntohl(lockPtr->expires) > tv.tv_sec) /* not expired */ ) { if (ntohl(lockPtr->instanceId) == instanceId) code = BUDB_SELFLOCKED; else code = BUDB_LOCKED; goto abort_exit; } lockPtr->lockState = htonl(1); /* lock it */ lockPtr->lockTime = htonl(tv.tv_sec); /* when locked */ lockPtr->expires = htonl(tv.tv_sec + expiration); lockPtr->instanceId = htonl(instanceId); code = dbwrite(ut, DBH_POS(lockPtr), (char *)lockPtr, sizeof(db_lockT)); if (code) ABORT(code); *lockHandle = (afs_uint32) (lockName + 1); code = ubik_EndTrans(ut); return (code); abort_exit: ubik_AbortTrans(ut); return (code); }
afs_int32 STC_ReadLabel(struct rx_call *acid, struct tc_tapeLabel *label, afs_uint32 *taskId) { afs_int32 code; #ifdef xbsa if (CONF_XBSA) return (TC_BADTASK); /* ReadLabel does not apply if XBSA */ #endif if (callPermitted(acid) == 0) return (TC_NOTPERMITTED); code = ReadLabel(label); /* Synchronous */ return code; }
afs_int32 GetTextVersion(struct rx_call *call, afs_int32 textType, afs_uint32 *tversion) { afs_int32 code; struct ubik_trans *ut; if (callPermitted(call) == 0) return (BUDB_NOTPERMITTED); if ((textType < 0) || (textType >= TB_NUM)) return (BUDB_BADARGUMENT); code = InitRPC(&ut, LOCKREAD, 1); if (code) return (code); *tversion = ntohl(db.h.textBlock[textType].version); code = ubik_EndTrans(ut); return (code); }
afs_int32 RestoreDbHeader(struct rx_call *call, struct DbHeader *header) { struct ubik_trans *ut = 0; afs_int32 code = 0; extern struct memoryDB db; if (callPermitted(call) == 0) ERROR(BUDB_NOTPERMITTED); code = InitRPC(&ut, LOCKWRITE, 1); if (code) goto error_exit; if (header->dbversion != ntohl(db.h.version)) ERROR(BUDB_VERSIONMISMATCH); /* merge rather than replace the header information */ if (db.h.lastDumpId < htonl(header->lastDumpId)) db.h.lastDumpId = htonl(header->lastDumpId); if (db.h.lastTapeId < htonl(header->lastTapeId)) db.h.lastTapeId = htonl(header->lastTapeId); if (db.h.lastInstanceId < htonl(header->lastInstanceId)) db.h.lastInstanceId = htonl(header->lastInstanceId); code = dbwrite(ut, 0, (char *)&db.h, sizeof(db.h)); if (code) code = BUDB_IO; error_exit: if (ut) ubik_EndTrans(ut); return (code); }
afs_int32 STC_PerformRestore(struct rx_call *acid, char *dumpSetName, tc_restoreArray *arestores, afs_int32 *taskID) { struct dumpNode *newNode; statusP statusPtr; afs_int32 code = 0; #ifdef AFS_PTHREAD_ENV pthread_t pid; pthread_attr_t tattr; AFS_SIGSET_DECL; #else PROCESS pid; #endif if (callPermitted(acid) == 0) return (TC_NOTPERMITTED); /* should verify parameter validity */ /* this creates a node in list, alots an id for it and prepares it for locking */ CreateNode(&newNode); newNode->restores = (struct tc_restoreDesc *) malloc(sizeof(struct tc_restoreDesc) * arestores->tc_restoreArray_len); newNode->arraySize = arestores->tc_restoreArray_len; CopyRestoreDesc(newNode->restores, arestores); *taskID = newNode->taskID; /* should log the intent */ /* create the status node */ statusPtr = createStatusNode(); if (!statusPtr) ERROR_EXIT(TC_INTERNALERROR); lock_Status(); statusPtr->taskId = newNode->taskID; statusPtr->flags &= ~STARTING; /* ok to examine */ statusPtr->lastPolled = time(0); strncpy(statusPtr->taskName, "Restore", sizeof(statusPtr->taskName)); unlock_Status(); newNode->statusNodePtr = statusPtr; /* create the LWP to do the real work behind the scenes */ #ifdef AFS_PTHREAD_ENV code = pthread_attr_init(&tattr); if (code) ERROR_EXIT(code); code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); if (code) ERROR_EXIT(code); AFS_SIGSET_CLEAR(); code = pthread_create(&pid, &tattr, Restorer, newNode); AFS_SIGSET_RESTORE(); #else code = LWP_CreateProcess(Restorer, 65368, 1, (void *)newNode, "restorer process", &pid); #endif error_exit: if (code) { if (statusPtr) deleteStatusNode(statusPtr); FreeNode(newNode->taskID); /* failed to create LWP to do the dump. */ } return (code); }
/* STC_DeleteDump */ afs_int32 STC_DeleteDump(struct rx_call *acid, afs_uint32 dumpID, afs_uint32 *taskId) { afs_int32 code = TC_BADTASK; /* If not compiled -Dxbsa then fail */ #ifdef xbsa struct deleteDumpIf *ptr = 0; statusP statusPtr = 0; #ifdef AFS_PTHREAD_ENV pthread_t pid; pthread_attr_t tattr; AFS_SIGSET_DECL; #else PROCESS pid; #endif #endif *taskId = 0; if (!CONF_XBSA) return (TC_BADTASK); /* Only do if butc is started as XBSA */ #ifdef xbsa code = 0; if (callPermitted(acid) == 0) return (TC_NOTPERMITTED); ptr = (struct deleteDumpIf *)malloc(sizeof(*ptr)); if (!ptr) ERROR_EXIT(TC_NOMEMORY); *taskId = allocTaskId(); ptr->dumpID = dumpID; ptr->taskId = *taskId; statusPtr = createStatusNode(); if (!statusPtr) ERROR_EXIT(TC_INTERNALERROR); lock_Status(); statusPtr->taskId = *taskId; statusPtr->lastPolled = time(0); statusPtr->flags &= ~STARTING; strncpy(statusPtr->taskName, "DeleteDump", sizeof(statusPtr->taskName)); unlock_Status(); #ifdef AFS_PTHREAD_ENV code = pthread_attr_init(&tattr); if (code) ERROR_EXIT(code); code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); if (code) ERROR_EXIT(code); AFS_SIGSET_CLEAR(); code = pthread_create(&pid, &tattr, DeleteDump, ptr); AFS_SIGSET_RESTORE(); #else code = LWP_CreateProcess(DeleteDump, 32768, 1, ptr, "deletedump process", &pid); #endif error_exit: if (code) { if (statusPtr) deleteStatusNode(statusPtr); if (ptr) free(ptr); } #endif /* xbsa */ return (code); }
afs_int32 DumpDB(struct rx_call *call, int firstcall, /* 1 - init. 0 - no init */ afs_int32 maxLength, charListT *charListPtr, afs_int32 *done) { #ifdef AFS_PTHREAD_ENV pthread_t dumperPid, watcherPid; pthread_attr_t dumperPid_tattr; pthread_attr_t watcherPid_tattr; #else PROCESS dumperPid, watcherPid; #endif int readSize; afs_int32 code = 0; if (callPermitted(call) == 0) ERROR(BUDB_NOTPERMITTED); ObtainWriteLock(&dumpSyncPtr->ds_lock); /* If asking for zero bytes, then this is a call to reset the timeToLive * timer. Reset it if there is a dump in progress. */ if (maxLength == 0) { charListPtr->charListT_val = NULL; charListPtr->charListT_len = 0; *done = ((dumpSyncPtr->statusFlags == 0) ? 1 : 0); /* reset the clock on dump timeout */ dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC; goto error_exit; } if (dumpSyncPtr->statusFlags == 0) { if (!firstcall) ERROR(BUDB_DUMPFAILED); LogDebug(5, "Setup dump\n"); /* no dump in progress - setup and retake lock */ memset(dumpSyncPtr, 0, sizeof(*dumpSyncPtr)); /* ObtainWriteLock(&dumpSyncPtr->ds_lock); */ /* mark dump in progress */ dumpSyncPtr->statusFlags = 1; code = pipe(dumpSyncPtr->pipeFid); if (code) ERROR(errno); #ifdef AFS_PTHREAD_ENV /* Initialize the condition variables and the mutexes we use * to signal and synchronize the reader and writer threads. */ assert(pthread_cond_init(&dumpSyncPtr->ds_readerStatus_cond, (const pthread_condattr_t *)0) == 0); assert(pthread_cond_init(&dumpSyncPtr->ds_writerStatus_cond, (const pthread_condattr_t *)0) == 0); assert(pthread_mutex_init(&dumpSyncPtr->ds_readerStatus_mutex, (const pthread_mutexattr_t *)0) == 0); assert(pthread_mutex_init(&dumpSyncPtr->ds_writerStatus_mutex, (const pthread_mutexattr_t *)0) == 0); /* Initialize the thread attributes and launch the thread */ assert(pthread_attr_init(&dumperPid_tattr) == 0); assert(pthread_attr_setdetachstate(&dumperPid_tattr, PTHREAD_CREATE_DETACHED) == 0); assert(pthread_create(&dumperPid, &dumperPid_tattr, (void *)setupDbDump, NULL) == 0); #else code = LWP_CreateProcess(setupDbDump, 16384, 1, (void *)(intptr_t)dumpSyncPtr->pipeFid[1], "Database Dumper", &dumperPid); if (code) goto error_exit; #endif dumpSyncPtr->dumperPid = dumperPid; dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC; #ifdef AFS_PTHREAD_ENV /* Initialize the thread attributes and launch the thread */ assert(pthread_attr_init(&watcherPid_tattr) == 0); assert(pthread_attr_setdetachstate(&watcherPid_tattr, PTHREAD_CREATE_DETACHED) == 0); assert(pthread_create(&watcherPid, &watcherPid_tattr, (void *)dumpWatcher, NULL) == 0); #else /* now create the watcher thread */ code = LWP_CreateProcess(dumpWatcher, 16384, 1, 0, "Database Dump Watchdog", &watcherPid); #endif } else if (firstcall) ERROR(BUDB_LOCKED); /* now read the database and feed it to the rpc connection */ /* wait for data */ while (dumpSyncPtr->ds_bytes == 0) { /* if no more data */ if ((dumpSyncPtr->ds_writerStatus == DS_DONE) || (dumpSyncPtr->ds_writerStatus == DS_DONE_ERROR)) { break; } if (dumpSyncPtr->ds_writerStatus == DS_WAITING) { LogDebug(6, "wakup writer\n"); dumpSyncPtr->ds_writerStatus = 0; #ifdef AFS_PTHREAD_ENV assert(pthread_cond_broadcast(&dumpSyncPtr->ds_writerStatus_cond) == 0); #else code = LWP_SignalProcess(&dumpSyncPtr->ds_writerStatus); if (code) LogError(code, "BUDB_DumpDB: signal delivery failed\n"); #endif } LogDebug(6, "wait for writer\n"); dumpSyncPtr->ds_readerStatus = DS_WAITING; ReleaseWriteLock(&dumpSyncPtr->ds_lock); #ifdef AFS_PTHREAD_ENV assert(pthread_mutex_lock(&dumpSyncPtr->ds_readerStatus_mutex) == 0); assert(pthread_cond_wait(&dumpSyncPtr->ds_readerStatus_cond, &dumpSyncPtr->ds_readerStatus_mutex) == 0); assert(pthread_mutex_unlock(&dumpSyncPtr->ds_readerStatus_mutex) == 0); #else LWP_WaitProcess(&dumpSyncPtr->ds_readerStatus); #endif ObtainWriteLock(&dumpSyncPtr->ds_lock); } charListPtr->charListT_val = (char *)malloc(maxLength); readSize = read(dumpSyncPtr->pipeFid[0], charListPtr->charListT_val, maxLength); /* reset the clock on dump timeout */ dumpSyncPtr->timeToLive = time(0) + DUMP_TTL_INC; LogDebug(4, "read of len %d returned %d\n", maxLength, readSize); charListPtr->charListT_len = readSize; if (readSize == 0) { /* last chunk */ *done = 1; close(dumpSyncPtr->pipeFid[0]); dumpSyncPtr->statusFlags = 0; } else *done = 0; dumpSyncPtr->ds_bytes -= readSize; if (dumpSyncPtr->ds_writerStatus == DS_WAITING) { dumpSyncPtr->ds_writerStatus = 0; #ifdef AFS_PTHREAD_ENV assert(pthread_cond_broadcast(&dumpSyncPtr->ds_writerStatus_cond) == 0); #else code = LWP_SignalProcess(&dumpSyncPtr->ds_writerStatus); if (code) LogError(code, "BUDB_DumpDB: signal delivery failed\n"); #endif } error_exit: if (!code && (dumpSyncPtr->ds_writerStatus == DS_DONE_ERROR)) code = -1; ReleaseWriteLock(&dumpSyncPtr->ds_lock); return (code); }
afs_int32 STC_ScanDumps(struct rx_call *acid, afs_int32 addDbFlag, afs_uint32 *taskId) { #ifdef AFS_PTHREAD_ENV pthread_t pid; pthread_attr_t tattr; AFS_SIGSET_DECL; #else PROCESS pid; #endif struct scanTapeIf *ptr; statusP statusPtr = NULL; afs_int32 code = 0; #ifdef xbsa if (CONF_XBSA) return (TC_BADTASK); /* ScanDumps does not apply if XBSA */ #endif if (callPermitted(acid) == 0) return (TC_NOTPERMITTED); *taskId = allocTaskId(); ptr = (struct scanTapeIf *)malloc(sizeof(*ptr)); if (!ptr) ERROR_EXIT(TC_NOMEMORY); ptr->addDbFlag = addDbFlag; ptr->taskId = *taskId; /* create the status node */ statusPtr = createStatusNode(); if (!statusPtr) ERROR_EXIT(TC_INTERNALERROR); lock_Status(); statusPtr->taskId = *taskId; statusPtr->lastPolled = time(0); statusPtr->flags &= ~STARTING; /* ok to examine */ strncpy(statusPtr->taskName, "Scantape", sizeof(statusPtr->taskName)); unlock_Status(); #ifdef AFS_PTHREAD_ENV code = pthread_attr_init(&tattr); if (code) ERROR_EXIT(code); code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); if (code) ERROR_EXIT(code); AFS_SIGSET_CLEAR(); code = pthread_create(&pid, &tattr, ScanDumps, ptr); AFS_SIGSET_RESTORE(); #else code = LWP_CreateProcess(ScanDumps, 32768, 1, ptr, "scandump process", &pid); #endif error_exit: if (code) { if (statusPtr) deleteStatusNode(statusPtr); if (ptr) free(ptr); } return code; }
afs_int32 GetText(struct rx_call *call, afs_uint32 lockHandle, afs_int32 textType, afs_int32 maxLength, afs_int32 offset, afs_int32 *nextOffset, charListT *charListPtr) { struct ubik_trans *ut = 0; struct block block; afs_int32 transferSize, chunkSize; afs_int32 blockOffset; dbadr lastBlockAddr; afs_int32 nblocks; struct textBlock *tbPtr; afs_int32 textRemaining; char *textPtr; afs_int32 code; LogDebug(5, "GetText: type %d, offset %d, nextOffset %"AFS_PTR_FMT ", maxLength %d\n", textType, offset, nextOffset, maxLength); if (callPermitted(call) == 0) { code = BUDB_NOTPERMITTED; goto no_xfer_abort; } /* check parameters */ if ((offset < 0) || (textType < 0) || (textType >= TB_NUM) ) { code = BUDB_BADARGUMENT; goto no_xfer_abort; } /* start the transaction */ code = InitRPC(&ut, LOCKWRITE, 1); if (code) goto no_xfer_abort; /* fetch the lock state */ if (checkLockHandle(ut, lockHandle) == 0) { code = BUDB_NOTLOCKED; goto no_xfer_abort; } tbPtr = &db.h.textBlock[textType]; if ((ntohl(tbPtr->size) > 0) && (offset >= ntohl(tbPtr->size)) ) { code = BUDB_BADARGUMENT; goto no_xfer_abort; } LogDebug(5, "GetText: store size is %d\n", ntohl(tbPtr->size)); /* compute minimum of remaining text or user buffer */ textRemaining = ntohl(tbPtr->size) - offset; transferSize = MIN(textRemaining, maxLength); /* allocate the transfer storage */ if (transferSize <= 0) { charListPtr->charListT_len = 0L; charListPtr->charListT_val = NULL; } else { charListPtr->charListT_len = transferSize; charListPtr->charListT_val = (char *)malloc(transferSize); if (charListPtr->charListT_val == 0) ABORT(BUDB_NOMEM); } textPtr = charListPtr->charListT_val; *nextOffset = offset + transferSize; /* setup the datablock. read and discard all blocks up to the one the * offset specifies */ nblocks = offset / BLOCK_DATA_SIZE; lastBlockAddr = ntohl(tbPtr->textAddr); while (nblocks--) { code = dbread(ut, lastBlockAddr, (char *)&block, sizeof(block)); if (code) ABORT(BUDB_IO); lastBlockAddr = ntohl(block.h.next); } while (transferSize > 0) { code = dbread(ut, lastBlockAddr, (char *)&block, sizeof(block)); if (code) ABORT(BUDB_IO); LogDebug(5, "fetched block %d\n", lastBlockAddr); /* compute the data size to extract */ blockOffset = offset % BLOCK_DATA_SIZE; textRemaining = BLOCK_DATA_SIZE - blockOffset; chunkSize = min(textRemaining, transferSize); memcpy(textPtr, &block.a[blockOffset], chunkSize); /* LogDebug(5, "transfering %d bytes: %s\n", chunkSize, textPtr); */ transferSize -= chunkSize; offset += chunkSize; textPtr += chunkSize; if (transferSize) { /* setup lastBlockAddr */ lastBlockAddr = ntohl(block.h.next); } } if (*nextOffset == ntohl(tbPtr->size)) { /* all done */ *nextOffset = -1; } /* error_exit: */ code = ubik_EndTrans(ut); /* printf("in error exit, code=%ld\n", code); */ return (code); no_xfer_abort: charListPtr->charListT_len = 0; charListPtr->charListT_val = (char *)malloc(0); abort_exit: if (ut) ubik_AbortTrans(ut); /* printf("in abort exit, code=%ld\n", code); */ return (code); }
afs_int32 STC_SaveDb(struct rx_call *rxCall, Date archiveTime, afs_uint32 *taskId) { #ifdef AFS_PTHREAD_ENV pthread_t pid; pthread_attr_t tattr; AFS_SIGSET_DECL; #else PROCESS pid; #endif statusP statusPtr = NULL; afs_int32 code = 0; struct saveDbIf *ptr; #ifdef xbsa if (CONF_XBSA) return (TC_BADTASK); /* LabelTape does not apply if XBSA */ #endif if (callPermitted(rxCall) == 0) return (TC_NOTPERMITTED); *taskId = allocTaskId(); ptr = (struct saveDbIf *)malloc(sizeof(struct saveDbIf)); if (!ptr) ERROR_EXIT(TC_NOMEMORY); ptr->archiveTime = archiveTime; ptr->taskId = *taskId; /* create the status node */ statusPtr = createStatusNode(); if (!statusPtr) ERROR_EXIT(TC_INTERNALERROR); lock_Status(); statusPtr->taskId = *taskId; statusPtr->lastPolled = time(0); statusPtr->flags &= ~STARTING; /* ok to examine */ strncpy(statusPtr->taskName, "SaveDb", sizeof(statusPtr->taskName)); unlock_Status(); ptr->statusPtr = statusPtr; #ifdef AFS_PTHREAD_ENV code = pthread_attr_init(&tattr); if (code) ERROR_EXIT(code); code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); if (code) ERROR_EXIT(code); AFS_SIGSET_CLEAR(); code = pthread_create(&pid, &tattr, saveDbToTape, ptr); AFS_SIGSET_RESTORE(); #else code = LWP_CreateProcess(saveDbToTape, 32768, 1, ptr, "Db save", &pid); #endif error_exit: if (code) { if (statusPtr) deleteStatusNode(statusPtr); if (ptr) free(ptr); } return (code); }
afs_int32 STC_RestoreDb(struct rx_call *rxCall, afs_uint32 *taskId) { #ifdef AFS_PTHREAD_ENV pthread_t pid; pthread_attr_t tattr; AFS_SIGSET_DECL; #else PROCESS pid; #endif statusP statusPtr; afs_int32 code = 0; #ifdef xbsa if (CONF_XBSA) return (TC_BADTASK); /* LabelTape does not apply if XBSA */ #endif if (callPermitted(rxCall) == 0) return (TC_NOTPERMITTED); *taskId = allocTaskId(); /* create the status node */ statusPtr = createStatusNode(); if (!statusPtr) ERROR_EXIT(TC_INTERNALERROR); lock_Status(); statusPtr->taskId = *taskId; statusPtr->flags &= ~STARTING; /* ok to examine */ statusPtr->lastPolled = time(0); strncpy(statusPtr->taskName, "RestoreDb", sizeof(statusPtr->taskName)); unlock_Status(); #ifdef AFS_PTHREAD_ENV code = pthread_attr_init(&tattr); if (code) ERROR_EXIT(code); code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); if (code) ERROR_EXIT(code); AFS_SIGSET_CLEAR(); code = pthread_create(&pid, &tattr, restoreDbFromTape, (void *)(intptr_t)*taskId); AFS_SIGSET_RESTORE(); #else code = LWP_CreateProcess(restoreDbFromTape, 32768, 1, (void *)(intptr_t)*taskId, "Db restore", &pid); #endif error_exit: if (code) { if (statusPtr) deleteStatusNode(statusPtr); } return (code); }
afs_int32 STC_LabelTape(struct rx_call *acid, struct tc_tapeLabel *label, afs_uint32 *taskId) { #ifdef AFS_PTHREAD_ENV pthread_t pid; pthread_attr_t tattr; AFS_SIGSET_DECL; #else PROCESS pid; #endif struct labelTapeIf *ptr; statusP statusPtr = NULL; afs_int32 code; #ifdef xbsa if (CONF_XBSA) return (TC_BADTASK); /* LabelTape does not apply if XBSA */ #endif if (callPermitted(acid) == 0) return (TC_NOTPERMITTED); ptr = (struct labelTapeIf *)malloc(sizeof(*ptr)); if (!ptr) ERROR_EXIT(TC_NOMEMORY); memcpy(&ptr->label, label, sizeof(ptr->label)); /* set up the status node */ *taskId = allocTaskId(); /* for bucoord */ ptr->taskId = *taskId; statusPtr = createStatusNode(); if (!statusPtr) ERROR_EXIT(TC_INTERNALERROR); lock_Status(); statusPtr->taskId = *taskId; statusPtr->lastPolled = time(0); statusPtr->flags &= ~STARTING; /* ok to examine */ strncpy(statusPtr->taskName, "Labeltape", sizeof(statusPtr->taskName)); unlock_Status(); /* create the LWP to do the real work behind the scenes */ #ifdef AFS_PTHREAD_ENV code = pthread_attr_init(&tattr); if (code) ERROR_EXIT(code); code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); if (code) ERROR_EXIT(code); AFS_SIGSET_CLEAR(); code = pthread_create(&pid, &tattr, Labeller, ptr); AFS_SIGSET_RESTORE(); #else code = LWP_CreateProcess(Labeller, 32768, 1, (void *)ptr, "labeller process", &pid); #endif error_exit: if (code) { if (statusPtr) deleteStatusNode(statusPtr); if (ptr) free(ptr); } return (code); }
afs_int32 SaveText(struct rx_call *call, afs_uint32 lockHandle, afs_int32 textType, afs_int32 offset, afs_int32 flags, charListT *charListPtr) { struct ubik_trans *ut; struct block diskBlock; dbadr diskBlockAddr; afs_int32 remainingInBlock, chunkSize; struct textBlock *tbPtr; afs_int32 textLength = charListPtr->charListT_len; char *textptr = charListPtr->charListT_val; afs_int32 code; LogDebug(5, "SaveText: type %d, offset %d, length %d\n", textType, offset, textLength); if (callPermitted(call) == 0) return (BUDB_NOTPERMITTED); if ((textLength > BLOCK_DATA_SIZE) || (offset < 0)) return (BUDB_BADARGUMENT); code = InitRPC(&ut, LOCKWRITE, 1); if (code) return (code); /* fetch the lock state */ if (checkLockHandle(ut, lockHandle) == 0) ABORT(BUDB_NOTLOCKED); if ((textType < 0) || (textType >= TB_NUM)) ABORT(BUDB_BADARGUMENT); tbPtr = &db.h.textBlock[textType]; LogDebug(5, "SaveText: lockHandle %d textType %d offset %d flags %d txtlength %d\n", lockHandle, textType, offset, flags, textLength); if (offset == 0) { /* release any blocks from previous transactions */ diskBlockAddr = ntohl(tbPtr->newTextAddr); freeOldBlockChain(ut, diskBlockAddr); if (textLength) { code = AllocBlock(ut, &diskBlock, &diskBlockAddr); if (code) ABORT(code); LogDebug(5, "allocated block %d\n", diskBlockAddr); /* set block type */ diskBlock.h.type = text_BLOCK; /* save it in the database header */ tbPtr->newsize = 0; tbPtr->newTextAddr = htonl(diskBlockAddr); dbwrite(ut, (char *)tbPtr - (char *)&db.h, (char *)tbPtr, sizeof(struct textBlock)); } else { tbPtr->newsize = 0; tbPtr->newTextAddr = 0; } } else { /* non-zero offset */ int nblocks; if (offset != ntohl(tbPtr->newsize)) ABORT(BUDB_BADARGUMENT); /* locate the block to which offset refers */ nblocks = offset / BLOCK_DATA_SIZE; diskBlockAddr = ntohl(tbPtr->newTextAddr); if (diskBlockAddr == 0) ABORT(BUDB_BADARGUMENT); code = dbread(ut, diskBlockAddr, (char *)&diskBlock, sizeof(diskBlock)); if (code) ABORT(code); while (nblocks--) { diskBlockAddr = ntohl(diskBlock.h.next); code = dbread(ut, diskBlockAddr, (char *)&diskBlock, sizeof(diskBlock)); if (code) ABORT(code); } } /* diskBlock and diskBlockAddr now point to the last block in the chain */ while (textLength) { /* compute the transfer size */ remainingInBlock = (BLOCK_DATA_SIZE - (offset % BLOCK_DATA_SIZE)); chunkSize = MIN(remainingInBlock, textLength); /* copy in the data */ memcpy(&diskBlock.a[offset % BLOCK_DATA_SIZE], textptr, chunkSize); /* LogDebug(5, "text is %s\n", textptr); */ textLength -= chunkSize; textptr += chunkSize; offset += chunkSize; tbPtr->newsize = htonl(ntohl(tbPtr->newsize) + chunkSize); if (textLength > 0) { afs_int32 prevBlockAddr; afs_int32 linkOffset; afs_int32 linkValue; /* have to add another block to the chain */ code = dbwrite(ut, diskBlockAddr, (char *)&diskBlock, sizeof(diskBlock)); if (code) ABORT(code); prevBlockAddr = (afs_int32) diskBlockAddr; code = AllocBlock(ut, &diskBlock, &diskBlockAddr); if (code) ABORT(code); LogDebug(5, "allocated block %d\n", diskBlockAddr); /* set block type */ diskBlock.h.type = text_BLOCK; /* now have to update the previous block's link */ linkOffset = (afs_int32) ((char*)& diskBlock.h.next - (char*)& diskBlock); linkValue = htonl(diskBlockAddr); code = dbwrite(ut, (afs_int32) prevBlockAddr + linkOffset, (char *)&linkValue, sizeof(afs_int32)); if (code) ABORT(code); } else { /* just write the old block */ code = dbwrite(ut, diskBlockAddr, (char *)&diskBlock, sizeof(diskBlock)); if (code) ABORT(code); } } if (flags & BUDB_TEXT_COMPLETE) { /* done */ /* this was the last chunk of text */ diskBlockAddr = ntohl(tbPtr->textAddr); freeOldBlockChain(ut, diskBlockAddr); tbPtr->textAddr = tbPtr->newTextAddr; tbPtr->newTextAddr = 0; tbPtr->size = tbPtr->newsize; tbPtr->newsize = 0; tbPtr->version = htonl(ntohl(tbPtr->version) + 1); /* saveTextToFile(ut, tbPtr); */ } /* update size and other text header info */ code = dbwrite(ut, (char *)tbPtr - (char *)&db.h, (char *)tbPtr, sizeof(struct textBlock)); if (code) ABORT(code); /*error_exit: */ code = ubik_EndTrans(ut); return (code); abort_exit: ubik_AbortTrans(ut); return (code); }
afs_int32 STC_PerformDump(struct rx_call *rxCallId, struct tc_dumpInterface *tcdiPtr, tc_dumpArray *tc_dumpArrayPtr, afs_int32 *taskId) { struct dumpNode *newNode = 0; statusP statusPtr = 0; #ifdef AFS_PTHREAD_ENV pthread_t pid; pthread_attr_t tattr; AFS_SIGSET_DECL; #else PROCESS pid; #endif afs_int32 code = 0; if (callPermitted(rxCallId) == 0) return (TC_NOTPERMITTED); /* should be verifying parameter validity */ *taskId = 0; /* this creates a node in list, alots an id for it and prepares it for locking */ CreateNode(&newNode); /*set up the parameters in the node, to be used by LWP */ strcpy(newNode->dumpSetName, tcdiPtr->dumpName); newNode->dumpName = (char *)malloc(strlen(tcdiPtr->dumpPath) + 1); strcpy(newNode->dumpName, tcdiPtr->dumpPath); newNode->volumeSetName = (char *)malloc(strlen(tcdiPtr->volumeSetName) + 1); strcpy(newNode->volumeSetName, tcdiPtr->volumeSetName); CopyTapeSetDesc(&(newNode->tapeSetDesc), &tcdiPtr->tapeSet); newNode->dumps = (struct tc_dumpDesc *) malloc(sizeof(struct tc_dumpDesc) * tc_dumpArrayPtr->tc_dumpArray_len); newNode->arraySize = tc_dumpArrayPtr->tc_dumpArray_len; CopyDumpDesc(newNode->dumps, tc_dumpArrayPtr); newNode->parent = tcdiPtr->parentDumpId; newNode->level = tcdiPtr->dumpLevel; newNode->doAppend = tcdiPtr->doAppend; #ifdef xbsa if (CONF_XBSA) newNode->doAppend = 0; /* Append flag is ignored if talking to XBSA */ #endif /* create the status node */ statusPtr = createStatusNode(); if (!statusPtr) ERROR_EXIT(TC_INTERNALERROR); lock_Status(); statusPtr->taskId = newNode->taskID; statusPtr->lastPolled = time(0); statusPtr->flags &= ~STARTING; /* ok to examine */ strncpy(statusPtr->taskName, "Dump", sizeof(statusPtr->taskName)); unlock_Status(); newNode->statusNodePtr = statusPtr; /* create the LWP to do the real work behind the scenes */ #ifdef AFS_PTHREAD_ENV code = pthread_attr_init(&tattr); if (code) ERROR_EXIT(code); code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); if (code) ERROR_EXIT(code); AFS_SIGSET_CLEAR(); code = pthread_create(&pid, &tattr, Dumper, newNode); AFS_SIGSET_RESTORE(); #else code = LWP_CreateProcess(Dumper, 32768, 1, (void *)newNode, "dumper process", &pid); #endif if (code) ERROR_EXIT(code); *taskId = newNode->taskID; error_exit: if (code) { if (statusPtr) deleteStatusNode(statusPtr); FreeNode(newNode->taskID); /* failed to create LWP to do the dump. */ } return (code); }