/* * commit sequence update * returns: * 0 -> ok * other -> link failed */ int cmtseq(void) { int ret; if ((ret = access(SQTMP, 0)) != 0) { rmlock(SQLOCK); return (0); } unlink(SQFILE); ret = link(SQTMP, SQFILE); unlink(SQTMP); rmlock(SQLOCK); return (ret); }
/*! Attempts to create the lock file. This function returns \c true if the lock was obtained; otherwise it returns \c false. If another process (or another thread) has created the lock file already, this function will wait for at most \a timeout milliseconds for the lock file to become available. Note: Passing a negative number as the \a timeout is equivalent to calling lock(), i.e. this function will wait forever until the lock file can be locked if \a timeout is negative. If the lock was obtained, it must be released with unlock() before another process (or thread) can successfully lock it. Calling this function multiple times on the same lock from the same thread without unlocking first is not allowed, this function will \e always return false when attempting to lock the file recursively. \sa lock(), unlock() */ bool QLockFile::tryLock(int timeout) { Q_D(QLockFile); #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) QElapsedTimer timer; #else QTime timer; #endif if (timeout > 0) timer.start(); int sleepTime = 100; Q_FOREVER { d->lockError = d->tryLock_sys(); switch (d->lockError) { case NoError: d->isLocked = true; return true; case PermissionError: case UnknownError: return false; case LockFailedError: if (!d->isLocked && d->isApparentlyStale()) { // Stale lock from another thread/process // Ensure two processes don't remove it at the same time QLockFile rmlock(d->fileName + QLatin1String(".rmlock")); if (rmlock.tryLock()) { if (d->isApparentlyStale() && d->removeStaleLock()) continue; } } break; } if (timeout == 0 || (timeout > 0 && (timer.elapsed() > timeout))) return false; QLockFileThread::msleep(sleepTime); if (sleepTime < 5 * 1000) sleepTime *= 2; } // not reached return false; }
/* * Open a file, locking using the lock types specified. Returns EAGAIN if lock * failed. */ int openlock(const char *path, int flags, u_int locks) { int fd, saved_errno; if (mklock(locks, path) != 0) return (-1); if ((fd = open(path, flags, 0)) == -1) goto error; if (lockfd(locks, fd) != 0) goto error; return (fd); error: saved_errno = errno; close(fd); rmlock(locks, path); errno = saved_errno; return (-1); }
/* Create a locked file. */ int createlock( const char *path, int flags, uid_t uid, gid_t gid, mode_t mode, u_int locks) { int fd, saved_errno; if (mklock(locks, path) != 0) return (-1); if ((fd = xcreate(path, flags, uid, gid, mode)) == -1) goto error; if (lockfd(locks, fd) != 0) goto error; return (fd); error: saved_errno = errno; close(fd); rmlock(locks, path); errno = saved_errno; return (-1); }
/*! Attempts to create the lock file. This function returns \c true if the lock was obtained; otherwise it returns \c false. If another process (or another thread) has created the lock file already, this function will wait for at most \a timeout milliseconds for the lock file to become available. Note: Passing a negative number as the \a timeout is equivalent to calling lock(), i.e. this function will wait forever until the lock file can be locked if \a timeout is negative. If the lock was obtained, it must be released with unlock() before another process (or thread) can successfully lock it. Calling this function multiple times on the same lock from the same thread without unlocking first is not allowed, this function will \e always return false when attempting to lock the file recursively. \sa lock(), unlock() */ bool QLockFile::tryLock(int timeout) { Q_D(QLockFile); QElapsedTimer timer; if (timeout > 0) timer.start(); int sleepTime = 100; forever { d->lockError = d->tryLock_sys(); switch (d->lockError) { case NoError: d->isLocked = true; return true; case PermissionError: case UnknownError: return false; case LockFailedError: if (!d->isLocked && d->isApparentlyStale()) { // Stale lock from another thread/process // Ensure two processes don't remove it at the same time QLockFile rmlock(d->fileName + QStringLiteral(".rmlock")); if (rmlock.tryLock()) { if (d->isApparentlyStale() && d->removeStaleLock()) continue; } } break; } if (timeout == 0 || (timeout > 0 && timer.hasExpired(timeout))) return false; QThread::msleep(sleepTime); if (sleepTime < 5 * 1000) sleepTime *= 2; } // not reached return false; }
/* Close locked file and remove locks. */ void closelock(int fd, const char *path, u_int locks) { close(fd); rmlock(locks, path); }
/* * get next conversation sequence number * rmtname -> name of remote system * returns: * 0 -> no entery * 1 -> 0 sequence number */ int gnxseq(char *rmtname) { register FILE *fp0, *fp1; register struct tm *tp; int count = 0, ct, ret; char buf[BUFSIZ], name[NAMESIZE]; time_t clock; if (access(SQFILE, 0) != 0) return (0); { int i; for (i = 0; i < 5; i++) if ((ret = mklock(SQLOCK)) == SUCCESS) break; sleep(5); } if (ret != SUCCESS) { logent("CAN'T LOCK", SQLOCK); DEBUG(4, "can't lock %s\n", SQLOCK); return (0); } if ((fp0 = fopen(SQFILE, "r")) == NULL) return (0); if ((fp1 = fopen(SQTMP, "w")) == NULL) { fclose(fp0); return (0); } chmod(SQTMP, DFILEMODE); while (fgets(buf, BUFSIZ, fp0) != NULL) { ret = sscanf(buf, "%s%d", name, &ct); if (ret < 2) ct = 0; name[7] = '\0'; if (ct > 9998) ct = 0; if (strncmp(rmtname, name, SYSNSIZE) != SAME) { fputs(buf, fp1); continue; } /* * found name */ count = ++ct; time(&clock); tp = localtime(&clock); fprintf(fp1, "%s %d %d/%d-%d:%2.2d\n", name, ct, tp->tm_mon + 1, tp->tm_mday, tp->tm_hour, tp->tm_min); /* * write should be checked */ while (fgets(buf, BUFSIZ, fp0) != NULL) fputs(buf, fp1); } fclose(fp0); fclose(fp1); if (count == 0) { rmlock(SQLOCK); unlink(SQTMP); } return (count); }
/* * unlock sequence file */ void ulkseq(void) { unlink(SQTMP); rmlock(SQLOCK); }