Prototype d'analyseur de log nfcapd, pour un reporting quotidien, et détermination de saturations sur les liens IP.

main.cpp 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. /// Main du parser/statistik-maker du projet YaPLog
  2. #include "main.hpp"
  3. /**
  4. * \brief Fonction principale.
  5. * Initialise les mutexes. Lance les threads. Attends la fin d'exécution.
  6. * \param int argc : nombre de paramètres (4), char* argv[] : liste de paramètres
  7. * \throws None
  8. * \return int : 0 <=> EXIT_SUCCESS, 1 <=> EXIT_FAILURE
  9. */
  10. int main(int argc, char **argv)
  11. {
  12. //std::vector<std::string> hm = genHourMin();
  13. std::string nomFic = argv[2]; //* nom des fichiers à lire */ nomFic += hm[64]; // "1600"... suffixes.
  14. std::cout << "nb de CPU/cœurs détectés : " << std::thread::hardware_concurrency() << std::endl;
  15. if (argc < 5) // program needs: -number of threads to launch, and -file, -no site. -OutFile
  16. {
  17. std::cerr << "\e[33m" << "usage :" << "\e[0m" <<
  18. " ./graphEchantTabl <nombre (pair de préférence) de threads> </path/file> <nosite> <outfile>"
  19. << '\n';
  20. std::cerr << "\e[32m" << "exemple :" << "\e[0m" <<
  21. " ./graphEchantTabl 4 /home/administrateur/archive/ascii_nfcapd.1745 110" <<
  22. " /home/administrateur/ex_res.csv" << std::endl;
  23. exit(1); // EXIT_FAILURE
  24. }
  25. int nbWorkerThread;// = atoi(argv[1]); // param -> int
  26. try
  27. {
  28. std::string tmparg1 = argv[1];
  29. nbWorkerThread = std::stoi(tmparg1);
  30. }
  31. catch (std::exception const & e)
  32. {
  33. std::cerr << "\e[32m" << "Parse 1st argument error" << "\e[0m" << std::endl;
  34. exit(1);
  35. }
  36. NomFicOut = argv[4]; // nom du fichier où écrire
  37. // au moins 1 worker, pas plus de 16 (!), optimal : nombre de CPU/cœurs, probablement 2 ou 4.
  38. if (nbWorkerThread < 1 || nbWorkerThread > 32)
  39. {
  40. // EINVAL 22 /* Invalid argument */, /usr/include/asm-generic/errno-base.h
  41. errno = 22; perror("nombre de threads invalide");
  42. std::cerr << "\e[33m" << "nbWorkerThread =" << "\e[0m" << " " << nbWorkerThread << std::endl;
  43. exit(1);
  44. }
  45. if (nbWorkerThread%2 != 0) // si nombre impair
  46. {
  47. std::cerr << "\e[33m" << "Attention" << "\e[0m" <<
  48. ", selon l'architecture choisie, il n'est pas évident qu'un nombre impair " <<
  49. "de threads soit optimal" << std::endl;
  50. // cf. speedtests :
  51. // passage 1 -> 2 CPU : gain *3.37
  52. // passage 2 -> 3 CPU : gain *1.12
  53. // passage 3 -> 4 CPU : gain *1.67
  54. }
  55. // le fichier passé en paramètres existe-t-il ?
  56. if (!couldFindFile(nomFic))
  57. {
  58. std::cerr << "\e[33m" << "Erreur :" << "\e[0m" << " fichier introuvable." << std::endl;
  59. exit(1);
  60. }
  61. nomSite += argv[3]; // global variable which holds site reference name.
  62. // initialize mutexes & verify status : ok/nok?
  63. if(int mutinitfq = pthread_mutex_init(&fileQmutex, NULL)) //
  64. {
  65. error(1, mutinitfq, "could not initialize mutex fileQmutex"); // EXIT_FAILURE
  66. }
  67. if(int mutinitres = pthread_mutex_init(&resQTmutex, NULL))
  68. {
  69. error(1, mutinitres, "could not initialize mutex resQTmutex"); // EXIT_FAILURE
  70. }
  71. if(int mutinitres = pthread_mutex_init(&resQDmutex, NULL))
  72. {
  73. error(1, mutinitres, "could not initialize mutex resQDmutex"); // EXIT_FAILURE
  74. }
  75. // declare 2 threads + pool of threads.
  76. std::vector<pthread_t> lswk; // list/pool of workers
  77. pthread_t tr, tw; // read, "write"
  78. int rclswk; // status du pool de threads.
  79. int rctr, rctw; // status du lancement des thread : ok/nok
  80. // lancement des threads
  81. rctr = pthread_create(&tr, NULL, thread_lecture, argv[2]); // crée threads lecteur
  82. if (rctr) // vérification que le thread lecteur est lancé
  83. {
  84. error(1, rctr, "pthread_create : lecture"); // le thread lecture pas lancé
  85. }
  86. for (int i=0;i<nbWorkerThread;i++) // crée pool de thread
  87. {
  88. pthread_t tmp; // descripteur de thread temporaire qui va être remplacé par lswk[..]
  89. void* numeroThread = calloc(1, sizeof(int)); // allouer un int
  90. numeroThread = memcpy(numeroThread, (void*) &i, (size_t) 4); // copie i dans numeroThread
  91. // lance le thread, rclswk est le résultat du lancement, threadworker est la fonction,
  92. // tmp est le thread (va dans la liste), numeroThread le n° du thread :
  93. rclswk = pthread_create(&tmp, NULL, threadworker, numeroThread);
  94. lswk.push_back(tmp); // tmp --> lswk[..]
  95. if (rclswk) // vérification que les threads workers sont lancés
  96. {
  97. std::string msg = "pthread_create : failed to create worker n°";
  98. std::stringstream ss; ss << i; msg += ss.str(); // msg += str(n° process)
  99. error(1, rclswk, msg.c_str()); // le thread worker-n pas lancé // 1 <=> EXIT_FAILURE
  100. }
  101. std::cout << "thread n°" << i << " lancé." << std::endl;
  102. }
  103. std::cout << ".............................main()..............................." << std::endl;
  104. rctr = pthread_join(tr, NULL); // attente thread lecture
  105. if (rctr) // vérification que le thread lecteur est bien arrêté
  106. {
  107. error(1, rctr, "pthread_join : lecture"); // le thread lecture pas arrêté
  108. }
  109. for (unsigned int i=0;i<lswk.size();i++) // attente du pool de workers
  110. {
  111. rclswk = pthread_join(lswk.at(i), NULL);
  112. if (rclswk)
  113. {
  114. std::string msg = "pthread_join : worker ";
  115. std::stringstream ss; ss << i; msg += ss.str(); // msg += str(n° process)
  116. error(1, rclswk, msg.c_str()); // le thread worker-n pas arrêté // 1 <=> EXIT_FAILURE
  117. }
  118. } // fins des threads lecture et workers
  119. rctw = pthread_create(&tw, NULL, threadwrite, NULL); // lancement du thread writer
  120. if (rctw) // vérification que le thread écrivain est bien lancé
  121. {
  122. error(1, rctw, "pthread_create : écriture"); // le thread écriture pas lancé
  123. }
  124. rctw = pthread_join(tw, NULL); // attente terminaison du writer
  125. if (rctw) // vérification que le thread écrivain est bien arrêté
  126. {
  127. error(1, rctw, "pthread_join : écriture"); // le thread écriture pas arrêté
  128. }
  129. std::cout << "fin du main" << std::endl;
  130. return 0;
  131. }
  132. ////////////////////////////////////////////////////////////////////////////////////////////////////
  133. /**
  134. * \brief thread lecteur.
  135. * lit le fichier en entrée et le charge 100 000 entrées dans une queue.
  136. * \param (char*) (void*) nom du fichier à lire
  137. * \throws None
  138. * \return None. pthread_exit(NULL);
  139. */
  140. void* thread_lecture(void* args)
  141. {
  142. std::cout << "début du thread de lecture" << '\n';
  143. //struct timespec sleeptime; sleeptime.tv_sec = 0; sleeptime.tv_nsec = NBLN/100; // fct nb ln à traiter.
  144. // we know args is (char*), call with argv[2]. Mandatory cast from (void*) with -Werror=conversion
  145. std::ifstream infile((char*) args, std::ios_base::in);
  146. int lockFile; // résultat de la prise de mutex. status : ok/nok ?
  147. std::string ligne; // là on lit infile avec getline
  148. // std::cout << args << std::endl; // ptrfic
  149. // std::cout << "blablablablablablablablablablablablablablabla" << (char*) args << std::endl; // nomfic
  150. while (!endoffile)
  151. {
  152. //std::cout << "1" << '\n';
  153. if ((lockFile = pthread_mutex_lock(&fileQmutex))) // lock error // assignation ! => (())
  154. {
  155. // 1 <=> EXIT_FAILURE
  156. error(1, lockFile, "thread_lecture : could not get lock properly");
  157. }
  158. //std::cout << "2" << '\n';
  159. while (fileQ.size() < NBLN)
  160. {
  161. //std::cout << "3" << '\n';
  162. //while (getline(infile, ligne, '\n')) // lire tout d'un coup, moins rapide.
  163. while (getline(infile, ligne, '\n') && fileQ.size() < NBLN) // lire 100 000 lignes.
  164. {
  165. //std::cout << "9" << '\n';
  166. fileQ.push(ligne);
  167. std::cout << fileQ.size() << '\n';
  168. }
  169. if (infile.eof()) // end of file ----
  170. {
  171. endoffile = true; // sortir du while (!endoffile)
  172. break; // sortir du while (fileQ.size() < SIZE)
  173. }
  174. }
  175. // end of file ----
  176. //std::cout << "4" << '\n';
  177. // nanosleep(&sleeptime, NULL); // mettre le lecteur en pause n'accélère pas.
  178. if ((lockFile = pthread_mutex_unlock(&fileQmutex)))
  179. {
  180. // 1 <=> EXIT_FAILURE
  181. error(1, lockFile, "thread_lecture : could not release lock properly");
  182. }
  183. //std::cout << "5" << '\n';
  184. //std::cin.ignore(); // ???
  185. }
  186. infile.close();
  187. std::cout << "fin du thread de lecture" << std::endl;
  188. // end thread.
  189. pthread_exit(NULL);
  190. }
  191. /**
  192. * \brief thread travailleur.
  193. * \param (int) (void*) args : numéro du worker
  194. * \throws None
  195. * \return None. pthread_exit(NULL);
  196. */
  197. void* threadworker(void* args)
  198. {
  199. int idth = *(int*) args; // args est un int : numéro du worker, 0..15
  200. free(args); // calloc(1, sizeof(int))
  201. std::cout << "début du thread de travail " << idth << "." << '\n';
  202. // attendre, au début la fileQ est vide, et on prendrait/relâcherait plusieurs fois un lock.
  203. struct timespec sleeptime;
  204. sleeptime.tv_sec = 0;
  205. sleeptime.tv_nsec = NBLN*1000; // fonction du nombre de lignes initial à traiter.
  206. nanosleep(&sleeptime, NULL); // attente "sleeptime"
  207. const std::regex rgx("(\\d{4}[-]\\d{2}[-]\\d{2})(;)\
  208. (\\d{2}[:]\\d{2}[:]\\d{2})([.])(\\d{3})(;)(\\d+[.]\\d{3})(;)\
  209. ([A-Z0-9]+)(;)(\\d{1,3}[.]\\d{1,3}[.]\\d{1,3}[.]\\d{1,3})([:])([0-9]{1,5})(([.]\\d+)?)(;;)\
  210. (\\d{1,3}[.]\\d{1,3}[.]\\d{1,3}[.]\\d{1,3})([:])([0-9]{1,5})(([.]\\d+)?)(;)(\\d+)(;)\
  211. (\\d+)(;)(1)");
  212. std::smatch regsrxmatch;
  213. std::vector<Traffic>* lsTraf = new std::vector<Traffic>(); // SELECT Packet WHERE ip/port IS ...
  214. Data* myData = new Data(); // journée échantillonnée
  215. std::cout << "fin d'attente " << '\n';
  216. std::regex regPtclSiteStr;
  217. std::smatch matchPtclSiteIp;
  218. try
  219. {
  220. regPtclSiteStr = site2ipsubnet(nomSite, "/home/administrateur/site2ip.csv");
  221. }
  222. catch(std::exception const& sece)
  223. {
  224. std::cerr << "site2ipsubnet() : " << sece.what() << "\e[33m " << nomSite << " \e[0m" << std::endl;
  225. exit(1);
  226. }
  227. catch(...)
  228. {
  229. std::cerr << "default site2ipsubnet()..." << std::endl;
  230. exit(1);
  231. }
  232. do
  233. {
  234. int lockFile;
  235. std::string ligne;
  236. while (fileQ.size() > 0)
  237. {
  238. // attente pour la lecture non-concurrente de fileQ
  239. if ((lockFile = pthread_mutex_lock(&fileQmutex))) // lock error // assignation ! => (())
  240. {
  241. error(1, lockFile, "threadworker : could not get lock properly"); // EXIT_FAILURE
  242. }
  243. if (fileQ.size() > 0) // récupérer et vire la plus vieille entrée de la queue si non vide
  244. {
  245. ligne = fileQ.front(); // récupérer la plus vieille entrée de la file dans la ligne
  246. fileQ.pop(); // supprime la plus vieille entrée
  247. }
  248. else
  249. {
  250. std::cerr << "\e[33m" << "erreur imprévue" << "\e[0m" << '\n';
  251. }
  252. // relaxe du verrou
  253. if ((lockFile = pthread_mutex_unlock(&fileQmutex))) // lock error // assignation ! (())
  254. {
  255. error(1, lockFile, "threadworker : could not release lock properly");
  256. } // travail, rendre le mutex le plus vite possible => travail après la relaxe
  257. ///
  258. std::string ipdst;
  259. if (regex_search(ligne, regsrxmatch, rgx))
  260. {
  261. ipdst = regsrxmatch[17]; // 11 : src, 17 : dst
  262. if (regex_search(ipdst, matchPtclSiteIp, regPtclSiteStr))
  263. {
  264. // Packet(int timestamp, int duration,
  265. // std::string ipsrc, std::string ipdst,
  266. // uint16_t srcport, uint16_t dstport, int taille);
  267. std::cout << idth;
  268. //std::cout << "DEBUG1 : " << date2epoch(regsrxmatch[3], regsrxmatch[5]) << '\n';
  269. //std::cout << "DEBUG2 : " << stoi(regsrxmatch[25]) << '\n';
  270. //std::cin.ignore();
  271. Packet* curPaq =
  272. new Packet(date2epoch(regsrxmatch[3], regsrxmatch[5]),
  273. stoi(regsrxmatch[7]), regsrxmatch[11], regsrxmatch[17],
  274. (uint16_t) stoi(regsrxmatch[13]), (uint16_t) stoi(regsrxmatch[19]),
  275. stoi(regsrxmatch[25]));
  276. /// makeDataTraffic(Packet* pq, Data* dt, std::vector<Traffic>* lstf)
  277. makeDataTraffic(curPaq, myData, lsTraf); // trois pointeurs passés, non const.
  278. //~ delete curPaq; // job de la fonction fille makeDataTraffic()
  279. }
  280. else
  281. {
  282. std::cerr << "\e[33m" << "Destination invalide." << "\e[0m" << " : " <<
  283. ligne << " does not match : " <<
  284. site2ipsubnet(nomSite, "/home/administrateur/site2ip.csv") <<
  285. ", got : " << regsrxmatch[17] << '\n';
  286. }
  287. }
  288. else
  289. {
  290. std::cerr << "\e[33m" << "Ligne invalide." << "\e[0m" << " : " << ligne << '\n';
  291. }
  292. /// // fin travail
  293. }
  294. } while (endoffile == false || fileQ.size() != 0);
  295. std::cout << " fin fic " << endoffile << " fic taille " << fileQ.size() << '\n';
  296. // on passe au thread finaliseur // prise du mutex, et test ok.
  297. if (int lockQTraf = pthread_mutex_lock(&resQTmutex)) // lock Traffic mutex
  298. {
  299. // EXIT_FAILURE
  300. std::string tmpmsg = "threadworker n°";
  301. std::stringstream ss; ss << idth; tmpmsg += ss.str();
  302. tmpmsg += " : could not get lock properly for Traffic";
  303. error(1, lockQTraf, tmpmsg.c_str());
  304. }
  305. resQT.push_back(lsTraf); // append std::vector<Traffic>*
  306. if (int unlockQTraf = pthread_mutex_unlock(&resQTmutex)) // relaxe du mutex, et test ok
  307. {
  308. std::string tmpmsg = "threadworker n°";
  309. std::stringstream ss; ss << idth; tmpmsg += ss.str();
  310. tmpmsg += " : could not release lock properly for Traffic";
  311. error(1, unlockQTraf, tmpmsg.c_str()); // unlock error // EXIT_FAILURE
  312. }
  313. if (int lockQDraf = pthread_mutex_lock(&resQDmutex)) // lock Data mutex
  314. {
  315. std::string tmpmsg = "threadworker n°";
  316. std::stringstream ss; ss << idth; tmpmsg += ss.str();
  317. tmpmsg += " : could not get lock properly for Data";
  318. error(1, lockQDraf, tmpmsg.c_str()); // lock error, EXIT_FAILURE
  319. }
  320. resQD.push_back(myData); // append Data*
  321. if (int unlockQDraf = pthread_mutex_unlock(&resQDmutex)) // relaxe du mutex, et test ok
  322. {
  323. std::string tmpmsg = "threadworker n°";
  324. std::stringstream ss; ss << idth; tmpmsg += ss.str();
  325. tmpmsg += " : could not release lock properly for Data";
  326. error(1, unlockQDraf, tmpmsg.c_str()); // lock error, EXIT_FAILURE
  327. }
  328. // fin du thread
  329. std::cout << "je suis le thread n°" << idth << " et mon v est de taille : " << lsTraf->size() << std::endl;
  330. pthread_exit(NULL); // fin du thread.
  331. }
  332. /**
  333. * \brief thread écrivain. finalise le traitement de la donnée
  334. * Somme les Data. appelle moyData() / sma() pour moyenner
  335. * \param None. "args" obligatoire pour une fonction de thread POSIX, non utilisée
  336. * \throws None
  337. * \return None. pthread_exit(NULL);
  338. */
  339. void* threadwrite(void* args)
  340. {
  341. std::cout << "début du thread d'écriture" << '\n';
  342. // free/delete
  343. /// Traffic()
  344. std::cout << "taille de resQT : " << resQT.size() << '\n';
  345. for (unsigned int i=0;i<resQT.size();i++)
  346. {
  347. //for (unsigned int j=0;j<resQT.at(i)->size();j++)
  348. {
  349. std::cout << "Attempting to free Traffic n°" << i << '\n'; // << ", " << j << '\n';
  350. //std::vector<std::vector<Traffic>*> onomnomnom;
  351. //resQT.at(i)->at(j).toString();
  352. //delete &(resQT.at(i)->at(j));
  353. //delete &(resQT.at(i));
  354. }
  355. }
  356. /// Data
  357. Data* resval = new Data();
  358. for (unsigned int i=0;i<resQD.size();i++)
  359. {
  360. for (unsigned int temps=0;temps<resQD.at(i)->getTaille();temps++)
  361. {
  362. resval->add2traffic(resQD.at(i)->getTrafficAt(temps), temps);
  363. }
  364. std::cout << "Attempting to free Data n°" << i << '\n';
  365. //resQD.at(i)->toString();
  366. //resQD.at(i)->writeout();
  367. std::cin.ignore();
  368. delete resQD.at(i);
  369. }
  370. std::cin.ignore(); //
  371. //~moyData(resval); // moyenne + écriture
  372. sma(resval);
  373. //resval->writeout(); // écriture des données.
  374. //
  375. std::cout << "fin du thread d'écriture" << std::endl;
  376. pthread_exit(NULL);
  377. }
  378. ////////////////////////////////////////////////////////////////////////////////////////////////////
  379. inline bool couldFindFile (const std::string& name)
  380. {
  381. struct stat buffer;
  382. return (stat (name.c_str(), &buffer) == 0);
  383. }
  384. /**
  385. * \brief (hh:mm:ss, ms) --> cs
  386. * horodatage en centisecondes.
  387. * \param string "hh:mm:ss", string "ms"
  388. * \throws None
  389. * \return int cs
  390. */
  391. int date2epoch(std::string h, std::string ms)
  392. {
  393. int res = -1;
  394. const std::regex rgxh("(\\d{2})([:])(\\d{2})([:])(\\d{2})");
  395. std::smatch regsrxmatch;
  396. //const std::regex rgxms("(\d{3})");
  397. if (regex_search(h, regsrxmatch, rgxh))
  398. {
  399. res = stoi(regsrxmatch[1])*3600*ECH // heure -> ech
  400. + stoi(regsrxmatch[3])*60*ECH // min
  401. + stoi(regsrxmatch[5])*ECH // s
  402. + static_cast<int>((ECH)*stof(ms)/(1000)); // ms -> ech
  403. }
  404. return res;
  405. }
  406. /**
  407. * \brief Range un Packet dans un Data (et potentiellement un Traffic)
  408. * \param Packet*, Data*, vector<Traffic>
  409. * \throws None
  410. * \return bool : true si ok.
  411. */
  412. bool makeDataTraffic(Packet* pq, Data* dt, std::vector<Traffic>* lstf)
  413. {
  414. /*
  415. /// Traffic()
  416. //std::cout << "entrée dans le SIGSEGV" << std::endl;
  417. bool pqRangeDansTraf = false; // a-t-on rangé le paquet dans un des traffics existants ?
  418. //std::cin.ignore();
  419. //std::cout << lstf->size() << std::endl;
  420. //std::cin.ignore();
  421. if (lstf->size() != 0)
  422. {
  423. for (unsigned int i=0;i<lstf->size();i++)
  424. {
  425. //std::cout << "boucle 1" << std::endl;
  426. if (lstf->at(i).getIP() == pq->getIPsrc())
  427. {
  428. lstf->at(i).add2taille(pq->getTaille());
  429. pqRangeDansTraf = true;
  430. break; // unicité des trafics, inutile de continuer le for
  431. }
  432. }
  433. }
  434. else
  435. {
  436. __asm__("nop");
  437. }
  438. if (!pqRangeDansTraf)
  439. {
  440. Traffic* tmpTraf = new Traffic();
  441. tmpTraf->setIP(pq->getIPsrc());
  442. lstf->push_back(*tmpTraf);
  443. }
  444. */
  445. /// Data()
  446. dt->traiterPaquet(pq);
  447. //std::cout << "coutNotNull() : " ;
  448. //dt->coutNotNull();
  449. //std::cout << " ; fin coutNotNull()" << '\n';
  450. ///
  451. delete pq; // Enfant free()/delete
  452. return true;
  453. }
  454. /**
  455. * \brief Réalise la moyenne à partir d'une instance Data
  456. * journée échantillonnée --> moyennée.
  457. * \param Data* vecData
  458. * \throws None
  459. * \return bool : true si ok.
  460. */
  461. bool moyData(Data* vData)
  462. {
  463. std::cout << "début de moyData" << '\n';
  464. // déclaration
  465. std::vector<int> resval; // [0, 0, ..., 0], 86 400 fois
  466. resval.reserve(86'400); //'// vecteur de secondes => taille connue
  467. // initialisation
  468. for (unsigned int i=0;i<86'400;i++)//'// 86 400 valeurs
  469. {
  470. resval.push_back(0);
  471. }
  472. std::cout << "Fin initialisation" << '\n';
  473. // travail
  474. for (unsigned int i=0;i<86'400;i++) //' // 86 400s
  475. {
  476. int somme = 0;
  477. for (unsigned int j=0;j<ECH;j++)
  478. {
  479. somme += vData->getTrafficAt(i*ECH + j);
  480. }
  481. resval.at(i) = somme;
  482. }
  483. std::cout << "Fin travail" << '\n';
  484. // écriture
  485. std::ofstream outfile("/tmp/bargraph.csv", std::ios_base::out);
  486. std::stringstream ss;
  487. for (unsigned int i=0;i<86'400;i++) //'//
  488. {
  489. ss << resval.at(i);
  490. ss << '\n';
  491. }
  492. outfile << ss.str();
  493. outfile.close();
  494. std::cout << "Fin écriture" << '\n';
  495. return true;
  496. }
  497. /**
  498. * \brief Réalise une moyenne Simple Moving Average à partir d'une instance Data
  499. * journée échantillonnée --> moyennée.
  500. * \param Data* vecData
  501. * \throws None
  502. * \return bool : true si ok.
  503. */
  504. bool sma(Data* vData)
  505. {
  506. // https://en.wikipedia.org/wiki/Moving_average
  507. std::cout << "début de moyData" << '\n';
  508. // déclaration
  509. //std::vector<int> resval; // [0, 0, ..., 0], 86 400 fois
  510. std::vector<uint64_t> resval; // [0, 0, ..., 0], 86 400 fois
  511. resval.reserve(86'400); //'// vecteur de secondes => taille connue
  512. // initialisation
  513. for (unsigned int i=0;i<86'400;i++)//'// 86 400 valeurs
  514. {
  515. resval.push_back((uint64_t) 0);
  516. }
  517. std::cout << "Fin initialisation" << '\n';
  518. // travail
  519. ///
  520. /*
  521. int pas = 30; // moyenne sur 10 (?) secondes, échantillonnage centiseconde
  522. int somme = 0; // init 0;
  523. std::queue<int> movAvgQ;
  524. for (int i=0;i<pas*ECH;i++) // taille de la queue : pas*ECH. 10s
  525. {
  526. movAvgQ.push(vData->getTrafficAt(i));
  527. somme += movAvgQ.back(); // <=> somme += vData->getTrafficAt(i);
  528. }
  529. for (int i=0;i<ECH*86'400;i++) //'// 1234 -> 2345 -> 3456 -> 4567 -> 5678 -> 6789 -> 789 -> 89 -> 9
  530. {
  531. if (i%ECH == 0) //
  532. {
  533. resval.at(i/ECH) = somme*pas/ECH;
  534. }
  535. somme -= movAvgQ.front(); // <=> somme -= vData->getTrafficAt(...);
  536. movAvgQ.pop(); // pop front
  537. if (i<ECH*86'400-pas*ECH)
  538. {
  539. movAvgQ.push(vData->getTrafficAt(i)); // push back
  540. somme += movAvgQ.back(); // <=> somme += vData->getTrafficAt(i);
  541. }
  542. }
  543. */
  544. ///
  545. int pas = 30; // moyenne sur 10 (?) secondes, échantillonnage centiseconde
  546. uint64_t somme = 0; // init 0;
  547. std::queue<uint64_t> movAvgQ;
  548. for (int i=0;i<pas*ECH;i++) // taille de la queue : pas*ECH. 10s
  549. {
  550. movAvgQ.push((uint64_t) vData->getTrafficAt(i));
  551. somme += movAvgQ.back(); // <=> somme += vData->getTrafficAt(i);
  552. }
  553. for (int i=0;i<ECH*86'400;i++) //'// 1234 -> 2345 -> 3456 -> 4567 -> 5678 -> 6789 -> 789 -> 89 -> 9
  554. {
  555. if (i%ECH == 0) //
  556. {
  557. //resval.at(i/ECH) = somme/pas/ECH; // moy faite sur pas*ECH
  558. resval.at(i/ECH) = somme/pas; // moy faite sur pas
  559. }
  560. somme -= movAvgQ.front(); // <=> somme -= vData->getTrafficAt(...);
  561. movAvgQ.pop(); // pop front
  562. if (i<ECH*86'400-pas*ECH)
  563. {
  564. movAvgQ.push((uint64_t) vData->getTrafficAt(i)); // push back
  565. somme += movAvgQ.back(); // <=> somme += vData->getTrafficAt(i);
  566. }
  567. }
  568. ///
  569. std::cout << "Fin travail" << '\n';
  570. // écriture
  571. std::ofstream outfile(NomFicOut, std::ios_base::out);
  572. std::stringstream ss;
  573. for (unsigned int i=0;i<86'400;i++) //'//
  574. {
  575. ss << resval.at(i);
  576. ss << '\n';
  577. }
  578. outfile << ss.str();
  579. outfile.close();
  580. std::cout << "Fin écriture" << '\n';
  581. return true;
  582. }