From 605dc3ee7dfd617cc048a27d60dfc322dadb0c37 Mon Sep 17 00:00:00 2001 From: Dmitri Pal Date: Fri, 27 Feb 2009 18:36:59 -0500 Subject: Added new high level interfaces. --- collection/elapi_util.c | 4 +- dispatcher/elapi_api.c | 325 +++++++++++++++++++++++++++++++++++++++ dispatcher/elapi_dispatcher.c | 2 +- dispatcher/elapi_dispatcher.h | 6 + dispatcher/elapi_dispatcher_ut.c | 110 ++++++++++++- etc/file_defaults.conf | 5 + sinks/file/elapi_sink_file.c | 4 +- 7 files changed, 446 insertions(+), 10 deletions(-) diff --git a/collection/elapi_util.c b/collection/elapi_util.c index 09c99a6..7b7b5ca 100644 --- a/collection/elapi_util.c +++ b/collection/elapi_util.c @@ -579,7 +579,7 @@ int sprintf_item(struct serial_data *data, int error = EOK; int i; int len_format = 0; - char *formats[] = {"\"%s\"","%d","%u","%ld","%lu","%.4f"}; + char *formats[] = {"%s","%d","%u","%ld","%lu","%.4f"}; char *fmt; int block; char *start; @@ -683,7 +683,7 @@ int sprintf_item(struct serial_data *data, if (len > -1) block = MAX(len+1,BLOCK_SIZE); else block = MAX(block *2,BLOCK_SIZE); - DEBUG_NUMBER("Need to gorw by:",block); + DEBUG_NUMBER("Need to grow by:",block); if((error=grow_buffer(data,block))) return error; } diff --git a/dispatcher/elapi_api.c b/dispatcher/elapi_api.c index 919dee2..073059f 100644 --- a/dispatcher/elapi_api.c +++ b/dispatcher/elapi_api.c @@ -19,6 +19,7 @@ #include +#include #include #include #include @@ -106,6 +107,328 @@ int create_event(struct collection_item **event,char *name) } +/* Internal untility function to tokenize a string */ +static char *get_next_property(char *cursor,int *type, char **property, int *has_len) +{ + int adjust_by; + char *start; + + DEBUG_STRING("get_next_property","Entry"); + + DEBUG_STRING("Cursor",cursor); + + /* Initialize passed in data */ + *has_len = 0; + *property = NULL; + *type = ELAPI_TYPE_STRING; + + while((*cursor != '\0') && (*cursor != '%')) cursor++; + + /* End of string - we are done */ + if(*cursor == '\0') { + DEBUG_STRING("End of format - returning.",""); + return NULL; + } + + /* This is the beginning of the formatted token */ + cursor++; + if((*cursor == '*') && (*(cursor+1) == 's') && (*(cursor+2) == '(')) { + *type = ELAPI_TYPE_STRING; + *has_len = 1; + adjust_by = 3; + } + else if((*cursor == 's') && (*(cursor+1) == '(')) { + *type = ELAPI_TYPE_STRING; + adjust_by = 2; + } + else if(((*cursor == 'i')||(*cursor == 'd')) && (*(cursor+1) == '(')) { + *type = ELAPI_TYPE_INTEGER; + adjust_by = 2; + } + else if((*cursor == 'u') && (*(cursor+1) == '(')) { + *type = ELAPI_TYPE_INTEGER; + adjust_by = 2; + } + else if((*cursor == 'l') && ((*(cursor+1) == 'i')||(*(cursor+1) == 'd')) && (*(cursor+2) == '(')) { + *type = ELAPI_TYPE_LONG; + adjust_by = 3; + } + else if((*cursor == 'l') && (*(cursor+1) == 'u') && (*(cursor+2) == '(')) { + *type = ELAPI_TYPE_LONG; + adjust_by = 3; + } + else if(((*cursor == 'f')||(*cursor == 'e')) && (*(cursor+1) == '(')) { + *type = ELAPI_TYPE_DOUBLE; + adjust_by = 2; + } + else if((*cursor == 'b') && (*(cursor+1) == '(')) { + *type = ELAPI_TYPE_BINARY; + adjust_by = 2; + } + else { + DEBUG_STRING("Invalid type specifier format:",cursor); + return cursor; + } + + cursor += adjust_by; + start = cursor; + + /* Now we need to extruct the name of the property */ + /* We will not be nice here - the add_property will validate if the name is ok */ + while((*cursor != '\0') && (*cursor != ')')) cursor++; + + /* End of string - we are done */ + if((*cursor == '\0') || (cursor==start)) { + DEBUG_STRING("Bad property",""); + return cursor; + } + + *cursor ='\0'; + *property = start; + *cursor++; + + DEBUG_STRING("Returning Property:",*property); + DEBUG_NUMBER("Returning Type:",*type); + DEBUG_NUMBER("Returning Has length:",*has_len); + + + DEBUG_STRING("get_next_property","Exit"); + + return cursor; +} + +/* Creates collection - event based on the specified format */ +int construct_event(struct collection_item **event,char *name, char *format, ...) +{ + int error; + char *dup_fmt; + char *cursor; + int type; + char *property; + int has_len; + va_list args; + char *data_str; + int data_int; + unsigned int data_uint; + long data_long; + unsigned long data_ulong; + void *data_bin; + double data_dbl; + int length; + void *data; + + DEBUG_STRING("constuct_event","Entry"); + + /* Create event with timestamp */ + error = create_event(event,name); + if(error) { + DEBUG_NUMBER("create_event returned error:",error); + return error; + } + + /* Format is omitted just return */ + if(format == NULL) { + DEBUG_STRING("constuct_event","NULL format exit"); + return EOK; + } + + /* Process the format */ + /* Duplicate it */ + errno = 0; + dup_fmt = strdup(format); + if(dup_fmt == NULL) { + error = errno; + DEBUG_NUMBER("Failed to dup format:",error); + destroy_collection(*event); + return ENOMEM; + } + + va_start(args,format); + + cursor = dup_fmt; + while((cursor = get_next_property(cursor,&type,&property,&has_len)) != NULL) { + + /* Handle the case when the parsing failed */ + if(property == NULL) { + DEBUG_STRING("Error parsing:",dup_fmt); + free(dup_fmt); + destroy_collection(*event); + va_end(args); + return error; + } + + /* Get data */ + switch(type) { + + case ELAPI_TYPE_STRING: data_str = va_arg(args,char *); + data = (void *)data_str; + if(has_len) length = va_arg(args,int); + else length = strlen(data_str)+1; + DEBUG_STRING("Adding string:",data_str); + DEBUG_NUMBER("Length:",length); + break; + case ELAPI_TYPE_BINARY: data_bin = va_arg(args,void *); + data = (void *)data_bin; + length = va_arg(args,int); + break; + case ELAPI_TYPE_INTEGER: data_int = va_arg(args,int); + data = (void *)(&data_int); + length = sizeof(int); + break; + case ELAPI_TYPE_UNSIGNED: data_uint = va_arg(args,unsigned int); + data = (void *)(&data_uint); + length = sizeof(unsigned int); + break; + case ELAPI_TYPE_LONG: data_long = va_arg(args,long); + data = (void *)(&data_long); + length = sizeof(long); + break; + case ELAPI_TYPE_ULONG: data_ulong = va_arg(args,unsigned long); + data = (void *)(&data_ulong); + length = sizeof(unsigned long); + break; + case ELAPI_TYPE_DOUBLE: data_dbl = va_arg(args,double); + data = (void *)(&data_dbl); + length = sizeof(double); + break; + + default: + DEBUG_NUMBER("Unknown type",type); + continue; + } + + /* Add property to the event */ + error = add_any_property(*event, NULL, property, type, data,length); + if(error) { + DEBUG_STRING("Error adding property:",property); + DEBUG_NUMBER("Type :",type); + DEBUG_NUMBER("Length :",length); + free(dup_fmt); + destroy_collection(*event); + va_end(args); + return error; + } + } + + va_end(args); + free(dup_fmt); + DEBUG_STRING("constuct_event","NULL format exit"); + return EOK; +} + +/* Add/Updates the event properties based on the format */ +int modify_event(struct collection_item *event, int update, char *format, ...) +{ + int error; + char *dup_fmt; + char *cursor; + int type; + char *property; + int has_len; + va_list args; + char *data_str; + int data_int; + unsigned int data_uint; + long data_long; + unsigned long data_ulong; + void *data_bin; + double data_dbl; + int length; + void *data; + + DEBUG_STRING("modify_event","Entry"); + + + /* Format is omitted just return */ + if(format == NULL) { + DEBUG_STRING("modify_event","NULL format exit"); + return EOK; + } + + /* Process the format */ + /* Duplicate it */ + errno = 0; + dup_fmt = strdup(format); + if(dup_fmt == NULL) { + error = errno; + DEBUG_NUMBER("Failed to dup format:",error); + return ENOMEM; + } + + va_start(args,format); + + cursor = dup_fmt; + while((cursor = get_next_property(cursor,&type,&property,&has_len)) != NULL) { + + /* Handle the case when the parsing failed */ + if(property == NULL) { + DEBUG_STRING("Error parsing:",dup_fmt); + free(dup_fmt); + va_end(args); + return error; + } + + /* Get data */ + switch(type) { + + case ELAPI_TYPE_STRING: data_str = va_arg(args,char *); + data = (void *)data_str; + if(has_len) length = va_arg(args,int); + else length = strlen(data_str)+1; + DEBUG_STRING("Modifying string:",data_str); + DEBUG_NUMBER("Length:",length); + break; + case ELAPI_TYPE_BINARY: data_bin = va_arg(args,void *); + data = (void *)data_bin; + length = va_arg(args,int); + break; + case ELAPI_TYPE_INTEGER: data_int = va_arg(args,int); + data = (void *)(&data_int); + length = sizeof(int); + break; + case ELAPI_TYPE_UNSIGNED: data_uint = va_arg(args,unsigned int); + data = (void *)(&data_uint); + length = sizeof(unsigned int); + break; + case ELAPI_TYPE_LONG: data_long = va_arg(args,long); + data = (void *)(&data_long); + length = sizeof(long); + break; + case ELAPI_TYPE_ULONG: data_ulong = va_arg(args,unsigned long); + data = (void *)(&data_ulong); + length = sizeof(unsigned long); + break; + case ELAPI_TYPE_DOUBLE: data_dbl = va_arg(args,double); + data = (void *)(&data_dbl); + length = sizeof(double); + break; + + default: + DEBUG_NUMBER("Unknown type",type); + continue; + } + + /* Try to update property first but only on the high level */ + if(update) { + error = update_property(event, property, type, data, length, ELAPI_TRAVERSE_IGNORE); + if(error == ENOENT) error = add_any_property(event, NULL, property, type, data,length); + } + else error = add_any_property(event, NULL, property, type, data,length); + if(error) { + DEBUG_STRING("Error adding/updating property:",property); + DEBUG_NUMBER("Type :",type); + DEBUG_NUMBER("Length :",length); + free(dup_fmt); + va_end(args); + return error; + } + } + + va_end(args); + DEBUG_STRING("modify_event","NULL format exit"); + return EOK; +} + /* Log event */ void log_event(char *format_string,struct collection_item *event) { @@ -113,3 +436,5 @@ void log_event(char *format_string,struct collection_item *event) log_audit_event(global_dispatcher, format_string, event); DEBUG_STRING("log_event","Entry"); } + + diff --git a/dispatcher/elapi_dispatcher.c b/dispatcher/elapi_dispatcher.c index ad943c4..2f54ce8 100644 --- a/dispatcher/elapi_dispatcher.c +++ b/dispatcher/elapi_dispatcher.c @@ -30,7 +30,7 @@ char sink_collection[] = "sinks"; char def_application_name[] = "default"; -char *default_sinks[] = { "ipa","kernel","syslog","file","stderr", NULL }; +char *default_sinks[] = { "remote","altremote","kernel","syslog","db","file","failover","stderr", NULL }; /* Structure to pass data from logging function to sinks */ diff --git a/dispatcher/elapi_dispatcher.h b/dispatcher/elapi_dispatcher.h index c47e8ff..1a49a18 100644 --- a/dispatcher/elapi_dispatcher.h +++ b/dispatcher/elapi_dispatcher.h @@ -114,4 +114,10 @@ void close_audit(void); /* Creates collection with the timestamp already prepopulated */ int create_event(struct collection_item **event,char *name); +/* Creates collection - event based on the specified format */ +int construct_event(struct collection_item **event,char *name, char *format, ...); + +/* Add/Updates the event properties based on the format */ +int modify_event(struct collection_item *event, int update, char *format, ...); + #endif diff --git a/dispatcher/elapi_dispatcher_ut.c b/dispatcher/elapi_dispatcher_ut.c index 994df17..3d2d6ac 100644 --- a/dispatcher/elapi_dispatcher_ut.c +++ b/dispatcher/elapi_dispatcher_ut.c @@ -33,14 +33,14 @@ struct collection_item *socket; struct collection_item *host; -int construct_event() +int build_event() { char binary_dump[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; int found = 0; int error = EOK; - DEBUG_STRING("construct_event","Entry."); + DEBUG_STRING("build_event","Entry."); if((error=create_collection(&peer,"peer")) || (error=add_str_property(peer,NULL,"hostname","peerhost.mytest.com",0)) || @@ -83,7 +83,7 @@ int construct_event() return error; } - /* Construct event */ + /* build event */ if((error=create_collection(&event,"event")) || (error=add_str_property(event,NULL,"escape1","ds\\sd=ewrw===sada",0)) || (error=add_str_property(event,NULL,"escape2","dss,d,=,ewrw===sada",0)) || @@ -125,6 +125,103 @@ int construct_event() return EOK; } +int other_high_level_test() +{ + int error = EOK; + char *sinks[]= { "syslog", "stderr", "file", NULL }; + char bin[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + + printf("Second high level test start\n"); + + printf("%s","=================\nOpening audit\n"); + error = open_audit("my_app",sinks); + if(error) { + printf("open_audit returned %d\n", error); + return error; + } + else printf("Success : %d\n",error); + + printf("%s","=================\nCreating collection\n"); + if((error=create_event(&event,"test_event")) || + (error=add_str_property(event,NULL,"name","some name",0)) || + (error=add_int_property(event,NULL,"number",-100)) || + (error=add_binary_property(event,NULL,"bin",bin,8)) || + (error=add_double_property(event,NULL,"double",3.141592))) { + printf("Failed to create collection. Error %d\n",error); + return error; + } + else printf("Success : %d\n",error); + + error = construct_event(&event,"test_event"," %b(bin)," + " %d(int_number)," + " %u(unsigned_number)," + " %ld(long_number)," + " %lu(long_unsigned_number)," + " %s(just_string)," + " %*s(sub_string)," + " %e(double_number)", + bin,8, + -200, + 300, + -1234567, + 1234567879, + "string", + "truncated string", 10, /* Expect word truncated */ + 3.141592 * 3); + if(error) { + printf("Failed to construct event %d\n", error); + return error; + } + else printf("Success : %d\n",error); + + + printf("%s","=================\nLog event using NULL format\n"); + log_event(NULL, event); + + printf("%s","=================\nLog event using format\n"); + log_event("%(stamp), %s(sub_string), %(int_number), %(unsigned_number), %(long_unsigned_number), %(bin), %e(double_number)", event); + + error = modify_event(event,1," %d(int_number)," + " %u(unsigned_number),", + -220, + 330); + + if(error) { + printf("Failed to modify event %d\n", error); + return error; + } + else printf("Success : %d\n",error); + + printf("%s","=================\nLog modified event using NULL format\n"); + log_event(NULL, event); + + printf("%s","=================\nLog modified event using format\n"); + log_event("%(stamp), %s(sub_string), %(int_number), %(unsigned_number), %(long_unsigned_number), %(bin), %e(double_number)", event); + + error = modify_event(event,0," %d(int_number)," + " %u(unsigned_number),", + -250, + 350); + if(error) { + printf("Failed to modify event %d\n", error); + return error; + } + else printf("Success : %d\n",error); + + printf("%s","=================\nLog modified event using NULL format\n"); + log_event(NULL, event); + + printf("%s","=================\nLog modified event using format\n"); + log_event("%(stamp), %s(sub_string), %(int_number), %(unsigned_number), %(long_unsigned_number), %(bin), %e(double_number)", event); + + destroy_collection(event); + close_audit(); + + printf("Low level test end\n"); + return error; +} + + int high_level_test(char *app) { int error = EOK; @@ -199,7 +296,7 @@ int high_level_test(char *app) printf("%s","=================\nNegative tests\n"); printf("%s","=================\nLog event using Third format\n"); - log_event("%-50s(timestamp), %50s(name, %lo(number), %a(bin), %%, %.8f(double)", event); + log_event("%-50s(stamp), %50s(name, %lo(number), %a(bin), %%, %.8f(double)", event); log_event("%(times), %z(name), %lo(number), %a(bin), %%, %.8f(double)", event); log_event("%(times), %(name ), %lo(number), %a(bin), %%, %.8f(double)", event); log_event("%(times), (name ), %lo(number), %a(bin), %%, %.8f(double)", event); @@ -231,7 +328,7 @@ int low_level_test() } printf("%s","=================\nCreating collection\n"); - error = construct_event(); + error = build_event(); if(error) { printf("Error creating event %d\n",error); return error; @@ -356,7 +453,10 @@ int main() error = high_level_test("my_app2"); printf("High level test second run returned: %d\n",error); + if(error) return error; + error = other_high_level_test(); + printf("Other high level test returned: %d\n",error); return error; } diff --git a/etc/file_defaults.conf b/etc/file_defaults.conf index e69de29..ca59727 100644 --- a/etc/file_defaults.conf +++ b/etc/file_defaults.conf @@ -0,0 +1,5 @@ +; This is the test application configuration +; Log into the given file: + +file_name="/tmp/log" + diff --git a/sinks/file/elapi_sink_file.c b/sinks/file/elapi_sink_file.c index 2d50b4f..649b0a6 100644 --- a/sinks/file/elapi_sink_file.c +++ b/sinks/file/elapi_sink_file.c @@ -112,7 +112,7 @@ static int init_config(struct data_descriptor *dblock) dblock->config = (void *)(conf_data); if((conf_data->file_name != NULL) && (conf_data->keep_open != 0)) { - conf_data->file = fopen(conf_data->file_name,"w"); + conf_data->file = fopen(conf_data->file_name,"a"); } else conf_data->file = stderr; @@ -257,7 +257,7 @@ static int file_sink_submit(struct data_descriptor *dblock) DEBUG_STRING("OUTPUT:",event_storage->buffer); if((conf_data->file_name != NULL) && (conf_data->keep_open == 0)) { - conf_data->file = fopen(conf_data->file_name,"w"); + conf_data->file = fopen(conf_data->file_name,"a"); } fprintf(conf_data->file, "%s\n", event_storage->buffer); -- cgit