Line data Source code
1 : #include "../inc/header.h"
2 : #include "../inc/param_manager.h"
3 : #include "../inc/global_param.h"
4 : #include "../inc/utils.h"
5 : #include "../inc/query_manager.h"
6 : #include "../inc/save_manager.h"
7 : #include <string>
8 : #include <sstream>
9 : #include <vector>
10 : #include <iterator>
11 :
12 :
13 :
14 : GlobalParam GlobalParam::instance_ = GlobalParam();
15 :
16 : /**
17 : * \file main.cu
18 : * \author martigan moilerat
19 : * \brief Fichier d entrée du programme
20 : * \fn int main(int argc, char **argv)
21 : * \def query_type
22 : * \fn void sig_handler(int signo)
23 : */
24 :
25 : #include <map>
26 : #include <iostream>
27 : #include <sstream>
28 : #include <algorithm>
29 :
30 :
31 : #include <fstream>
32 :
33 : /*
34 : compilation :
35 : nvcc -g main.cu gpu.cu server.cu file.cu -o fvs
36 : =>
37 : use make instead of this
38 : gcc -g main.cu server.cu file.cu utils.cu -DONLY_CPU -o fvs
39 : x86_64-linux-gnu-gcc -g main.cu -DONLY_CPU -o fvs
40 : execution :
41 : gdb fvs run quand ca plante : bt
42 : -
43 : ou bien
44 : fvs puis quand ca plante
45 : gdb fvs core et bt
46 :
47 : //si bt ne donne rien sortir avec quit puis
48 : ulimit -c unlimited
49 : // et reexecuter
50 :
51 : valgrind dans un fichier :
52 : valgrind --leak-check=full --show-leak-kinds=all ./fvs P3333 R/home/fotonower/workarea/temp_0606/ A$PWD/fvs_conf_26_15.ini > file.txt 2>&1
53 :
54 : pour debugger avec valgrind :
55 : valgrind --leak-check=full --show-leak-kinds=all --vgdb=yes --vgdb-error=0 ./fvs P3333 R/home/fotonower/workarea/temp_0606/ A$PWD/fvs_conf_26_15.ini
56 : gdb -args ./fvs P3333 A$PWD/fvs_conf_26_15.ini R/home/fotonower/workarea/temp_0606/
57 : dans gdb target remote | vgdb
58 : puis set breakpoints
59 : puis c
60 : dans gdb le leak check est accesssible :
61 :
62 : monitor leak_check full reachable any
63 : */
64 :
65 : #define COMPARE(x,y) ((x)<(y)?0:1)
66 :
67 :
68 : /*
69 : int saveOnExitWithSomeTry(std::vector<int> &indexCurrent, int verbose)
70 : {
71 : GlobalParam &gp = GlobalParam::Instance();
72 : for (int i = 0; i < gp.nbtype_; ++i)
73 : {
74 : int prevIndexCurrent = indexCurrent.at(i);
75 : if (indexCurrent.at(i) == 0)
76 : continue;
77 : indexCurrent.at(i) = (indexCurrent.at(i) > INSERT ? 0 : indexCurrent.at(i));
78 : printf("About to insert : %d, %d\n", indexCurrent.at(i), INSERT);
79 : int token = getTokenWriteIndex(GlobalParam::Instance().pid_, gp.WriteCache[i][0].dire);
80 : int nb_try = 20;
81 : int count_try = 0;
82 : while (token != -1 && count_try < nb_try)
83 : {
84 : if (count_try == nb_try)
85 : {
86 : printf("Token on index is used, we stopped without saving this amount of data : %d\n", prevIndexCurrent);
87 : return 1;
88 : }
89 : usleep(10);
90 : token = getTokenWriteIndex(GlobalParam::Instance().pid_, gp.WriteCache[i][0].dire);
91 : count_try++;
92 : }
93 : save(gp.WriteCache[i][0].dire, GlobalParam::Instance().filename_photo_id_list_str_, gp.WriteCache[i], gp.WriteCache[i][0].dire, indexCurrent.at(i), verbose);
94 : giveBackToken(gp.WriteCache[i][0].dire);
95 : }
96 : return 0;
97 : }*/
98 :
99 3 : int configureParamFromArgAndPrintHelp(LocalParam & lp, int argc, char **argv)
100 : {
101 16 : for (int i = 0; i < argc; ++i)
102 : {
103 13 : if (argv[i][0] == 'L')
104 : {
105 0 : lp.limit_data = atoi(&argv[i][1]);
106 0 : lp.empty_server = lp.limit_data == 0;
107 : }
108 13 : if (argv[i][0] == 'P')
109 : {
110 2 : GlobalParam::Instance().port_ = atoi(&argv[i][1]);
111 : }
112 13 : if (argv[i][0] == 'C')
113 1 : lp.cleaning_data = 1;
114 13 : if (argv[i][0] == 'R')
115 : // pourquoi est-ce qu'on ne convertit pas en std::string ce truc la ?
116 3 : GlobalParam::Instance().velours_std_ += &argv[i][1];
117 13 : if (argv[i][0] == 'T')
118 2 : if(atoi(&argv[i][1])<-1)
119 0 : lp.desc_type_dyn = atoi(&argv[i][1]);
120 : else
121 2 : lp.descriptor_type = atoi(&argv[i][1]);
122 13 : if (argv[i][0] == 'F')
123 0 : lp.cleanCPU = 1;
124 13 : if (argv[i][0] == 'A')
125 : {
126 2 : char *conf_file = &argv[i][1];
127 2 : lp.conf_file = std::string(conf_file);
128 : }
129 13 : if (argv[i][0] == 'S')
130 0 : lp.insert_save_file = 0;
131 13 : if (argv[i][0] == 'N')
132 0 : lp.insert_sync_cache = 0;
133 13 : if (argv[i][0] == 'v')
134 0 : lp.verbose = 1;
135 13 : if (argv[i][0] == 'O')
136 0 : lp.load_only_main = 1;
137 13 : if (argv[i][0] == 'D')
138 : {
139 0 : GlobalParam::Instance().dontCheckDuplicateIdObject_ = true;
140 : }
141 13 : if (argv[i][0] == 'H' || argv[i][0] == 'h')
142 : {
143 0 : puts("help : arguments are \n LX to limit data loading where X is number\n PX to set the port for socket where X is number\n C to clean datas and exit afterwards\n RX to set datas path where X is path\n TX to set a particular data type for server where X is number\n F to set variable cleanCPU \n AX to set server with configuration file where X is path/to/conf_file\n v for verbose mode\n O to set load_only_main (wtf ?)\n ");
144 0 : puts("D to avoid checking duplicate entry of id objcet when writing the files after insertion (should increase speed by 10000)\n hH To display this help \n List of possible arguments : LPCRTFAvODHh\n S not save in file \n N not load in cache\n");
145 0 : return 1;
146 : }
147 : }
148 : return 0;
149 : }
150 :
151 :
152 3 : int InitWriteCache(GlobalParam & gp, LocalParam & lp, std::vector<std::vector<to_insert_t> > & WriteCache)
153 : {
154 : // VR 4-11-16 a mettre dans
155 3 : lp.ReadCacheCPU.resize(gp.nbtype_);
156 3 : if (lp.verbose)
157 : {
158 0 : printf("M alloc struct for insertion of datas %d\n", INSERT_MAX);
159 0 : printf("gp.WriteCache will be allocated, current size : %ld \n", (gp.WriteCache.size()));
160 : }
161 3 : if (lp.ReadCacheCPU.size() == 0)
162 : {
163 0 : printf("ERROR &(ReadCacheCPU.size()) is of size empty %ld : \n", (lp.ReadCacheCPU.size()));
164 0 : puts("ERROR, we had bette to stop this !");
165 : }
166 3 : gp.WriteCache.resize(gp.nbtype_);
167 16 : for (int i = 0; i < gp.WriteCache.size(); i++)
168 : {
169 13 : gp.WriteCache[i].resize(INSERT_MAX);
170 : }
171 :
172 3 : if (lp.verbose)
173 0 : printf("gp.WriteCache has been allocated : current size %ld\n", gp.WriteCache.size());
174 3 : gp.indexCurrent.resize(gp.nbtype_);
175 3 : lp.indexCurrent.resize(gp.nbtype_);
176 3 : std::fill(gp.indexCurrent.begin(), gp.indexCurrent.end(), 0);
177 3 : std::fill(lp.indexCurrent.begin(), lp.indexCurrent.end(), 0);
178 16 : for (int i = 0; i < lp.ReadCacheCPU.size(); ++i)
179 : {
180 13 : if (lp.verbose)
181 0 : printf("ReadCacheCPU[%d].size = %u\n", i, lp.ReadCacheCPU[i].size);
182 :
183 13 : gp.WriteCache[i].resize(INSERT_MAX);
184 : }
185 3 : return 0;
186 : }
187 :
188 :
189 :
190 3 : int setCacheParamWhenNoDataLoaded(std::vector<types_datas_t> & ReadCacheCPU, GlobalParam & gp, LocalParam & lp)
191 : {
192 3 : lp.dimension = ReadCacheCPU[0].size;
193 3 : std::cout<<"in No data loaded settings "<<std::endl;
194 16 : for (int i = 0; i < ReadCacheCPU.size(); ++i)
195 : {
196 : // VR 3-11-16 : je suis tres etonné par cela, au moins dans l'autre sens et puis de toute facon cela a l'air farfelu
197 13 : lp.dimension = (lp.dimension < ReadCacheCPU[i].size ? ReadCacheCPU[i].size : lp.dimension);
198 13 : if (ReadCacheCPU[i].size != 0)
199 12 : ReadCacheCPU[i].resizeDatas(ReadCacheCPU[i].datas_vec.size() / ReadCacheCPU[i].size);
200 :
201 : // Cette partie me parait un tout petit peu plus raisonnable mais je prefererai que ce soit fait dans commitInsert
202 13 : if (lp.nb_data_in_file == 0)
203 : {
204 12 : ReadCacheCPU[i].nb_max_data = SIZE_ALLOCATION_BUFFER / 10;
205 :
206 : // VR TODO weird 26-9-16
207 12 : ReadCacheCPU[i].resizeDatas(ReadCacheCPU[i].nb_max_data);
208 : }
209 : }
210 :
211 : //std::cout<<"ReadCache size : "<<ReadCacheCPU[0].nb_max_data<<std::endl;
212 :
213 3 : if (lp.verbose)
214 0 : printf("gp.WriteCache size after load data %ld \n", gp.WriteCache.size());
215 3 : return 0;
216 : }
217 :
218 3 : void initFolderDataLocation(GlobalParam &gp, LocalParam &lp)
219 : {
220 : /**
221 : * Initialise le chemin vers le dossier des descripteurs dans GeneralParam
222 : */
223 : // VR 26-9-16 std::string buildFolder(std::string local_folder)
224 3 : if (gp.velours_std_.size() == 0)
225 : {
226 : // MG 4-11-16 : il n'y a pas de fonction c++ getenv
227 : // VR 4-11-16 : l'absence de preuve n'est pas la preuve de l'absence
228 : // VR 4-11-16 : tu peux la faire
229 : // remove pointer, VR 13-10-16 : je ne sais pas trop comment tester cette ligne
230 0 : char * env_aux = getenv(gp.velours_root_env_name_.c_str());
231 0 : if (env_aux)
232 0 : gp.velours_std_ += env_aux;
233 0 : std::cout<<" Affichage de la var environnement Velours_Root_2"<<std::endl;
234 0 : if (!gp.velours_std_.size())
235 : {
236 0 : std::cout << "Please set env var VELOURS_ROOT_2, or pass argument R/path/to/binaryfolders\n";
237 0 : std::cout << "Aborting launch\n";
238 0 : exit(1);
239 : }
240 0 : if (lp.descriptor_type != -1)
241 : {
242 0 : if (gp.velours_std_[gp.velours_std_.size() - 1] != '/')
243 : {
244 0 : gp.velours_std_ += "/";
245 : }
246 0 : gp.velours_std_ += "binary";
247 0 : gp.velours_std_ += boost::lexical_cast<std::string>(lp.descriptor_type);
248 : }
249 : }
250 3 : if (gp.velours_std_[gp.velours_std_.size() - 1] != '/')
251 : {
252 2 : gp.velours_std_ += "/";
253 : }
254 3 : std::cout<<"path to binary : "<<gp.velours_std_<<std::endl;
255 3 : }
256 :
257 :
258 : // Initialisation du supporteed_type_vec je dois modifie cette fonction car var globale a supprimer
259 3 : int configureTypeAvailable(GlobalParam &gp, LocalParam &lp)
260 : {
261 : /**
262 : * initialise le desc type dans LocalParam
263 : */
264 :
265 3 : if (gp.port_ == 0 && (lp.cleaning_data == 0))
266 : {
267 0 : puts("wrong port argument, exiting");
268 0 : exit(1);
269 : }
270 :
271 3 : std::cout<<"ConfTypeAvail args : port "<< gp.port_<<" cleaning "<<lp.cleaning_data<<std::endl;
272 3 : if (lp.conf_file != "")
273 : {
274 : // chargement du conf file pour recuperer les desc type (initialisation des supported_vec)
275 2 : int ret = set_with_conf_file(lp.conf_file,gp,lp);
276 2 : if (ret == 1)
277 : {
278 0 : std::cout << "Returning non 0 status while reading conf_file : " << lp.conf_file << std::endl;
279 0 : return 1;
280 : }
281 : }
282 : else
283 : {
284 1 : setdefault(gp,lp);
285 : }
286 3 : if (lp.descriptor_type != -1)
287 : {
288 2 : std::cout<<"desc type in local "<<lp.descriptor_type<<std::endl;
289 2 : int type_it = FindDescIndex(lp.ReadCacheCPU, lp.descriptor_type);
290 2 : if (type_it == -1){
291 0 : puts("type not in conf file");
292 0 : return 3;
293 : }
294 : }
295 :
296 : return 0;
297 : }
298 :
299 3 : int init(LocalParam & lp, int argc = 0, char **argv = NULL)
300 : {
301 3 : GlobalParam &gp = GlobalParam::Instance();
302 :
303 : // VR 6-11-16 : il faut utiliser ceci avec intelligence dans un souci de clarté
304 3 : std::vector<types_datas_t> & ReadCacheCPU = lp.ReadCacheCPU;
305 :
306 3 : int ret = configureParamFromArgAndPrintHelp(lp, argc, argv);
307 3 : if (ret != 0)
308 : return ret;
309 :
310 :
311 3 : if (lp.verbose)
312 0 : printf("gp.WriteCache size before get env %ld \n", (gp.WriteCache.size()));
313 :
314 : // VR 4-11-16 : fonction d'initialisation de dossier de données
315 3 : initFolderDataLocation(gp, lp);
316 :
317 3 : if (lp.verbose)
318 0 : printf("gp.WriteCache size after checking velours_root %ld \n", (gp.WriteCache.size()));
319 :
320 3 : std::cout << " lp.insert_save_file : " << lp.insert_save_file<< " lp.insert_sync_cache : "<<lp.insert_sync_cache << std::endl;
321 3 : puts("");
322 :
323 : // VR 26-9-16 void configureTypeAvailable()
324 3 : ret = configureTypeAvailable(gp, lp);
325 3 : if (ret != 0)
326 : return ret;
327 3 : printf("Nb Data in Search Engine before WriteCache data: %d\n",lp.nb_data_in_file);
328 :
329 3 : InitWriteCache(gp, lp, gp.WriteCache);
330 :
331 3 : printf("Nb Data in Search Engine before loading data: %d\n", lp.nb_data_in_file);
332 :
333 : // VR 5-11-16 Il faut passer a cette fonction les memes arguments que setCacheParamAMoitie pour les mettre ensemble
334 3 : ret = LoadDataInCache(gp, lp, lp.descriptor_type, lp.verbose, gp.velours_std_, 0, lp.cleaning_data);
335 3 : if (ret != 0)
336 : {
337 0 : std::cout << " LoadDataInCache return non 0 status " << std::endl;
338 0 : return ret;
339 : }
340 :
341 :
342 : // VR 4-11-16 On voudrait virer tout ce bout la ou le mettre dans le setCacheParam
343 : // la dedans on initialise ReadCacheCPU lorsqu'il n'y a pas de données et on fais quelquechose d'autres, mais on pourrait faire cela dans commitInsert eventuellement
344 3 : setCacheParamWhenNoDataLoaded(ReadCacheCPU, gp, lp);
345 :
346 : //------------------------------------------------------------------------------
347 3 : printf("Nb Data in Search Engine : %d\n", lp.nb_data_in_file);
348 3 : printf("limit_return : %d\n", LIMIT_RETURN);
349 :
350 : // mettre la suite dans cette fonction bloque les tests, y aurait-il un os ici ?
351 :
352 :
353 : // pour plus avoir les datas_vec en CPU
354 3 : if (lp.cleanCPU)
355 : {
356 : // void fonction cleanCPUData(ReadCacheCPU) quand on veut
357 0 : for (int i = 0; i < gp.nbtype_; ++i)
358 : {
359 0 : ReadCacheCPU[i].resizeDatas(ReadCacheCPU[i].nb_data);
360 : }
361 : }
362 3 : std::cout<<"Init RC size : "<<ReadCacheCPU[0].datas_vec.size()<<std::endl;
363 : ////////////// fin lecture données ///////////////////
364 :
365 :
366 : // VR 6-11-16 : je serais tenter de faire cela seulement avant le remplissage, et pas trop content de cette variable global SIZE_ALLOCATION_BUFFER
367 : // VR 6-11-16 : il faut comenter la ligne suivante, mais cela casse les tests
368 3 : lp.idc_vec.resize(lp.nb_data_in_file + SIZE_ALLOCATION_BUFFER);
369 :
370 3 : gp.sock_ = create_server(GlobalParam::Instance().port_);
371 3 : if (gp.sock_ == -1)
372 : {
373 0 : puts("error opening socket\n");
374 0 : return 3;
375 : }
376 :
377 3 : if (lp.cleaning_data > 0)
378 : {
379 1 : puts("start cleaning data");
380 1 : exit(cleanTokenProof(gp, lp));
381 : }
382 :
383 2 : puts("end initialisation\n");
384 2 : if (lp.verbose)
385 2 : printf("gp.WriteCache size after begin while %ld \n", gp.WriteCache.size());
386 :
387 : return 0;
388 : }
389 :
390 :
391 :
392 3 : int main(int argc, char **argv)
393 : {
394 :
395 : // VR 12-10-16 : la prochaine de refacto etape sera d'enlever le plus de variable global possible
396 3 : GlobalParam &gp = GlobalParam::Instance();
397 3 : LocalParam lp;
398 3 : printf("lp.nb_data_in_file : %d\n",lp.nb_data_in_file);
399 :
400 : #ifndef ONLY_CPU
401 : int nDevices;
402 :
403 : cudaGetDeviceCount(&nDevices);
404 :
405 : std::cout<<"nb devices : "<<nDevices<<std::endl;
406 : for (int i = 0; i < nDevices; i++){
407 : cudaDeviceProp prop;
408 : cudaGetDeviceProperties(&prop, i);
409 : printf("Device Number: %d\n", i);
410 : printf(" Device name: %s\n", prop.name);
411 : printf(" Memory Clock Rate (KHz): %d\n",
412 : prop.memoryClockRate);
413 : printf(" Memory Bus Width (bits): %d\n",
414 : prop.memoryBusWidth);
415 : printf(" Peak Memory Bandwidth (GB/s): %f\n\n",
416 : 2.0*prop.memoryClockRate*(prop.memoryBusWidth/8)/1.0e6);
417 : }
418 : #endif
419 :
420 : // MG 13/07/16 : need to test with mapped memory for distance transfert : not sure if we will gain much time, we may loose some actually => VR 4-11-16 : je crois que Lokmane l'a fait, non ?
421 :
422 : //------------------------------------------------------------------------------
423 : // VR 4-11-16 : fonction d'initialisation
424 3 : if (0 != init(lp, argc, argv))
425 : return 1;
426 :
427 2 : Query & cur_query = lp.query;
428 2 : std::cout<<" Start main while loop, cleaning_data : "<<lp.cleaning_data<<std::endl;
429 17 : clock_t timer;
430 17 : while (true)
431 : {
432 17 : displayTime(timer);
433 17 : lp.cs = createConnectionAndOutputIp(gp.sock_);
434 17 : printf(" lp.cs %d, gp.sock_ %d, gp.port_ %d \n",lp.cs,gp.sock_, gp.port_);
435 17 : displayTime(timer, "Got Connection");
436 17 : lp.retval_set_query = cur_query.load_query(lp.cs, lp.descriptor_type, lp, lp.verbose);
437 17 : displayTime(timer, "Query loaded");
438 17 : std::cout<<"photo desc : " << lp.descriptor_type <<std::endl;
439 17 : if (lp.retval_set_query == 0)
440 : {
441 16 : std::cout<<"avant executeQuery"<<std::endl;
442 16 : int rete = executeQuery(cur_query, lp, gp);
443 16 : displayTime(timer, "Query executed ! ");
444 16 : if (rete != 0)
445 : {
446 11 : if (rete == 100)
447 : break;
448 9 : if (rete == 101)
449 9 : continue;
450 :
451 0 : std::cout << " ERROR in executeQuery : " << rete << std::endl;
452 : return rete;
453 : }
454 : }
455 : else
456 : {
457 : //puts("on a recu un buffer vide");
458 1 : if (lp.retval_set_query == -3)
459 1 : send(lp.cs, "first char of query not valid, use a char in dDsSqacrReiECmlkzgpPeof", 68, 0);
460 0 : else if (lp.retval_set_query == 2)
461 0 : send(lp.cs, "type not loaded in servereof", 28, 0);
462 0 : else if (lp.retval_set_query == -5 || lp.retval_set_query == -2)
463 0 : send(lp.cs, "error in receiving messageeof", 29, 0);
464 0 : else if (lp.retval_set_query == -1)
465 0 : send(lp.cs, "empty messageeof", 20, 0);
466 : else
467 0 : send(lp.cs, "error in messageeof", 19, 0);
468 : }
469 :
470 6 : cur_query.reset_query();
471 6 : close(lp.cs);
472 6 : if (lp.counter < 0)
473 : break;
474 : }
475 :
476 2 : int ret_val = 0;
477 : // VR 13-10-16 : c'est quoi ce type de indexCurrent, saveOnExitWithSomeTry attend un int* (a virer d'ailleurs !)
478 : //ret_val = saveOnExitWithSomeTry(lp.indexCurrent, lp.verbose, gp.dontCheckDuplicateIdObject_);
479 2 : close(gp.sock_);
480 :
481 2 : std::cout<<" Fin de fvs ! "<<std::endl;
482 :
483 : return ret_val;
484 : }
|