little fixes

This commit is contained in:
2026-05-22 09:45:35 +03:00
parent 51869f0137
commit 768d46060d
7 changed files with 65 additions and 32 deletions

View File

@@ -66,6 +66,19 @@ meteologger -n <node> -o <directory> [options]
| `-i` | `--interval` | `0.5` | Request interval in seconds. Allowed range: `[0.2, 900]`. | | `-i` | `--interval` | `0.5` | Request interval in seconds. Allowed range: `[0.2, 900]`. |
| `-t` | `--timeout` | `1.0` | Network timeout for server responses (seconds). Allowed range: `[0.1, 30]`. | | `-t` | `--timeout` | `1.0` | Network timeout for server responses (seconds). Allowed range: `[0.1, 30]`. |
### Rotation of database files
The daemon keeps all DB files opened during its work, so for correct log rotation after renaming
all files (like `rename log log00 *.log`) you should send SIGUSR1 or SIGUSR2 to daemon, like
```bash
kill -USR1 $(cat /tmp/meteologger.pid)
```
After receiving of this signal daemon will open new DB files and you will be able to compress old
files.
### Examples ### Examples
1. Connect to a local daemon on port 5555 and store data in `/var/log/weather`: 1. Connect to a local daemon on port 5555 and store data in `/var/log/weather`:

View File

@@ -53,6 +53,7 @@ void signals(int signo){
kill(childpid, signo); kill(childpid, signo);
LOGMSG("Send received signal %d to child", signo); LOGMSG("Send received signal %d to child", signo);
if(signo != SIGUSR1) catchsig = signo; if(signo != SIGUSR1) catchsig = signo;
else signal(signo, signals);
}else catchsig = signo; }else catchsig = signo;
} }
} }
@@ -76,7 +77,10 @@ int main(int argc, char **argv){
signal(SIGINT, signals); signal(SIGINT, signals);
signal(SIGQUIT, signals); signal(SIGQUIT, signals);
signal(SIGPIPE, SIG_IGN); // for sockets signal(SIGPIPE, SIG_IGN); // for sockets
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGUSR1, signals); // reload DB signal(SIGUSR1, signals); // reload DB
signal(SIGUSR2, signals); // reload DB
#ifndef EBUG #ifndef EBUG
if(sl_daemonize()) ERRX("Can't daemonize"); if(sl_daemonize()) ERRX("Can't daemonize");
#endif #endif

View File

@@ -38,8 +38,8 @@ static const char *key_timestamp = "TWEATH";
// sensor's db filename mask: DBpath/weatherXX.log // sensor's db filename mask: DBpath/weatherXX.log
static const char *dbfilename_mask = "%s/weather%02d.log"; static const char *dbfilename_mask = "%s/weather%02d.log";
// and search regex // and search regex inside DB directory
static const char *dbfilename_regex = "weather[[:digit:]]{2}\\.log"; static const char *dbfilename_regex = "^weather[[:digit:]]{2}\\.log$";
static volatile atomic_bool isrunning = true; static volatile atomic_bool isrunning = true;
static volatile atomic_bool logreinit = false; static volatile atomic_bool logreinit = false;
@@ -189,6 +189,7 @@ static ssize_t get_answer_line(sl_sock_t *sock, char *buf, size_t buflen){
// @return false if failed // @return false if failed
bool reinit_logs(){ bool reinit_logs(){
FNAME(); FNAME();
LOGMSG("Got 'reinit' command");
logreinit = true; logreinit = true;
return true; return true;
} }
@@ -217,8 +218,9 @@ static bool find_old_file(senslog_t *sensor){
if(sensor->fd > -1){ if(sensor->fd > -1){
DBG("found opened file %s with fd %d -> close", sensor->path, sensor->fd); DBG("found opened file %s with fd %d -> close", sensor->path, sensor->fd);
close(sensor->fd); close(sensor->fd);
sensor->fd = -1;
} }
LOGMSG("Try to find old file");
regex_t regex; regex_t regex;
// Compile regex // Compile regex
if(regcomp(&regex, dbfilename_regex, REG_EXTENDED | REG_NOSUB) != 0){ if(regcomp(&regex, dbfilename_regex, REG_EXTENDED | REG_NOSUB) != 0){
@@ -235,16 +237,16 @@ static bool find_old_file(senslog_t *sensor){
// Check if filename matches regex // Check if filename matches regex
if(regexec(&regex, dir->d_name, 0, NULL, 0) == 0){ if(regexec(&regex, dir->d_name, 0, NULL, 0) == 0){
DBG("Found: %s", dir->d_name); DBG("Found: %s", dir->d_name);
char fname[PATH_MAX], line[BUFSIZ]; char line[BUFSIZ];
snprintf(fname, PATH_MAX, "%s/%s", DBpath, dir->d_name); snprintf(sensor->path, PATH_MAX, "%s/%s", DBpath, dir->d_name);
FILE *fp = fopen(fname, "r"); FILE *fp = fopen(sensor->path, "r");
if(!fp){ if(!fp){
LOGERR("Cannot open %s for reading: %s", fname, strerror(errno)); LOGWARN("Cannot open %s for reading: %s", sensor->path, strerror(errno));
DBG("Can't open"); DBG("Can't open");
continue; continue;
} }
if(fgets(line, sizeof(line), fp) == NULL){ if(fgets(line, sizeof(line), fp) == NULL){
LOGWARN("Found empty BD file %s - WTF???", fname); LOGWARN("Found empty BD file %s - WTF???", sensor->path);
fclose(fp); fclose(fp);
continue; continue;
} }
@@ -252,18 +254,19 @@ static bool find_old_file(senslog_t *sensor){
int len = strlen(line); int len = strlen(line);
if(len > 0 && line[len-1] == '\n') line[len-1] = 0; // remove trailing newline if(len > 0 && line[len-1] == '\n') line[len-1] = 0; // remove trailing newline
if(line[0] != '#' || line[1] != ' '){ // should starts from comment with station's name if(line[0] != '#' || line[1] != ' '){ // should starts from comment with station's name
LOGWARN("Found broken database file: %s", fname); LOGWARN("Found broken database file: %s", sensor->path);
continue; continue;
} }
const char *stname = line + 2; // station name from comment const char *stname = line + 2; // station name from comment
DBG("Check name: '%s' and '%s'", stname, sensor->sensname); DBG("Check name: '%s' and '%s'", stname, sensor->sensname);
if(0 == strcmp(stname, sensor->sensname)){ // good, we found this file! if(0 == strcmp(stname, sensor->sensname)){ // good, we found this file!
DBG("Found existant file %s -> append to it", fname); DBG("Found existant file %s -> append to it", sensor->path);
int newfd = open(fname, O_WRONLY | O_APPEND); int newfd = open(sensor->path, O_WRONLY | O_APPEND);
if(newfd < 0){ if(newfd < 0){
LOGERR("Can't open existant BD file %s for append, try to create new", fname); LOGWARN("Can't open existant BD file %s for append, try to create new", sensor->path);
continue; continue;
} }
LOGMSG("Station '%s': opened existant DB file '%s'", sensor->sensname, sensor->path);
sensor->fd = newfd; sensor->fd = newfd;
ret = true; ret = true;
break; break;
@@ -274,6 +277,7 @@ static bool find_old_file(senslog_t *sensor){
}else{ }else{
LOGERR("Can't open %s: %s", DBpath, strerror(errno)); LOGERR("Can't open %s: %s", DBpath, strerror(errno));
} }
if(sensor->fd < 0) LOGERR("Error opening DB file for '%s'", sensor->sensname);
regfree(&regex); regfree(&regex);
return ret; return ret;
} }
@@ -286,12 +290,12 @@ static bool create_db_file(senslog_t *sensor){
WARNX("create_db_file() should be called only with fully initialized `sensor`"); WARNX("create_db_file() should be called only with fully initialized `sensor`");
return false; return false;
} }
LOGMSG("Try to create new DB file for '%s'", sensor);
int num = sensor->idx; // try to start from sensor's index int num = sensor->idx; // try to start from sensor's index
char path[PATH_MAX];
for(; num <= 99; ++num){ for(; num <= 99; ++num){
snprintf(path, PATH_MAX, dbfilename_mask, DBpath, num); snprintf(sensor->path, PATH_MAX, dbfilename_mask, DBpath, num);
DBG("Try to create %s", path); DBG("Try to create %s", path);
if(access(path, F_OK) != 0) break; // no such file if(access(sensor->path, F_OK) != 0) break; // no such file
} }
if(num > 99){ if(num > 99){
LOGERR("Can't find free filename for station '%s', all numbers from 0 to 99 are busy! WTF???", LOGERR("Can't find free filename for station '%s', all numbers from 0 to 99 are busy! WTF???",
@@ -300,29 +304,30 @@ static bool create_db_file(senslog_t *sensor){
return false; return false;
} }
// create and open write-only // create and open write-only
int newfd = open(path, O_WRONLY | O_CREAT, 0644); int newfd = open(sensor->path, O_WRONLY | O_CREAT, 0644);
if(newfd < 0){ if(newfd < 0){
LOGERR("Can't open file %s for station %s: %s", path, sensor->sensname, strerror(errno)); LOGERR("Can't open file %s for station %s: %s", sensor->path, sensor->sensname, strerror(errno));
WARNX("Can't open %s", path); WARNX("Can't open %s", sensor->path);
return false; return false;
} }
DBG("OK, %s opened, try to write header", path); DBG("OK, %s opened, try to write header", path);
sensor->fd = newfd; sensor->fd = newfd;
ssize_t len = snprintf(path, PATH_MAX, "# %s\n", sensor->sensname); char path[2*PATH_MAX];
ssize_t len = snprintf(path, 2*PATH_MAX, "# %s\n", sensor->sensname);
if(!write2fd(sensor, path, len)) return false; if(!write2fd(sensor, path, len)) return false;
len = snprintf(path, PATH_MAX, "# Station #%d, format: KEYWORD[level],...\n# TIMESTAMP, ", sensor->idx); len = snprintf(path, 2*PATH_MAX, "# Station #%d, format: KEYWORD[level],...\n# TIMESTAMP, ", sensor->idx);
if(!write2fd(sensor, path, len)) return false; if(!write2fd(sensor, path, len)) return false;
char *ptr = path; char *ptr = path;
len = 0; len = 0;
for(int i = 0; i < sensor->nvalues; ++i){ for(int i = 0; i < sensor->nvalues; ++i){
ssize_t L = snprintf(ptr, PATH_MAX-len, "%s%s[%d]", i ? ", " : "", sensor->keys[i], sensor->levels[i]); ssize_t L = snprintf(ptr, 2*PATH_MAX-len, "%s%s[%d]", i ? ", " : "", sensor->keys[i], sensor->levels[i]);
len += L; len += L;
ptr += L; ptr += L;
} }
len += snprintf(ptr, PATH_MAX-len, "\n"); len += snprintf(ptr, 2*PATH_MAX-len, "\n");
if(!write2fd(sensor, path, len)) return false; if(!write2fd(sensor, path, len)) return false;
DBG("%s now have descriptor %d: %s", sensor->sensname, newfd, path); DBG("%s now have descriptor %d: %s", sensor->sensname, newfd, sensor->path);
LOGMSG("OK, data for '%s' now will be stored @ '%s'", sensor->sensname, sensor->path);
return true; return true;
} }
@@ -335,6 +340,7 @@ static bool create_db_file(senslog_t *sensor){
static bool get_sensor_keys(senslog_t *sensor, sl_sock_t *sock){ static bool get_sensor_keys(senslog_t *sensor, sl_sock_t *sock){
if(!sensor || !sock) return false; if(!sensor || !sock) return false;
char str[BUFSIZ], key[SL_KEY_LEN], value[SL_VAL_LEN]; char str[BUFSIZ], key[SL_KEY_LEN], value[SL_VAL_LEN];
LOGMSG("Send request to receive all keys for sensors");
snprintf(str, BUFSIZ, "%s=%d\n", commands[CMD_CHKLEVEL], sensor->idx); snprintf(str, BUFSIZ, "%s=%d\n", commands[CMD_CHKLEVEL], sensor->idx);
if(!send_request(sock, str)){ if(!send_request(sock, str)){
LOGERR("Can't send request '%s'", commands[CMD_CHKLEVEL]); LOGERR("Can't send request '%s'", commands[CMD_CHKLEVEL]);
@@ -376,6 +382,7 @@ static bool get_sensor_keys(senslog_t *sensor, sl_sock_t *sock){
// this function called at start and on any logs reinit // this function called at start and on any logs reinit
static bool prepare_files(sl_sock_t *sock){ static bool prepare_files(sl_sock_t *sock){
if(!sock || !DBpath || Nsensors < 1) return false; if(!sock || !DBpath || Nsensors < 1) return false;
LOGMSG("Prepare files for DB");
for(int i = 0; i < Nsensors; ++i){ for(int i = 0; i < Nsensors; ++i){
senslog_t *sensor = &sensors[i]; senslog_t *sensor = &sensors[i];
if(!sensor->initialized && !get_sensor_keys(sensor, sock)) return false; if(!sensor->initialized && !get_sensor_keys(sensor, sock)) return false;
@@ -387,6 +394,8 @@ static bool prepare_files(sl_sock_t *sock){
return false; return false;
} }
} }
sensor->buflen = 0;
sensor->lastvalidx = -1;
} }
DBG("All ready!"); DBG("All ready!");
return true; return true;
@@ -458,7 +467,7 @@ static bool analyse_list(sl_sock_t *sock){
if(sensor->nvalues < 1){ if(sensor->nvalues < 1){
LOGWARN("Zero keys for station %s", sensor->sensname); LOGWARN("Zero keys for station %s", sensor->sensname);
ans = false; break; ans = false; break;
} }else LOGMSG("Found station '%s' with %d keys", sensor->sensname, sensor->nvalues);
} }
if(ans) ans = prepare_files(sock); if(ans) ans = prepare_files(sock);
if(ans == false) sensors_delete(); if(ans == false) sensors_delete();
@@ -477,6 +486,7 @@ static bool prepare_logfiles(sl_sock_t *sock, const char *path){
return false; return false;
} }
DBG("Store files in %s; send `list` request", DBpath); DBG("Store files in %s; send `list` request", DBpath);
LOGMSG("Store files in %s; send `list` request", DBpath);
snprintf(buf, 255, "%s\n", commands[CMD_LIST]); snprintf(buf, 255, "%s\n", commands[CMD_LIST]);
if(!send_request(sock, buf)){ if(!send_request(sock, buf)){
LOGERR("Can't send inited request"); LOGERR("Can't send inited request");

View File

@@ -41,6 +41,7 @@ static const val_t values[NAMOUNT] = {
static void *mainthread(void *s){ static void *mainthread(void *s){
FNAME(); FNAME();
sensordata_t *sensor = (sensordata_t *)s; sensordata_t *sensor = (sensordata_t *)s;
double t0 = sl_dtime();
while(sensor->fdes > -1){ while(sensor->fdes > -1){
if(check_shm_block(&sdat)){ if(check_shm_block(&sdat)){
//DBG("Got next"); //DBG("Got next");
@@ -57,7 +58,8 @@ static void *mainthread(void *s){
pthread_mutex_unlock(&sensor->valmutex); pthread_mutex_unlock(&sensor->valmutex);
if(sensor->freshdatahandler) sensor->freshdatahandler(sensor); if(sensor->freshdatahandler) sensor->freshdatahandler(sensor);
}else break; // no connection? }else break; // no connection?
sleep(1); while(sl_dtime() - t0 < sensor->tpoll) usleep(500);
t0 = sl_dtime();
} }
return NULL; return NULL;
} }

View File

@@ -109,7 +109,7 @@ static void *mainthread(void *s){
sensordata_t *sensor = (sensordata_t *)s; sensordata_t *sensor = (sensordata_t *)s;
while(sensor->fdes > -1){ while(sensor->fdes > -1){
time_t tnow = time(NULL); time_t tnow = time(NULL);
if(tnow - tpoll > sensor->tpoll){ if(tnow - tpoll > sensor->tpoll){ // tpoll + 1 second
int dlen = sprintf(buf, "%s0\n%s1\n", commands[CMD_DISTANCE], commands[CMD_DISTANCE]); int dlen = sprintf(buf, "%s0\n%s1\n", commands[CMD_DISTANCE], commands[CMD_DISTANCE]);
if(dlen != write(sensor->fdes, buf, dlen)){ if(dlen != write(sensor->fdes, buf, dlen)){
WARN("Can't ask new data from lightning monitor"); WARN("Can't ask new data from lightning monitor");
@@ -144,16 +144,20 @@ static void *mainthread(void *s){
int idx = parse_string(buf, &val, &nsens); int idx = parse_string(buf, &val, &nsens);
if(idx > -1){ if(idx > -1){
DBG("Got index=%d", idx); DBG("Got index=%d", idx);
gotfresh = TRUE;
if(idx == NINTERRUPT && val == ANS_LIGHTNING){ if(idx == NINTERRUPT && val == ANS_LIGHTNING){
DBG("Interrupt: lightning"); DBG("Interrupt: lightning");
sensor->values[NSENSNO].value.u = nsens; sensor->values[NSENSNO].value.u = nsens;
sensor->values[NSENSNO].time = tnow; sensor->values[NSENSNO].time = tnow;
} }
if(idx == NDISTANCE && val == 63){
// do nothing: this is just polling signal
}else{
gotfresh = TRUE;
sensor->values[idx].value.u = val; sensor->values[idx].value.u = val;
sensor->values[idx].time = tnow; sensor->values[idx].time = tnow;
} }
}
}else break; }else break;
} }
// now check values // now check values

View File

@@ -77,7 +77,7 @@ static void *mainthread(void *s){
sensordata_t *sensor = (sensordata_t *)s; sensordata_t *sensor = (sensordata_t *)s;
while(sensor->fdes > -1){ while(sensor->fdes > -1){
time_t tnow = time(NULL); time_t tnow = time(NULL);
if(tnow - tpoll > sensor->tpoll){ if(tnow - tpoll >= sensor->tpoll){
if(4 != write(sensor->fdes, "?U\r\n", 4)){ if(4 != write(sensor->fdes, "?U\r\n", 4)){
WARN("Can't ask new data"); WARN("Can't ask new data");
break; break;

View File

@@ -126,7 +126,7 @@ static void *mainthread(void *s){
sensordata_t *sensor = (sensordata_t *)s; sensordata_t *sensor = (sensordata_t *)s;
while(sensor->fdes > -1){ while(sensor->fdes > -1){
time_t tnow = time(NULL); time_t tnow = time(NULL);
if(tnow - tpoll > sensor->tpoll){ if(tnow - tpoll >= sensor->tpoll){
if(6 != write(sensor->fdes, "!0R0\r\n", 6)){ if(6 != write(sensor->fdes, "!0R0\r\n", 6)){
WARN("Can't ask new data"); WARN("Can't ask new data");
break; break;