int makeLock(char *host, char *lockDir) /* Return lock file handle. */ { char *name = lockName(lockDir, host); int fd; fd = open(name, O_CREAT | O_EXCL | O_WRONLY, 0666); return fd; }
/* ** Unlock an vfstrace-file. */ static int vfstraceUnlock(sqlite3_file *pFile, int eLock){ vfstrace_file *p = (vfstrace_file *)pFile; vfstrace_info *pInfo = p->pInfo; int rc; vfstrace_printf(pInfo, "%s.xUnlock(%s,%s)", pInfo->zVfsName, p->zFName, lockName(eLock)); rc = p->pReal->pMethods->xUnlock(p->pReal, eLock); vfstrace_print_errcode(pInfo, " -> %s\n", rc); return rc; }
void ccFirst(char *source, char *dest, char *hostList, char *lockDir) /* Do first instance of this program. Copy file to first host, * make up lock directory, and then poll lock directory to see * if we're done. */ { char *firstHost, *lastHost; char **hosts; char *hostBuf; int hostCount; int firstLock; int childPid; char *thisHost = getenv("HOST"); char ok; long startTime = clock1000(); if (thisHost == NULL) errAbort("HOST environment variable undefined\n"); readAllWords(hostList, &hosts, &hostCount, &hostBuf); if (hostCount <= 0) errAbort("%s is empty.", hostList); if (stringArrayIx(thisHost, hosts, hostCount) < 0) errAbort("Current host (%s) not in host list\n", thisHost); if (mkdir(lockDir, 0777) < 0) errAbort("Couldn't make lock directory %s\n", lockDir); firstHost = thisHost; lastHost = hosts[hostCount-1]; if (sameString(lastHost, thisHost) && hostCount > 1) lastHost = hosts[hostCount-2]; firstLock = makeLock(firstHost, lockDir); if (firstLock < 0) errAbort("Couldn't make lock file %s/%s\n", lockDir, firstHost); if (cpFile(source, dest) != 0) { warn("Couldn't copy %s to %s:%d\n", source, firstHost, dest); close(firstLock); cleanupLocks(lockDir); errAbort("Cleaned up locks in %s, aborting copy.", lockDir); } ok = 1; write(firstLock, &ok, 1); close(firstLock); childPid = fork(); if (childPid == 0) { /* Have child process keep copying. */ ccMore(dest, hostList, 0, lockDir); } else { int sleepIx = 0; int sleepTime = 10; int lastStart = 0, lastErr = 0, lastEnd = 0; /* Have parent process wait until last file done. */ for (sleepIx = 0; ; ++sleepIx) { int lockFd; int i; int startCount = 0; int endCount = 0; int errCount = 0; int toGo = 0; int procCount = 0; int lastProcCount = 0; int finCount; boolean reportErr; for (i=0; i<hostCount; ++i) { char *ln = lockName(lockDir, hosts[i]); lockFd = open(ln, O_RDONLY); if (lockFd < 0) ++toGo; else { char ok; if (read(lockFd, &ok, 1) < 1) ++startCount; else { if (ok) ++endCount; else ++errCount; } close(lockFd); } } finCount = endCount + errCount; // if (lastStart != startCount || lastEnd != endCount || lastErr != errCount) { printf(" copies in progress %d finished %d errors %d total %d\n", startCount, endCount, errCount, hostCount); lastStart = startCount; lastEnd = endCount; lastErr = errCount; } if (finCount >= hostCount) { if (errCount > 0) { fprintf(stderr, "Errors copying to hosts:"); for (i=0; i<hostCount; ++i) { char *ln = lockName(lockDir, hosts[i]); lockFd = open(ln, O_RDONLY); if (lockFd < 0) { fprintf(stderr, " ??%s??", hosts[i]); } else { char ok; if (read(lockFd, &ok, 1) < 1) { fprintf(stderr, " ?%s?", hosts[i]); ++startCount; } else { if (!ok) { fprintf(stderr, " %s", hosts[i]); ++errCount; } } close(lockFd); } } fprintf(stderr, "\n"); } cleanupLocks(lockDir); break; } sleep(sleepTime); } } }
// Index the token bool OSToken::index(bool isFirstTime /* = false */) { // Check if re-indexing is required if (!isFirstTime && (!valid || !gen->wasUpdated())) { return true; } // Check the integrity if (!tokenDir->refresh() || !tokenObject->valid) { valid = false; return false; } DEBUG_MSG("Token %s has changed", tokenPath.c_str()); // Retrieve the directory listing std::vector<std::string> tokenFiles = tokenDir->getFiles(); // Filter out the objects std::set<std::string> newSet; for (std::vector<std::string>::iterator i = tokenFiles.begin(); i != tokenFiles.end(); i++) { if ((i->size() > 7) && (!(i->substr(i->size() - 7).compare(".object"))) && (i->compare("token.object"))) { newSet.insert(*i); } else { DEBUG_MSG("Ignored file %s", i->c_str()); } } // Compute the changes compared to the last list of files std::set<std::string> addedFiles; std::set<std::string> removedFiles; // No access to object mutable fields before MutexLocker lock(tokenMutex); if (!isFirstTime) { // First compute which files were added for (std::set<std::string>::iterator i = newSet.begin(); i != newSet.end(); i++) { if (currentFiles.find(*i) == currentFiles.end()) { addedFiles.insert(*i); } } // Now compute which files were removed for (std::set<std::string>::iterator i = currentFiles.begin(); i != currentFiles.end(); i++) { if (newSet.find(*i) == newSet.end()) { removedFiles.insert(*i); } } } else { addedFiles = newSet; } currentFiles = newSet; DEBUG_MSG("%d objects were added and %d objects were removed", addedFiles.size(), removedFiles.size()); DEBUG_MSG("Current directory set contains %d objects", currentFiles.size()); // Now update the set of objects // Add new objects for (std::set<std::string>::iterator i = addedFiles.begin(); i != addedFiles.end(); i++) { if ((i->find_last_of('.') == std::string::npos) || (i->substr(i->find_last_of('.')) != ".object")) { continue; } std::string lockName(*i); lockName.replace(lockName.find_last_of('.'), std::string::npos, ".lock"); // Create a new token object for the added file ObjectFile* newObject = new ObjectFile(this, tokenPath + OS_PATHSEP + *i, tokenPath + OS_PATHSEP + lockName); DEBUG_MSG("(0x%08X) New object %s (0x%08X) added", this, newObject->getFilename().c_str(), newObject); objects.insert(newObject); allObjects.insert(newObject); } // Remove deleted objects std::set<OSObject*> newObjects; for (std::set<OSObject*>::iterator i = objects.begin(); i != objects.end(); i++) { ObjectFile* fileObject = dynamic_cast<ObjectFile*>((*i)); if (fileObject == NULL) { ERROR_MSG("Object type not compatible with this token class 0x%08X", (*i)); return false; } DEBUG_MSG("Processing %s (0x%08X)", fileObject->getFilename().c_str(), *i); if (removedFiles.find(fileObject->getFilename()) == removedFiles.end()) { DEBUG_MSG("Adding object %s", fileObject->getFilename().c_str()); // This object gets to stay in the set newObjects.insert(*i); } else { fileObject->invalidate(); } } // Set the new objects objects = newObjects; DEBUG_MSG("The token now contains %d objects", objects.size()); return true; }