1 /*------------------------------------------------------------------------------
2 *
3 * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4 * The YADIFA TM software product is provided under the BSD 3-clause license:
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of EURid nor the names of its contributors may be
16 * used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *------------------------------------------------------------------------------
32 *
33 */
34
35 /** @defgroup test
36 * @ingroup test
37 * @brief logger_test file
38 *
39 * logger_test test program, will not be installed with a "make install"
40 *
41 * To create a new test based on the logger_test:
42 *
43 * _ copy the folder
44 * _ replace "logger_test" by the name of the test
45 * _ add the test to the top level Makefile.am and configure.ac
46 *
47 */
48 #include <sys/mman.h>
49
50 #include <dnscore/dnscore.h>
51 #include <dnscore/logger.h>
52 #include <dnscore/fdtools.h>
53 #include <dnscore/file_output_stream.h>
54 #include <dnscore/logger_channel_stream.h>
55 #include <dnscore/thread_pool.h>
56 #include <dnscore/zalloc.h>
57 #include <dnscore/shared-heap.h>
58 #include <dnscore/buffer_output_stream.h>
59 #include <dnscore/process.h>
60 #include <dnscore/async.h>
61 #include <dnscore/server-setup.h>
62 #include <dnscore/socket-server.h>
63
64 pid_t fork_ex();
65
66
67 static logger_handle *g_parent_logger = LOGGER_HANDLE_SINK;
68 static logger_handle *g_child_logger = LOGGER_HANDLE_SINK;
69
70 #define HEAP_SIZE 0x40000000
71
72 #define CHILDREN 4
73
74 #define MMAP_TEST 0
75 #if 0
76 #define MICROPAUSE 10000
77 #endif
78
79 static char one_kb_string[1048] =
80 "BEGIN0123456789ABCDEFGHIJKLMNOPQ"
81 "RSTUVWXYZabcdefghijklmnopqrstuvw"
82 "xyz-j7YZ5sjpN2GPC6B870yZ3HJBIbpk"
83 "7v6hmzxHu6eAomRhAb9ikkfxSP1qy7S6"
84 "Q6cnNREREssBkSv8hlsEoD0GR0Ip1Tu1"
85 "yDQj2LhCpzTJacaJ1qxJ2TjoQxoVi6xe"
86 "m7DHzeUvyJca06wmuZOs0oKGQmJFRu9a"
87 "uz9f8fT8onBFjgBpBcPmzor7rEpqWrcK"
88 "NEtpoueRln6q1qSK6RUkULbYwLShTWgD"
89 "bMstlAEVp5EqUIPhlQXSf4eOpImJM4Yt"
90 "Lu4LFThG5GU8n9zNTk4WlxcGQCj8Emx1"
91 "pqtjHWx55lLiqoJCLgDYPDN99vjB8ukz"
92 "XfaXHQIjq44rnxvwpf7cEpMMxHCp7IOO"
93 "18nJ42O4CmxTfoKtIkJkuA0NczkitEeF"
94 "64Gtj3TubiBLtfRra8zBN8ByqfeeQZG1"
95 "XgHaO6s6covHabtb0gzLVV1GenCPvYfp"
96 "pivvH8lSWvkeH0xJ5zTjG19Voql883Ii"
97 "y28NCXTosBFe81DhvqHQgQ7FU7Njv96o"
98 "kiC9Cr8f6CEXp23qe8fL3A4iaEcMPg4f"
99 "iRZzUAQtblzzf3nryBpe7gHZiIjE1kUG"
100 "eMXJehH0LDFrWR4AmUhZNxR8aK1RSFKZ"
101 "Uy32zPIx6TMrTFncSTBgqluwObbFAk6R"
102 "1G6ToGPL1X75JNpwXhURN752RNQQUCGo"
103 "Vv1SMKBTzpMXH9hfy33wllyiru6ZAciJ"
104 "iAa0KmlE9vfqYIv6hA0PyMqIwP7twDRs"
105 "kuVI4tbBBY5ScHsa42SnsFpYEXBJuKk1"
106 "LFQ4sQED1Stvt5rtf7FDUx316eZ64qVB"
107 "1k1sO9YgNzrrv3gpip3vcHr6SWLybVMa"
108 "yw047f0YZhjfNXg2YOXPJaNmXvKaUiOe"
109 "SyeINNqCIQuDzCUYeLscEEWaoyx5NAyt"
110 "mj9hcK4v3S4zLpB3fs1xa5icmV9uz2SW"
111 "Uk75WhbSnQ3iW8kMcP1TYz9yDIufAz6m"
112 "THE-END";
113
114 struct thread_ctx
115 {
116 async_wait_s *aw;
117 logger_handle *logger;
118 int f;
119 int count;
120 };
121
122 static char logging_stuff_thread_tag[8] = "stuff";
123
124 static void*
logging_stuff_thread(void * args)125 logging_stuff_thread(void *args)
126 {
127 struct thread_ctx *ctx = (struct thread_ctx*)args;
128 async_wait_s *aw = ctx->aw;
129 int f = ctx->f;
130 int count = ctx->count;
131
132 #define MODULE_MSG_HANDLE ctx->logger
133
134 logger_handle_set_thread_tag(logging_stuff_thread_tag);
135
136 async_wait(aw);
137
138 for(int j = 0; j < count; j += 100)
139 {
140 for(int i = 0; i < 50; ++i)
141 {
142 log_info("child #%i log line %i that will require a growth of the originally allocated 48 bytes buffer (thread)", f, j + i);
143 #if MICROPAUSE > 0
144 usleep(MICROPAUSE);
145 #endif
146 }
147
148 for(int i = 50; i < 100; ++i)
149 {
150 log_info("child #%i log line %i '%s' (thread)", f, j + i, &one_kb_string[(j + i) & 1023]);
151 #if MICROPAUSE > 0
152 usleep(MICROPAUSE);
153 #endif
154 }
155
156 #if 0
157 if(j < 250)
158 {
159 logger_flush();
160 }
161
162 if(j < 500)
163 {
164 usleep(10000);
165 }
166 #endif
167 }
168
169 #undef MODULE_MSG_HANDLE
170
171 logger_handle_clear_thread_tag();
172
173 return NULL;
174 }
175
176 static void
main_exit()177 main_exit()
178 {
179 logger_handle_msg(g_system_logger, MSG_INFO, "main_exit: terminating this process");
180 logger_flush();
181 flushout();
182 flusherr();
183 }
184
185 int
main(int argc,char * argv[])186 main(int argc, char *argv[])
187 {
188 /* initializes the core library */
189
190 int count = 0;
191 if(argc >= 2)
192 {
193 count = atoi(argv[1]);
194 }
195
196 if(count <= 1)
197 {
198 count = 1000;
199 }
200
201 dnscore_init_ex(DNSCORE_ALL, argc, argv);
202
203 atexit(main_exit);
204
205 #if MMAP_TEST
206 int *please_dont_be_shared_ptr;
207 please_dont_be_shared_ptr = (int*)mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
208 *please_dont_be_shared_ptr = 0;
209 #endif
210
211 logger_init_ex(0x100000, HEAP_SIZE);
212 logger_start();
213
214 {
215 output_stream stdout_os;
216 logger_channel *stdout_channel;
217
218 static const char * const log_file_name = "/tmp/daemonised-logger-test.log";
219 unlink(log_file_name);
220
221 ya_result ret;
222 //fd_output_stream_attach(&stdout_os, dup_ex(1));
223 if(FAIL(ret = file_output_stream_create(&stdout_os, log_file_name, 0644)))
224 {
225 formatln("failed to create %s: %r", log_file_name, ret);
226 exit(1);
227 }
228 buffer_output_stream_init(&stdout_os, &stdout_os, 65536);
229 stdout_channel = logger_channel_alloc();
230 logger_channel_stream_open(&stdout_os, FALSE, stdout_channel);
231 logger_channel_register("stdout", stdout_channel);
232
233 logger_handle_create("system", &g_system_logger);
234 logger_handle_create("parent", &g_parent_logger);
235 logger_handle_create("child", &g_child_logger);
236
237 logger_handle_add_channel("system", MSG_ALL_MASK, "stdout");
238 logger_handle_add_channel("parent", MSG_ALL_MASK, "stdout");
239 logger_handle_add_channel("child", MSG_ALL_MASK, "stdout");
240
241 logger_flush();
242
243 sleep(1);
244 }
245
246 async_wait_s *aw = async_wait_create_shared(0, 1);
247
248 logger_handle_msg(g_system_logger, MSG_INFO, "system: before daemonise");
249 logger_handle_msg(g_parent_logger, MSG_INFO, "parent: before daemonise");
250 logger_handle_msg(g_child_logger, MSG_INFO, "child: before daemonise");
251
252 server_setup_daemon_go();
253
254 logger_handle_msg(g_system_logger, MSG_INFO, "system: after daemonise");
255 logger_handle_msg(g_parent_logger, MSG_INFO, "parent: after daemonise");
256 logger_handle_msg(g_child_logger, MSG_INFO, "child: after daemonise");
257
258 logger_flush();
259
260 // the socket server is spawned before the damonise: let's see if it still works
261
262 struct addrinfo *addr;
263
264 if(FAIL(getaddrinfo("127.0.0.1", "8080", NULL, &addr)))
265 {
266 logger_handle_msg(g_parent_logger, MSG_INFO, "getaddrinfo failed with: %r", ERRNO_ERROR);
267 return EXIT_FAILURE;
268 }
269
270 static int on = 1;
271 socket_server_opensocket_s socket;
272 ya_result ret;
273
274 if(FAIL(ret = socket_server_opensocket_init(&socket, addr, SOCK_STREAM)))
275 {
276 logger_handle_msg(g_parent_logger, MSG_INFO, "socekt init failed with: %r", ret);
277 return EXIT_FAILURE;
278 }
279 socket_server_opensocket_setopt(&socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
280 #ifndef WIN32
281 socket_server_opensocket_setopt(&socket, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
282 #endif
283
284 int sockfd = socket_server_opensocket_open(&socket);
285
286 if(sockfd < 0)
287 {
288 logger_handle_msg(g_parent_logger, MSG_INFO, "socket_server_opensocket_open failed with: %r", sockfd);
289 return EXIT_FAILURE;
290 }
291
292 #if CHILDREN
293 u8 child_heap_id[CHILDREN];
294 pid_t pid[CHILDREN];
295
296 for(int f = 0; f < CHILDREN; ++f)
297 {
298 int id = shared_heap_create(HEAP_SIZE);
299 if(id < 0)
300 {
301 formatln("failed to allocate heap #%i", f);
302 exit(1);
303 }
304 child_heap_id[f] = (u8)id;
305 }
306
307 for(int f = 0; f < CHILDREN; ++f)
308 {
309 pid[f] = fork_ex();
310
311 if(pid[f] < 0)
312 {
313 formatln("failed to spawn child #%i", f);
314 exit(2);
315 }
316
317 if(pid[f] == 0)
318 {
319 #if DNSCORE_HAS_LOG_THREAD_TAG
320 static char childid_thread_tag[9] = "childid";
321 logger_handle_set_thread_tag(childid_thread_tag);
322 #endif
323 logger_set_shared_heap(child_heap_id[f]);
324
325 #if MMAP_TEST
326 for(int j = 0; j < 1000; j += 100)
327 {
328 for(int i = 0; i < 100; ++i)
329 {
330 please_dont_be_shared_ptr[1] = j + i;
331 formatln("[CHILD] *please_dont_be_shared_ptr = %i,%i", please_dont_be_shared_ptr[0], please_dont_be_shared_ptr[1]);
332 }
333 flushout();
334 }
335 #endif
336
337 struct thread_ctx ctx;
338 ctx.aw = aw;
339 ctx.logger = g_child_logger;
340 ctx.f =f;
341 ctx.count = count;
342
343 thread_t tid = 0;
344 if(thread_create(&tid, logging_stuff_thread, &ctx) != 0)
345 {
346 }
347
348 async_wait(aw);
349
350 #if !HAS_SHARED_QUEUE_SUPPORT
351 logger_init_ex(16384);
352 logger_start_client();
353 #endif
354
355 #define MODULE_MSG_HANDLE g_child_logger
356 //formatln("client logger @ %p = %p", g_child_logger, MODULE_MSG_HANDLE);
357 //flushout();
358
359 for(int j = 0; j < count; j += 100)
360 {
361 for(int i = 0; i < 50; ++i)
362 {
363 log_info("child #%i log line %i that will require a growth of the originally allocated 48 bytes buffer", f, j + i);
364 #if MICROPAUSE > 0
365 usleep(MICROPAUSE);
366 #endif
367 }
368
369 for(int i = 50; i < 100; ++i)
370 {
371 log_info("child #%i log line %i", f, j + i);
372 #if MICROPAUSE > 0
373 usleep(MICROPAUSE);
374 #endif
375 }
376
377 #if 0
378 if(j < 250)
379 {
380 logger_flush();
381 }
382
383 if(j < 500)
384 {
385 usleep(10000);
386 }
387 #endif
388 }
389
390 log_info("child #%i done", f);
391
392 #undef MODULE_MSG_HANDLE
393
394 if(tid != 0)
395 {
396 thread_join(tid, NULL);
397 }
398
399 //logger_stop_client();
400 exit(0);
401 }
402 }
403
404 #endif
405
406 {
407 #if MMAP_TEST
408 for(int j = 0; j < 1000; j += 100)
409 {
410 for(int i = 0; i < 100; ++i)
411 {
412 please_dont_be_shared_ptr[0] = j + i;
413 formatln("[PARNT] *please_dont_be_shared_ptr = %i,%i", please_dont_be_shared_ptr[0], please_dont_be_shared_ptr[1]);
414 }
415 flushout();
416 }
417 #endif
418 #if !HAS_SHARED_QUEUE_SUPPORT
419 logger_start_server();
420 #endif
421
422 #define MODULE_MSG_HANDLE g_parent_logger
423
424 //formatln("parent logger @ %p = %p", g_parent_logger, MODULE_MSG_HANDLE);
425 //flushout();
426
427 struct thread_ctx ctx;
428 ctx.aw = aw;
429 ctx.logger = g_parent_logger;
430 ctx.f = -1;
431 ctx.count = count;
432
433 thread_t tid = 0;
434 if(thread_create(&tid, logging_stuff_thread, &ctx) != 0)
435 {
436 }
437
438 sleep(1);
439
440 async_wait_progress(aw, 1);
441
442 for(int j = 0; j < count; j += 100)
443 {
444 for(int i = 0; i < 50; ++i)
445 {
446 log_info("parent log line %i", j + i);
447 #if MICROPAUSE > 0
448 usleep(MICROPAUSE);
449 #endif
450 }
451
452 for(int i = 50; i < 100; ++i)
453 {
454 log_info("parent log line %i that will require a growth of the originally allocated 48 bytes buffer", j + i);
455 #if MICROPAUSE > 0
456 usleep(MICROPAUSE);
457 #endif
458 }
459
460 #if 0
461 if(j < 250)
462 {
463 logger_flush();
464 }
465
466 if(j < 500)
467 {
468 usleep(10000);
469 }
470 #endif
471 }
472
473 #if CHILDREN
474 log_info("waiting for child");
475
476 for(int f = 0; f < CHILDREN; ++f)
477 {
478 waitpid_ex(pid[f], NULL, 0);
479 }
480 #endif
481
482 if(tid != 0)
483 {
484 thread_join(tid, NULL);
485 }
486
487 log_info("done");
488
489 #undef MODULE_MSG_HANDLE
490
491 #if !HAS_SHARED_QUEUE_SUPPORT
492 logger_stop_server();
493 #endif
494 logger_stop();
495 }
496
497 async_wait_destroy_shared(aw);
498
499 {
500 size_t total, count;
501 formatln("[0] testing block");
502 flushout();
503 shared_heap_count_allocated(0, &total, &count);
504 formatln("[0] after use: %llu allocated blocs using %llu bytes", count, total);
505 flushout();
506
507
508 #if CHILDREN
509 for(int f = 0; f < CHILDREN; ++f)
510 {
511 formatln("[%i] testing block", child_heap_id[f]);
512 flushout();
513 shared_heap_count_allocated(child_heap_id[f], &total, &count);
514 formatln("[%i] after use: %llu allocated blocs using %llu bytes", child_heap_id[f], count, total);
515 flushout();
516 }
517 #endif
518 }
519
520 flushout();
521 flusherr();
522 fflush(NULL);
523
524 dnscore_finalize();
525
526 return EXIT_SUCCESS;
527 }
528