backend.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. #include "backend.h"
  2. #include "bus.h"
  3. #ifdef __linux__
  4. #include <signal.h>
  5. #include <errno.h>
  6. #include <unistd.h>
  7. #include <time.h>
  8. #include "config.h"
  9. #include "timer.h"
  10. #include "mount.h"
  11. int data[3]={0};
  12. #include "io.h"
  13. typedef struct
  14. {
  15. uint16_t year;
  16. uint8_t month;
  17. uint8_t day;
  18. } db_date_t;
  19. typedef struct
  20. {
  21. db_date_t date;
  22. off_t index;
  23. } db_metadata_t;
  24. typedef struct
  25. {
  26. db_date_t date;
  27. uint32_t micros;
  28. } db_data_t;
  29. static int need_flush=0;
  30. static pthread_t thread;
  31. int init_data_files(config_t* cfg)
  32. {
  33. char file[256];
  34. FILE* f = NULL;
  35. sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
  36. config_get_string(cfg, "storage.years"));
  37. f=fopen(file, "rb");
  38. if(!f)
  39. {
  40. f=fopen(file, "w+");
  41. if(!f)
  42. {
  43. fprintf(stderr, "Unable to init file '%s' : %s\n", file, strerror(errno));
  44. return -1;
  45. }
  46. }
  47. fclose(f);
  48. sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
  49. config_get_string(cfg, "storage.monthes"));
  50. f=fopen(file, "rb");
  51. if(!f)
  52. {
  53. f=fopen(file, "w+");
  54. if(!f)
  55. {
  56. fprintf(stderr, "Unable to init file '%s' : %s\n", file, strerror(errno));
  57. return -1;
  58. }
  59. }
  60. fclose(f);
  61. sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
  62. config_get_string(cfg, "storage.days"));
  63. f=fopen(file, "rb");
  64. if(!f)
  65. {
  66. f=fopen(file, "w+");
  67. if(!f)
  68. {
  69. fprintf(stderr, "Unable to init file '%s' : %s\n", file, strerror(errno));
  70. return -1;
  71. }
  72. }
  73. fclose(f);
  74. sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
  75. config_get_string(cfg, "storage.data"));
  76. f=fopen(file, "rb");
  77. if(!f)
  78. {
  79. f=fopen(file, "w+");
  80. if(!f)
  81. {
  82. fprintf(stderr, "Unable to init file '%s' : %s\n", file, strerror(errno));
  83. return -1;
  84. }
  85. }
  86. fclose(f);
  87. sprintf(file, "%s", config_get_string(cfg, "cache.file"));
  88. f=fopen(file, "w+");
  89. if(!f)
  90. {
  91. fprintf(stderr, "Unable to init file '%s' : %s\n", file, strerror(errno));
  92. return -1;
  93. }
  94. fclose(f);
  95. return 0;
  96. }
  97. int do_pid_file(config_t* cfg)
  98. {
  99. const char* file = config_get_string(cfg, "misc.pidfile");
  100. FILE* f;
  101. int x;
  102. f=fopen(file, "w+");
  103. if(!f)
  104. {
  105. fprintf(stderr, "Erreur unable to open pid file '%s'\n", file);
  106. perror(" ");
  107. return -1;
  108. }
  109. x=getpid();
  110. fprintf(f, "%d\n", x);
  111. fclose(f);
  112. return 0;
  113. }
  114. void usr1_handler(int signo)
  115. {
  116. if (signo == SIGUSR1)
  117. {
  118. need_flush=1;
  119. }
  120. }
  121. int backend_init(config_t* cfg, bus_t* bus, const char* config)
  122. {
  123. time(NULL);
  124. setup_io();
  125. config_init(cfg, "config.cfg");
  126. config_print(cfg);
  127. if(do_pid_file(cfg)) return -1;
  128. if(init_data_files(cfg)) return -1;
  129. if (signal(SIGUSR1, usr1_handler) == SIG_ERR)
  130. fprintf(stderr, "Error unable to catch signal : %s\n", strerror(errno));
  131. if(config_get_int(cfg, "mount") && !is_mounted(config_get_string(cfg, "mount.dst")))
  132. {
  133. if(mount_samba(cfg))
  134. return -1;
  135. }
  136. bus_init_recv(bus, config_get_int(cfg, "pin.data"),
  137. config_get_int(cfg, "pin.clk"),
  138. config_get_int(cfg, "pin.ack"));
  139. init_read_pin(config_get_int(cfg, "pin.data"),
  140. config_get_int(cfg, "pin.clk"),
  141. config_get_int(cfg, "pin.ack"));
  142. #ifdef ARM
  143. pthread_create(&thread, NULL, bus_recv_thread, &bus);
  144. #endif
  145. return 0;
  146. }
  147. void get_date(uint64_t time, date_t* date)
  148. {
  149. struct tm t;
  150. time_t ti = time;
  151. t=*localtime(&ti);
  152. date->year = t.tm_year+1900;
  153. date->month = t.tm_mon+1;
  154. date->day = t.tm_mday;
  155. date->sec = t.tm_sec + t.tm_min*60 + t.tm_hour*3600;
  156. date->usec = time%1000000;
  157. }
  158. int insert_index_day(config_t *cfg, db_metadata_t* db)
  159. {
  160. char file[256];
  161. sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
  162. config_get_string(cfg, "storage.days"));
  163. FILE* f = fopen(file, "r+");
  164. if(!f)
  165. {
  166. fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en ecriture : %s\n"
  167. , file, strerror(errno));
  168. return -1;
  169. }
  170. fseek(f, 0, SEEK_END);
  171. fwrite(db, sizeof(db_metadata_t), 1, f);
  172. fclose(f);
  173. return 0;
  174. }
  175. int insert_index_month(config_t *cfg, db_metadata_t* _db)
  176. {
  177. char file[256];
  178. FILE* f;
  179. db_metadata_t db = {0};
  180. db.date.year=_db->date.year;
  181. db.date.month=_db->date.month;
  182. db.index=_db->index;
  183. sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
  184. config_get_string(cfg, "storage.monthes"));
  185. f = fopen(file, "r+");
  186. if(!f)
  187. {
  188. fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en ecriture : %s\n"
  189. , file, strerror(errno));
  190. return -1;
  191. }
  192. fseek(f, 0, SEEK_END);
  193. fwrite(&db, sizeof(db_metadata_t), 1, f);
  194. fclose(f);
  195. return 0;
  196. }
  197. int insert_index_year(config_t *cfg, db_metadata_t* _db)
  198. {
  199. char file[256];
  200. FILE* f;
  201. db_metadata_t db = {0};
  202. db.date.year=_db->date.year;
  203. db.index=_db->index;
  204. sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
  205. config_get_string(cfg, "storage.years"));
  206. f = fopen(file, "r+");
  207. if(!f)
  208. {
  209. fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en ecriture : %s\n"
  210. , file, strerror(errno));
  211. return -1;
  212. }
  213. fseek(f, 0, SEEK_END);
  214. fwrite(&db, sizeof(db_metadata_t), 1, f);
  215. fclose(f);
  216. return 0;
  217. }
  218. int get_last_index_date(config_t* cfg, db_data_t* md, off_t* iy, off_t* im, off_t* id)
  219. {
  220. FILE* f;
  221. char file[256];
  222. md->micros=0;
  223. md->date.year=md->date.month=md->date.day=0;
  224. //data
  225. sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
  226. config_get_string(cfg, "storage.data"));
  227. f=fopen(file, "rb");
  228. if(!f)
  229. {
  230. fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en lecture : %s\n"
  231. , file, strerror(errno));
  232. return -1;
  233. }
  234. fseek(f, -sizeof(db_data_t), SEEK_END);
  235. fread(md, sizeof(db_data_t), 1, f);
  236. fclose(f);
  237. //index Year
  238. sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
  239. config_get_string(cfg, "storage.years"));
  240. f=fopen(file, "rb");
  241. if(!f)
  242. {
  243. fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en lecture : %s\n"
  244. , file, strerror(errno));
  245. return -1;
  246. }
  247. fseek(f, 0, SEEK_END);
  248. *im = ftell(f) / sizeof(db_metadata_t);
  249. fclose(f);
  250. //index month
  251. sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
  252. config_get_string(cfg, "storage.monthes"));
  253. f=fopen(file, "rb");
  254. if(!f)
  255. {
  256. fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en lecture : %s\n"
  257. , file, strerror(errno));
  258. return -1;
  259. }
  260. fseek(f,0, SEEK_END);
  261. *im = ftell(f) / sizeof(db_metadata_t);
  262. fclose(f);
  263. //index day
  264. sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
  265. config_get_string(cfg, "storage.days"));
  266. f=fopen(file, "rb");
  267. if(!f)
  268. {
  269. fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en lecture : %s\n"
  270. , file, strerror(errno));
  271. return -1;
  272. }
  273. fseek(f, 0, SEEK_END);
  274. *id = ftell(f) / sizeof(db_metadata_t);
  275. fclose(f);
  276. return 0;
  277. }
  278. int backend_flush(config_t* cfg)
  279. {
  280. db_data_t curr, last;
  281. off_t indexY, indexM, indexDay, indexData;
  282. char file[256];
  283. sprintf(file, "%s/%s", config_get_string(cfg, "storage.location"),
  284. config_get_string(cfg, "storage.data"));
  285. get_last_index_date(cfg, &last, &indexY, &indexM, &indexDay);
  286. FILE* f = fopen(file, "wb");
  287. if(!f)
  288. {
  289. fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en lecture : %s\n"
  290. , file, strerror(errno));
  291. return -1;
  292. }
  293. fseek(f, 0, SEEK_END);
  294. indexData=ftell(f)/sizeof(db_data_t);
  295. FILE* in = fopen(config_get_string(cfg, "cache.file"), "rb");
  296. if(!in)
  297. {
  298. fprintf(stderr, "Erreur impossible d'ouvrir le fichier '%s' en lecture : %s\n"
  299. , config_get_string(cfg, "cache.file"), strerror(errno));
  300. return -1;
  301. }
  302. while( (fread(&curr, sizeof(db_data_t), 1, in))>0 )
  303. {
  304. if(curr.date.day != last.date.day)
  305. {
  306. db_metadata_t t={0};
  307. t.date=curr.date;
  308. t.index=indexData;
  309. indexDay++;
  310. insert_index_day(cfg, &t);
  311. last.date.day=curr.date.day;
  312. }
  313. if(curr.date.month != last.date.month)
  314. {
  315. db_metadata_t t={0};
  316. t.date.year=curr.date.year;
  317. t.date.month=curr.date.month;
  318. t.index=indexDay-1;
  319. indexM++;
  320. insert_index_month(cfg, &t);
  321. last.date.month=curr.date.month;
  322. }
  323. if(curr.date.year != last.date.year)
  324. {
  325. db_metadata_t t={0};
  326. t.date.year=curr.date.year;
  327. t.index=indexM-1;
  328. indexY++;
  329. insert_index_year(cfg, &t);
  330. last.date.year=curr.date.year;
  331. }
  332. fwrite(&curr, sizeof(db_data_t), 1, f);
  333. indexData++;
  334. }
  335. fprintf(stderr, "Sortie: %s\n", strerror(errno) );
  336. fclose(f);
  337. fclose(in);
  338. f = fopen(config_get_string(cfg, "cache.file"), "w+");
  339. fclose(f);
  340. return 0;
  341. }
  342. void backend_insert(config_t* cfg, uint64_t c)
  343. {
  344. db_data_t d;
  345. date_t dd;
  346. FILE* f = fopen(config_get_string(cfg, "cache.file"), "r+");
  347. if(!f)
  348. {
  349. fprintf(stderr, "Cant open cache file '%s' : %s\n", config_get_string(cfg, "cache.file"), strerror(errno));
  350. return;
  351. }
  352. get_date(c, &dd);
  353. d.date.year=dd.year;
  354. d.date.month=dd.month;
  355. d.date.day=dd.day;
  356. d.micros=dd.sec*1000 + dd.usec/1000;
  357. //printf("Insert: %d-%d-%d : %d:%d:%d.%d \n", dd.year, dd.month, dd.day, d.micros/3600000, (d.micros%3600000)/60000, d.micros%60000/1000, d.micros%1000);
  358. fseek(f, 0, SEEK_END);
  359. fwrite(&d, sizeof(db_data_t), 1, f);
  360. fclose(f);
  361. }
  362. void backend_loop(config_t* cfg, bus_t* bus)
  363. {
  364. uint64_t interval = config_get_int(cfg, "cache.flush_interval");
  365. uint64_t last_flush = get_time_us()/1000000, current;
  366. int i=0, n=(28*12*2)*100;
  367. while(1)
  368. {
  369. uint32_t c;
  370. current=get_time_us()/1000000;
  371. if(current>= interval +last_flush || need_flush || i==n)
  372. {
  373. printf("Flushing\n");
  374. last_flush=current;
  375. backend_flush(cfg);
  376. need_flush=0;
  377. if(i==n) return;
  378. }
  379. bus_read(bus, &c, 4);
  380. backend_insert(cfg, c);
  381. i++;
  382. }
  383. return;
  384. }
  385. #endif