3
3
#include "../../core/client/keys.h"
4
4
#include <math.h>
5
5
#include <stdio.h>
6
- static void die (char * msg ) {
7
- fprintf (stderr , COLORT_RED "Error: %s" COLORT_RESET "\n" , msg );
8
- exit (EXIT_FAILURE );
9
- }
6
+
7
+ typedef struct recorder_entry {
8
+ char * name ;
9
+ char * * args ;
10
+ int argl ;
11
+ sb_t content ;
12
+ struct recorder_entry * next ;
13
+
14
+ } recorder_entry_t ;
10
15
11
16
typedef struct {
12
17
char * file ;
13
18
in3_transport_send transport ;
14
19
FILE * f ;
15
20
in3_storage_handler_t * cache ;
16
21
uint64_t time ;
22
+ recorder_entry_t * queue ;
17
23
} recorder_t ;
18
24
19
- typedef struct {
20
- char * name ;
21
- char * * args ;
22
- int argl ;
23
-
24
- } recorder_entry_t ;
25
-
26
25
static recorder_t rec = {
27
26
.file = NULL ,
28
27
.transport = NULL ,
29
28
.f = NULL ,
30
29
.cache = NULL ,
30
+ .queue = NULL ,
31
31
.time = 0 };
32
32
33
33
static int rand_out (void * s ) {
@@ -38,64 +38,89 @@ static int rand_out(void* s) {
38
38
return r ;
39
39
}
40
40
41
- recorder_entry_t read_entry (sb_t * sb ) {
42
- recorder_entry_t entry = {0 };
41
+ static inline bool match (recorder_entry_t * entry , const char * type , const char * first_arg ) {
42
+ return entry && entry -> name && strcmp (type , entry -> name ) == 0 && (first_arg == NULL || (entry -> argl && strcmp (entry -> args [0 ], first_arg ) == 0 ));
43
+ }
43
44
44
- char buffer [1024 ];
45
+ static recorder_entry_t * read_one_entry () {
46
+ recorder_entry_t * entry = NULL ;
47
+ char buffer [1024 ];
45
48
while (fgets (buffer , 1023 , rec .f )) {
46
49
int l = strlen (buffer );
47
50
if (buffer [l - 1 ] == '\n' )
48
51
buffer [-- l ] = 0 ;
49
52
if (!l ) break ;
50
- if (!entry .name ) {
51
- char * ptr = strtok (buffer + 3 , " " );
52
- entry .name = _strdupn (ptr , -1 );
53
+ if (!entry ) {
54
+ entry = _calloc (sizeof (recorder_entry_t ), 1 );
55
+ char * ptr = strtok (buffer + 3 , " " );
56
+ entry -> name = _strdupn (ptr , -1 );
53
57
while ((ptr = strtok (NULL , " " ))) {
54
- entry . args = entry . argl ? _realloc (entry . args , sizeof (char * ) * (entry . argl + 1 ), sizeof (char * ) * entry . argl ) : _malloc (sizeof (char * ));
55
- entry . args [entry . argl ++ ] = _strdupn (ptr , -1 );
58
+ entry -> args = entry -> argl ? _realloc (entry -> args , sizeof (char * ) * (entry -> argl + 1 ), sizeof (char * ) * entry -> argl ) : _malloc (sizeof (char * ));
59
+ entry -> args [entry -> argl ++ ] = _strdupn (ptr , -1 );
56
60
}
57
61
} else
58
- sb_add_chars (sb , buffer );
62
+ sb_add_chars (& entry -> content , buffer );
59
63
}
60
-
61
64
return entry ;
62
65
}
63
- static void entry_free (recorder_entry_t * e , sb_t * sb ) {
66
+
67
+ recorder_entry_t * next_entry (const char * type , const char * firs_arg ) {
68
+
69
+ recorder_entry_t * last = rec .queue , * end = NULL ;
70
+ for (recorder_entry_t * n = last ; n ; last = n , n = n -> next ) {
71
+ if (match ((end = n ), type , firs_arg )) {
72
+ if (last == n )
73
+ rec .queue = n -> next ;
74
+ else
75
+ last -> next = n -> next ;
76
+ return n ;
77
+ }
78
+ }
79
+
80
+ do {
81
+ if (match ((last = read_one_entry ()), type , firs_arg ))
82
+ return last ;
83
+ if (!last ) {
84
+ fprintf (stderr , COLORT_RED "Error: expected entry %s %s but did not find it!" COLORT_RESET "\n" , type , firs_arg ? firs_arg : "" );
85
+ exit (EXIT_FAILURE );
86
+ }
87
+ if (end )
88
+ end -> next = last ;
89
+ else
90
+ rec .queue = last ;
91
+ end = last ;
92
+
93
+ } while (true);
94
+ }
95
+
96
+ static void entry_free (recorder_entry_t * e ) {
64
97
if (e -> name ) _free (e -> name );
65
98
for (int i = 0 ; i < e -> argl ; i ++ ) _free (e -> args [i ]);
66
99
_free (e -> args );
67
- if (sb && sb -> data ) _free (sb -> data );
68
- if ( sb ) * sb = ( sb_t ){ 0 } ;
100
+ if (e -> content . data ) _free (e -> content . data );
101
+ _free ( e ) ;
69
102
}
70
103
static int rand_in (void * s ) {
71
104
UNUSED_VAR (s );
72
- sb_t sb = {0 };
73
- recorder_entry_t entry = read_entry (& sb );
74
- if (!entry .name || strcmp (entry .name , "rand" )) die ("expected rand in recorder!" );
75
- if (entry .argl != 1 ) die ("expect one arg for random" );
76
- int r = atoi (entry .args [0 ]);
77
- entry_free (& entry , & sb );
78
-
105
+ recorder_entry_t * entry = next_entry ("rand" , NULL );
106
+ int r = atoi (entry -> args [0 ]);
107
+ entry_free (entry );
79
108
return r ;
80
109
}
81
110
82
111
static in3_ret_t recorder_transport_in (in3_request_t * req ) {
83
- sb_t sb = {0 };
84
- recorder_entry_t entry = {0 };
112
+
85
113
if (req -> action == REQ_ACTION_SEND ) {
86
- entry = read_entry (& sb );
87
- if (!entry .name || strcmp (entry .name , "request" )) die ("expected request in recorder!" );
88
- entry_free (& entry , & sb );
114
+ entry_free (next_entry ("request" , NULL ));
89
115
req -> cptr = & rec ;
90
116
}
91
117
if (req -> action != REQ_ACTION_CLEANUP ) {
92
- entry = read_entry (& sb );
93
- if (!entry .name || strcmp (entry .name , "response" )) die ("expected response in recorder!" );
94
- in3_response_t * r = req -> ctx -> raw_response + atoi (entry .args [0 ]);
95
- sb_add_chars (& r -> data , sb .data );
96
- r -> state = atoi (entry .args [3 ]);
97
- r -> time = atoi (entry .args [4 ]);
98
- entry_free (& entry , & sb );
118
+ recorder_entry_t * entry = next_entry ("response" , d_get_stringk (req -> ctx -> requests [0 ], K_METHOD ));
119
+ in3_response_t * r = req -> ctx -> raw_response + atoi (entry -> args [1 ]);
120
+ sb_add_chars (& r -> data , entry -> content .data );
121
+ r -> state = atoi (entry -> args [3 ]);
122
+ r -> time = atoi (entry -> args [4 ]);
123
+ entry_free (entry );
99
124
}
100
125
101
126
return 0 ;
@@ -116,7 +141,7 @@ static in3_ret_t recorder_transport_out(in3_request_t* req) {
116
141
for (int i = 0 ; m ; i ++ , m = m -> next ) {
117
142
in3_response_t * r = req -> ctx -> raw_response + i ;
118
143
if (r -> time ) {
119
- fprintf (rec .f , ":: response %i %s %s %i %i\n" , i , d_get_stringk (req -> ctx -> requests [0 ], K_METHOD ), ctx_get_node (chain , m )-> url , r -> state , r -> time );
144
+ fprintf (rec .f , ":: response %s %i %s %i %i\n" , d_get_stringk (req -> ctx -> requests [0 ], K_METHOD ), i , ctx_get_node (chain , m )-> url , r -> state , r -> time );
120
145
char * data = format_json (r -> data .data ? r -> data .data : "" );
121
146
fprintf (rec .f , "%s\n\n" , data );
122
147
fflush (rec .f );
@@ -130,13 +155,9 @@ static in3_ret_t recorder_transport_out(in3_request_t* req) {
130
155
bytes_t * rec_get_item_in (void * cptr , const char * key ) {
131
156
UNUSED_VAR (cptr );
132
157
UNUSED_VAR (key );
133
- sb_t sb = {0 };
134
- recorder_entry_t entry = read_entry (& sb );
135
- if (!entry .name || strcmp (entry .name , "cache" )) die ("expected cache in recorder!" );
136
- if (entry .argl != 2 ) die ("expect 2 args for cache" );
137
- if (strcmp (key , entry .args [0 ])) die ("wrong cache key" );
138
- bytes_t * found = atoi (entry .args [1 ]) ? hex_to_new_bytes (sb .data , sb .len ) : NULL ;
139
- entry_free (& entry , & sb );
158
+ recorder_entry_t * entry = next_entry ("cache" , key );
159
+ bytes_t * found = atoi (entry -> args [1 ]) ? hex_to_new_bytes (entry -> content .data , entry -> content .len ) : NULL ;
160
+ entry_free (entry );
140
161
141
162
return found ;
142
163
}
@@ -177,13 +198,16 @@ uint64_t static_time(void* t) {
177
198
return rec .time ;
178
199
}
179
200
180
- void recorder_write_start (in3_t * c , char * file ) {
201
+ void recorder_write_start (in3_t * c , char * file , int argc , char * argv [] ) {
181
202
rec .file = file ;
182
203
rec .transport = c -> transport ;
183
204
c -> transport = recorder_transport_out ;
184
205
rec .f = fopen (file , "w" );
185
206
rec .cache = c -> cache ;
186
207
in3_set_func_rand (rand_out );
208
+ fprintf (rec .f , ":: cmd" );
209
+ for (int i = 0 ; i < argc ; i ++ ) fprintf (rec .f , " %s" , strcmp (argv [i ], "-fo" ) ? argv [i ] : "-fi" );
210
+ fprintf (rec .f , "\n\n" );
187
211
in3_set_storage_handler (c , rec_get_item_out , rec_set_item_out , rec_clear_out , & rec );
188
212
fprintf (rec .f , ":: time %u\n\n" , (uint32_t ) in3_time (NULL ));
189
213
}
@@ -195,9 +219,22 @@ void recorder_read_start(in3_t* c, char* file) {
195
219
rec .f = fopen (file , "r" );
196
220
in3_set_func_rand (rand_in );
197
221
in3_set_storage_handler (c , rec_get_item_in , rec_set_item_in , rec_clear_in , & rec );
198
- sb_t sb = {0 };
199
- recorder_entry_t entry = read_entry (& sb );
200
- rec .time = entry .argl >= 1 ? atoll (entry .args [0 ]) : 0 ;
201
- entry_free (& entry , & sb );
222
+ recorder_entry_t * entry = next_entry ("time" , NULL );
223
+ rec .time = entry -> argl >= 1 ? atoll (entry -> args [0 ]) : 0 ;
224
+ entry_free (entry );
202
225
in3_set_func_time (static_time );
203
226
}
227
+
228
+ void recorder_update_cmd (char * file , int * argc , char * * argv []) {
229
+ rec .file = file ;
230
+ rec .f = fopen (file , "r" );
231
+ recorder_entry_t * entry = next_entry ("cmd" , NULL );
232
+ * argc = entry -> argl ;
233
+ * argv = entry -> args ;
234
+ for (int i = 0 ; i < entry -> argl ; i ++ ) {
235
+ if (strcmp (entry -> args [i ], "-fi" ) == 0 ) entry -> args [i + 1 ] = file ;
236
+ }
237
+ fclose (rec .f );
238
+ rec .f = NULL ;
239
+ rec .queue = NULL ;
240
+ }
0 commit comments