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:
| A | filelock.c | | | 197 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | filelock.h | | | 104 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | filelockInternal.h | | | 4 | ++++ |
| A | package.yml | | | 16 | ++++++++++++++++ |
| A | test.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();
+
+}