source: trunk/src/arm4_daemon.cpp @ 704

Revision 689, 31.7 KB checked in by dcarter, 3 years ago (diff)

see #118: catch various exceptions in the daemon

Line 
1/**********************************************************************
2 * Copyright (c) 2005-2008 David Carter <dcarter@arm4.org> and others.
3 * All rights reserved.   This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * David Carter - Initial API and implementation
10 **********************************************************************/
11
12#include "config.h"
13
14#include <sys/types.h>
15#include <sys/time.h>
16#include <errno.h>
17
18#include <stddef.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <math.h>
23#include <signal.h>
24#include <pthread.h>
25#include <syslog.h>
26#include <time.h>
27
28#ifdef HAVE_GETOPT_H
29#include <getopt.h>
30#endif
31
32#include <db.h>
33#include "arm4.h"
34#include "Arm4db.h"
35#include "Logger.h"
36#include "Arm4dbConfig.h"
37#include "Arm4dbCommon.h"
38#include "Arm4dbDaemonSharedMemory.h"
39#include "arm4agent.h"
40
41/* Prototypes */
42static void on_close (void);
43static void process_queues (void);
44static void usage (void);
45
46/* Flag set by `--verbose'. */
47static int g_verbose = 0;
48static int g_debug = 0;
49static int g_stats = 0;
50static int g_off = 0;
51
52static void
53arm_sleep (int seconds)
54{
55        /* Implements the sleep function using nanosleep */
56        struct timespec required;
57
58        required.tv_sec = seconds;
59        required.tv_nsec = 0;
60
61        nanosleep (&required, NULL);
62}
63
64static void
65backup (void)
66{
67    if (g_verbose)
68        printf ("Starting backup...\n");
69
70        try
71        {
72                Arm4db::getArm4db ()->backup ();
73        }
74        catch (Arm4dbException e)
75        {
76                Logger::getLogger().exceptionError (e, "backup");
77        }
78
79    if (g_verbose)
80        printf ("... complete.\n");
81}
82
83static void
84checkpoint (void)
85{
86    if (g_verbose)
87        printf ("Starting checkpoint...\n");
88
89        try
90        {
91                Arm4db::getArm4db ()->checkpoint ();
92        }
93        catch (Arm4dbException e)
94        {
95                Logger::getLogger().exceptionError (e, "backup");
96        }
97
98    if (g_verbose)
99        printf ("... complete.\n");
100}
101
102static void
103termination_handler (int signum)
104{
105        /*on_close ();*/
106
107        /* Should also message the threads that we're aborting */
108        exit (0);
109}
110
111static void
112on_close (void)
113{
114    /* Turn collection off so that programs can continue */
115    Arm4dbDaemonSharedMemory::setNullCollector (ARM_TRUE);
116
117    if (g_verbose)
118                printf ("Closing databases...\n");
119
120        try
121        {
122                Arm4dbDaemonSharedMemory::sampleFlush ();
123        }
124        catch (Arm4dbException e)
125        {
126                Logger::getLogger().exceptionError (e, "on_close");
127        }
128
129        try
130        {
131                Arm4db::getArm4db ()->checkpoint ();
132        }
133        catch (Arm4dbException e)
134        {
135                Logger::getLogger().exceptionError (e, "on_close");
136        }
137
138        try
139        {
140                Arm4db::getArm4db ()->closeDatabases ();
141        }
142        catch (Arm4dbException e)
143        {
144                Logger::getLogger().exceptionError (e, "on_close");
145        }
146
147        if (g_verbose)
148                printf ("...done\n");
149}
150
151static void *
152application_thread( void *ptr )
153{
154        arm4_shm_application_instance_t app_instance;
155        int status;
156
157        try
158        {
159                Arm4db::getArm4db ()->initializeThread ();
160       
161                for (;;)
162                {
163                        status = Arm4dbDaemonSharedMemory::getAppInstances (&app_instance);
164                        try
165                        {
166                                if (status > 0)
167                                        Arm4db::getArm4db ()->processApplicationInstances (&app_instance);
168                        }
169                        catch (Arm4dbException e)
170                        {
171                                Logger::getLogger().exceptionError (e, "application_thread");
172                        }
173                }
174        }
175        catch (Arm4dbException e)
176        {
177                Logger::getLogger().exceptionError (e, "application_thread initialization");
178        }
179
180        pthread_exit (NULL);
181}
182
183static void *
184application_group_thread( void *ptr )
185{
186        arm4_shm_property_t app_group;
187        int status;
188
189        try
190        {
191                Arm4db::getArm4db ()->initializeThread ();
192       
193                for (;;)
194                {
195                        status = Arm4dbDaemonSharedMemory::getAppGroup (&app_group);
196                        try
197                        {
198                                if (status > 0)
199                                        Arm4db::getArm4db ()->processApplicationGroup (&app_group);
200                        }
201                        catch (Arm4dbException e)
202                        {
203                                Logger::getLogger().exceptionError (e, "application_group_thread");
204                        }
205                }
206        }
207        catch (Arm4dbException e)
208        {
209                Logger::getLogger().exceptionError (e, "application_group_thread initialization");
210        }
211
212        pthread_exit (NULL);
213}
214
215static void *
216application_instance_id_thread( void *ptr )
217{
218        arm4_shm_property_t property;
219        int status;
220
221        try
222        {
223                Arm4db::getArm4db ()->initializeThread ();
224       
225                for (;;)
226                {
227                        status = Arm4dbDaemonSharedMemory::getAppInstanceId (&property);
228                        try
229                        {
230                                if (status > 0)
231                                        Arm4db::getArm4db ()->processApplicationInstanceId (&property);
232                        }
233                        catch (Arm4dbException e)
234                        {
235                                Logger::getLogger().exceptionError (e, "application_instance_id_thread");
236                        }
237                }
238        }
239        catch (Arm4dbException e)
240        {
241                Logger::getLogger().exceptionError (e, "application_instance_id_thread initialization");
242        }
243
244        pthread_exit (NULL);
245}
246
247static void *
248application_context_thread( void *ptr )
249{
250        arm4_shm_context_property_t property;
251        int status;
252
253        try
254        {
255                Arm4db::getArm4db ()->initializeThread ();
256       
257                for (;;)
258                {
259                        status = Arm4dbDaemonSharedMemory::getAppContext (&property);
260                        try
261                        {
262                                if (status > 0)
263                                        Arm4db::getArm4db ()->processApplicationContext (&property);
264                        }
265                        catch (Arm4dbException e)
266                        {
267                                Logger::getLogger().exceptionError (e, "application_context_thread");
268                        }
269                }
270        }
271        catch (Arm4dbException e)
272        {
273                Logger::getLogger().exceptionError (e, "application_context_thread initialization");
274        }
275
276        pthread_exit (NULL);
277}
278
279static void *
280application_address_thread( void *ptr )
281{
282        arm4_shm_address_t address;
283        int status;
284
285        try
286        {
287                Arm4db::getArm4db ()->initializeThread ();
288       
289                for (;;)
290                {
291                        status = Arm4dbDaemonSharedMemory::getAppAddress (&address);
292                        try
293                        {
294                                if (status > 0)
295                                        Arm4db::getArm4db ()->processApplicationAddress (&address);
296                        }
297                        catch (Arm4dbException e)
298                        {
299                                Logger::getLogger().exceptionError (e, "application_address_thread");
300                        }
301                }
302        }
303        catch (Arm4dbException e)
304        {
305                Logger::getLogger().exceptionError (e, "application_address_thread initialization");
306        }
307
308        pthread_exit (NULL);
309}
310
311static void *
312transaction_thread( void *ptr )
313{
314        arm4_shm_transaction_instance_t tran_instance;
315        int status;
316
317        try
318        {
319                Arm4db::getArm4db ()->initializeThread ();
320       
321                for (;;)
322                {
323                        status = Arm4dbDaemonSharedMemory::getTranInstances (&tran_instance);
324                        try
325                        {
326                                if (status > 0)
327                                        Arm4db::getArm4db ()->processTransactionInstances (&tran_instance);
328                        }
329                        catch (Arm4dbException e)
330                        {
331                                Logger::getLogger().exceptionError (e, "transaction_thread");
332                        }
333                }
334        }
335        catch (Arm4dbException e)
336        {
337                Logger::getLogger().exceptionError (e, "transaction_thread initialization");
338        }
339
340        pthread_exit (NULL);
341}
342
343static void *
344transaction_context_thread( void *ptr )
345{
346        arm4_shm_context_property_t property;
347        int status;
348
349        try
350        {
351                Arm4db::getArm4db ()->initializeThread ();
352       
353                for (;;)
354                {
355                        status = Arm4dbDaemonSharedMemory::getTranContext (&property);
356                        try
357                        {
358                                if (status > 0)
359                                        Arm4db::getArm4db ()->processTransactionContext (&property);
360                        }
361                        catch (Arm4dbException e)
362                        {
363                                Logger::getLogger().exceptionError (e, "transaction_context_thread");
364                        }
365                }
366        }
367        catch (Arm4dbException e)
368        {
369                Logger::getLogger().exceptionError (e, "transaction_context_thread initialization");
370        }
371
372        pthread_exit (NULL);
373}
374
375static void *
376transaction_uri_thread( void *ptr )
377{
378        arm4_shm_uri_t uri;
379        int status;
380
381        try
382        {
383                Arm4db::getArm4db ()->initializeThread ();
384       
385                for (;;)
386                {
387                        status = Arm4dbDaemonSharedMemory::getTranUri (&uri);
388                        try
389                        {
390                                if (status > 0)
391                                        Arm4db::getArm4db ()->processTransactionUri (&uri);
392                        }
393                        catch (Arm4dbException e)
394                        {
395                                Logger::getLogger().exceptionError (e, "transaction_uri_thread");
396                        }
397                }
398        }
399        catch (Arm4dbException e)
400        {
401                Logger::getLogger().exceptionError (e, "transaction_uri_thread initialization");
402        }
403
404        pthread_exit (NULL);
405}
406
407static void *
408transaction_metric_values_thread( void *ptr )
409{
410        arm4_shm_metric_value_t metric;
411        int status;
412
413        try
414        {
415                Arm4db::getArm4db ()->initializeThread ();
416       
417                for (;;)
418                {
419                        status = Arm4dbDaemonSharedMemory::getTranMetricValues (&metric);
420                        try
421                        {
422                                if (status > 0)
423                                        Arm4db::getArm4db ()->processTransactionMetricValue (&metric);
424                        }
425                        catch (Arm4dbException e)
426                        {
427                                Logger::getLogger().exceptionError (e, "transaction_metric_values_thread");
428                        }
429                }
430        }
431        catch (Arm4dbException e)
432        {
433                Logger::getLogger().exceptionError (e, "transaction_metric_values_thread initialization");
434        }
435
436        pthread_exit (NULL);
437}
438
439static void *
440transaction_user_thread( void *ptr )
441{
442        arm4_shm_user_t user;
443        int status;
444
445        try
446        {
447                Arm4db::getArm4db ()->initializeThread ();
448       
449                for (;;)
450                {
451                        status = Arm4dbDaemonSharedMemory::getTranUser (&user);
452                        try
453                        {
454                                if (status > 0)
455                                        Arm4db::getArm4db ()->processTransactionUser (&user);
456                        }
457                        catch (Arm4dbException e)
458                        {
459                                Logger::getLogger().exceptionError (e, "transaction_user_thread");
460                        }
461                }
462        }
463        catch (Arm4dbException e)
464        {
465                Logger::getLogger().exceptionError (e, "transaction_user_thread initialization");
466        }
467
468        pthread_exit (NULL);
469}
470
471static void *
472transaction_diag_thread( void *ptr )
473{
474        arm4_shm_diag_t diag;
475        int status;
476
477        try
478        {
479                Arm4db::getArm4db ()->initializeThread ();
480       
481                for (;;)
482                {
483                        status = Arm4dbDaemonSharedMemory::getTranDiag (&diag);
484                        try
485                        {
486                                if (status > 0)
487                                        Arm4db::getArm4db ()->processTransactionDiag (&diag);
488                        }
489                        catch (Arm4dbException e)
490                        {
491                                Logger::getLogger().exceptionError (e, "transaction_diag_thread");
492                        }
493                }
494        }
495        catch (Arm4dbException e)
496        {
497                Logger::getLogger().exceptionError (e, "transaction_diag_thread initialization");
498        }
499
500        pthread_exit (NULL);
501}
502
503static void *
504correlator_thread( void *ptr )
505{
506        arm4_shm_correlator_t correlators;
507        int status;
508
509        try
510        {
511                Arm4db::getArm4db ()->initializeThread ();
512       
513                for (;;)
514                {
515                        status = Arm4dbDaemonSharedMemory::getCorellators (&correlators);
516                        try
517                        {
518                                if (status > 0)
519                                        Arm4db::getArm4db ()->processCorrelators (&correlators);
520                        }
521                        catch (Arm4dbException e)
522                        {
523                                Logger::getLogger().exceptionError (e, "correlator_thread");
524                        }
525                }
526        }
527        catch (Arm4dbException e)
528        {
529                Logger::getLogger().exceptionError (e, "correlator_thread initialization");
530        }
531
532        pthread_exit (NULL);
533}
534
535static void *
536sequence_thread( void *ptr )
537{
538        arm4_shm_db_sequence_t sequence;
539        int status;
540
541        try
542        {
543                Arm4db::getArm4db ()->initializeThread ();
544       
545                for (;;)
546                {
547                        status = Arm4dbDaemonSharedMemory::getSequence (&sequence);
548                        try
549                        {
550                                if (status > 0)
551                                        Arm4db::getArm4db ()->processSequence (&sequence);
552                        }
553                        catch (Arm4dbException e)
554                        {
555                                Logger::getLogger().exceptionError (e, "sequence_thread");
556                        }
557                }
558        }
559        catch (Arm4dbException e)
560        {
561                Logger::getLogger().exceptionError (e, "sequence_thread initialization");
562        }
563
564        pthread_exit (NULL);
565}
566
567static void *
568register_application_thread( void *ptr )
569{
570        arm4_shm_register_application_t application;
571        arm_id_t appid;
572        arm_boolean_t is_new;
573        int status;
574
575        /** IMPORTANT: There should only be one instance of this thread to prevent the same application being registered twice! **/
576
577        try
578        {
579                Arm4db::getArm4db ()->initializeThread ();
580       
581                for (;;)
582                {
583                        status = Arm4dbDaemonSharedMemory::getRegisterApplication (&application);
584                        try
585                        {
586                                if (status > 0)
587                                {
588                                        status = Arm4db::getArm4db ()->processRegisterApplication (&application, &appid, &is_new);
589                                        if (status == 0)
590                                                Arm4dbDaemonSharedMemory::registerApplicationReturn (application.message.application_index, appid, is_new);
591                                        else
592                                        {
593                                                /* Send bad return */
594                                                memset (&appid, 0, sizeof (arm_id_t));
595                                                Arm4dbDaemonSharedMemory::registerApplicationReturn (application.message.application_index, appid, ARM_FALSE);
596                                        }
597                                }
598                                else
599                                {
600                                        /* Send bad return */
601                                        memset (&appid, 0, sizeof (arm_id_t));
602                                        Arm4dbDaemonSharedMemory::registerApplicationReturn (application.message.application_index, appid, ARM_FALSE);
603                                }
604                        }
605                        catch (Arm4dbException e)
606                        {
607                                Logger::getLogger().exceptionError (e, "register_application_thread");
608                        }
609                }
610        }
611        catch (Arm4dbException e)
612        {
613        Logger::getLogger().exceptionError (e, "register_application_thread initialization");
614        }
615
616        pthread_exit (NULL);
617}
618
619static void *
620register_application_identity_thread( void *ptr )
621{
622        arm4_shm_register_application_identity_t identity;
623        int status;
624
625        try
626        {
627                Arm4db::getArm4db ()->initializeThread ();
628       
629                for (;;)
630                {
631                        status = Arm4dbDaemonSharedMemory::getRegisterApplicationIdentity (&identity);
632                        try
633                        {
634                                if (status > 0)
635                                        Arm4db::getArm4db ()->processRegisterApplicationIdentity (&identity);
636                        }
637                        catch (Arm4dbException e)
638                        {
639                                Logger::getLogger().exceptionError (e, "register_application_identity_thread");
640                        }
641                }
642        }
643        catch (Arm4dbException e)
644        {
645        Logger::getLogger().exceptionError (e, "register_application_identity_thread initialization");
646        }
647
648        pthread_exit (NULL);
649}
650
651static void *
652register_application_context_thread( void *ptr )
653{
654        arm4_shm_register_application_context_t context;
655        int status;
656
657        try
658        {
659                Arm4db::getArm4db ()->initializeThread ();
660       
661                for (;;)
662                {
663                        status = Arm4dbDaemonSharedMemory::getRegisterApplicationContext (&context);
664                        try
665                        {
666                                if (status > 0)
667                                        Arm4db::getArm4db ()->processRegisterApplicationContext (&context);
668                        }
669                        catch (Arm4dbException e)
670                        {
671                                Logger::getLogger().exceptionError (e, "register_application_context_thread");
672                        }
673                }
674        }
675        catch (Arm4dbException e)
676        {
677        Logger::getLogger().exceptionError (e, "register_application_context_thread initialization");
678        }
679
680        pthread_exit (NULL);
681}
682
683static void *
684register_transaction_thread( void *ptr )
685{
686        arm4_shm_register_transaction_t transaction;
687        arm_id_t tran_id;
688        arm_boolean_t is_new;
689        int status;
690
691        /** IMPORTANT: There should only be one instance of this thread to prevent the same transaction being registered twice! **/
692
693        try
694        {
695                Arm4db::getArm4db ()->initializeThread ();
696       
697                for (;;)
698                {
699                        status = Arm4dbDaemonSharedMemory::getRegisterTransaction (&transaction);
700                        try
701                        {
702                                if (status > 0)
703                                {
704                                        status = Arm4db::getArm4db ()->processRegisterTransaction (&transaction, &tran_id, &is_new);
705                                        if (status == 0)
706                                                Arm4dbDaemonSharedMemory::registerTransactionReturn (transaction.message.transaction_index, tran_id, is_new);
707                                        else
708                                        {
709                                                /* Send bad return */
710                                                memset (&tran_id, 0, sizeof (arm_id_t));
711                                                Arm4dbDaemonSharedMemory::registerTransactionReturn (transaction.message.transaction_index, tran_id, ARM_FALSE);
712                                        }
713                                }
714                                else
715                                {
716                                        /* Send bad return */
717                                        memset (&tran_id, 0, sizeof (arm_id_t));
718                                        Arm4dbDaemonSharedMemory::registerTransactionReturn (transaction.message.transaction_index, tran_id, ARM_FALSE);
719                                }
720                        }
721                        catch (Arm4dbException e)
722                        {
723                                Logger::getLogger().exceptionError (e, "register_transaction_thread");
724                        }
725                }
726        }
727        catch (Arm4dbException e)
728        {
729                Logger::getLogger().exceptionError (e, "register_transaction_thread initialization");
730        }
731
732        pthread_exit (NULL);
733}
734
735static void *
736register_transaction_identity_thread( void *ptr )
737{
738        arm4_shm_register_application_identity_t identity;
739        int status;
740
741        try
742        {
743                Arm4db::getArm4db ()->initializeThread ();
744       
745                for (;;)
746                {
747                        status = Arm4dbDaemonSharedMemory::getRegisterTransactionIdentity (&identity);
748                        try
749                        {
750                                if (status > 0)
751                                        Arm4db::getArm4db ()->processRegisterTransactionIdentity (&identity);
752                        }
753                        catch (Arm4dbException e)
754                        {
755                                Logger::getLogger().exceptionError (e, "register_transaction_identity_thread");
756                        }
757                }
758        }
759        catch (Arm4dbException e)
760        {
761                Logger::getLogger().exceptionError (e, "register_transaction_identity_thread initialization");
762        }
763
764        pthread_exit (NULL);
765}
766
767static void *
768register_transaction_context_thread( void *ptr )
769{
770        arm4_shm_register_application_context_t context;
771        int status;
772
773        try
774        {
775                Arm4db::getArm4db ()->initializeThread ();
776       
777                for (;;)
778                {
779                        status = Arm4dbDaemonSharedMemory::getRegisterTransactionContext (&context);
780                        try
781                        {
782                                if (status > 0)
783                                        Arm4db::getArm4db ()->processRegisterTransactionContext (&context);
784                        }
785                        catch (Arm4dbException e)
786                        {
787                                Logger::getLogger().exceptionError (e, "register_transaction_context_thread");
788                        }
789                }
790        }
791        catch (Arm4dbException e)
792        {
793                Logger::getLogger().exceptionError (e, "register_transaction_context_thread initialization");
794        }
795
796        pthread_exit (NULL);
797}
798
799static void *
800register_transaction_uri_thread( void *ptr )
801{
802        arm4_shm_register_transaction_uri_t uri;
803        int status;
804
805        try
806        {
807                Arm4db::getArm4db ()->initializeThread ();
808       
809                for (;;)
810                {
811                        status = Arm4dbDaemonSharedMemory::getRegisterTransactionUri (&uri);
812                        try
813                        {
814                                if (status > 0)
815                                        Arm4db::getArm4db ()->processRegisterTransactionUri (&uri);
816                        }
817                        catch (Arm4dbException e)
818                        {
819                                Logger::getLogger().exceptionError (e, "register_transaction_uri_thread");
820                        }
821                }
822        }
823        catch (Arm4dbException e)
824        {
825                Logger::getLogger().exceptionError (e, "register_transaction_uri_thread initialization");
826        }
827
828        pthread_exit (NULL);
829}
830
831static void *
832register_transaction_metric_binding_thread( void *ptr )
833{
834        arm4_shm_register_transaction_metric_t metric;
835        int status;
836
837        try
838        {
839                Arm4db::getArm4db ()->initializeThread ();
840       
841                for (;;)
842                {
843                        status = Arm4dbDaemonSharedMemory::getRegisterTransactionMetricBinding (&metric);
844                        try
845                        {
846                                if (status > 0)
847                                        Arm4db::getArm4db ()->processRegisterTransactionMetricBinding (&metric);
848                        }
849                        catch (Arm4dbException e)
850                        {
851                                Logger::getLogger().exceptionError (e, "register_transaction_metric_binding_thread");
852                        }
853                }
854        }
855        catch (Arm4dbException e)
856        {
857                Logger::getLogger().exceptionError (e, "register_transaction_metric_binding_thread initialization");
858        }
859
860        pthread_exit (NULL);
861}
862
863static void *
864register_metric_thread( void *ptr )
865{
866        arm4_shm_register_metric_t metric;
867        arm_id_t metric_id;
868        int status;
869
870        /** IMPORTANT: There should only be one instance of this thread to prevent the same metric being registered twice! **/
871        try
872        {
873                Arm4db::getArm4db ()->initializeThread ();
874       
875                for (;;)
876                {
877                        status = Arm4dbDaemonSharedMemory::getRegisterMetric (&metric);
878                        try
879                        {
880                                if (status > 0)
881                                {
882                                        status = Arm4db::getArm4db ()->processRegisterMetric (&metric, &metric_id);
883                                        if (status == 0)
884                                                Arm4dbDaemonSharedMemory::registerMetricReturn (metric.message.metric_index, metric_id);
885                                        else
886                                        {
887                                                /* Send bad return */
888                                                memset (&metric_id, 0, sizeof (arm_id_t));
889                                                Arm4dbDaemonSharedMemory::registerMetricReturn (metric.message.metric_index, metric_id);
890                                        }
891                                }
892                                else
893                                {
894                                        /* Send bad return */
895                                        memset (&metric_id, 0, sizeof (arm_id_t));
896                                        Arm4dbDaemonSharedMemory::registerMetricReturn (metric.message.metric_index, metric_id);
897                                }
898                        }
899                        catch (Arm4dbException e)
900                        {
901                                Logger::getLogger().exceptionError (e, "register_metric_thread");
902                        }
903                }
904        }
905        catch (Arm4dbException e)
906        {
907                Logger::getLogger().exceptionError (e, "register_metric_thread initialization");
908        }
909
910        pthread_exit (NULL);
911}
912
913static void *
914utility_thread( void *ptr )
915{
916        arm4_shm_utility_t command;
917        int status;
918
919        /** IMPORTANT: There should only be one instance of this thread to prevent the same metric being registered twice! **/
920        try
921        {
922                Arm4db::getArm4db ()->initializeThread ();
923       
924                for (;;)
925                {
926                        status = Arm4dbDaemonSharedMemory::getUtilityCommand (&command);
927                        try
928                        {
929                                if (status > 0)
930                                {
931                                        switch (command.message.command)
932                                        {
933                                                case ARM4_SHM_COMMAND_BACKUP:
934                                                        backup ();
935                                                        break;
936               
937                                                case ARM4_SHM_COMMAND_CHECKPOINT:
938                                                        checkpoint ();
939                                                        break;
940               
941                                                case ARM4_SHM_COMMAND_STOP:
942                                                        exit (0); /* Our termination handlers ensure an orderly shutdown */
943                                                        break;
944               
945                                                default:
946                                                        syslog (LOG_ERR, "arm4_daemon unknown command %ld", command.message.command);
947                                        }
948                                }
949                        }
950                        catch (Arm4dbException e)
951                        {
952                                Logger::getLogger().exceptionError (e, "utility_thread");
953                        }
954                }
955        }
956        catch (Arm4dbException e)
957        {
958                Logger::getLogger().exceptionError (e, "utility_thread initialization");
959        }
960
961        pthread_exit (NULL);
962}
963
964static void *
965sample_thread( void *ptr )
966{
967        /* Background thread flushes the sampled traces, and ensures time sampled traces are taken */
968        struct timespec requested_sleep;
969
970        /* Request a 0.1 second sleep */
971        requested_sleep.tv_sec = 0;
972        requested_sleep.tv_nsec = 100000000;
973
974        try
975        {
976                Arm4db::getArm4db ()->initializeThread ();
977       
978                for (;;)
979                {
980                        nanosleep (&requested_sleep, NULL);
981                        try
982                        {
983                                Arm4dbDaemonSharedMemory::sampleFlush ();
984                        }
985                        catch (Arm4dbException e)
986                        {
987                                Logger::getLogger().exceptionError (e, "sample_thread");
988                        }
989                }
990        }
991        catch (Arm4dbException e)
992        {
993                Logger::getLogger().exceptionError (e, "sample_thread initialization");
994        }
995
996        pthread_exit (NULL);
997}
998
999static void *
1000stats_thread( void *ptr )
1001{
1002        arm4_shm_stats_t stats;
1003    DB_TXN_STAT *dbstats_ptr;
1004
1005        try
1006        {
1007                Arm4db::getArm4db ()->initializeThread ();
1008       
1009                for (;;)
1010                {
1011                        try
1012                        {
1013                                Arm4dbDaemonSharedMemory::getStats (&stats);
1014                                printf ("\nCurrent Message Queue\n");
1015                                printf ("Messages\tBytes\tMax Bytes\n");
1016                                printf ("%lu\t%lu\t%lu\n",
1017                                                stats.mq_n_messages,
1018                                                stats.mq_n_bytes,
1019                                                stats.mq_max_bytes);
1020               
1021                                dbstats_ptr = (DB_TXN_STAT *) Arm4db::getArm4db ()->getStats ();
1022                                if (dbstats_ptr)
1023                                {
1024                                        printf ("\nTransactions\n");
1025                                        printf ("Max %d\tActive %d\tMax Active %d\n",
1026                                                        dbstats_ptr->st_maxtxns,
1027                                                        dbstats_ptr->st_nactive,
1028                                                        dbstats_ptr->st_maxnactive);
1029                                        printf ("Begun %d\tAborted %d\tCommitted %d\tRestored %d\n",
1030                                                        dbstats_ptr->st_nbegins,
1031                                                        dbstats_ptr->st_naborts,
1032                                                        dbstats_ptr->st_ncommits,
1033                                                        dbstats_ptr->st_nrestores);
1034                                        free (dbstats_ptr);
1035                                }
1036                        }
1037                        catch (Arm4dbException e)
1038                        {
1039                                Logger::getLogger().exceptionError (e, "stats_thread");
1040                        }
1041
1042                        arm_sleep (5);
1043                }
1044        }
1045        catch (Arm4dbException e)
1046        {
1047                Logger::getLogger().exceptionError (e, "stats_thread initialization");
1048        }
1049
1050        pthread_exit (NULL);
1051}
1052
1053static void *
1054db_checkpoint_thread( void *ptr )
1055{
1056        // This thread is used to maintain database consistency.
1057        // Transactions are checkpointed every 2 minutes, but this
1058        // can be changed in the config file
1059        int interval = Arm4dbConfig::getConfig ().getCheckpointInterval ();
1060
1061        try
1062        {
1063                Arm4db::getArm4db ()->initializeThread ();
1064       
1065                for (;;)
1066                {
1067                        // A negative value indicates checkpointing is disabled
1068                        if (interval > 0)
1069                        {
1070                                try
1071                                {
1072                                        checkpoint ();
1073                                }
1074                                catch (Arm4dbException e)
1075                                {
1076                                        Logger::getLogger().exceptionError (e, "db_checkpoint_thread");
1077                                }
1078                                arm_sleep (interval);
1079                        }
1080                        else
1081                        {
1082                                arm_sleep (3600);
1083                        }
1084                }
1085        }
1086        catch (Arm4dbException e)
1087        {
1088                Logger::getLogger().exceptionError (e, "db_checkpoint_thread initialization");
1089        }
1090
1091        pthread_exit (NULL);
1092}
1093
1094static void
1095process_queues (void)
1096{
1097        pthread_t thread;
1098        int i;
1099
1100        if (g_verbose)
1101                printf ("Creating shared memory\n");
1102
1103    /* Turn collection on or off when creating the shared memory segment */
1104    if (g_off)
1105        Arm4dbDaemonSharedMemory::setNullCollector (ARM_TRUE); /* Set the library as inactive. */
1106    else
1107        Arm4dbDaemonSharedMemory::setNullCollector (ARM_FALSE); /* Set the library as active. */
1108
1109        /* Create the databases if required */
1110        if (g_verbose)
1111                printf ("Opening databases\n");
1112        Arm4db::getArm4db ()->openDatabases ();
1113
1114        atexit (on_close);
1115
1116        if (g_verbose)
1117                printf ("Starting queue threads\n");
1118
1119        /* EXPERIMENT: Launch 2 of all queues to try and improve throughput */
1120        for (i = 0; i < 1; i++)
1121                {
1122                pthread_create( &thread, NULL, application_thread, NULL);
1123                pthread_create( &thread, NULL, application_group_thread, NULL);
1124                pthread_create( &thread, NULL, application_instance_id_thread, NULL);
1125                pthread_create( &thread, NULL, application_context_thread, NULL);
1126                pthread_create( &thread, NULL, application_address_thread, NULL);
1127                pthread_create( &thread, NULL, transaction_thread, NULL);
1128                pthread_create( &thread, NULL, transaction_context_thread, NULL);
1129                pthread_create( &thread, NULL, transaction_uri_thread, NULL);
1130                pthread_create( &thread, NULL, transaction_metric_values_thread, NULL);
1131                pthread_create( &thread, NULL, transaction_user_thread, NULL);
1132                pthread_create( &thread, NULL, transaction_diag_thread, NULL);
1133                pthread_create( &thread, NULL, correlator_thread, NULL);
1134                pthread_create( &thread, NULL, sequence_thread, NULL);
1135                pthread_create( &thread, NULL, register_application_identity_thread, NULL);
1136                pthread_create( &thread, NULL, register_application_context_thread, NULL);
1137                pthread_create( &thread, NULL, register_transaction_identity_thread, NULL);
1138                pthread_create( &thread, NULL, register_transaction_context_thread, NULL);
1139                pthread_create( &thread, NULL, register_transaction_uri_thread, NULL);
1140                pthread_create( &thread, NULL, register_transaction_metric_binding_thread, NULL);
1141                }
1142
1143        /* These threads should only have a single instance */
1144        pthread_create( &thread, NULL, register_application_thread, NULL);
1145        pthread_create( &thread, NULL, register_transaction_thread, NULL);
1146    pthread_create( &thread, NULL, register_metric_thread, NULL);
1147        pthread_create( &thread, NULL, utility_thread, NULL);
1148
1149        /* Thread to flush sampled values, or ensure sampled values get measured */
1150        pthread_create( &thread, NULL, sample_thread, NULL);
1151
1152        if (g_stats)
1153                pthread_create( &thread, NULL, stats_thread, NULL);
1154
1155        if (g_verbose)
1156                printf ("Open for business\n");
1157
1158        db_checkpoint_thread (NULL); /* Shouldn't return */
1159}
1160
1161static void
1162version (void)
1163{
1164        printf ("Package %s\n", PACKAGE);
1165        printf ("Version %s\n", VERSION);
1166}
1167
1168static void
1169usage (void)
1170{
1171        printf ("Usage:\n");
1172#ifdef HAVE_GETOPT_LONG
1173        printf ("\tarm4_daemon --help|-h\n");
1174        printf ("\t\tShow this help message\n");
1175        printf ("\tarm4_daemon --version|-V\n");
1176        printf ("\t\tDisplay implementation version\n");
1177        printf ("\tarm4_daemon [--verbose|-v] [--debug|-d] [--config|-C config_file] [--stats|-s] [--off|-o]\n");
1178        printf ("\t\t--verbose displays the setup progress\n");
1179        printf ("\t\t--debug runs the server in the foreground\n");
1180    printf ("\t\t--config specifies a path to the configuration file. The default is /etc/arm4.conf\n");
1181        printf ("\t\t--stats display the message queue stats\n");
1182    printf ("\t\t--off turns off all ARM 4 data collection. The daemon remains active\n");
1183#else
1184        printf ("\tarm4_daemon -h\n");
1185        printf ("\t\tShow this help message\n");
1186        printf ("\tarm4_daemon -V\n");
1187        printf ("\t\tDisplay implementation version\n");
1188        printf ("\tarm4_daemon -vdso [-C config_file]\n");
1189        printf ("\t\t-v displays the setup progress\n");
1190        printf ("\t\t-d runs the server in the foreground\n");
1191    printf ("\t\t-C specifies a path to the configuration file. The default is /etc/arm4.conf\n");
1192        printf ("\t\t-s display the message queue stats\n");
1193    printf ("\t\t-o turns off all ARM 4 data collection. The daemon remains active\n");
1194#endif
1195}
1196
1197static void
1198initialize_configuration (const char *config_filename)
1199{
1200    if (g_verbose)
1201    {
1202        printf("Configuration filename '%s'\n", config_filename);
1203    }
1204        /* Set the DB parameters */
1205        const Arm4dbConfig &config = Arm4dbConfig::getConfig (config_filename);
1206
1207        if (g_verbose)
1208        {
1209                printf ("Instance %d\n", config.getInstance ());
1210        }
1211
1212        /* Set our user mask to allow user and group access */
1213    if (g_verbose)
1214    {
1215        printf("Setting umask to %04o\n", config.getUmask ());
1216    }
1217        umask (config.getUmask ());
1218    Arm4dbDaemonSharedMemory::setUmask (config.getUmask ());
1219
1220    /* Create the database home directory */
1221    Arm4dbCommon::createPath (config.getDbHomeC ());
1222    int status = chown (config.getDbHomeC (), config.getUid (),  config.getGid ());
1223        if (status != 0)
1224        {
1225                perror ("chown");
1226                exit (1);
1227        }
1228
1229        /* Create the IPC directory */
1230        if (config.getInstance () == 0)
1231        {
1232                status = Arm4dbCommon::createPath (ARM4DATA_QUEUE_DIR);
1233                if (status == ARM_SUCCESS)
1234                {
1235                    status = chown (ARM4DATA_QUEUE_DIR, config.getUid (),  config.getGid ());
1236                        if (status != 0)
1237                        {
1238                                perror ("chown");
1239                                exit (1);
1240                        }
1241                }
1242                else
1243                        exit (1);
1244        }
1245
1246        /* Set our user and group - group first in case we're an unprivileged user */
1247        if (config.getGid () != (gid_t) -1)
1248        {
1249                if (setegid (config.getGid ()) < 0)
1250                {
1251                        perror ("setgid");
1252                        exit (1);
1253                }
1254        }
1255        if (config.getUid () != (uid_t) -1)
1256        {
1257                if (seteuid (config.getUid ()) < 0)
1258                {
1259                        perror ("setuid");
1260                        exit (1);
1261                }
1262        }
1263    // Set our umask again since our user has changed
1264        umask (config.getUmask ());
1265}
1266
1267static void
1268daemonize (void)
1269{
1270        pid_t pid;
1271
1272        if (g_debug)
1273        {
1274                if (g_verbose)
1275                        printf ("Running in the foreground\n");
1276                return;
1277        }
1278
1279        if (g_verbose)
1280                printf ("Switching to background processing...\n");
1281
1282        pid = fork ();
1283
1284        if (pid == 0)
1285        {
1286                /* This is the child process */
1287                Arm4dbDaemonSharedMemory::setDaemon (ARM_TRUE); /* Replace the parent PID */
1288                return;
1289        }
1290
1291        if (pid == -1)
1292        {
1293                perror ("fork");
1294                exit (1);
1295        }
1296
1297        if (g_verbose)
1298                printf ("...pid = %d\n", pid);
1299        exit (0);       /* This is the parent */
1300}
1301
1302int
1303main (int argc, char *argv[])
1304{
1305        int c;
1306        struct sigaction new_action, old_action;
1307    char config_filename [1024];
1308
1309    // Initialize the logger
1310    Logger::getLogger().setName ("arm4_daemon");
1311
1312    /* Set the default config file */
1313    strcpy (config_filename, "/etc/arm4.conf");
1314
1315        while (1)
1316        {
1317#ifdef HAVE_GETOPT_LONG
1318                static struct option long_options[] =
1319                        {
1320                                        /* These options set a flag. */
1321                                {"verbose",  no_argument,       &g_verbose, 1},
1322                                {"brief",    no_argument,       &g_verbose, 0},
1323                                {"debug",    no_argument,       &g_debug, 1},
1324                                {"stats",    no_argument,       &g_stats, 1},
1325                                {"off",      no_argument,       &g_off, 1},
1326                                        /* These options don't set a flag. We distinguish them by their indices. */
1327                                {"help",     no_argument,       0, 'h'},
1328                                {"version",  no_argument,       0, 'V'},
1329                {"config",   required_argument, 0, 'C'},
1330                                {0, 0, 0, 0}
1331                        };
1332
1333                /* getopt_long stores the option index here. */
1334                int option_index = 0;
1335
1336                c = getopt_long (argc, argv, "vdhsoVC:",
1337                                                long_options, &option_index);
1338#else
1339                c = getopt (argc, argv, "vdhsoVC:");
1340#endif
1341
1342                /* Detect the end of the options. */
1343                if (c == -1)
1344                        break;
1345
1346                switch (c)
1347                {
1348                case 0:
1349                        /* If this option set a flag, do nothing else now. */
1350#ifdef HAVE_GETOPT_LONG
1351                        if (long_options[option_index].flag != 0)
1352                                break;
1353
1354                        printf ("option %s", long_options[option_index].name);
1355                        if (optarg)
1356                                printf (" with arg %s", optarg);
1357                        printf ("\n");
1358#endif
1359                        break;
1360
1361                case 'v':
1362                        g_verbose = 1;
1363                        break;
1364
1365                case '?':
1366                        /* getopt_long already printed an error message. */
1367                        break;
1368
1369                case 'd':
1370                        g_debug = 1;
1371                        break;
1372
1373                case 's':
1374                        g_stats = 1;
1375                        break;
1376
1377        case 'o':
1378            g_off = 1;
1379            break;
1380
1381                case 'h':
1382                        usage ();
1383                        exit (0);
1384
1385                case 'V':
1386                        version ();
1387                        exit (0);
1388
1389        case 'C':
1390            strncpy (config_filename, optarg, sizeof(config_filename));
1391            break;
1392
1393                default:
1394                        usage ();
1395                        abort ();
1396                }
1397        }
1398
1399        /* Instead of reporting `--verbose'
1400                and `--brief' as they are encountered,
1401                we report the final status resulting from them. */
1402        if (g_verbose)
1403    {
1404                puts ("verbose flag is set");
1405        Logger::getLogger().setFile (stderr);
1406    }
1407
1408    initialize_configuration (config_filename);
1409
1410        if (!g_verbose)
1411        {
1412                Logger::getLogger().setFile (Arm4dbConfig::getConfig ().getLogFilename ());
1413        }
1414
1415        // Make sure the IPC structures are created if they don't already exist
1416        //  and start as a null collector
1417        Arm4dbDaemonSharedMemory::shmCreate (ARM_TRUE);
1418
1419        pid_t daemon_pid = Arm4dbDaemonSharedMemory::getActiveDaemon ();
1420        if ((daemon_pid != 0) && (daemon_pid != getpid()))
1421        {
1422                fprintf (stderr, "arm4_daemon is already running\n");
1423                exit (1);
1424        }
1425        Arm4dbDaemonSharedMemory::setDaemon (ARM_FALSE); /* Claim the daemon for now */
1426
1427        if (g_verbose)
1428                puts ("Setting signal handlers");
1429
1430    /* Set up the structure to specify the new action. */
1431    new_action.sa_handler = termination_handler;
1432    sigemptyset (&new_action.sa_mask);
1433    new_action.sa_flags = 0;
1434
1435    sigaction (SIGINT, NULL, &old_action);
1436    if (old_action.sa_handler != SIG_IGN)
1437                sigaction (SIGINT, &new_action, NULL);
1438    sigaction (SIGTERM, NULL, &old_action);
1439    if (old_action.sa_handler != SIG_IGN)
1440                sigaction (SIGTERM, &new_action, NULL);
1441        sigaction (SIGHUP, NULL, &old_action);
1442        if (old_action.sa_handler != SIG_IGN)
1443                sigaction (SIGHUP, &new_action, NULL);
1444
1445        /* Print any remaining command line arguments (not options). */
1446        if (optind < argc)
1447        {
1448                printf ("non-option ARGV-elements: ");
1449                while (optind < argc)
1450                        printf ("%s ", argv[optind++]);
1451                putchar ('\n');
1452        }
1453
1454        daemonize ();
1455        process_queues (); /* Should not return */
1456
1457        /* Stop the main thread allowing the children to continue */
1458        pthread_exit (NULL);
1459}
1460
Note: See TracBrowser for help on using the repository browser.