315 lines
7.3 KiB
C
315 lines
7.3 KiB
C
#include <fcntl.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <sys/time.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include "err_handling.h"
|
|
#include "str_util.h"
|
|
#include "tecs_dlog.h"
|
|
|
|
#define VERSION 1.1
|
|
|
|
#define DEFINED(F) (abs((F)-dset->undef)>1.0e-5*(F))
|
|
|
|
static time_t gmtoff;
|
|
|
|
int DlogWrite(DlogSet *dset, int idx, void *data) {
|
|
int p;
|
|
|
|
p = dset->headsize + (idx % dset->nlen) * dset->fsize;
|
|
if (p!=dset->pos) {
|
|
ERR_SI(lseek(dset->fd, p, SEEK_SET));
|
|
}
|
|
ERR_SI(write(dset->fd, data, dset->fsize));
|
|
dset->pos = p + dset->fsize;
|
|
return(0);
|
|
OnError:
|
|
return(-1);
|
|
}
|
|
|
|
#define FILL_BUF_SIZE 1024
|
|
|
|
int DlogFill(DlogSet *dset, int from, int to) {
|
|
int p, q, e, i, size;
|
|
float fill[FILL_BUF_SIZE];
|
|
|
|
for (i=0;i<FILL_BUF_SIZE;i++) fill[i]=dset->undef;
|
|
e = 0;
|
|
if (to-from>=dset->nlen) { /* fill all */
|
|
p = dset->headsize;
|
|
q = dset->headsize + dset->nlen * dset->fsize;
|
|
} else {
|
|
p = dset->headsize + (from % dset->nlen) * dset->fsize;
|
|
q = dset->headsize + (to % dset->nlen) * dset->fsize;
|
|
if (q<p) {
|
|
e = q;
|
|
q = dset->headsize + dset->nlen * dset->fsize;
|
|
}
|
|
}
|
|
ERR_SI(lseek(dset->fd, p, SEEK_SET));
|
|
for (i=p; i<q-sizeof(fill); i+=sizeof(fill)) {
|
|
ERR_SI(write(dset->fd, fill, sizeof(fill)));
|
|
}
|
|
if (q>i) ERR_SI(write(dset->fd, fill, q-i));
|
|
|
|
if (e>0) {
|
|
p = dset -> headsize;
|
|
ERR_SI(lseek(dset->fd, p, SEEK_SET));
|
|
for (i=p; i<e-sizeof(fill); i+=sizeof(fill)) {
|
|
ERR_SI(write(dset->fd, fill, sizeof(fill)));
|
|
}
|
|
if (e>i) ERR_SI(write(dset->fd, fill, q-i));
|
|
}
|
|
dset->pos = -1; /* set position to undefined */
|
|
return(0);
|
|
OnError:
|
|
return(-1);
|
|
}
|
|
|
|
/*
|
|
int DlogRead(DlogSet *dset, int idx, void *data) {
|
|
int p;
|
|
|
|
p = dset->headsize + (idx % dset->nlen) * dset->fsize;
|
|
if (p!=dset->pos) {
|
|
ERR_SI(lseek(dset->fd, p, SEEK_SET));
|
|
}
|
|
ERR_SI(read(dset->fd, data, dset->fsize));
|
|
dset->pos = p + dset->fsize;
|
|
return(0);
|
|
OnError:
|
|
return(-1);
|
|
}
|
|
*/
|
|
|
|
int DlogRead(DlogSet *dset, int idx, int max, void *data) {
|
|
int i, p, m;
|
|
|
|
i = idx % dset->nlen;
|
|
p = dset->headsize + i * dset->fsize;
|
|
if (max > dset->nlen - i) {
|
|
max = dset->nlen - i;
|
|
}
|
|
if (p!=dset->pos) {
|
|
ERR_SI(lseek(dset->fd, p, SEEK_SET));
|
|
}
|
|
ERR_SI(read(dset->fd, data, dset->fsize * max));
|
|
dset->pos = p + dset->fsize * max;
|
|
return(max);
|
|
OnError:
|
|
return(-1);
|
|
}
|
|
|
|
int DlogOpenOld(DlogSet *dset, char *name, int write) {
|
|
int i, p, np, fd, flags;
|
|
time_t tim;
|
|
struct tm *timp;
|
|
|
|
fd=0;
|
|
str_copy(dset->name, name);
|
|
if (write) {
|
|
flags=O_RDWR | O_SYNC;
|
|
} else {
|
|
flags=O_RDONLY | O_SYNC;
|
|
}
|
|
#ifdef __VMS
|
|
ERR_SI(fd=open(name, flags, 0, "SHR=UPD"));
|
|
gmtoff=0;
|
|
#else
|
|
ERR_SI(fd=open(name, flags, 0));
|
|
time(&tim);
|
|
timp=localtime(&tim);
|
|
gmtoff=timp->tm_gmtoff;
|
|
#endif
|
|
dset->fd=fd;
|
|
|
|
p=(char *)&dset->fd - (char *)dset;
|
|
ERR_SI(read(dset->fd, dset, p));
|
|
dset->pos=p;
|
|
if ((int)(dset->version*1000+0.5) != (int)(VERSION*1000+0.5)) ERR_MSG("version mismatch");
|
|
if (dset->headsize != p) ERR_MSG("illegal dlog file");
|
|
return(0);
|
|
OnError:
|
|
if (fd!=0) close(fd);
|
|
return(-1);
|
|
}
|
|
|
|
int DlogOpen(DlogSet *dset, char *name) {
|
|
return(DlogOpenOld(dset, name, 0));
|
|
}
|
|
|
|
int DlogOpenWrt(DlogSet *dset, char *name, time_t start, int nset, int nlen, int period, float undef) {
|
|
int fd, i, j, p, iret;
|
|
va_list ap;
|
|
float f[DLOG_MAX_SET];
|
|
|
|
iret=DlogOpenOld(dset, name, 1);
|
|
if (iret>=0 && dset->nset==nset
|
|
&& dset->nlen==nlen
|
|
&& dset->last+nlen*period>start
|
|
&& dset->undef == undef) {
|
|
return(1); /* take old file only if it matches */
|
|
}
|
|
fd=0;
|
|
if (nset>DLOG_MAX_SET) ERR_MSG("nset too large");
|
|
dset->nset=nset;
|
|
dset->nlen=nlen;
|
|
dset->start=start;
|
|
dset->last=start-period;
|
|
dset->period=period;
|
|
dset->undef=undef;
|
|
dset->version=VERSION;
|
|
str_copy(dset->name, name);
|
|
|
|
for (i=0; i<nset; i++) {
|
|
f[i]=dset->undef;
|
|
}
|
|
ERR_SI(fd=open(name, O_RDWR | O_CREAT | O_SYNC | O_TRUNC, 0666));
|
|
dset->fd=fd;
|
|
p=(char *)&dset->fd - (char *)dset;
|
|
dset->headsize = p;
|
|
dset->fsize = nset * sizeof(float);
|
|
ERR_SI(write(dset->fd, dset, p));
|
|
dset->pos=p;
|
|
return(0);
|
|
OnError:
|
|
if (fd!=0) close(fd);
|
|
return(-1);
|
|
}
|
|
|
|
int DlogPut(DlogSet *dset, time_t tim, int nset, float val[]) {
|
|
int i, i0, j;
|
|
float f[DLOG_MAX_SET], f0[DLOG_MAX_SET];
|
|
|
|
if (nset > dset->nset) nset = dset->nset;
|
|
|
|
for (j=0; j < nset; j++) { f[j]=val[j]; }
|
|
for (j=nset; j < dset->nset; j++) { f[j]=dset->undef; }
|
|
|
|
i = ( tim - dset->start ) / dset->period;
|
|
i0 = ( dset->last - dset->start ) / dset->period;
|
|
|
|
if (i0==i) {
|
|
ERR_I(DlogRead(dset, i, 1, f0));
|
|
for (j=0; j<nset; j++) {
|
|
if (DEFINED(f0[j]) && /* when last point defined */
|
|
(i%2 && f0[j]>f[j] || /* take maximum (for odd i) */
|
|
!i%2 && f0[j]<f[j] ) /* or minimum (for even i) */
|
|
) f[j]=f0[j]; /* of f0 and f0 */
|
|
}
|
|
} else if (i0<i-1) {
|
|
DlogFill(dset, i0+1, i);
|
|
}
|
|
ERR_I(DlogWrite(dset, i, f));
|
|
dset->last=tim;
|
|
return(0);
|
|
OnError:
|
|
return(-1);
|
|
}
|
|
|
|
#define RD_BUF_SIZE 1024
|
|
|
|
int DlogGet(DlogSet *dset, int iset, int nmax, double *starttime, float x[], float y[]) {
|
|
int j, i0, i1, i, n, nread, undef;
|
|
float f, fbuf[RD_BUF_SIZE+1];
|
|
|
|
if (iset<0) ERR_MSG("illegal iset");
|
|
if (iset>=dset->nset) return(0);
|
|
|
|
i = ( dset->last - dset->start ) / dset->period;
|
|
if (i - dset->nlen > 0) {
|
|
i1 = i - dset->nlen + 1;
|
|
} else {
|
|
i1 = 0;
|
|
}
|
|
i0=i1;
|
|
|
|
*starttime = dset->start + i1 * dset->period + gmtoff;
|
|
n=0;
|
|
undef=2;
|
|
while (i0<=i) {
|
|
ERR_I(nread=DlogRead(dset, i0, RD_BUF_SIZE/dset->nset, fbuf));
|
|
for (j=0; j<nread; j++) {
|
|
if (n>=nmax) return(n);
|
|
f=fbuf[j * dset->nset + iset];
|
|
i0++;
|
|
if (DEFINED(f)) {
|
|
x[n]=(float)(i0-i1)*dset->period;
|
|
y[n]=f;
|
|
n++;
|
|
undef=0;
|
|
} else if (undef==0) {
|
|
undef=1;
|
|
} else if (undef==1) {
|
|
undef=2;
|
|
x[n]=0;
|
|
y[n]=0;
|
|
n++;
|
|
}
|
|
}
|
|
}
|
|
return(n);
|
|
OnError:
|
|
return(-1);
|
|
}
|
|
|
|
int DlogGetMany(DlogSet *dset, int nset, int nmax, double *starttime, float x[], float y[], int index[]) {
|
|
int n, k, nmx, ntot;
|
|
|
|
ntot=0;
|
|
for (k=0; k<nset; k++) {
|
|
index[k]=ntot;
|
|
nmx=(nmax-ntot)/(nset-k);
|
|
ERR_I(n=DlogGet(dset, k, nmx, starttime, &x[ntot], &y[ntot]));
|
|
ntot+=n;
|
|
}
|
|
return(ntot);
|
|
OnError:
|
|
return(-1);
|
|
}
|
|
|
|
int dlog_get_(char *name, int *nset, int *nmax, double *starttime, float x[], float y[], int index[], int namlen) {
|
|
DlogSet dset;
|
|
char buf[64];
|
|
int ntot;
|
|
/* for compaq unix */
|
|
str_trim(buf, name, namlen);
|
|
ERR_I(DlogOpen(&dset, buf));
|
|
ERR_I(ntot=DlogGetMany(&dset, *nset, *nmax, starttime, x, y, index));
|
|
DlogClose(&dset);
|
|
return(ntot);
|
|
OnError:
|
|
ErrWrite("error in dlog_get_");
|
|
return(-1);
|
|
}
|
|
|
|
int Dlog_Get(char **name, int *nset, int *nmax, double *starttime, float x[], float y[], int index[]) {
|
|
/* for VMS */
|
|
return(dlog_get_(name[1], nset, nmax, starttime, x, y, index, *(short *)name));
|
|
}
|
|
|
|
int DlogUpd(DlogSet *dset) {
|
|
ERR_SI(lseek(dset->fd, 0, SEEK_SET));
|
|
ERR_SI(write(dset->fd, &dset->last, sizeof(int)));
|
|
dset->pos=sizeof(int);
|
|
#ifdef __VMS
|
|
close(dset->fd);
|
|
ERR_I(DlogOpenOld(dset, dset->name, 1));
|
|
#endif
|
|
return(0);
|
|
OnError:
|
|
return(-1);
|
|
}
|
|
|
|
int DlogClose(DlogSet *dset) {
|
|
ERR_I(DlogUpd(dset));
|
|
close(dset->fd);
|
|
return(0);
|
|
OnError:
|
|
return(-1);
|
|
}
|