#include #include #include #include #include "myc_mem.h" #include "myc_str.h" #include "myc_err.h" #include "myc_time.h" #include "coc_logfile.h" #include "tecs_data.h" #include "logger.h" #define RUN_SIZE 1024 #define SET_LEN 1024 typedef struct { int tmin, tmax, tlim; float dmin, dmax; int reset; } Summary; typedef struct Run { struct Run *next; int size, step; int startTime, endTime; float data[RUN_SIZE]; } Run; typedef struct Set { DataSet set; struct Set *next; int nRuns; int step, lifetime; int start, end; float *var; float undef; Run *runs; Summary sum; Logger *log; } Set; typedef struct { Set *head; } Base; typedef struct { Base *base; int tim, from, to; int stdStep; } ScanData; static Base database; static float undef_value = DATA_UNDEF; /* additonal undef value */ void DataUndef(float undef) { undef_value = undef; } void InsSum(Summary *sum, int t, float d) { if (sum->tmin == 0) { sum->tmin = t; sum->tmax = t; sum->dmin = d; sum->dmax = d; } else { if (d <= sum->dmin) { sum->dmin = d; sum->tmin = t; } else if (d >= sum->dmax) { sum->dmax = d; sum->tmax = t; } } } void ResetSum(Summary *sum) { sum->reset = 1; sum->tmin = 0; sum->dmin = DATA_UNDEF; sum->dmax = DATA_UNDEF; } void PutSum(Summary *sum, float *data) { if (sum->tmin == 0) { data[1] = sum->dmin; data[0] = sum->dmax; } else if (sum->tmin > sum->tmax) { data[1] = sum->dmin; data[0] = sum->dmax; sum->dmin = sum->dmax; } else if (sum->tmin < sum->tmax) { data[1] = sum->dmax; data[0] = sum->dmin; sum->dmax = sum->dmin; } else { data[1] = sum->dmin; data[0] = sum->dmax; } sum->tmin = 0; if (sum->reset) { sum->dmin = DATA_UNDEF; sum->dmax = DATA_UNDEF; sum->reset = 0; } } Set *FindSet(Base *base, char *name) { Set *s; int total; total=0; s = base->head; while (s!=NULL && 0!=strcasecmp(name, s->set.name)) { s = s->next; } return s; } Set *CreateSet(Base *base, char *name, float *var, int step, int lifetime, int start) { Set *s; char *nam; s = FindSet(base, name); if (s != NULL) ERR_MSG("dataset exists"); NEW(s, Set); s->next = base->head; base->head = s; NEW_STR(nam, name); s->set.name = nam; s->runs = NULL; s->nRuns = 0; s->lifetime = lifetime; s->start = start; s->step = step; s->var = var; s->undef = undef_value; s->log = NULL; ResetSum(&s->sum); return s; OnError: return NULL; } DataSet *DataFindSet(DataBase *dBase, char *name) { Base *base; if (dBase==NULL) { base=&database; } else { base=(Base *)dBase; } return (DataSet *) FindSet(base, name); } DataSet *DataCreateSet(DataBase *dBase, char *name, float *var, int step, int lifetime, int start) { Base *base; if (dBase==NULL) { base=&database; } else { base=(Base *)dBase; } return (DataSet *) CreateSet(base, name, var, step, lifetime, start); } int DataSetStep(DataSet *set, int step) { Set *s; ERR_P(set); ERR_I(step-1); /* step > 0 */ s = (Set *)set; s->step = step; return 0; OnError: return -1; } int DataSetLifetime(DataSet *set, int lifetime) { Set *s; ERR_P(set); s = (Set *)set; s->lifetime = lifetime; return 0; OnError: return -1; } Run *InsertRun(Set *s, int time) { Run *r, *next, *last; NEW(r, Run); r->next = s->runs; s->runs = r; r->step = s->step; s->nRuns++; if (s->nRuns * s->step > s->lifetime) { next=r->next; last=r; while (next!=NULL && next->endTime > time - s->lifetime) { last = next; next = last->next; } while (next!=NULL) { last->next = next->next; FREE(next); s->nRuns--; next = last->next; } } return r; OnError: return NULL; } int Put(Set *set, int time, float value) { Run *r; int t; int size; float last; static int errcnt=0; ERR_P(set); if (value == DATA_UNDEF) return 0; r = set->runs; if (r == NULL || r->step != set->step || r->size+3 > RUN_SIZE) { ERR_P(r = InsertRun(set, time)); r->startTime = time; r->endTime = time - r->step; size = 0; t = 1; } else { size = r->size; t = (time - r->endTime) / r->step; last = r->data[size-1]; } if (t<0) { if (t<-1) { if (errcnt<4) { errcnt++; logfileOut(LOG_MAIN, "%s %d set.name, time, r->endTime); } ERR_MSG("back in time not possible"); } if (errcnt>0) errcnt--; t=0; } if (t == 0) { InsSum(&set->sum, time, value); } else { if (size % 2) { PutSum(&set->sum, r->data+size-1); size++; r->endTime += r->step; t--; } if (t > 2) { r->data[size]=t-1; size++; r->data[size]=DATA_UNDEF; size++; set->sum.reset = 1; r->endTime += r->step * (t-1); t=1; } InsSum(&set->sum, time, value); if (t % 2) { r->data[size]=value; size++; /* put a provisory value */ r->endTime += r->step; } else if (t == 2) { PutSum(&set->sum, r->data+size); size+=2; r->endTime += r->step * 2; } } r->size = size; return 0; OnError: return -1; } int DataPut(DataSet *set, int time, float value) { return Put((Set *)set, time, value); } int DataPutAll(DataBase *base, int mytime) { Set *s; char value[32]; char tname[32]; static time_t lastOpen = 0; float val; if (base == NULL) { s=database.head; } else { s=((Base *)base)->head; } while (s!=NULL) { if (s->var!=NULL) { val = *s->var; if (val == s->undef) { val = DATA_UNDEF; } ERR_I(Put(s, mytime, val)); if (s->log == NULL && val != DATA_UNDEF && time(NULL) > lastOpen + 300) { /* try to make logger if not yet tried in the last 5 min. */ snprintf(tname, sizeof tname, "tt.%s", s->set.name); s->log = LoggerMake(tname, s->step, 0); if (s->log == NULL) { lastOpen = time(NULL); } } if (s->log != NULL) { if (val == DATA_UNDEF) { value[0]='\0'; } else { snprintf(value, sizeof value, "%.5g", val); } LoggerWrite(s->log, mycUnixTime(mytime), s->step, value); } } s=s->next; } return 0; OnError: return -1; } int Start(Set *s) { Run *r; int t1, t2; r = s->runs; t1 = s->start; if (r != NULL) { t2 = r->endTime - s->lifetime; if (t1 < t2) { while (r != NULL) { t1 = r->startTime; r = r->next; } if (t1 > t2) { t1 = t2; } } } return t1; } void FreeBase(Base *base) { Set *s, *sFree; Run *r, *rFree; s = base->head; while (s != NULL) { r = s->runs; while (r != NULL) { rFree = r; r = r->next; FREE(rFree); } sFree=s; s = s->next; FREE(sFree); } } int GetSet(Set *s, int startTime, int endTime, int size, float *data) { Run *r; int t, tlim; float d; int i, idx; Summary sum; if (size<=0 || size%2 != 0) ERR_MSG("size must be even and positive"); ERR_P(s); ERR_P(data); r = s->runs; ResetSum(&sum); idx = size - 2; tlim = (endTime - startTime) * idx / size + startTime; while (r != NULL) { if (startTime > r->endTime) break; if (endTime >= r->startTime) { t = r->endTime; d = 0; for (i = r->size - 1; i>=0; i--, t-=r->step) { d = r->data[i]; if (d == DATA_UNDEF) { i--; t -= (int)(r->data[i] + 0.5) * r->step; sum.reset = 1; } else { if (t < startTime) break; if (t < endTime) { while (t < tlim) { PutSum(&sum, data+idx); idx-=2; tlim = (endTime - startTime) * idx / size + startTime; } InsSum(&sum, t, d); } } } } r = r->next; } sum.reset = 1; while (idx >= 0) { PutSum(&sum, data+idx); idx-=2; } return 0; OnError: return -1; } void Scan(void *sData, char *line) { Set *set; Run *run; Base *base; char str[64], nam[64]; int l, iret, hh, mm, ss; float num; int tim, tshift, t0; base=((ScanData *)sData)->base; tim=((ScanData *)sData)->tim; /* read time */ l=0; iret=sscanf(line, "%d:%d:%d%n", &hh, &mm, &ss, &l); line+=l; if (iret!=3) return; tim+=hh*3600+mm*60+ss; if (tim < ((ScanData *)sData)->from || tim > ((ScanData *)sData)->to) return; set=NULL; l=0; iret=sscanf(line, "%64s%n", str, &l); line+=l; while (iret==1) { if (str[0] >= 'A') { str_copy(nam, str); l=0; iret=sscanf(line, "%64s%n", str, &l); line+=l; if (iret==1) { iret=sscanf(str, "%f", &num); if (iret==1) { tshift = 0; if (0 != strcmp(nam, "_")) { set=FindSet(base, nam); if (set!=NULL) tshift = 1; } if (set!=NULL && tim < set->end) { if (tshift) { t0 = tim - ((ScanData *)sData)->stdStep*2; run = set->runs; if (run != NULL && run->endTime >= t0) { t0 = run->endTime; } t0 += set->step; if (t0 > tim) t0 = tim; Put(set, t0, num); } else { Put(set, tim, num); } } } } } else { l=0; iret=sscanf(line, "%64s%n", str, &l); line+=l; } } } void Load(Base *base, int from, int to, int stdStep) { ScanData scanData; int t; scanData.base = base; scanData.stdStep = stdStep; scanData.from = from; scanData.to = to; /* round down "from" and "to" to 00:00 local time */ from = from - (from % (24*3600)); to = to - (to % (24*3600)); for (t=from; t<=to; t+=24*3600) { scanData.tim=t; logfileScan(mycDate(t), Scan, &scanData); } } int DataGetMult(char *names, int startTime, int endTime, int step, int stdStep, float *data, int data_len) { Base base; Set *set, *s; int stp, minStep, period, s1; char *nams, nam[32]; int p, l, n, i, j, siz1, siz2, halfsiz, start; base.head = NULL; period = endTime - startTime; if (period<=0) period=1; n=0; nams = names; while (nams != NULL) { /* count names */ nams = str_split(nam, nams, ' '); if (nam[0] != '\0') n++; } stp=step; if (stp startTime) { set=CreateSet(&base, nam, NULL, stp, period, startTime); if (set != NULL) set->end = start; } } } if (base.head != NULL) { /* load if needed */ Load(&base, startTime, endTime, stdStep); } p=0; nams=names; while (nams!=NULL) { nams=str_split(nam, nams, ' '); if (nam[0]!='\0') { s = FindSet(&database, nam); set = FindSet(&base, nam); s1 = startTime; if (s == NULL) { if (set == NULL) { s1 = 0; } else { s = set; } } else { minStep = s->step; if (set != NULL) { s1 = Start(s); if (s1 >= endTime) { s = set; s1 = startTime; } else if (s1 < startTime || s1 <= Start(set)) { s1 = startTime; } } } if (s1 == 0) { /* empty array */ data[p++]=0; } else { minStep = s->step; stp = step; halfsiz = period / (2 * stp) + 1; if (startTime + minStep * halfsiz * 2 > endTime) { if (stp < minStep) stp = minStep; halfsiz = period / (2 * stp) + 1; if (halfsiz * 2 + n > data_len) { /* check if enough space */ halfsiz = ((data_len - p) / n - 1) / 2; } } siz1 = (s1 - startTime) * halfsiz / period * 2; siz2 = halfsiz * 2 - siz1; s1 = startTime + (siz1 * period + halfsiz) / halfsiz / 2; p++; if (siz1 > 0) { halfsiz = (s1 - startTime) / set->step / 2; if (halfsiz * 2 < siz1 && halfsiz > 0) { ERR_I(GetSet(set, startTime, s1, halfsiz*2, data+p)); j = siz1 - 1; for (i = halfsiz * 2-1; i >= 0; i--) { /* expand data */ while (j > siz1 / 2 * i / halfsiz) { data[p+j]=DATA_GAP; j--; } data[p+j]=data[p+i]; j--; } } else { ERR_I(GetSet(set, startTime, s1, siz1, data+p)); } l=siz1; } else { l=0; } if (siz2 > 0) { ERR_I(GetSet(s, s1, endTime, siz2, data+p+siz1)); l+=siz2; } data[p-1]=l; p+=l; } n--; } } FreeBase(&base); return p; OnError: return -1; }