Skip to content

Instantly share code, notes, and snippets.

@mrbid
Last active August 19, 2022 13:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrbid/c3ead14d48a1867d9415d8bdd2cb062d to your computer and use it in GitHub Desktop.
Save mrbid/c3ead14d48a1867d9415d8bdd2cb062d to your computer and use it in GitHub Desktop.
Mission critical file increment helper process.
/*
James William Fletcher (github.com/mrbid)
February 2021
Mission critical file increments.
https://james-william-fletcher.medium.com/mission-critical-integer-increment-operations-from-php-c1c71fb42451
This file is compiled to a program that any
service can externally execute to ensure
a file increment or decrement operation
never fails.
Assuming that there is no condition where the
operating system will terminate the process
and that your max process limit;
/proc/sys/kernel/pid_max is not exceeded.
Integers are processed as long long with a maximum
value of 9223372036854775807, and are saved in string
format as a maximum of 19 bytes long.
*/
#include <sys/file.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define CHMOD 0666
#define MAX_BUFF 20 // +1 for the null terminator
int main(int argc, char *argv[])
{
// check all params supplied
if(argc < 3)
{
printf("Incorrect arguments.\n");
return 0;
}
char tb[MAX_BUFF] = {0}; // temporary buffer for file read
int faw = 0; // failed write signifier
int wlen = 0; // new write length
// keep looping until success
int f = -1;
while(1)
{
if(faw == 0)
{
// file is already open? unlock and close it
if(f > -1)
{
flock(f, LOCK_UN);
close(f);
}
// open file
f = open(argv[1], O_CREAT | O_RDWR, CHMOD);
if(f < 0)
{
sleep(1);
continue;
}
// lock file
if(flock(f, LOCK_EX) < 0)
{
sleep(1);
continue;
}
// get file size in bytes
off_t len = lseek(f, (size_t)0, SEEK_END);
if(len < 0)
{
sleep(1);
continue;
}
// check size of read fits into memory
// this should never fail but if it
// does we should exit the process or
// it would hang forever and eventually
// the system max process limit would
// be exceeded.
if(len >= MAX_BUFF)
{
printf("len >= MAX_BUFF\n");
close(f);
return 0;
}
// seek back to beginning of file
if(lseek(f, (size_t)0, SEEK_SET) < 0)
{
sleep(1);
continue;
}
// read file
if(read(f, &tb, len) != len)
{
sleep(1);
continue;
}
//printf("%s > ", tb);
// convert to long long and increment
long long ll = atoll(tb);
ll += atoll(argv[2]);
// set temp buff to write data
sprintf(tb, "%lld", ll);
wlen = strlen(tb);
}
// trunc
if(ftruncate(f, 0) < 0)
{
sleep(1);
continue;
}
// seek
if(lseek(f, (size_t)0, SEEK_SET) < 0)
{
sleep(1);
continue;
}
// write
if(write(f, tb, wlen) != wlen)
{
faw = 1;
sleep(1);
continue;
}
// unlock
flock(f, LOCK_UN);
//done
//printf("%s\n", tb);
fsync(f);
close(f);
return 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment