François Gautrais пре 9 година
родитељ
комит
2ff28a4943
7 измењених фајлова са 864 додато и 0 уклоњено
  1. 26 0
      server/Makefile
  2. 112 0
      server/cache.c
  3. 36 0
      server/cache.h
  4. 193 0
      server/db.c
  5. 57 0
      server/db.h
  6. 361 0
      server/db_access.c
  7. 79 0
      server/db_access.h

+ 26 - 0
server/Makefile

@@ -0,0 +1,26 @@
+OBJ=db_access.o cache.o db.o
+TARGET=server
+CC=gcc
+OBJCOPY=$(CROSS_COMPILE)avr-objcopy
+DEVICE=/dev/ttyUSB0 
+
+CFLAGS_ATTINY=-D_LARGEFILE64_SOURCE  -Wall -fno-exceptions -ffunction-sections -fdata-sections  -g
+CFLAGS=$(CFLAGS_ATTINY)
+
+LDFLAGS_ATINY= 
+LDFLAGS=$(LDFLAGS_ATINY) 
+
+all: $(TARGET)
+
+
+$(TARGET): clean $(OBJ) 
+	$(CC) $(OBJ) $(LDFLAGS)  -lm  -o $@
+	
+
+%.o: %.c
+	echo compile
+	$(CC)  -o $@ -c $<  $(CFLAGS)
+
+
+clean:
+	rm *.o *.d *.elf *.eep *.hex  $(TARGET) || true

+ 112 - 0
server/cache.c

@@ -0,0 +1,112 @@
+#include "cache.h"
+
+
+
+cache_page_t* cache_page_new(cache_t* parent, db_data_t* data)
+{
+	cache_page_t* cp = NULL;
+	cp = (cache_page_t*) malloc(sizeof(cache_page_t));
+	if(!cp)
+	{
+		fprintf(stderr, "Unable to allocate %ld bytes for cache page (cache_page_new())",
+												sizeof(cache_page_t));
+		perror(" ");
+		return NULL;
+	}
+	
+	memset(cp, 0, sizeof(cache_page_t));
+	cp->ptr=data;
+	cp->page_size=parent->page_size;
+	return cp;
+}
+
+void cache_page_set_value(cache_page_t* cp, db_interval_t inter, db_data_t* data)
+{
+	memcpy(cp->ptr, data, sizeof(db_data_t)*cp->page_size);
+	cp->inter=inter;
+}
+
+void cache_page_insert(cache_page_t* parent, cache_page_t* new)
+{
+	cache_page_t *tmp = parent->next;
+	parent->next=new;
+	new->next=tmp;
+	new->prev=parent;
+	if(tmp) tmp->prev=new;
+}
+
+cache_page_t* cache_page_remove(cache_page_t* tr)
+{
+	if(tr->next)
+		tr->next->prev=tr->prev;
+	if(tr->prev)
+		tr->prev->next=tr->next;
+	
+	
+	tr->next=NULL;
+	tr->prev=NULL;
+	return tr;
+}
+
+void cache_page_free(cache_page_t* tr)
+{
+	free(tr);
+}
+
+
+int cache_init(cache_t *cache, int page_size_byte, int page_count)
+{
+	cache_page_t *curr=NULL;
+	int i;
+	if(!cache) return -1;
+	cache->page_count=page_count;
+	cache->page_size=(1+page_size_byte)/sizeof(db_data_t*);
+	cache->cache=(db_data_t*) malloc((page_count)*page_size_byte);
+	if(!cache->cache)
+	{
+		fprintf(stderr, "Unable to allocate %d bytes for cache (cache_init())",
+												(page_count)*page_size_byte);
+		perror(" ");
+		return -1;
+	}
+	
+	cache->head=cache_page_new(cache, NULL);
+	for(i=0, curr=cache->head; i<page_count; i++, curr=curr->next)
+	{
+		cache_page_t *cp = cache_page_new(cache, &cache->cache[i]);
+		cache_page_insert(curr, cp);
+	}
+	
+	return 0;
+}
+
+
+void cache_free(cache_t *cache)
+{
+	cache_page_t* curr = cache->head;
+	free(cache->cache);
+	while(curr)
+	{
+		cache_page_t * c = curr;
+		curr=curr->next;
+		cache_page_free(c);
+	}
+}
+
+
+
+void cache_get(cache_t* cache, db_time_t start, db_time_t end)
+{
+	
+}
+
+void printcache(cache_page_t* cache)
+{
+	cache_page_t *cp = cache->next;
+	while(cp)
+	{
+		printf("%d ", cp->data);
+		cp=cp->next;
+	}
+	printf("\n");
+}

+ 36 - 0
server/cache.h

@@ -0,0 +1,36 @@
+#ifndef CACHE_H
+#define CACHE_H
+
+#include "db_access.h"
+
+#define CACHE_PAGE_SIZE 65536
+#define CACHE_PAGE_COUNT 256
+
+
+typedef struct cache_page_t cache_page_t;
+
+struct cache_page_t
+{
+	db_interval_t inter;
+	db_data_t* ptr;
+	cache_page_t* next;
+	cache_page_t* prev;
+	int page_size;
+	int data;
+};
+
+
+typedef struct 
+{
+	int page_size;
+	int page_count;
+	db_data_t* cache;
+	cache_page_t* head;
+	cache_page_t* tail;
+} cache_t;
+
+
+int cache_init(cache_t *cache, int page_size_byte, int page_count);
+void cache_free(cache_t *cache);
+
+#endif

+ 193 - 0
server/db.c

@@ -0,0 +1,193 @@
+#include "db.h"
+#include "cache.h"
+#include "db_access.h"
+
+
+off_t _db_index_year(db_t* db, db_date_t d)
+{
+	db_metadata_t* md = db->index.years;
+	int max = db->index.nyears, min=0;
+	int i = max/2;
+	
+	while(1)
+	{
+		if(md[i].date.year==d.year)
+			return md[i].index;
+		else if(d.year>md[i].date.year)
+		{
+			if( max!=min )
+			{
+				min=i+1;
+				i=(max-i)/2+i;
+			}
+			else if(max==db->index.nyears) return db->index.nmonthes;
+			else return 0xffffffff;
+		}
+		else
+		{
+			if( max!=min )
+			{
+				max=i;
+				i=(i-min)/2+min;
+			}
+			else if(!min) return 0;
+			else return 0xffffffff;
+		}
+	}
+}
+
+off_t _db_index_month(db_t* db, db_date_t d, off_t start, off_t len)
+{
+	db_metadata_t* md = db->index.monthes;
+	int max = len, min = 0;
+	int i = max/2;
+	if(min==max) return min;
+	while(1)
+	{
+		if(md[i+start].date.month==d.month)
+			return md[i+start].index;
+		else if(d.month>md[i+start].date.month)
+		{
+			if( max!=min )
+			{
+				min=i+1;
+				i=(max-i)/2+i;
+			}
+			else if(max==len && len+start<db->index.nmonthes) return md[len+start].index;
+			else if(max==len && len+start>=db->index.nmonthes) return db->index.ndays;
+			else return 0xffffffff;
+		}
+		else
+		{
+			if( max!=min )
+			{
+				max=i;
+				i=(i-min)/2+min;
+			}
+			else if(!min) return 0;
+			else return 0xffffffff;
+		}
+	}
+}
+
+
+off_t _db_index_day(db_t* db, db_date_t d, off_t start, off_t len)
+{
+	db_metadata_t* md = db->index.days;
+	int max = len, min=0;
+	int i = max/2;
+	
+	if(min==max) return min;
+	while(1)
+	{
+		if(md[i+start].date.day==d.day)
+			return md[i+start].index;
+		else if(d.day>md[i+start].date.day)
+		{
+			if( max!=min ) 
+			{
+				min=i+1;
+				i=(max-i)/2+i;
+			}
+			else if(max==len && len+start<db->index.ndays) return md[len+start].index;
+			else if(max==len && len+start>=db->index.ndays) return db->index.data_count;
+			else return 0xffffffff;
+		}
+		else
+		{
+			if( max!=min) 
+			{
+				max=i;
+				i=(i-min)/2+min;
+			}
+			else if(!min) return 0;
+			else return 0xffffffff;
+		}
+	}
+}
+
+
+db_interval_t db_inter_get(db_t* db, db_date_t d)
+{
+	db_interval_t inter;
+	db_date_t d2;
+	off_t ys, yl, ms, ml;
+	inter.start=0xFFFFFFFF;
+	inter.len=0xFFFFFFFF;
+	
+	d2=d; 
+	ys=_db_index_year(db, d2);
+	if(ys==0XFFFFFFFF) return inter;
+	d2.year++;
+	yl=_db_index_year(db, d2);
+	if(yl==0XFFFFFFFF) return inter;
+	
+	d2=d; 
+	ms=_db_index_month(db, d2, ys, yl-ys);
+	if(ms==0XFFFFFFFF) return inter;
+	d2.month++;
+	ml=_db_index_month(db, d2, ys, yl-ys);
+	if(ml==0XFFFFFFFF) return inter;
+	
+	d2=d;
+	inter.start=_db_index_day(db, d2, ms, ml-ms);
+	if(inter.start==0XFFFFFFFF) return inter;
+	d2.day++;
+	inter.len=_db_index_day(db, d2, ms, ml-ms)-inter.start;
+	return inter;
+}
+
+
+int  db_init(db_t* db)
+{
+	if(!db) return -1;
+
+	if(db_index_load(&db->index));
+	return 0;
+}
+
+void db_free(db_t* db)
+{
+	if(!db) return;
+	db_index_release(&db->index);
+}
+
+int db_time_cmp( db_time_t* a, db_time_t* b)
+{
+	if(a->date.year > b->date.year) return 1;
+	if(a->date.year < b->date.year) return -1;
+	
+	if(a->date.month > b->date.month) return 1;
+	if(a->date.month < b->date.month) return -1;
+	
+	if(a->date.day > b->date.day) return 1;
+	if(a->date.day < b->date.day) return -1;
+	
+	if(a->millis > b->millis) return 1;
+	if(a->millis < b->millis) return -1;
+	return 0;
+}
+
+
+db_data_set_t* db_get(db_t* db, db_time_t* start, db_time_t* end)
+{
+	db_interval_t s, e, total;
+	s=db_inter_get(db, start->date);
+	e=db_inter_get(db, end->date);
+	total.start=s.start;
+	total.len=e.start+e.len-s.start;
+	
+	return NULL;
+}
+
+int main(int argc, char** argv)
+{
+	cache_t cache;
+	cache_init(&cache, CACHE_PAGE_SIZE, CACHE_PAGE_COUNT);
+	
+	
+	cache_free(&cache);
+}
+
+
+

+ 57 - 0
server/db.h

@@ -0,0 +1,57 @@
+#ifndef DB_H
+#define DB_H
+
+#include "db_access.h"
+#include "cache.h"
+
+typedef struct 
+{
+	db_index_t index;
+} db_t;
+
+
+typedef db_data_interval_t db_data_set_t;
+
+typedef struct 
+{
+	db_time_t start;
+	db_time_t end;
+} db_time_interval_t;
+
+typedef struct 
+{
+	int n;
+	db_time_interval_t data[256]; 
+} db_time_interval_set_t;
+
+db_interval_t db_inter_get(db_t* db, db_date_t d);
+
+/**
+ *  Init (load) database (only metadata)
+ * \param db An allocate db_t object (output)
+ * \return Errno if errors occur else 0
+ */
+int  db_init(db_t* db);
+
+/**
+ *  Free the content of a db_t object
+ * \param db The database
+ */
+void db_free(db_t* db);
+
+
+
+db_data_set_t* db_get(db_t* db, db_time_t* start, db_time_t* end);
+
+/**
+ *  Load an entire data interval from databse
+ * \param db The input database
+ * \param ds The start date
+ * \param dsm The start time (in microseconds)
+ * \param de The end date
+ * \param dem The end time (in microseconds)
+ */
+db_data_interval_t* db_load_fault(db_t* db, db_date_t ds, uint32_t dsm,
+																					 db_date_t de, uint32_t dem);
+
+#endif

+ 361 - 0
server/db_access.c

@@ -0,0 +1,361 @@
+#include "db_access.h"
+#include "db.h"
+#define N_ANNEES 4
+#define N_MONTH 12
+#define N_DAYS 31
+#define N_BY_DAYS (3600*24)
+
+
+
+int  _db_index_load(db_metadata_t** out, off_t *n,  const char* path)
+{
+	int f = open(path, O_RDONLY );
+	if(f<0)
+	{
+		fprintf(stderr, "Error reading '%s' (_db_index_load())", path);
+		perror(" ");
+		*out=NULL;
+		return errno;
+	}
+	*n=lseek(f, 0, SEEK_END)/sizeof(db_metadata_t);
+	*out=malloc(sizeof(db_metadata_t)* (*n));
+	if(!*out)
+	{
+		fprintf(stderr, "Error allocating %ld bytes (_db_index_load())", sizeof(db_metadata_t)*(*n));
+		perror(" ");
+		return errno;
+	}
+	lseek(f,0,SEEK_SET);
+	read(f, *out, sizeof(db_metadata_t)* (*n));
+	close(f);
+	
+	return 0;	
+}
+
+int  db_index_load(db_index_t* out)
+{
+	int fd;
+	if(!out) return -1;
+	if(_db_index_load(&out->days, &out->ndays, "metadata_days")) 		return errno;
+	if(_db_index_load(&out->monthes, &out->nmonthes, "metadata_monthes")) return errno;
+	if(_db_index_load(&out->years, &out->nyears, "metadata_years")) return errno;
+	fd = open("data",  O_RDONLY);
+	if(fd<0)
+	{
+		fprintf(stderr, "Unable to open data file (db_index_load())");
+		perror(" ");
+		return -1;
+	}
+	out->data_count=lseek(fd, 0, SEEK_END)/sizeof(db_data_t);
+	close(fd);	
+	return 0;
+}
+
+void db_index_release(db_index_t* in)
+{
+	if(!in) return;
+	if(in->days) free(in->days);
+	if(in->monthes) free(in->monthes);
+	if(in->years) free(in->years);
+}
+
+db_data_interval_t* db_data_interval_new(uint32_t start, uint32_t len)
+{
+	db_data_interval_t* ret;
+	ret=malloc(sizeof(db_data_interval_t));
+	if(!ret)
+	{
+		fprintf(stderr, "Unable to allocate %ld bytes (db_data_interval_new())", 
+					sizeof(db_data_interval_t));
+		perror(" ");
+		return NULL;
+	}
+	
+	ret->start=start;
+	ret->len=len;
+	ret->data=malloc((ret->len)*sizeof(db_data_t));
+	if(!ret->data)
+	{
+		fprintf(stderr, "Unable to allocate %ld bytes (db_data_interval_new())", 
+					(ret->len)*sizeof(db_data_t));
+		perror(" ");
+		free(ret);
+		return NULL;
+	}
+	
+	return ret;
+}
+
+void 								db_data_interval_free(db_data_interval_t* dbdi)
+{
+	if(!dbdi) return;
+	if(dbdi->data) free(dbdi->data);
+	free(dbdi);
+}
+
+
+uint32_t db_index_get(db_t* db, db_date_t d, uint32_t time, int f)
+{
+	db_interval_t inter;
+	db_data_t *buffer=NULL;
+	off_t size;
+	int i,n;
+	
+	inter = db_inter_get(db, d);
+	if(inter.start==0xFFFFFFFF || inter.len==0xFFFFFFFF) return 0xFFFFFFFF;
+	n=inter.len;
+	
+	buffer = malloc(inter.len*sizeof(db_data_t));
+	if(!buffer)
+	{
+		fprintf(stderr, "Unable to allocate %ld bytes (db_index_get())", inter.len*sizeof(db_data_t));
+		perror(" ");
+		return 0xffffffff;
+	}
+	lseek(f, inter.start*sizeof(db_data_t), SEEK_SET);
+	size=read(f, buffer, sizeof(db_data_t) * inter.len);
+	if(size<inter.len*sizeof(db_data_t))
+	{
+		fprintf(stderr, "Unable to read entire %ld / %ld bytes (db_index_get())", size, inter.len*sizeof(db_data_t));
+		perror(" ");
+		return 0xffffffff;
+	}
+	
+	for(i=0; i<n; i++)
+		if(buffer[i].micros>time) break;
+		
+	free(buffer);
+	i--;
+	if(inter.start==0) return 0;
+	return inter.start+i;
+}
+
+
+
+void write_data()
+{
+	int f = open("data", O_RDWR | O_CREAT, 0777);
+	int i;
+	db_data_t data;
+	data.date.day=1;
+	data.date.month=1;
+	data.date.year=2016;
+	data.micros=0;
+	
+	for(i=0; i<N_ANNEES*N_MONTH*N_DAYS*N_BY_DAYS; i++)
+	{
+		if(data.micros>=N_BY_DAYS*1000)
+		{
+			data.date.day++;
+			data.micros=0;
+			if(data.date.day>N_DAYS)
+			{
+				data.date.day=1;
+				data.date.month++;
+				if(data.date.month>N_MONTH)
+				{
+					data.date.month=1;
+					data.date.year++;
+				}
+			}
+		}
+		write(f, &data, sizeof(db_data_t));
+		
+		data.micros+=1000;
+		//fprintf(f, "%d %d %d : %ld\n", data.date.year, data.date.month, data.date.day, data.micros);
+	}
+	
+	close(f);
+}
+
+void write_day()
+{
+	int f = open("metadata_days", O_RDWR | O_CREAT, 0777 );
+	off_t i;
+	db_metadata_t data;
+	data.date.day=0;
+	data.date.month=1;
+	data.date.year=2016;
+	data.index=0;
+	
+	for(i=0; i<N_ANNEES*N_MONTH*N_DAYS; i++)
+	{
+		data.index=i*N_BY_DAYS;
+		//data.index=i;
+		data.date.day++;
+		if(data.date.day>N_DAYS)
+		{
+			data.date.day=1;
+			data.date.month++;
+			if(data.date.month>N_MONTH)
+			{
+				data.date.month=1;
+				data.date.year++;
+			}
+		}
+		write(f, &data, sizeof(db_metadata_t));
+	}
+	
+	close(f);
+}
+
+void write_month()
+{
+	int f = open("metadata_monthes", O_RDWR | O_CREAT, 0777 );
+	int i;
+	db_metadata_t data;
+	data.date.day=1;
+	data.date.month=0;
+	data.date.year=2016;
+	data.index=0;
+	
+	for(i=0; i<N_MONTH*N_ANNEES; i++)
+	{
+		data.index=i*N_DAYS;
+		
+		data.date.month++;
+		if(data.date.month>N_MONTH)
+		{
+			data.date.month=1;
+			data.date.year++;
+		}
+		write(f, &data, sizeof(db_metadata_t));
+	}
+	
+	close(f);
+}
+
+
+void write_year()
+{
+	int f = open("metadata_years", O_RDWR | O_CREAT, 0777 );
+	int i;
+	db_metadata_t data;
+	data.date.day=1;
+	data.date.month=1;
+	data.date.year=2016-1;
+	data.index=0;
+	
+	for(i=0; i<N_ANNEES; i++)
+	{
+		data.index=i*N_MONTH;
+		data.date.year++;
+		
+		write(f, &data, sizeof(db_metadata_t));
+	}
+	
+	close(f);
+}
+
+
+
+db_data_interval_t* db_load_fault(db_t* db, db_date_t ds, uint32_t dsm,
+																							db_date_t de, uint32_t dem)
+{
+	int f;
+	db_data_interval_t *inter=NULL;
+	uint32_t start, len;
+	off_t size;
+	
+	f=open("data", O_RDONLY | O_LARGEFILE);
+	if(f<0)
+	{
+		fprintf(stderr, "Unable to open 'data' (db_data_load())");
+		perror(" ");
+		return NULL;
+	}
+	start=db_index_get(db, ds, dsm, f);
+	len=db_index_get(db, de, dem, f)-start+1;
+	
+	if(start==0xffffffff || len==0xffffffff)
+	{
+		close(f);
+		return NULL;
+	}
+	
+	inter=db_data_interval_new(start, len);
+	lseek(f, start*sizeof(db_data_t), SEEK_SET);
+	size=read(f, inter->data, sizeof(db_data_t)*(len));
+	if(size<(len)*sizeof(db_data_t))
+	{
+		fprintf(stderr, "Unable to read entire %ld / %ld bytes (db_data_load())",
+							size, (len)*sizeof(db_data_t));
+		perror(" ");
+		return inter;
+	}
+	close(f);
+	return inter;
+}
+
+
+/*
+int main(int argc, char** argv)
+{
+	write_data();
+	write_day();
+	write_month();
+	write_year();
+	db_t db;
+	db_data_interval_t *di;
+	db_date_t ds, de;
+	int i;
+	uint32_t dsm=9999;
+	ds.year=2019; ds.month=12; ds.day=31;
+	de.year=2016; de.month=12; de.day=7;
+	db_init(&db);
+	//di=db_data_load(&db, ds, dsm, de, dsm+100000000);
+	
+	di=db_data_load(&db, ds, dsm, ds, dsm);
+	for(i=0; i<di->len; i++)
+	{
+		printf("%ld : (%.2ld-%.2ld-%.4ld) -> %ld\n", di->start+i
+																				, di->data[i].date.day
+																				, di->data[i].date.month
+																				, di->data[i].date.year
+																				, di->data[i].micros);
+	}
+	free(di->data);
+
+	
+	
+	int a,m,j,ms;
+	for(a=2015; a<2021; a++)
+	{
+		printf("year: %d\n", a);
+		ds.year=a;
+		de.year=a;
+		for(m=1; m<13; m++)
+		{
+			printf("\tmonth: %d\n", m);
+			ds.month=m;
+			de.month=m;
+			for(j=1; j<31; j++)
+			{
+				printf("\t\tday: %d\n", j);
+				ds.day=j;
+				de.day=j+1;
+				
+				for(ms=0; ms<24*3600*1000; ms+=60*1000)
+				{
+					di=db_data_load(&db, ds, dsm, ds, dsm);
+					if(!di)
+					{
+						fprintf(stderr , "Error on (%.2d-%.2d-%.2d : %d)\n", j, m ,a ,ms/1000);
+					}
+					else free(di->data);
+				} 
+				
+				di=db_data_load(&db, ds, dsm, de, dsm);
+				if(!di)
+				{
+					fprintf(stderr , "Error on (%.2d-%.2d-%.2d : %d)\n", j, m ,a ,ms/1000);
+				}
+				else free(di->data);
+				
+			}
+		}
+	}
+	db_free(&db);
+	
+	return 0;
+}*/

+ 79 - 0
server/db_access.h

@@ -0,0 +1,79 @@
+#ifndef DB_ACCESS_H
+#define DB_ACCESS_H
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+
+typedef struct
+{
+	uint16_t year;
+	uint8_t  month;
+	uint8_t  day;
+} db_date_t;
+
+typedef struct 
+{
+	db_date_t date;
+	uint32_t millis;
+}db_time_t;
+
+typedef struct 
+{
+	db_date_t date;
+	uint32_t micros;
+} db_data_t;
+
+typedef struct
+{
+	off_t start;
+	off_t len;
+} db_interval_t;
+
+typedef struct 
+{
+	db_date_t date;
+	off_t index;
+} db_metadata_t;
+
+typedef struct 
+{
+	off_t ndays;
+	db_metadata_t* days;
+	
+	off_t nmonthes;
+	db_metadata_t* monthes;
+	
+	off_t nyears;
+	db_metadata_t* years;
+	
+	off_t data_count;
+} db_index_t;
+
+
+typedef struct 
+{
+	off_t   start;
+	off_t   len;
+	db_data_t* data;
+} db_data_interval_t;
+
+
+
+
+
+
+void db_index_release(db_index_t* in);
+int  db_index_load(db_index_t* out);
+
+void 								db_data_interval_free(db_data_interval_t* dbdi);
+
+
+#endif