summaryrefslogtreecommitdiffstats
path: root/common/elapi/elapi_internal.c
blob: 2e93a355ce58683800f4b7d67ed72d0df586d793 (plain)
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
/*
    ELAPI

    Implementation of the ELAPI logging interface.

    Copyright (C) Dmitri Pal <dpal@redhat.com> 2009

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#define _GNU_SOURCE
#include <errno.h>      /* for errors */
#include <stdio.h>      /* for printf() - temporarily */

#include "elapi_priv.h"
#include "elapi_event.h"
#include "elapi_sink.h"
#include "trace.h"
#include "config.h"
#include "ini_config.h"

#include "collection_tools.h" /*temporarily */

/* Buffer size for time string */
#define MAX_TIMESTR         200

/* I was told during review that I have to hard code the name.
 * So it is hardcoded now.
 */
#define ELAPI_DEFAULT_ERROR_FILE "elapiconf.err"

/* Handler for logging through the sinks */
int elapi_internal_sink_handler(const char *sink,
                                int sink_len,
                                int type,
                                void *data,
                                int length,
                                void *passed_data,
                                int *stop)
{
    struct elapi_sink_context *sink_env;
    TRACE_FLOW_STRING("elapi_internal_sink_handler", "Entry.");

    /* FIXME THIS IS A PLACEHOLDER FUNCTION FOR NOW */

    sink_env = (struct elapi_sink_context *)(passed_data);

    if (type == COL_TYPE_COLLECTION) {
        printf("\n\n\nPROCESSING EVENT:\n");
        col_debug_collection(sink_env->event, COL_TRAVERSE_DEFAULT);
    }
    else printf("Sink: %s\n", sink);

    TRACE_FLOW_STRING("elapi_internal_sink_handler", "Exit.");
    return EOK;
}

/* Internal sink cleanup function */
int elapi_internal_sink_cleanup_handler(const char *sink,
                                        int sink_len,
                                        int type,
                                        void *data,
                                        int length,
                                        void *passed_data,
                                        int *stop)
{
    TRACE_FLOW_STRING("elapi_internal_sink_cleanup_handler", "Entry.");

    /* FIXME THIS IS A PLACEHOLDER FUNCTION FOR NOW */

    if (type != COL_TYPE_COLLECTION) printf("Cleaning Sink: %s\n", sink);

    TRACE_FLOW_STRING("elapi_internal_sink_cleanup_handler", "Exit.");
    return EOK;
}

/* Function to add a sink to the collection */
int elapi_internal_add_sink_to_collection(struct collection_item *sink_list,
                                          char *sink,
                                          char *appname)
{
    int error = EOK;
    int found = 0;
    struct sink_descriptor sink_data;

    TRACE_FLOW_STRING("elapi_internal_add_sink_to_collection", "Entry");
    error = col_is_item_in_collection(sink_list,
                                      sink,
                                      COL_TYPE_ANY,
                                      COL_TRAVERSE_DEFAULT,
                                      &found);
    if (error) {
        TRACE_ERROR_NUMBER("Search returned error", error);
        return error;
    }

    /* Check if it was found */
    if (found) {
        TRACE_ERROR_NUMBER("Attempt to add an exiting sink.", "");
        return EINVAL;
    }

    /* Save the pointer to application name into the sink's data block */
    sink_data.dblock.appname = appname;
    TRACE_INFO_STRING("add_sink_to_list - saving appname:", sink_data.dblock.appname);

    /* Try to load the sink library */

    /* FIXME - we need to have at least one sink implemented to enable this code.
     * It is a placeholder for now.
    error = load_sink(&sink_data, sink);
    if (error != 0) {
        DEBUG_NUMBER("Failed to load sink", error);
        return error;
    }
    */


    /* We got a valid sink so add it to the collection */
    error = col_add_binary_property(sink_list, NULL,
                                    sink, (void *)(&sink_data),
                                    sizeof(struct sink_descriptor));
    if (error != 0) {
        TRACE_ERROR_NUMBER("Failed to add sink data as property", error);
        return error;
    }

    TRACE_FLOW_NUMBER("elapi_internal_add_sink_to_collection returning", error);
    return error;
}

/* Function to create a list of sinks */
int elapi_internal_construct_sink_list(struct elapi_dispatcher *handle)
{
    int error = EOK;
    char **current_sink;

    TRACE_FLOW_STRING("elapi_internal_construct_sink_list", "Entry");

    /* Allocate collection to store sinks */
    error = col_create_collection(&(handle->sink_list),
                                  ELAPI_SINKS,
                                  COL_CLASS_ELAPI_SINK);
    if (error != 0) {
        TRACE_ERROR_NUMBER("Failed to create sink collection. Error", error);
        /* No cleanup here.
         * The calling function will call a cleanup
         * of the dispatcher as a whole.*/
        return error;
    }

    current_sink = handle->sinks;
    handle->sink_counter = 0;

    /* Add sinks as properties to the sink collection */
    while (*current_sink != NULL) {

        TRACE_INFO_STRING("Current sink", *current_sink);
        TRACE_INFO_STRING("Will use appname:", handle->appname);

        /* Load sink */
        error = elapi_internal_add_sink_to_collection(handle->sink_list,
                                                      *current_sink,
                                                      handle->appname);
        if ((error != 0) && (error != ELIBACC)) {
            TRACE_ERROR_NUMBER("Failed to add sink", error);
            /* No cleanup here. */
            return error;
        }

        handle->sink_counter++;
        current_sink++;
    }

    /* Check if we have any sinks available */
    if (handle->sink_counter == 0) {
        TRACE_ERROR_NUMBER("No sinks", ELIBACC);
        /* No cleanup here. */
        /* Return "Cannot access a needed shared library" */
        return ELIBACC;
    }

    TRACE_FLOW_STRING("elapi_internal_construct_sink_list", "Returning success");
    return EOK;
}

/* If we failed to read configuration record this in the local file */
void elapi_internal_dump_errors_to_file(struct collection_item *error_list)
{
    FILE *efile;
    char timestr[MAX_TIMESTR];
    time_t time_in_sec;
    struct tm *time_as_struct;
    struct tm time_data;

    TRACE_FLOW_STRING("elapi_internal_dump_errors_to_file", "Entry point");

    efile = fopen(ELAPI_DEFAULT_ERROR_FILE, "a");
    if (efile == NULL) {
        TRACE_ERROR_STRING("No output available.", "Returning.");
        return;
    }

    time_in_sec = time(NULL);
    time_as_struct = localtime_r(&time_in_sec, &time_data);

    fprintf(efile, "\n\n%*s\n\n", 80, "=");

    if ((time_as_struct != NULL) &&
        (strftime(timestr, sizeof(timestr), E_TIMESTAMP_FORMAT, time_as_struct) == 0)) {
        fprintf(efile, "%s\n", timestr);
    }
    else {
        TRACE_FLOW_STRING("elapi_internal_dump_errors_to_file", "Was not able to process time.");
    }

    fprintf(efile, "\n");
    print_file_parsing_errors(efile, error_list);

    fclose(efile);
    TRACE_FLOW_STRING("elapi_internal_dump_errors_to_file", "Exit");
}