diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/internal.h | 7 | ||||
| -rw-r--r-- | src/librcc.c | 90 | ||||
| -rw-r--r-- | src/rccdb4.c | 26 | 
3 files changed, 122 insertions, 1 deletions
| diff --git a/src/internal.h b/src/internal.h index 5e64551..c5170be 100644 --- a/src/internal.h +++ b/src/internal.h @@ -5,6 +5,10 @@  # define LIBRCC_DATA_DIR "/usr/lib/rcc"  #endif /* LIBRCC_DATA_DIR */ +#ifndef LIBRCC_LOCK_WAIT +# define LIBRCC_LOCK_WAIT 3000 /* ms */ +#endif /* LIBRCC_LOCK_WAIT */ +  #define RCC_MAX_LANGUAGE_PARRENTS 4  #define RCC_MAX_RELATIONS RCC_MAX_LANGUAGES @@ -91,6 +95,9 @@ struct rcc_context_t {  };  typedef struct rcc_context_t rcc_context_s; +int rccLock(); +void rccUnLock(); +  int rccConfigure(rcc_context ctx);  char *rccCreateResult(rcc_context ctx, size_t len); diff --git a/src/librcc.c b/src/librcc.c index 1ffe00b..6d3ce24 100644 --- a/src/librcc.c +++ b/src/librcc.c @@ -1,6 +1,8 @@  #include <stdio.h>  #include <string.h>  #include <stdlib.h> +#include <time.h> +#include <errno.h>  #include "../config.h" @@ -19,6 +21,11 @@  # include <pwd.h>  #endif /* HAVE_PWD_H */ +#ifdef HAVE_SYS_FILE_H +# include <sys/file.h> +#endif /* HAVE_SYS_FILE_H */ + +  #include "internal.h"  #include "rccconfig.h"  #include "rccenca.h" @@ -135,6 +142,89 @@ void rccFree() {      initialized = 0;  } +static int lockfd = -1; + +int rccLock() { +# ifdef HAVE_SYS_FILE_H +    int err, i; +    int size; +    char *stmp; +    struct timespec wait = { 0, 10000000 }; +     +    if (lockfd>=0) return -1;     +     +    size = strlen(rcc_home_dir) + 32; +    stmp = (char*)malloc(size*sizeof(char)); +    if (!stmp) return -1; + +    sprintf(stmp,"%s/.rcc/", rcc_home_dir); +    mkdir(stmp, 00755); +     +    sprintf(stmp,"%s/.rcc/locks/", rcc_home_dir); +    mkdir(stmp, 00700); + +    sprintf(stmp,"%s/.rcc/locks/rcc.lock", rcc_home_dir); + +    lockfd = open(stmp, O_RDWR|O_CREAT, 0644); +    if (lockfd >= 0) { +	for (err = -1, i = 0; i < (LIBRCC_LOCK_WAIT/10); i++) { +	    err = flock(lockfd, LOCK_EX|LOCK_NB); +	    if ((err)&&(errno == EWOULDBLOCK)) nanosleep(&wait, NULL); +	    else break; +	} + +	if (err) { +	    close(lockfd); + +		// Removing invalid lock +	    if (i == (LIBRCC_LOCK_WAIT/10)) { +		remove(stmp); + +		lockfd = open(stmp, O_RDWR|O_CREAT, 0644); +		if (lockfd >= 0) { +		    for (err = -1, i = 0; i < (LIBRCC_LOCK_WAIT/10); i++) { +			err = flock(lockfd, LOCK_EX|LOCK_NB); +			if ((err)&&(errno == EWOULDBLOCK)) nanosleep(&wait, NULL); +			else break; +		    } +		     +		    if (err) close(lockfd); +		    else return 0; +		}  +	    } +	     +	    lockfd = -1; +	    return -1; +	}  + +	return 0; +    } +     +    return -1; +# else  /* HAVE_SYS_FILE_H */ +    return 0; +# endif /* HAVE_SYS_FILE_H */ +} + +void rccUnLock() { +#ifdef HAVE_SYS_FILE_H +    int size; +    char *stmp; + +    if (lockfd<0) return; +     +    size = strlen(rcc_home_dir) + 32; +    stmp = (char*)malloc(size*sizeof(char)); +    if (!stmp) return; + +    sprintf(stmp,"%s/.rcc/locks/rcc.lock", rcc_home_dir); + +    flock(lockfd, LOCK_UN); +    close(lockfd); +    lockfd = -1; +#endif /* HAVE_SYS_FILE_H */ +} +  rcc_context rccCreateContext(const char *locale_variable, unsigned int max_languages, unsigned int max_classes, rcc_class_ptr defclasses, rcc_init_flags flags) {      unsigned int i; diff --git a/src/rccdb4.c b/src/rccdb4.c index 6a57a5f..a4e0976 100644 --- a/src/rccdb4.c +++ b/src/rccdb4.c @@ -15,11 +15,35 @@ db4_context rccDb4CreateContext(const char *dbpath, rcc_db4_flags flags) {  #ifdef HAVE_DB_H      DB_ENV *dbe;      DB *db; + +    char stmp[160];      err = db_env_create(&dbe, 0);      if (err) return NULL; + +    err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 00644); +    if (err == DB_VERSION_MISMATCH) { + +	if (!rccLock()) {     +	    err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_USE_ENVIRON|DB_PRIVATE|DB_RECOVER, 0); +	    rccUnLock(); +	} else err = -1; + +	dbe->close(dbe, 0); +	if (err) return NULL; + +	if (strlen(dbpath)<128) { +	    sprintf(stmp, "%s/log.0000000001", dbpath); +	    remove(stmp); +	} +	     +	err = db_env_create(&dbe, 0); +	if (err) return NULL; +	     +	err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 00644); +	 +    } -    err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 00755);      if (err) {  	dbe->close(dbe, 0);  	return NULL; | 
