/** * This does the query execution for the new mongodb based sicslog. * * COPYRIGHT GPL * * Mark Koennecke, February 2016 */ #include #include #include #include #include static char lastError[1024]; static char mongoURL[1024]; static char inst[132]; static mongoc_client_t *client; static mongoc_collection_t *collection; /*--------------------------------------------------------------------------------*/ char * sicslogGetError(void) { /* May be change to strdup(lastError); */ return lastError; } /*--------------------------------------------------------------------------------*/ int sicslogSetup(char *url, char *instPar) { memset(inst,0,sizeof(inst)); if(instPar != NULL){ strncpy(inst,instPar, sizeof(inst)); } strncpy(mongoURL,url,sizeof(mongoURL)); mongoc_init(); client = mongoc_client_new (mongoURL); if(!client){ snprintf(lastError,sizeof(lastError),"ERROR: failed to connect to mongodb, bad URL?"); return 1; } return 0; } /*--------------------------------------------------------------------------------*/ static unsigned int sevFromText(const char *txt) { static const char *severityText[] = {"fatal", "error", "warn", "info", "verbose", "debug", NULL }; int sev = 0; while(severityText[sev] != NULL){ if(strcmp(txt,severityText[sev]) == 0){ break; } sev++; } sev++; /* starting at 1 rather then 0 */ return sev; } /*---------------------------------------------------------------------------*/ int sicslogQuery(int argc, char *argv[], ResultCallback_t func, void *userData) { char c; time_t to = time(NULL), from = to - 3600; int severity = INFO, mult = 1, status = 0; char *sub = NULL; char *exp = NULL; char *instLocal = NULL; char *tmp, *pPtr; char jsonQuery[2024], subQuery[132]; struct timeval tv; mongoc_collection_t *collection = NULL; bson_t *query; const bson_t *doc; mongoc_cursor_t *cursor; bson_error_t err; /* parse options */ optind = 1; while((c = getopt(argc,argv,"s:l:f:t:i:e:c:h")) != -1) { switch (c){ case 's': sub = strdup(optarg); break; case 'l': tmp = strdup(optarg); if((pPtr = strrchr(tmp,(int)'h')) != NULL){ mult = 60; *pPtr = '\0'; } else if((pPtr = strrchr(tmp,(int)'d')) != NULL){ mult = 24*60; *pPtr = '\0'; } from = to - atoi(tmp)*mult*60; free(tmp); break; case 'f': if(approxidate(optarg,&tv) == 0){ from = tv.tv_sec; } else { snprintf(lastError,sizeof(lastError),"Failed to parse date from %s", optarg); return 1; } break; case 't': if(approxidate(optarg,&tv) == 0){ to = tv.tv_sec; } else { snprintf(lastError,sizeof(lastError),"Failed to parse date from %s", optarg); return 1; } break; case 'i': instLocal = strdup(optarg); break; case 'e': exp = strdup(optarg); break; case 'c': severity = sevFromText(optarg); break; case 'h': snprintf( lastError,sizeof(lastError), "Options: \n-s subsystem\n-l last(h,d)\n-f fromtime\n-t totime\n-i instrument\n-c severity\n%s", "-e search-expression"); return 1; break; case '?': if( optopt == 's' || optopt == 'l' || optopt == 'f' || optopt == 't' || optopt == 'i' || optopt == 'e' || optopt == 'c') { snprintf(lastError,sizeof(lastError),"Option %c requires an argument", optopt); } else { snprintf(lastError,sizeof(lastError),"Unknown option %c", optopt); } return 1; break; } } if(instLocal == NULL && strlen(inst) > 1){ instLocal = strdup(inst); } if(instLocal == NULL){ snprintf(lastError,sizeof(lastError),"Do not know which instrument log to query, specify with -i"); return 1; } /* build the query */ snprintf(jsonQuery, sizeof(jsonQuery),"{ \"timestamp\" : {\"$gt\": %ld, \"$lt\": %ld}, \"severity\": {\"$lte\": %d}", from,to,severity); if(sub != NULL){ snprintf(subQuery,sizeof(subQuery),", \"sub\" : \"%s\"", sub); strncat(jsonQuery,subQuery,sizeof(jsonQuery)); } if(exp != NULL){ snprintf(subQuery,sizeof(subQuery),", \"message\" : {\"$regex\": \"%s\" }", exp); strncat(jsonQuery,subQuery,sizeof(jsonQuery)); } strncat(jsonQuery,"}",sizeof(jsonQuery)); /* now execute the query */ collection = mongoc_client_get_collection(client,instLocal,"log"); if(collection == NULL){ snprintf(lastError,sizeof(lastError),"Failed to find log for %s", instLocal); status = 1; goto cleanup; } fprintf(stdout,"The query: %s\n", jsonQuery); query = bson_new_from_json((const uint8_t *)jsonQuery,strlen(jsonQuery), &err); if(query == NULL){ snprintf(lastError,sizeof(lastError),"Failed to parse query with %s", err.message); status = 1; goto cleanup; } cursor = mongoc_collection_find (collection, MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL); while (mongoc_cursor_next (cursor, &doc)) { func(doc,userData); } cleanup: if(sub != NULL){ free(sub); } if(exp != NULL){ free(exp); } if(query != NULL){ bson_destroy(query); } if(cursor != NULL){ /* mongoc_cursor_destroy(cursor); */ } if(collection != NULL){ mongoc_collection_destroy(collection); } return status; }