filelock

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

filelock.c (4809B)


      1 //
      2 //
      3 //
      4 
      5 #include "libsheepyObject.h"
      6 #include "filelock.h"
      7 #include "filelockInternal.h"
      8 
      9 #define internal static
     10 
     11 #include <stdlib.h>
     12 #include <string.h>
     13 #include <stdio.h>
     14 #include <sys/stat.h> // open
     15 #include <fcntl.h>    // open
     16 #include <unistd.h>   // close
     17 
     18 void initiateFilelock(filelockt *self);
     19 void registerMethodsFilelock(filelockFunctionst *f);
     20 void initiateAllocateFilelock(filelockt **self);
     21 void finalizeFilelock(void);
     22 filelockt* allocFilelock(const char *filepath);
     23 internal void freeFilelock(filelockt *self);
     24 internal void terminateFilelock(filelockt **self);
     25 internal char* toStringFilelock(filelockt *self);
     26 internal filelockt* duplicateFilelock(filelockt *self);
     27 internal void smashFilelock(filelockt **self);
     28 internal void finishFilelock(filelockt **self);
     29 internal void setDelaysFilelock (filelockt *self, f32 timeout, f32 delay);
     30 internal void logFilelock       (filelockt *self);
     31 internal bool acquireFilelock   (filelockt *self);
     32 internal void releaseFilelock   (filelockt *self);
     33 internal void setFilelock       (filelockt *self, const char *filepath);
     34 internal const char* getFilelock(filelockt *self);
     35 
     36 void initiateFilelock(filelockt *self) {
     37 
     38   self->type = "filelock";
     39   if (!filelockF) {
     40     filelockF            = malloc(sizeof(filelockFunctionst));
     41     registerMethodsFilelock(filelockF);
     42     pErrorNot0(atexit(finalizeFilelock));
     43   }
     44   self->f = filelockF;
     45 
     46   self->isLocked = false;
     47   self->lockfile = NULL;
     48   self->filename = NULL;
     49   self->timeout  = 10;
     50   self->delay    = 0.05;
     51   self->fd       = -1;
     52 }
     53 
     54 void registerMethodsFilelock(filelockFunctionst *f) {
     55 
     56   f->free      = freeFilelock;
     57   f->terminate = terminateFilelock;
     58   f->toString  = toStringFilelock;
     59   f->duplicate = duplicateFilelock;
     60   f->smash     = smashFilelock;
     61   f->finish    = finishFilelock;
     62   f->setDelays = setDelaysFilelock;
     63   f->log       = logFilelock;
     64   f->acquire   = acquireFilelock;
     65   f->release   = releaseFilelock;
     66   f->set       = setFilelock;
     67   f->get       = getFilelock;
     68 }
     69 
     70 void initiateAllocateFilelock(filelockt **self) {
     71 
     72   if (self) {
     73     (*self) = malloc(sizeof(filelockt));
     74     if (*self) {
     75       initiateFilelock(*self);
     76     }
     77   }
     78 }
     79 
     80 void finalizeFilelock(void) {
     81 
     82   if (filelockF) {
     83     free(filelockF);
     84     filelockF = NULL;
     85   }
     86 }
     87 
     88 filelockt* allocFilelock(const char *filepath) {
     89   filelockt *r = NULL;
     90 
     91   initiateAllocateFilelock(&r);
     92   if (filepath) {
     93     r->filename = strdup(filepath);
     94     r->lockfile = formatS("%s.lock", filepath);
     95   }
     96   return(r);
     97 }
     98 
     99 
    100 internal void freeFilelock(filelockt *self) {
    101 
    102   freeManyS(self->lockfile, self->filename);
    103   return;
    104 }
    105 
    106 internal void terminateFilelock(filelockt **self) {
    107 
    108   freeFilelock(*self);
    109   free(*self);
    110   *self = NULL;
    111 }
    112 
    113 
    114 internal char* toStringFilelock(filelockt *self) {
    115 
    116   return(strdup("filelock"));
    117 }
    118 
    119 internal filelockt* duplicateFilelock(filelockt *self) {
    120 
    121   createAllocateFilelock(dup);
    122   dup->isLocked = self->isLocked;
    123   dup->filename = dupS(self->filename);
    124   dup->lockfile = dupS(self->lockfile);
    125   dup->timeout  = self->timeout;
    126   dup->delay    = self->delay;
    127   dup->fd       = self->fd;
    128   return(dup);
    129 }
    130 
    131 internal void smashFilelock(filelockt **self) {
    132 
    133   finishFilelock(self);
    134 }
    135 
    136 internal void finishFilelock(filelockt **self) {
    137 
    138   free(*self);
    139   *self = NULL;
    140 }
    141 
    142 internal void setDelaysFilelock (filelockt *self, f32 timeout, f32 delay) {
    143 
    144   self->timeout = timeout;
    145   self->delay   = delay;
    146 }
    147 
    148 internal void logFilelock       (filelockt *self) {
    149   char *s = toStringG(self->isLocked);
    150   printf("isLocked: %s\n", s);
    151   free(s);
    152   printf("filename: %s\n", self->filename);
    153   printf("timeout:  %f\n", self->timeout);
    154   printf("delay:    %f\n", self->delay);
    155   printf("lockfile: %s\n", self->lockfile);
    156 }
    157 
    158 internal bool acquireFilelock   (filelockt *self) {
    159 
    160   u64 startTime = getMonotonicTime();
    161 
    162   if (not self->lockfile) return false;
    163 
    164   if (not self->isLocked) {
    165     while (true) {
    166       self->fd = open(self->lockfile, O_CREAT|O_EXCL|O_RDWR);
    167       if (self->fd != -1) break;
    168       if ((getMonotonicTime() - startTime) > (self->timeout*1E9)) return false;
    169       nanoSleep(self->delay*1E9);
    170     }
    171     self->isLocked = true;
    172     return true;
    173   }
    174   return false;
    175 }
    176 
    177 internal void releaseFilelock   (filelockt *self) {
    178 
    179   if (self->isLocked) {
    180     close(self->fd);
    181     rmAll(self->lockfile);
    182     self->isLocked = false;
    183   }
    184 }
    185 
    186 internal void setFilelock(filelockt *self, const char *filepath) {
    187   if (not filepath) return;
    188   if (self->filename) {
    189     freeManyS(self->filename, self->lockfile);
    190   }
    191   self->filename = strdup(filepath);
    192   self->lockfile = formatS("%s.lock", filepath);
    193 }
    194 
    195 internal const char* getFilelock(filelockt *self) {
    196   return self->filename;
    197 }
    198 
    199 bool checkLibsheepyVersionFilelock(const char *currentLibsheepyVersion) {
    200   return eqG(currentLibsheepyVersion, LIBSHEEPY_VERSION);
    201 }
    202