-
Notifications
You must be signed in to change notification settings - Fork 0
/
simulador.cpp
2870 lines (2312 loc) · 134 KB
/
simulador.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
fase 1: re-executar algoritmo de alocacao entre todos os servidores
fase 2: achar componente conexo para alocacao de banda, pensar em outros algorimos de selecao de servidores
*/
/*
fazer testes e tirar estimativas:
homogeneo:
por todos com mesma banda
dps aumentar a banda dos clientes
depois clientes homogeneos , servidores hetero: servidores mais banda
depois aumenta banda dos clientes
fazer alguns testes e comparar com resultados analiticos
MEDIA 0.1 (DETAL 10) ENTRADA DOS CLIENTES
EXPERIMENTOS:
100 CLIENTES E 100 SERVIDORES
DROP_CONNECTION
CONNECTION_COST: PAGA 2% DA BANDA DO CLIENTE
SET_SIZE: SEMPRE COMEÇAM COM 2 E PODEM AUMENTAR ATE {4, 8, 12}
TAMANHO ARQUIVO : 1 MILHAO (1GB)
CAPACIDADE DOS SERVIDORES: 1000 (1 MEGA)
CAPACIDADE DOS CLIENTES:
1) TODOS 100
2) TODOS 300
3) TODOS 600
4) TODOS 1000
5) TODOS 1300
6) TODOS 1500
CAPACIDADE DOS CLIENTES: 1000 (1 MEGA)
CAPACIDADE DOS SERVIDORES:
1) TODOS 100
2) TODOS 300
3) TODOS 600
4) TODOS 1000
5) TODOS 1300
6) TODOS 1500
TENTAR CALCULAR O LIMITE INFERIOR DAS COISAS.
TESTAR CLIENTES: SET_SIZE = 4, COMEÇANDO COM 2, TODOS COM MESMA CAPACIDA
NUMERO DE CLIENTES:
50
100
150
200
100 SERVIDORES, ARQUIVO 1MILHAO, BANDA DE CLIENTES E SERVIDORES MIL
CALCULAR O TEMPO MINIMO QUE DEVERIA LEVAR.
*/
/*
CODIGO DE DIVISAO DE GRUPOS
-1: CLIENTES E SERVIDORES COM MESMA BANDA - so com random == 1
0: TODOS DO MESMO GRUPO COM CAPACIDADES DISTINTAS
1: TODOS DO MESMO GRUPO COM A MESMA CAPACIDADE
2: 1/2 - 1/2
3: 1/3 - 1/3 - 1/3
4: 1/3 - 2/3
NAO IMPLEMENTADO:
5: 1/4 - 1/4 - 1/4 - 1/4
6: 1/4 - 1/4 - 1/2
7: 1/4 - 3/4
*/
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <list>
#include <algorithm>
#include <iterator>
#include <vector>
#include <cassert>
#include <ctype.h>
#include <math.h>
//#include <boost/random/mersenne_twister.hpp>
//#include <boost/random/uniform_int_distribution.hpp>
#define DEBUG_LEVEL 3
#define NUMBER_SERVERS 100
#define NUMBER_CLIENTS 100
#define KNOWLEDGE 100
#define RANDOM_CAP 0
#define SERVERS_BAND_DIVISION 1
#define CLIENTS_BAND_DIVISION 1
//setar variaveis se RANDOM == 0 / inicio
#define CAP_SERVER_1 100
#define CAP_SERVER_2 100
#define CAP_SERVER_3 100
#define CAP_CLIENT_1 1000
#define CAP_CLIENT_2 1000
#define CAP_CLIENT_3 1000
//setar variaveis se RANDOM == 0 / fim
//setar variaveis se RANDOM == 1 / inicio
#define MAX_CAP_SERVER 100
#define MAX_CAP_CLIENT 1000
#define MIN_CAP_SERVER 100
#define MIN_CAP_CLIENT 1000
//setar variaveis se RANDOM == 1 / fim
#define CONNECTION_LIMIT 1
#define DROP_SERVERS 1
#define SET_SIZE 50
#define INITIAL_SET_SIZE 1
#define FILE_SIZE 1000000
#define MAX_TIME 100000
#define CONNLIMIT 1
#define OVERHEAD 2
#define ALGORITHM 2
// DELTA2>>DELTA3
#define DELTA1 1 //entrada-saida
#define DELTA2 20 //mudanca de fluxo (media pelo menos duas vezes maior)
#define DELTA3 1 //des-conexao
#define VARIACAO 10 //porcentagem da variacao: (fluxo antigo)*(VARIACAO/100) = maximo de diferenca entre fluxo antigo e atual
#define FLOW_PERCEPTION 3
#define CONNECTION_COST 12
#define FLOW_EVENT 0
#define CLIENT_EXIT_EVENT 1
#define CLIENT_ARRIVAL_EVENT 2
#define SERVER_ARRIVAL_EVENT 5
#define SERVER_EXIT_EVENT 6
#define CONNECTION_EVENT 3
#define DISCONNECTION_EVENT 4
#define INF 999999999999
#define MAX_BAND_COST 100
using namespace std;
FILE *output;
int t_print;
float t, t_last, t_last_fi;
float server_arrive_time[NUMBER_SERVERS];
float client_arrive_time[NUMBER_CLIENTS];
float server_exit_time[NUMBER_SERVERS];
float client_exit_time[NUMBER_CLIENTS];
float soma_t_c[NUMBER_CLIENTS];
float soma_t_s[NUMBER_SERVERS];
float t_last_fi_c[NUMBER_CLIENTS];
float t_last_fi_s[NUMBER_SERVERS];
float Servers_cap[NUMBER_SERVERS];
float Clients_cap[NUMBER_CLIENTS];
float Servers_connection_cost[NUMBER_CLIENTS];
int nsamples;
int global_nsamples_c[NUMBER_CLIENTS];
int global_nsamples_s[NUMBER_SERVERS];
long double mean_c[NUMBER_CLIENTS];
long double mean_s[NUMBER_SERVERS];
long double var_c[NUMBER_CLIENTS];
long double var_s[NUMBER_SERVERS];
long double oldmean_c[NUMBER_CLIENTS];
long double oldmean_s[NUMBER_SERVERS];
long double oldvar_c[NUMBER_CLIENTS];
long double oldvar_s[NUMBER_SERVERS];
long double mean_clients_flow[NUMBER_CLIENTS];
long double mean_servers_flow[NUMBER_SERVERS];
long double mean_system_flow;
long double oldmean_clients_flow[NUMBER_CLIENTS];
long double oldmean_servers_flow[NUMBER_SERVERS];
long double oldmean_system_flow;
//long double var_clients_flow[NUMBER_CLIENTS];
//long double var_servers_flow[NUMBER_SERVERS];
//long double var_system_flow;
long double mean_servers_number_connections[NUMBER_SERVERS];
long double mean_clients_number_connections[NUMBER_CLIENTS];
long double oldmean_servers_number_connections[NUMBER_SERVERS];
long double oldmean_clients_number_connections[NUMBER_CLIENTS];
//long double var_servers_number_connections[NUMBER_SERVERS];
//long double var_clients_number_connections[NUMBER_CLIENTS];
struct event{
float time; //tempo de ocorrencia do evento
int event_id; //tipo de evento
int client_id; //id do cliente que gerou evento
int server_id; //no caso de conexao/desconexao, com qual servidor
struct event *next; //ponteiro para proximo evento
struct event *prev; //ponteiro para evento anterior
bool operator <(const event& rhs)const{
return time < rhs.time;} //caso seja necessario ordenar a lista de eventos usando a funcao sort, exemplo: sort(events,events+number_events)
};
struct client{
int client_id; //id do cliente
int flow_event_alloc; //flag para saber se ha um evento de fluxo alocado na lista de eventos
long double band_filled; //flag para saber se banda do cliente esta sendo toda utilizada
float last_connection_scheduled; //variavel auxiliar, guarda tempo do evento de conexao/desconexao gerado que ocorrera mais no futuro
struct event* exit_event; //ponteiro para o evento de saida desse cliente
struct event* flow_event; //ponteiro para o evento de mudanca de fluxo desse cliente - nem sempre esta alocado em uma lista
int own_connections[NUMBER_SERVERS]; //lista de servidores que o cliente esta conectado/pediu conexao (conexao pode ou nao já estar estabelecida)
int own_connections_old[NUMBER_SERVERS]; //idem, vetor auxiliar
long double own_flow[NUMBER_SERVERS]; //fluxo observado pelo cliente vindo de cada servidor
};
//funcoes que processam os eventos - retornam 1 se ocorrer um erro
int process_exit_event(event *, event *, event *, client[NUMBER_CLIENTS], int[][NUMBER_CLIENTS], int[NUMBER_CLIENTS], int[NUMBER_SERVERS], int *, int * ,int, int);
int process_arrival_event(event *, event *, client[NUMBER_CLIENTS], int[][KNOWLEDGE], int[][NUMBER_CLIENTS], float[][NUMBER_CLIENTS], int[NUMBER_CLIENTS], int[NUMBER_SERVERS], int *, int *, int, int, int * );
int process_flow_event(event *, event *, client[NUMBER_CLIENTS], int[][KNOWLEDGE], int[][NUMBER_CLIENTS], float[][NUMBER_CLIENTS], int, int * );
int process_connection_event(event *, event *, event *, client[NUMBER_CLIENTS], int[][NUMBER_CLIENTS], int[NUMBER_SERVERS], int[NUMBER_CLIENTS], float[][NUMBER_CLIENTS], long double[NUMBER_CLIENTS], long double[NUMBER_SERVERS], long double[][NUMBER_CLIENTS], int[NUMBER_CLIENTS], int[NUMBER_SERVERS], int , int, int, int * , int );
int erase ( event *, event*); //remove evento da lista e desaloca evento da memoria
void remove_event(event *); //somente remove evento da lista - não desaloca da memoria
void recoloca ( event *, int, float,int, int, event *); //insere evento na lista no devido lugar - ordenado em ordem crescente no tempo
event * insere ( event *, int, float, int, int); //cria e insere evento numa lista, retorna endereco da estrutura(evento)
void busca ( event *, float , int, int, event **, event **); //busca evento na lista de eventos: fluxo, conexao, desconexao
void busca2 ( event *, int , event **, event **); //busca evento na lista de saidas
void busca_tempo ( event *, float , event **, event **);
void listar (struct event *); //lista eventos de uma lista
void print_system_state(int, int[NUMBER_CLIENTS], int[NUMBER_SERVERS],long double[NUMBER_CLIENTS], long double[NUMBER_SERVERS]);
double gera_aleatorio(double parametro); //gera numero aleatorio com distribuicao exponencial
int algoritmo_overhead(client[NUMBER_CLIENTS], int, int[][KNOWLEDGE], int[][NUMBER_CLIENTS], float[][NUMBER_CLIENTS], int ); //seleciona servidores, retorna 1 se erro
int algoritmo_connlimit(client[NUMBER_CLIENTS], int, int [][KNOWLEDGE], int[][NUMBER_CLIENTS], float[][NUMBER_CLIENTS], int ); //seleciona servidores, retorna 1 se erro
int alocacao(client[NUMBER_CLIENTS], int[NUMBER_CLIENTS], int[NUMBER_SERVERS], int[][NUMBER_CLIENTS], float[][NUMBER_CLIENTS], long double[NUMBER_CLIENTS], long double[NUMBER_SERVERS], int[NUMBER_CLIENTS], int[NUMBER_SERVERS], int ); //aloca banda dos servidores para os clientes, retorna numero de controle, 1 se erro
struct event * malloc_flow(int); //aloca evento de fluxo na memoria, passa o endereco
struct event * get_next(event *); //retorna endereco do proximo evento na lista
float get_time(event *); //retorna tempo do evento
int get_client_id(event *); //retorna id do cliente envolvido com o evento
int get_server_id(event *); //retorna id do servidor envolvido com o evento
int get_event_id(event *); //retorna o tipo do evento
void set_servers_capacite_random();
void set_clients_capacite_random();
void set_servers_capacite();
void set_clients_capacite();
int main(int argc, char *argv[]) {
int i, j, k;
int number_events, number, servers_up, clients_up;
int event_id, client_id, server_id;
double when, exp_paramenter;
struct event **ant, **pont;
struct client clients_vector[NUMBER_CLIENTS]; //vetor de instancias de clientes
struct event *exits; //lista de saidas, duplamente enc. ordenada no tempo
struct event *events; //lista de eventos: des/conexao, fluxo, duplamente enc. ordenada no tempo
struct event *temp_event_exits, *temp_event_events; //ponteiro para primeiro evento a ser processados de cada lista
int clients_state[NUMBER_CLIENTS];
int servers_state[NUMBER_SERVERS];
int knowledge_temp[NUMBER_SERVERS];
int knowledge_servers[NUMBER_CLIENTS][KNOWLEDGE];
int connections[NUMBER_SERVERS][NUMBER_CLIENTS]; //1 se servidor i estiver contado a cliente j
int servers_number_connections[NUMBER_SERVERS]; //numero de conexoes estabelecidas por cada servidor
int clients_number_connections[NUMBER_CLIENTS]; //numero de conexoes estabelecidas por cada cliente
char randstate[256];
float flow[NUMBER_SERVERS][NUMBER_CLIENTS]; //(X) fluxo atual do servidor i para cliente j
long double data[NUMBER_SERVERS][NUMBER_CLIENTS]; //(B) total de dados transmitidos ate o tempo t. do servidor i para cliente j
long double clients_flow[NUMBER_CLIENTS]; //fluxo real total alocado
long double servers_flow[NUMBER_SERVERS];
long double ic_clients_flow[NUMBER_CLIENTS];
long double dp_clients_flow[NUMBER_CLIENTS];
long double ic_servers_flow[NUMBER_SERVERS];
long double dp_servers_flow[NUMBER_SERVERS];
long double ic_system_flow;
long double dp_system_flow;
long double ic_servers_number_connections[NUMBER_SERVERS];
long double ic_clients_number_connections[NUMBER_CLIENTS];
long double dp_servers_number_connections[NUMBER_SERVERS];
long double dp_clients_number_connections[NUMBER_CLIENTS];
if(initstate(time(NULL), randstate, 256)==NULL) return 1;
srandom( (int)time(NULL) );
//printf("%d %d %d\n", NUMBER_SERVERS, NUMBER_CLIENTS, CONNECTION_LIMIT);
exits = NULL;
events = NULL;
ant = ( event **) malloc(sizeof ( event *));
pont = ( event **) malloc(sizeof ( event *));
//Criando no cabeca para lista de eventos 'events' que contem eventos de fluxo, conexao e desconexao
if (( events = ( event *) malloc(sizeof( event )) ) == NULL )
{
printf("ERROR: Nao foi possivel alocar memoria para events\n");
return 1;
}
events->event_id = -1;
events->time = 0;
events->next = NULL;
events->prev = NULL;
//Criando no cabeca para lista de eventos 'exits' que contem eventos de saida
if (( exits = ( event *) malloc(sizeof( event)) ) == NULL )
{
printf("ERROR: Nao foi possivel alocar memoria para exits\n");
return 1;
}
exits->event_id = -1;
exits->time = 0;
exits->next = NULL;
exits->prev = NULL;
//Gerando capacidades
if(RANDOM_CAP) {
set_servers_capacite_random();
set_clients_capacite_random();}
else{
set_servers_capacite();
set_clients_capacite();}
for(i=0; i<NUMBER_SERVERS ; i++)
{
servers_number_connections[i]=0;
servers_state[i]=1;
servers_flow[i]=0;
knowledge_temp[i]=NUMBER_CLIENTS;
global_nsamples_s[i]=0;
for(j=0; j<NUMBER_CLIENTS; j++)
{
if(i==0) //para realizar esta operacao apenas uma vez
{
//setando custo de conexao
Servers_connection_cost[j] = (((float)(CONNECTION_COST))/100)*Clients_cap[j];
if(DEBUG_LEVEL>1) printf("Client %d connection cost: %f\n", j,Servers_connection_cost[j] );
//setando valores iniciais dos clientes
clients_vector[j].client_id=j;
clients_number_connections[j]=0;
clients_vector[j].band_filled = 0;
clients_vector[j].last_connection_scheduled = 0;
clients_flow[j] = 0;
}
global_nsamples_c[j]=0;
//setando valores iniciais
flow[i][j] = 0;
data[i][j] = 0;
connections[i][j] = 0;
clients_state[j]=0;
clients_vector[j].own_flow[i]=0;
clients_vector[j].own_connections[i]=0;
clients_vector[j].own_connections_old[i]=0;
mean_c[j]=0;
mean_s[i]=0;
var_c[j]=0;
var_s[i]=0;
mean_clients_flow[j] =0;
mean_servers_flow[i] =0;
mean_system_flow =0;
mean_servers_number_connections[i]=0;
mean_clients_number_connections[j]=0;
}
}
if(DEBUG_LEVEL>1) printf("\n");
//INICIANDO CRIACAO E PROCESSAMENTO DE EVENTOS
t = 0;
t_last = 0;
t_print = 0;
t_last_fi = 0;
number_events = 0;
nsamples = 0;
mean_system_flow=0;
servers_up = NUMBER_SERVERS;
if(DEBUG_LEVEL>0) printf( "%f BEGIN\n", t);
//Criando eventos de chegada, saida e fluxo
for(j=0; j<NUMBER_CLIENTS ; j++)
{
//criando evento de chegada para cliente no vetor de eventos
while(true)
{
exp_paramenter = (float)(1/(float)DELTA1);
when = t+gera_aleatorio(exp_paramenter);
if( when < t )
{
printf("ERROR: %f ERROR_TIME_EVENT - CLIENT_ARRIVAL_EVENT %d %f\n", t, j, when);
return 1;
}
busca_tempo (events, when, ant, pont);
if(*pont==NULL) break;
}
insere(events,CLIENT_ARRIVAL_EVENT,when,0,j);
number_events++;
if(DEBUG_LEVEL>3) printf("%f PUSH CLIENT_ARRIVAL_EVENT %d %f\n", t, j, when);
//criando evento de saida para cliente no vetor de saidas e passando endereço para o cliente
when=INF;
clients_vector[j].exit_event = insere(exits,CLIENT_EXIT_EVENT,when,0,j);
number_events++;
if(DEBUG_LEVEL>3) printf("%f PUSH CLIENT_EXIT_EVENT %i %f\n", t, j, when);
//criando evento de fluxo para cliente e passando endereço para o cliente
when = INF;
clients_vector[j].flow_event = malloc_flow(j);
clients_vector[j].flow_event_alloc=0;
if(KNOWLEDGE < NUMBER_SERVERS ) {
for(i=0; i<KNOWLEDGE ; i++)
{
while(true)
{
number = rand() % NUMBER_SERVERS;
if (knowledge_temp[number]!=j) break;
}
knowledge_servers[j][i]=number;
knowledge_temp[number] = j;
}
}
else{
for(i=0; i<KNOWLEDGE ; i++){
knowledge_servers[j][i]=i;
}
}
}
//Processando a lista de eventoS
temp_event_events = get_next(events);
temp_event_exits = get_next(exits);
if(temp_event_events == NULL)
{
printf("ERROR: Nao ha eventos para comecar a simulacao\n");
return 1;
}
t_print++;
while( number_events )
{
if(DEBUG_LEVEL>3) printf( "\n%f REMAINING EVENTS TO PROCESS %d\n", t, number_events);
if(DEBUG_LEVEL>3) listar(exits);
if(DEBUG_LEVEL>3) listar(events);
if(DEBUG_LEVEL>3) printf("\n");
if(get_time(temp_event_events) >= get_time(temp_event_exits)) //verificando qual evento ocorre primeiro: events ou exits
{
//EXIT_EVENT OCORRE PRIMEIRO
t= get_time(temp_event_exits);
client_id = get_client_id(temp_event_exits);
process_exit_event(temp_event_exits, exits, events, clients_vector, connections, clients_state, servers_state, &servers_up, &number_events, CLIENT_EXIT_EVENT,client_id );
}
else{
//EVENTO DA LISTA EVENTS OCORRE PRIMEIRO QUE UMA SAIDA
t = get_time(temp_event_events);
event_id = get_event_id(temp_event_events);
client_id = get_client_id(temp_event_events);
server_id = get_server_id(temp_event_events);
switch(event_id)
{
case CLIENT_ARRIVAL_EVENT:
i = process_arrival_event(temp_event_events, events, clients_vector, knowledge_servers, connections, flow, clients_state, servers_state, &servers_up, &number_events, CLIENT_ARRIVAL_EVENT, client_id, &clients_up);
if( i == 1) return 1;
break;
case SERVER_ARRIVAL_EVENT:
i = process_arrival_event(temp_event_events, events, clients_vector, knowledge_servers, connections, flow, clients_state, servers_state, &servers_up, &number_events, SERVER_ARRIVAL_EVENT, server_id, &clients_up );
if( i == 1) return 1;
break;
case FLOW_EVENT:
i = process_flow_event(temp_event_events, events, clients_vector, knowledge_servers, connections, flow, client_id, &number_events);
if( i == 1) return 1;
break;
case CONNECTION_EVENT:
i = process_connection_event(temp_event_events, events, exits, clients_vector, connections, servers_number_connections, clients_number_connections, flow, clients_flow, servers_flow, data, clients_state, servers_state, event_id, server_id, client_id, &number_events, clients_up);
if( i == 1) return 1;
break;
case DISCONNECTION_EVENT:
i = process_connection_event(temp_event_events, events, exits, clients_vector, connections, servers_number_connections, clients_number_connections, flow, clients_flow, servers_flow, data, clients_state, servers_state, event_id, server_id, client_id, &number_events,clients_up);
if( i == 1) return 1;
break;
case SERVER_EXIT_EVENT:
i = process_exit_event(temp_event_exits, exits, events, clients_vector, connections, clients_state, servers_state, &servers_up, &number_events, SERVER_EXIT_EVENT, server_id );
if( i == 1) return 1;
break;
}
}//END else event time < exit time
//atualizando evento de saida mais proximo
temp_event_exits = get_next(exits);
temp_event_events = get_next(events);
}//END while - ENQUANTO HOUVER EVENTOS
for(j=0;j<NUMBER_CLIENTS;j++)
{
//dp_clients_number_connections[j] = sqrt(var_clients_number_connections[j]);
//ic_clients_number_connections[j] = ((1.96*dp_clients_number_connections[j])/sqrt(nsamples));
//dp_clients_flow[j] = sqrt(var_clients_flow[j]);
//ic_clients_flow[j] = ((1.96*dp_clients_flow[j])/sqrt(nsamples));
mean_clients_number_connections[j] += oldmean_clients_number_connections[j]*(t-t_last_fi);
mean_clients_flow[j] += oldmean_clients_flow[j]*(t-t_last_fi);
mean_clients_number_connections[j] = mean_clients_number_connections[j]/t;
mean_clients_flow[j] = mean_clients_flow[j]/t;
printf( "CLIENT_CONNECTION_STATISTIC %d %Lf\n", j, mean_clients_number_connections[j]);
printf( "CLIENT_FLOW_STATISTIC %d %Lf\n", j, mean_clients_flow[j]);
if(DEBUG_LEVEL>2) {
mean_c[j]+=oldmean_c[j]*(t-t_last_fi);
mean_c[j] = mean_c[j]/t;
var_c[j]+=oldvar_c[j]*(t-t_last_fi);
var_c[j] = var_c[j]/t;
printf( "CLIENT_FLOW_MAT %d %Lf %Lf\n", j, mean_c[j], var_c[j]);
}
}
for(i=0; i< NUMBER_SERVERS ; i++)
{
//dp_servers_number_connections[i] = sqrt(var_servers_number_connections[i]);
//ic_servers_number_connections[i] = ((1.96*dp_servers_number_connections[i])/sqrt(nsamples));
//dp_servers_flow[i] = sqrt(var_servers_flow[i]);
//ic_servers_flow[i] = ((1.96*dp_servers_flow[i])/sqrt(nsamples));
mean_servers_number_connections[i] += oldmean_servers_number_connections[i]*(t-t_last_fi);
mean_servers_flow[i] += oldmean_servers_flow[i]*(t-t_last_fi);
mean_servers_number_connections[i] = mean_servers_number_connections[i]/t;
mean_servers_flow[i] = mean_servers_flow[i]/t;
printf( "SERVER_CONNECTION_STATISTIC %d %Lf\n", i, mean_servers_number_connections[i]);
printf( "SERVER_FLOW_STATISTIC %d %Lf\n", i, mean_servers_flow[i]);
if(DEBUG_LEVEL>2) {
mean_s[i]+=oldmean_s[i]*(t-t_last_fi);
mean_s[i] = mean_s[i]/t;
var_s[i]+=oldvar_s[i]*(t-t_last_fi);
var_s[i] = var_s[i]/t;
printf( "SERVER_FLOW_MAT %d %Lf %Lf\n", i, mean_s[i], var_s[i]);
}
}
//dp_system_flow = sqrt(var_system_flow);
//ic_system_flow = ((1.96*dp_system_flow)/sqrt(nsamples));
mean_system_flow += oldmean_system_flow*(t-t_last_fi);
mean_system_flow = mean_system_flow/t;
printf( "SYSTEM_FLOW_STATISTIC 0 %Lf\n", mean_system_flow);
if(DEBUG_LEVEL>0) printf( "%f END", t);
return 0;
}//END main
//gera numero aleatorio com distribuicao exponencial
double gera_aleatorio(double parametro)
{
double number;
while(true)
{
number = (double)random()/RAND_MAX;
if(number != 0) break;
}
return (double)log(1-number)/(-parametro);
}
//remove evento da lista de eventos, mas nao desaloca a memoria
void remove_event(event *event_toremove)
{
struct event *prev, *next;
prev = event_toremove->prev;
next = event_toremove->next;
prev->next=next;
if(next != NULL) next->prev=prev;
}
//reinsere evento na lista de eventos
void recoloca ( event *list, int event_id, float time, int server_id, int client_id, event *fix_event )
{
struct event *pont, *ant;
ant = list;
pont = list->next;
//procura posicao correta
while(pont)
{
if( pont->time < time )
{ ant=pont;
pont=pont->next;}
else{
break;}
}
fix_event->time = time;
fix_event->next = (ant)->next;
fix_event->prev = (ant);
(ant)->next = fix_event;
if((fix_event->next) != NULL) (fix_event->next)->prev = fix_event;
}
void busca_tempo ( event *events, float when, event **ant, event **ponte) {
struct event *ptr;
*ant = events; // aponta no anterior
*ponte = NULL; // aponta no procurado, se nao achar retorna nulo
ptr = events->next; // aponta para candidato
while (ptr)
{
if ((ptr->time) < when)
{ // ainda nao chegou no no
*ant = ptr;
ptr = ptr->next;
}
else
{
//a principio enocontramos o evento, ou no caso de insercao, a posicao a ser inserido
if (ptr->time == when)
{
*ponte = ptr; // achou evento
}
//CASO DE INSERCAO: (ou evento deveria estar na lista e nao esta - ERROR)
ptr = NULL; //esta deveria ser a posicao do evento
//no caso de insercao, "ant" fica apontando para evento que ira antecer novo evento
//laco eh quebrado aqui pois ptr recebe valor null
}
}
}
// funcao usada para busca de eventos lista "events" - ou para encontrar posicao de insercao
void busca ( event *events, float when, int server_id, int client_id, event **ant, event **ponte) {
struct event *ptr;
*ant = events; // aponta no anterior
*ponte = NULL; // aponta no procurado, se nao achar retorna nulo
ptr = events->next; // aponta para candidato
while (ptr)
{
if ((ptr->time) < when)
{ // ainda nao chegou no no
*ant = ptr;
ptr = ptr->next;
}
else
{
//a principio enocontramos o evento, ou no caso de insercao, a posicao a ser inserido
if (ptr->time == when)
{
if((client_id == ptr->client_id) && (server_id == ptr->server_id))
{
*ponte = ptr; // achou evento
break;
}
else {
//temos um evento com mesmo horario, mas nao eh o evento que buscamos
*ant = ptr;
ptr = ptr->next;
continue;}
}
//CASO DE INSERCAO: (ou evento deveria estar na lista e nao esta - ERROR)
ptr = NULL; //esta deveria ser a posicao do evento
//no caso de insercao, "ant" fica apontando para evento que ira antecer novo evento
//laco eh quebrado aqui pois ptr recebe valor null
}
}
}
// funcao usada para busca de eventos lista "exits" - ou para encontrar posicao de insercao
//equivalente a funcao "busca"
void busca2 ( event *events, int who, event **ant, event **ponte) {
event *ptr;
*ant = events;
*ponte = NULL;
ptr = events->next;
while (ptr)
{
if ((ptr->client_id) != who)
{ // ainda nao chegou no no
*ant = ptr;
ptr = ptr->next;
}
else
{
if (ptr->client_id == who)
{
*ponte = ptr; // achou
break;
}
ptr = NULL; // nao estava na lista - ou: posicao para insercao, "ant" aponta para evento que o antecede
//laco eh rompido aqui
}
}
}
event * insere ( event *list, int event_id, float time, int server_id, int client_id )
{
struct event *temp_event1, // ponteiro para o novo no a inserir
**ant, // ponteiro para ponteiro na lista - vai apontar para evento que ja existe na lista e antecede imediatamente novo evento
**pont; // ponteiro para ponteiro, auxilia busca
ant = ( event **) malloc(sizeof ( event *));
pont = ( event **) malloc(sizeof ( event *));
temp_event1 = (event *)malloc(1*sizeof(event));
if(event_id==CLIENT_EXIT_EVENT){
busca2 (list, client_id, ant, pont);}
else{
busca (list, time, server_id, client_id, ant, pont);}
temp_event1->event_id = event_id;
temp_event1->client_id = client_id;
temp_event1->server_id = server_id;
temp_event1->time = time;
temp_event1->next = (*ant)->next;
temp_event1->prev = (*ant);
(*ant)->next = temp_event1;
if(temp_event1->next!=NULL){
(temp_event1->next)->prev = temp_event1;}
return temp_event1;
}
//remove e desaloca evento de listas - eventos de fluxo somente sao removidos da lista
int erase ( event *list, event * event_remove )
{
int event_id, client_id, server_id;
struct event *pont, *ant;
float time;
event_id = event_remove->event_id;
client_id = event_remove->client_id;
server_id = event_remove->server_id;
time = event_remove->time;
ant = list;
pont = list->next;
//buscando evento utilizando posicao da memoria como base de comparacao
while(pont)
{
if( pont == event_remove )
{break;}
else
{ ant=pont;
pont=pont->next;}
}
//arrumando ponteiros
if (pont) {
(ant)->next = (pont)->next;
if(((pont)->next) != NULL) ((pont)->next)->prev = (pont)->prev;
if(event_id!=FLOW_EVENT) free(pont);
}
else
{
if(event_id == CLIENT_EXIT_EVENT){
printf("DELETE_ERROR CLIENT_EXIT_EVENT | Time: %f | Client id: %d \n", time, client_id);}
else{
if(event_id == SERVER_EXIT_EVENT){
printf("DELETE_ERROR SERVER_EXIT_EVENT | Time: %f | Server id: %d \n", time, server_id);}
if(event_id == FLOW_EVENT){
printf("DELETE_ERROR FLOW_EVENT | Time: %f | Server id: %d | Client id: %d \n", time, server_id, client_id);}
else if(event_id == DISCONNECTION_EVENT){
printf("DELETE_ERROR DISCONNECTION_EVENT | Time: %f | Server id: %d | Client id: %d \n", time, server_id, client_id);}
else if(event_id == CONNECTION_EVENT){
printf("DELETE_ERROR CONNECTION_EVENT | Time: %f | Server id: %d | Client id: %d \n", time, server_id, client_id);
if(event_id == SERVER_ARRIVAL_EVENT){
printf("DELETE_ERROR SERVER_ARRIVAL_EVENT | Time: %f | Server id: %d \n", time, server_id);}
if(event_id == CLIENT_ARRIVAL_EVENT){
printf("DELETE_ERROR CLIENT_ARRIVAL_EVENT | Time: %f | Server id: %d \n", time, client_id);}
}
}
return 1;
}
return 0;
}
void listar (struct event *ptlista) {
struct event *pont;
pont = ptlista->next;
while (pont)
{
if(pont->event_id == CLIENT_EXIT_EVENT){
printf("QUEUE_CLIENT_EXIT_EVENT | Time: %f | Client id: %d \n", pont->time, pont->client_id);}
else{
if(pont->event_id == CLIENT_ARRIVAL_EVENT){
printf("QUEUE_CLIENT_ARRIVAL_EVENT | Time: %f | Client id: %d \n", pont->time, pont->client_id);}
if(pont->event_id == SERVER_ARRIVAL_EVENT){
printf("QUEUE_SERVER_ARRIVAL_EVENT | Time: %f | Server id: %d \n", pont->time, pont->server_id);}
if(pont->event_id == CLIENT_ARRIVAL_EVENT){
printf("QUEUE_SERVER_EXIT_EVENT | Time: %f | Server id: %d \n", pont->time, pont->server_id);}
if(pont->event_id == FLOW_EVENT){
printf("QUEUE_FLOW_EVENT | Time: %f | Client id: %d \n", pont->time, pont->client_id);}
else if(pont->event_id == DISCONNECTION_EVENT){
printf("QUEUE_DISCONNECTION_EVENT | Time: %f | Server id: %d | Client id: %d \n", pont->time, pont->server_id, pont->client_id);}
else if(pont->event_id == CONNECTION_EVENT){
printf("QUEUE_CONNECTION_EVENT | Time: %f | Server id: %d | Client id: %d \n", pont->time, pont->server_id, pont->client_id);}
}
pont = pont->next;
}
}
void print_system_state(int t_print, int clients_number_connections[NUMBER_CLIENTS], int servers_number_connections[NUMBER_SERVERS], long double client_flow[NUMBER_CLIENTS], long double server_flow[NUMBER_SERVERS])
{
int i, j;
long double flow_accumulator, system_total_flow;
system_total_flow = 0;
for(j=0;j<NUMBER_CLIENTS;j++)
{
system_total_flow += client_flow[j];
printf("%d CLIENT_STATE %d %d %Lf\n", t_print, j, clients_number_connections[j], client_flow[j]);
}
for(j=0;j<NUMBER_SERVERS;j++)
{
//system_total_flow += client_flow[j];
printf("%d SERVER_STATE %d %d %Lf\n", t_print, j, servers_number_connections[j], server_flow[j]);
}
printf("%d SYSTEM_STATE %Lf\n", t_print, system_total_flow );
}
struct event * malloc_flow(int client_id)
{
struct event *temp_event1; // ponteiro para o novo no a inserir
temp_event1 = (event *)malloc(1*sizeof(event));
temp_event1->event_id = FLOW_EVENT;
temp_event1->client_id = client_id;
temp_event1->server_id = 0;
temp_event1->time = INF;
temp_event1->next = NULL;
temp_event1->prev = NULL;
//retorna endereco do evento de fluxo alocado
return temp_event1;
}
struct event * get_next(event *list)
{
return list->next;
}
float get_time(event *temp)
{
if(temp == NULL) return INF;
return temp->time;
}
int get_client_id(event *temp)
{
return temp->client_id;
}
int get_server_id(event *temp)
{
return temp->server_id;
}
int get_event_id(event *temp)
{
return temp->event_id;
}
void set_servers_capacite_random()
{
// CODIGO DE DIVISAO DE GRUPOS:
// 0: TODOS COM CAPACIDADES DISTINTAS
// 1: TODOS COM A MESMA CAPACIDADE
// 2: 1/2 - 1/2
// 3: 1/3 - 1/3 - 1/3
// 4: 1/3 - 2/3
// 5: 1/4 - 1/4 - 1/4 - 1/4
// 6: 1/4 - 1/4 - 1/2
// 7: 1/4 - 3/4
int i, j;
float cap1, cap2, cap3, cap4;
float num_servers;
num_servers = (float)NUMBER_SERVERS;
switch(SERVERS_BAND_DIVISION)
{
case -1:
// -1: TODOS COM CAPACIDADES IGUAIS - CLIENTES E SERVIDORES
while(true)
{
cap1 = rand();
if((cap1 > MIN_CAP_SERVER) && (cap1 < MAX_CAP_SERVER) && (cap1 > MIN_CAP_CLIENT) && (cap1 < MAX_CAP_CLIENT)) break;
}