filelock

class for locking files in filesystem
git clone https://noulin.net/git/filelock.git
Log | Files | Refs | LICENSE

commit 86f93301b0557d49ffe8279bdf9950a96591ff7e
parent 803a7addbc34b66f614a612c8bd396ef10c1602d
Author: Remy Noulin <loader2x@gmail.com>
Date:   Sun, 20 May 2018 00:12:19 +0200

filelock package

filelock.c         | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++++
filelock.h         | 104 ++++++++++++++++++++++++++++
filelockInternal.h |   4 ++
package.yml        |  16 +++++
test.c             |  40 +++++++++++
5 files changed, 361 insertions(+)

Diffstat:
Afilelock.c | 197+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Afilelock.h | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AfilelockInternal.h | 4++++
Apackage.yml | 16++++++++++++++++
Atest.c | 40++++++++++++++++++++++++++++++++++++++++
5 files changed, 361 insertions(+), 0 deletions(-)

diff --git a/filelock.c b/filelock.c @@ -0,0 +1,197 @@ +// +// +// + +#include "libsheepyObject.h" +#include "filelock.h" +#include "filelockInternal.h" + +#define internal static + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <sys/stat.h> // open +#include <fcntl.h> // open +#include <unistd.h> // close + +void initiateFilelock(filelockt *self); +void registerMethodsFilelock(filelockFunctionst *f); +void initiateAllocateFilelock(filelockt **self); +void finalizeFilelock(void); +filelockt* allocFilelock(const char *filepath); +internal void freeFilelock(filelockt *self); +internal void terminateFilelock(filelockt **self); +internal char* toStringFilelock(filelockt *self); +internal filelockt* duplicateFilelock(filelockt *self); +internal void smashFilelock(filelockt **self); +internal void finishFilelock(filelockt **self); +internal void setDelaysFilelock (filelockt *self, f32 timeout, f32 delay); +internal void logFilelock (filelockt *self); +internal bool acquireFilelock (filelockt *self); +internal void releaseFilelock (filelockt *self); +internal void setFilelock (filelockt *self, const char *filepath); +internal const char* getFilelock(filelockt *self); + +void initiateFilelock(filelockt *self) { + + self->type = "filelock"; + if (!filelockF) { + filelockF = malloc(sizeof(filelockFunctionst)); + registerMethodsFilelock(filelockF); + pErrorNot0(atexit(finalizeFilelock)); + } + self->f = filelockF; + + self->isLocked = false; + self->lockfile = NULL; + self->filename = NULL; + self->timeout = 10; + self->delay = 0.05; + self->fd = -1; +} + +void registerMethodsFilelock(filelockFunctionst *f) { + + f->free = freeFilelock; + f->terminate = terminateFilelock; + f->toString = toStringFilelock; + f->duplicate = duplicateFilelock; + f->smash = smashFilelock; + f->finish = finishFilelock; + f->setDelays = setDelaysFilelock; + f->log = logFilelock; + f->acquire = acquireFilelock; + f->release = releaseFilelock; + f->set = setFilelock; + f->get = getFilelock; +} + +void initiateAllocateFilelock(filelockt **self) { + + if (self) { + (*self) = malloc(sizeof(filelockt)); + if (*self) { + initiateFilelock(*self); + } + } +} + +void finalizeFilelock(void) { + + if (filelockF) { + free(filelockF); + filelockF = NULL; + } +} + +filelockt* allocFilelock(const char *filepath) { + filelockt *r = NULL; + + initiateAllocateFilelock(&r); + if (filepath) { + r->filename = strdup(filepath); + r->lockfile = formatS("%s.lock", filepath); + } + return(r); +} + + +internal void freeFilelock(filelockt *self) { + + freeManyS(self->lockfile, self->filename); + return; +} + +internal void terminateFilelock(filelockt **self) { + + freeFilelock(*self); + free(*self); + *self = NULL; +} + + +internal char* toStringFilelock(filelockt *self) { + + return(strdup("filelock")); +} + +internal filelockt* duplicateFilelock(filelockt *self) { + + createAllocateFilelock(dup); + dup->isLocked = self->isLocked; + dup->filename = dupS(self->filename); + dup->lockfile = dupS(self->lockfile); + dup->timeout = self->timeout; + dup->delay = self->delay; + dup->fd = self->fd; + return(dup); +} + +internal void smashFilelock(filelockt **self) { + + finishFilelock(self); +} + +internal void finishFilelock(filelockt **self) { + + free(*self); + *self = NULL; +} + +internal void setDelaysFilelock (filelockt *self, f32 timeout, f32 delay) { + + self->timeout = timeout; + self->delay = delay; +} + +internal void logFilelock (filelockt *self) { + char *s = toStringG(self->isLocked); + printf("isLocked: %s\n", s); + free(s); + printf("filename: %s\n", self->filename); + printf("timeout: %f\n", self->timeout); + printf("delay: %f\n", self->delay); + printf("lockfile: %s\n", self->lockfile); +} + +internal bool acquireFilelock (filelockt *self) { + + u64 startTime = getMonotonicTime(); + + if (not self->lockfile) return false; + + if (not self->isLocked) { + while (true) { + self->fd = open(self->lockfile, O_CREAT|O_EXCL|O_RDWR); + if (self->fd != -1) break; + if ((getMonotonicTime() - startTime) > (self->timeout*1E9)) return false; + nanoSleep(self->delay*1E9); + } + self->isLocked = true; + return true; + } + return false; +} + +internal void releaseFilelock (filelockt *self) { + + if (self->isLocked) { + close(self->fd); + rmAll(self->lockfile); + self->isLocked = false; + } +} + +internal void setFilelock(filelockt *self, const char *filepath) { + if (not filepath) return; + if (self->filename) { + freeManyS(self->filename, self->lockfile); + } + self->filename = strdup(filepath); + self->lockfile = formatS("%s.lock", filepath); +} + +internal const char* getFilelock(filelockt *self) { + return self->filename; +} diff --git a/filelock.h b/filelock.h @@ -0,0 +1,104 @@ +#pragma once + +#define acquireO(obj) (obj)->f->acquire(obj) +#define acquireG acquireO + +#define releaseO(obj) (obj)->f->release(obj) +#define releaseG releaseO + +#define setFileO(obj, path) (obj)->f->set(obj, path) +#define setFileG setFileO + +#define getFileO(obj) (obj)->f->get(obj) +#define getFileG getFileO + +// Class filelock +typedef struct filelock filelockt; + +// for object inheriting filelock, cast to filelock to be able to use this class functions and generics +#define cFilelock(self) ( (filelockt*) self ) + +typedef void (*freeFilelockFt) (filelockt *self); +typedef void (*terminateFilelockFt) (filelockt **self); +typedef char* (*toStringFilelockFt) (filelockt *self); +typedef filelockt* (*duplicateFilelockFt) (filelockt *self); +typedef void (*smashFilelockFt) (filelockt **self); + +/** + * free filelock + */ +typedef void (*finishFilelockFt) (filelockt **self); + +typedef void (*setDelaysFilelockFt) (filelockt *self, f32 timeout, f32 delay); +typedef void (*logFilelockFt) (filelockt *self); +typedef bool (*acquireFilelockFt) (filelockt *self); +typedef void (*releaseFilelockFt) (filelockt *self); +typedef void (*setFilelockFt) (filelockt *self, const char *filepath); +typedef const char* (*getFilelockFt) (filelockt *self); + +/** + * class functions + * allocated once for all objects + * + * freed with finalizeFilelock or finalizeLibsheepy + */ + +/** + * use this define in child classes and add the new function after this class functions + * + * in this define, add the methods after <finishFilelockFt finish;> + * + * Example: + * #define RINGFUNCTIONST \ + * CLASSTEMPLATEFUNCTIONST; \ + * setSizeRingFt setSize + */ +#define CLASSTEMPLATEFUNCTIONST \ + setDelaysFilelockFt setDelays;\ + logFilelockFt log;\ + acquireFilelockFt acquire;\ + releaseFilelockFt release;\ + setFilelockFt set;\ + getFilelockFt get + +typedef struct { + freeFilelockFt free; + terminateFilelockFt terminate; + toStringFilelockFt toString; + duplicateFilelockFt duplicate; + smashFilelockFt smash; + finishFilelockFt finish; + CLASSTEMPLATEFUNCTIONST; +} filelockFunctionst; + +/** + * class + */ +struct filelock { + const char *type; + filelockFunctionst *f; + + // private + bool isLocked; + char *filename; + char *lockfile; + f32 timeout; + f32 delay; + int fd; +}; + +// filelock + +#define createFilelock(obj) filelockt obj; initiateFilelock(&obj) +#define createAllocateFilelock(obj) filelockt *obj; initiateAllocateFilelock(&obj) + +void initiateFilelock(filelockt *self); +void initiateAllocateFilelock(filelockt **self); +void finalizeFilelock(void); + +// initialize class methods, call registerMethodsFilelock from classes inheriting this class +void registerMethodsFilelock(filelockFunctionst *f); + +filelockt* allocFilelock(const char *filepath); + +// end class filelock diff --git a/filelockInternal.h b/filelockInternal.h @@ -0,0 +1,4 @@ +#pragma once + + +static filelockFunctionst *filelockF = NULL; diff --git a/package.yml b/package.yml @@ -0,0 +1,16 @@ +--- + name: filelock + version: 0.0.2 + description: "class for locking files in filesystem" + bin: ./filelock.c + repository: + type: git + url: git+https://github.com/RemyNoulin/filelock.git + keywords: + - utility + author: Remy + license: MIT + bugs: + url: https://github.com/RemyNoulin/filelock/issues + homepage: https://github.com/RemyNoulin/filelock#readme + #compileHelp: # text displayed when there is a compilation error diff --git a/test.c b/test.c @@ -0,0 +1,40 @@ +#! /usr/bin/env sheepy + +#include "libsheepyObject.h" +#include "filelock.h" + +int argc; char **argv; + +int main(int ARGC, char** ARGV) { + + argc = ARGC; argv = ARGV; + + initLibsheepy(argv[0]); + + //filelockt *fileLock = allocFilelock("wefef"); + createAllocateFilelock(fileLock); + setFileG(fileLock, "w"); + logVarG(getFileG(fileLock)); + setFileG(fileLock, "wefef"); + filelockt *fileLock2 = allocFilelock("wefef"); + + logG(fileLock); + + acquireG(fileLock); + + logG(fileLock); + + logVarG(acquireG(fileLock2)); + + releaseG(fileLock); + releaseG(fileLock2); + + logG(fileLock); + + terminateG(fileLock); + terminateG(fileLock2); + + finalizeFilelock(); + finalizeLibsheepy(); + +}