From: Jeremy Tan Date: Fri, 13 Sep 2013 03:04:52 +0000 (+0800) Subject: Some bugfixes for sensor/data code + add FCGI_INT_T X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=1a311e29d6b72830d62e2cba21c1b9e33433cfbf;hp=d0f77e15cfa58191a7683caf343037c25be9f31c;p=matches%2FMCTX3420.git Some bugfixes for sensor/data code + add FCGI_INT_T Note: PrintByTime/Points have exclusive ends now. --- diff --git a/server/data.c b/server/data.c index 82aadb6..c4d7b58 100644 --- a/server/data.c +++ b/server/data.c @@ -14,8 +14,7 @@ void Data_Init(DataFile * df) { // Everything is NULL df->filename = NULL; - df->read_file = NULL; - df->write_file = NULL; + df->file = NULL; } /** @@ -34,26 +33,12 @@ void Data_Open(DataFile * df, const char * filename) // Set number of DataPoints df->num_points = 0; - // Set write FILE* - df->write_file = fopen(filename, "w+"); - if (df->write_file == NULL) + // Set file pointer + df->file = fopen(filename, "wb+"); + if (df->file == NULL) { Fatal("Error opening DataFile %s - %s", filename, strerror(errno)); } - - // Set read FILE* - df->read_file = df->write_file; - - //NOTE: Opening the same file in read mode gives funny results; fread generally reads less than expected - // The strerror is: "Transport endpoint is not connected" - /* - fopen(filename, "r"); - if (df->read_file == NULL) - { - Fatal("Error opening DataFile %s - %s", filename, strerror(errno)); - } - */ - } /** @@ -66,11 +51,10 @@ void Data_Close(DataFile * df) //TODO: Write data to TSV? - // Clear the FILE*s - df->read_file = NULL; - df->write_file = NULL; + fclose(df->file); - fclose(df->write_file); + // Clear the FILE*s + df->file = NULL; // Clear the filename free(df->filename); @@ -85,19 +69,19 @@ void Data_Close(DataFile * df) */ void Data_Save(DataFile * df, DataPoint * buffer, int amount) { - pthread_mutex_unlock(&(df->mutex)); + pthread_mutex_lock(&(df->mutex)); assert(df != NULL); assert(buffer != NULL); assert(amount >= 0); // Go to the end of the file - if (fseek(df->write_file, 0, SEEK_END) < 0) + if (fseek(df->file, 0, SEEK_END) < 0) { Fatal("Error seeking to end of DataFile %s - %s", df->filename, strerror(errno)); } // Attempt to write the DataPoints - int amount_written = fwrite(buffer, sizeof(DataPoint), amount, df->write_file); + int amount_written = fwrite(buffer, sizeof(DataPoint), amount, df->file); // Check if the correct number of points were written if (amount_written != amount) @@ -109,7 +93,6 @@ void Data_Save(DataFile * df, DataPoint * buffer, int amount) df->num_points += amount_written; pthread_mutex_unlock(&(df->mutex)); - } /** @@ -131,21 +114,21 @@ int Data_Read(DataFile * df, DataPoint * buffer, int index, int amount) // If we would read past the end of the file, reduce the amount of points to read - if (index + amount > df->num_points) - { - Log(LOGDEBUG, "Requested %d points but will only read %d to get to EOF (%d)", amount, df->num_points - index, df->num_points); - amount = df->num_points - index; - } + if (index + amount > df->num_points) + { + Log(LOGDEBUG, "Requested %d points but will only read %d to get to EOF (%d)", amount, df->num_points - index, df->num_points); + amount = df->num_points - index; + } // Go to position in file - if (fseek(df->read_file, index*sizeof(DataPoint), SEEK_SET)) + if (fseek(df->file, index*sizeof(DataPoint), SEEK_SET)) { Fatal("Error seeking to position %d in DataFile %s - %s", index, df->filename, strerror(errno)); } // Attempt to read the DataPoints - int amount_read = fread(buffer, sizeof(DataPoint), amount, df->read_file); + int amount_read = fread(buffer, sizeof(DataPoint), amount, df->file); // Check if correct number of points were read if (amount_read != amount) @@ -161,7 +144,7 @@ int Data_Read(DataFile * df, DataPoint * buffer, int index, int amount) * Print data points between two indexes using a given format * @param df - DataFile to print * @param start_index - Index to start at (inclusive) - * @param end_index - Index to end at (inclusive) + * @param end_index - Index to end at (exclusive) * @param format - The format to use */ void Data_PrintByIndexes(DataFile * df, int start_index, int end_index, DataFormat format) @@ -169,53 +152,47 @@ void Data_PrintByIndexes(DataFile * df, int start_index, int end_index, DataForm assert(df != NULL); assert(start_index >= 0); assert(end_index >= 0); - assert(end_index <= df->num_points-1 || df->num_points == 0); + assert(end_index <= df->num_points || df->num_points == 0); const char * fmt_string; // Format for each data point - char seperator; // Character used to seperate successive data points + char separator; // Character used to seperate successive data points - // Determine what format string and seperator character to use + // Determine what format string and separator character to use switch (format) { case JSON: fmt_string = "[%f,%f]"; - seperator = ','; + separator = ','; // For JSON we need an opening bracket FCGI_PrintRaw("["); break; case TSV: fmt_string = "%f\t%f"; - seperator = '\n'; + separator = '\n'; break; } - DataPoint buffer[DATA_BUFSIZ]; // Buffer - // initialise buffer to stop stuff complaining - memset(buffer, 0, sizeof(DataPoint)*DATA_BUFSIZ); - - if (start_index < end_index) + DataPoint buffer[DATA_BUFSIZ] = {{0}}; // Buffer + int index = start_index; + + // Repeat until all DataPoints are printed + while (index < end_index) { + // Fill the buffer from the DataFile + int amount_read = Data_Read(df, buffer, index, DATA_BUFSIZ); - int index = start_index; - // Repeat until all DataPoints are printed - while (index <= end_index) + // Print all points in the buffer + for (int i = 0; i < amount_read && index < end_index; ++i) { - // Fill the buffer from the DataFile - int amount_read = Data_Read(df, buffer, index, DATA_BUFSIZ); - - // Print all points in the buffer - for (int i = 0; i < amount_read && index <= end_index; ++i) - { - // Print individual DataPoint - FCGI_PrintRaw(fmt_string, buffer[i].time_stamp, buffer[i].value); - - // Last seperator is not required - if (index+1 <= end_index) - FCGI_PrintRaw("%c", seperator); - - // Advance the position in the DataFile - ++index; - } + // Print individual DataPoint + FCGI_PrintRaw(fmt_string, buffer[i].time_stamp, buffer[i].value); + + // Last separator is not required + if (index+1 < end_index) + FCGI_PrintRaw("%c", separator); + + // Advance the position in the DataFile + ++index; } } @@ -235,35 +212,25 @@ void Data_PrintByIndexes(DataFile * df, int start_index, int end_index, DataForm * Prints nothing if the time stamp * @param df - DataFile to print * @param start_time - Time to start from (inclusive) - * @param end_time - Time to end at (inclusive) + * @param end_time - Time to end at (exclusive) * @param format - The format to use */ void Data_PrintByTimes(DataFile * df, double start_time, double end_time, DataFormat format) { assert(df != NULL); - assert(start_time >= 0); - assert(end_time >= 0); - assert(end_time >= start_time); - - DataPoint closest; - - // Get starting index - int start_index = Data_FindByTime(df, start_time, &closest); - - // Start time is greater than most recent time stamp - if (start_index >= df->num_points-1) + //Clamp boundaries + if (start_time < 0) + start_time = 0; + if (end_time < 0) + end_time = 0; + + int start_index = 0, end_index = 0; + if (start_time < end_time) { - if (start_index == 0 || closest.time_stamp < start_time) - { - Data_PrintByIndexes(df, 0, 0, format); // Will print "empty" dataset - return; - } + start_index = Data_FindByTime(df, start_time, NULL); + end_index = Data_FindByTime(df, end_time, NULL); } - // Get finishing index - int end_index = Data_FindByTime(df, end_time, &closest); - - // Print data between the indexes Data_PrintByIndexes(df, start_index, end_index, format); } @@ -278,7 +245,7 @@ int Data_FindByTime(DataFile * df, double time_stamp, DataPoint * closest) { assert(df != NULL); assert(time_stamp >= 0); - assert(closest != NULL); + //assert(closest != NULL); DataPoint tmp; // Current DataPoint in binary search diff --git a/server/data.h b/server/data.h index e52dadc..a64d635 100644 --- a/server/data.h +++ b/server/data.h @@ -34,8 +34,7 @@ typedef enum */ typedef struct { - FILE * read_file; // used for reading - FILE * write_file; // used for writing + FILE * file; // file pointer int num_points; // Number of DataPoints in the file char * filename; // Name of the file pthread_mutex_t mutex; // Mutex around num_points diff --git a/server/fastcgi.c b/server/fastcgi.c index b58ba79..34c337a 100644 --- a/server/fastcgi.c +++ b/server/fastcgi.c @@ -237,14 +237,19 @@ bool FCGI_ParseRequest(FCGIContext *context, char *params, FCGIValue values[], s case FCGI_BOOL_T: *((bool*) val->value) = true; break; - case FCGI_LONG_T: - *((long*) val->value) = strtol(value, &ptr, 10); + case FCGI_INT_T: case FCGI_LONG_T: { + long parsed = strtol(value, &ptr, 10); if (!*value || *ptr) { snprintf(buf, BUFSIZ, "Expected int for '%s' but got '%s'", key, value); FCGI_RejectJSON(context, FCGI_EscapeJSON(buf)); return false; } - break; + + if (FCGI_TYPE(val->flags) == FCGI_INT_T) + *((int*) val->value) = parsed; + else + *((long*) val->value) = parsed; + } break; case FCGI_DOUBLE_T: *((double*) val->value) = strtod(value, &ptr); if (!*value || *ptr) { @@ -439,8 +444,6 @@ void * FCGI_RequestLoop (void *data) Log(LOGDEBUG, "First request..."); while (FCGI_Accept() >= 0) { - - Log(LOGDEBUG, "Got request #%d", context.response_number); ModuleHandler module_handler = NULL; char module[BUFSIZ], params[BUFSIZ]; diff --git a/server/fastcgi.h b/server/fastcgi.h index 965cf5c..f0b8bd9 100644 --- a/server/fastcgi.h +++ b/server/fastcgi.h @@ -23,9 +23,10 @@ typedef enum StatusCodes { #define FCGI_PARAM_REQUIRED (1 << 0) #define FCGI_PARAM_RECEIVED (1 << 1) #define FCGI_BOOL_T (1 << 2) -#define FCGI_LONG_T (1 << 3) -#define FCGI_DOUBLE_T (1 << 4) -#define FCGI_STRING_T (1 << 5) +#define FCGI_INT_T (1 << 3) +#define FCGI_LONG_T (1 << 4) +#define FCGI_DOUBLE_T (1 << 5) +#define FCGI_STRING_T (1 << 6) #define FCGI_REQUIRED(x) ((x) | FCGI_PARAM_REQUIRED) #define FCGI_IS_REQUIRED(x) ((x) & FCGI_PARAM_REQUIRED) #define FCGI_RECEIVED(x) ((x) & FCGI_PARAM_RECEIVED) diff --git a/server/sensor.c b/server/sensor.c index 227ea42..0bbfc94 100644 --- a/server/sensor.c +++ b/server/sensor.c @@ -225,8 +225,8 @@ Sensor * Sensor_Identify(const char * id_str) /** * Helper: Begin sensor response in a given format * @param context - the FCGIContext - * @param format - Format * @param id - ID of sensor + * @param format - Format */ void Sensor_BeginResponse(FCGIContext * context, SensorId id, DataFormat format) { @@ -277,11 +277,11 @@ void Sensor_Handler(FCGIContext *context, char * params) int id = 0; double start_time = 0; double end_time = current_time; - char * fmt_str; + const char * fmt_str; // key/value pairs FCGIValue values[] = { - {"id", &id, FCGI_REQUIRED(FCGI_LONG_T)}, + {"id", &id, FCGI_REQUIRED(FCGI_INT_T)}, {"format", &fmt_str, FCGI_STRING_T}, {"start_time", &start_time, FCGI_DOUBLE_T}, {"end_time", &end_time, FCGI_DOUBLE_T}, @@ -301,20 +301,14 @@ void Sensor_Handler(FCGIContext *context, char * params) // Error occured; FCGI_RejectJSON already called return; } - - // Get Sensor - Sensor * s = NULL; - - // Error checking on sensor id - if (id < 0 || id >= NUMSENSORS) - { - Log(LOGERR, "Invalid id %d", id); - } - else + else if (id < 0 || id >= NUMSENSORS) { - s = g_sensors+id; + FCGI_RejectJSON(context, "Invalid sensor id specified"); + return; } - + + // Get Sensor and format + Sensor * s = g_sensors+id; DataFormat format = JSON; // Check if format type was specified @@ -324,17 +318,18 @@ void Sensor_Handler(FCGIContext *context, char * params) format = JSON; else if (strcmp(fmt_str, "tsv") == 0) format = TSV; - else - Log(LOGERR, "Unknown format type \"%s\"", fmt_str); + else + { + FCGI_RejectJSON(context, "Unknown format type specified."); + return; + } } - - // Begin response Sensor_BeginResponse(context, id, format); // If a time was specified - if ((s != NULL) && (FCGI_RECEIVED(values[START_TIME].flags) || FCGI_RECEIVED(values[END_TIME].flags))) + if (FCGI_RECEIVED(values[START_TIME].flags) || FCGI_RECEIVED(values[END_TIME].flags)) { // Wrap times relative to the current time if (start_time < 0) @@ -344,13 +339,12 @@ void Sensor_Handler(FCGIContext *context, char * params) // Print points by time range Data_PrintByTimes(&(s->data_file), start_time, end_time, format); - } - else if (s != NULL) // No time was specified; just return a recent set of points + else // No time was specified; just return a recent set of points { pthread_mutex_lock(&(s->data_file.mutex)); int start_index = s->data_file.num_points-DATA_BUFSIZ; - int end_index = s->data_file.num_points-1; + int end_index = s->data_file.num_points; pthread_mutex_unlock(&(s->data_file.mutex)); // Bounds check