diff core/WriteFile.cpp @ 153:3b7270949a97

Added WriteFile class to log data to disc in a low priority thread
author Giulio Moro <giuliomoro@yahoo.it>
date Wed, 07 Oct 2015 20:58:53 +0100
parents
children f36313cbb55d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/WriteFile.cpp	Wed Oct 07 20:58:53 2015 +0100
@@ -0,0 +1,245 @@
+/*
+ * WriteFile.cpp
+ *
+ *  Created on: 5 Oct 2015
+ *      Author: giulio
+ */
+
+#include "WriteFile.h"
+//initialise static members
+bool WriteFile::staticConstructed=false;
+AuxiliaryTask WriteFile::writeAllFilesTask=NULL;
+std::vector<WriteFile *> WriteFile::objAddrs(0);
+bool WriteFile::threadRunning;
+bool WriteFile::threadIsExiting;
+int WriteFile::sleepTimeMs;
+
+void WriteFile::staticConstructor(){
+	if(staticConstructed==true)
+			return;
+	staticConstructed=true;
+	threadIsExiting=false;
+	threadRunning=false;
+	writeAllFilesTask = BeagleRT_createAuxiliaryTask(WriteFile::run, 60, "writeAllFilesTask");
+}
+
+WriteFile::WriteFile(){
+	buffer = NULL;
+	format = NULL;
+	header = NULL;
+	footer = NULL;
+	stringBuffer = NULL;
+};
+
+void WriteFile::init(const char* filename){ //if you do not call this before using the object, results are undefined
+	file = fopen(filename, "w");
+	variableOpen = false;
+	lineLength = 0;
+	echo = false;
+	bufferLength = 0;
+	readPointer = 0;
+	writePointer = 0;
+	sleepTimeMs = 1;
+	stringBufferLength = 1000;
+	stringBuffer = (char*)malloc(sizeof(char) * (stringBufferLength));
+	setHeader("variable=[\n");
+	setFooter("];\n");
+	staticConstructor(); //TODO: this line should be in the constructor, but cannot because of a bug in BeagleRT
+	objAddrs.push_back(this);
+}
+
+void WriteFile::setEcho(bool newEcho){
+	echo=newEcho;
+}
+
+void WriteFile::print(const char* string){
+	if(echo == true){
+		printf("%s", string);
+	}
+	if(file != NULL){
+		fprintf(file, "%s", string);
+	}
+}
+
+void WriteFile::writeLine(){
+	int stringBufferPointer = 0;
+	for(unsigned int n = 0; n < formatTokens.size(); n++){
+		int numOfCharsWritten = snprintf( &stringBuffer[stringBufferPointer], stringBufferLength - stringBufferPointer,
+							formatTokens[n], buffer[readPointer]);
+		stringBufferPointer += numOfCharsWritten;
+		readPointer++;
+		if (readPointer >= bufferLength){
+			readPointer -= bufferLength;
+		}
+	}
+	print(stringBuffer);
+}
+
+void WriteFile::setLineLength(int newLineLength){
+	lineLength=newLineLength;
+	free(buffer);
+	bufferLength = lineLength * 10000; // circular buffer of length 10000 lineLenghts
+	buffer = (float*)malloc(sizeof(float) * bufferLength);
+}
+
+void WriteFile::log(float value){
+	if(format == NULL || buffer == NULL)
+		return;
+	buffer[writePointer] = value;
+	writePointer++;
+	if(writePointer == bufferLength){
+		writePointer = 0;
+	}
+	if(writePointer == readPointer){
+		fprintf(stderr, "WriteFile: pointers crossed, you should probably write less data to disk\n");
+	}
+	if(threadRunning == false){
+		startThread();
+	}
+}
+
+void WriteFile::log(float* array, int length){
+	for(int n = 0; n < length; n++){
+		log(array[n]);
+	}
+}
+
+WriteFile::~WriteFile() {
+	free(format);
+	free(buffer);
+	free(header);
+	free(footer);
+	free(stringBuffer);
+}
+
+void WriteFile::setFormat(const char* newFormat){
+	allocateAndCopyString(newFormat, &format);
+	for(unsigned int n = 0; n < formatTokens.size(); n++){
+		free(formatTokens[n]);
+	}
+	formatTokens.clear();
+	int tokenStart = 0;
+	bool firstToken = true;
+	for(unsigned int n = 0; n < strlen(format)+1; n++){
+		if(format[n] == '%' && format[n + 1] == '%'){
+			n++;
+		} else if (format[n] == '%' || format[n] == 0){
+			if(firstToken == true){
+				firstToken = false;
+				continue;
+			}
+			char* string;
+			unsigned int tokenLength = n - tokenStart;
+			if(tokenLength == 0)
+				continue;
+			string = (char*)malloc((1+tokenLength)*sizeof(char));
+			for(unsigned int i = 0; i < tokenLength; i++){
+				string[i] = format[tokenStart + i];
+			}
+			string[tokenLength] = 0;
+			formatTokens.push_back(string);
+			tokenStart = n;
+		}
+	}
+	setLineLength(formatTokens.size());
+}
+
+int WriteFile::getNumInstances(){
+	return objAddrs.size();
+}
+
+void WriteFile::startThread(){
+	BeagleRT_scheduleAuxiliaryTask(writeAllFilesTask);
+}
+
+void WriteFile::stopThread(){
+	threadIsExiting=true;
+}
+
+bool WriteFile::threadShouldExit(){
+	return(gShouldStop || threadIsExiting);
+}
+
+bool WriteFile::isThreadRunning(){
+	return threadRunning;
+}
+
+float WriteFile::getBufferStatus(){
+	return 1-getOffset()/(float)bufferLength;
+}
+
+int WriteFile::getOffset(){
+	int offset = writePointer - readPointer;
+	if( offset < 0)
+		offset += bufferLength;
+	return offset;
+}
+
+void WriteFile::writeOutput(){
+	while( getOffset() >= lineLength ){ //if there is less than one line worth of data to write, skip over.
+							 	 // So we make sure we always write full lines
+		writeLine();
+	}
+}
+
+void WriteFile::writeAllOutputs(){
+	for(unsigned int n = 0; n < objAddrs.size(); n++){
+		objAddrs[n] -> writeOutput();
+	}
+}
+
+void WriteFile::writeAllHeaders(){
+	for(unsigned int n = 0; n < objAddrs.size(); n++){
+		objAddrs[n] -> writeHeader();
+	}
+}
+
+void WriteFile::writeAllFooters(){
+	for(unsigned int n = 0; n < objAddrs.size(); n++){
+		objAddrs[n] -> writeFooter();
+	}
+}
+
+void WriteFile::writeHeader(){
+	print(header);
+}
+
+void WriteFile::writeFooter(){
+	print(footer);
+	fflush(file);
+	fclose(file);
+}
+
+void WriteFile::setHeader(const char* newHeader){
+	allocateAndCopyString(newHeader, &header);
+	sanitizeString(header);
+}
+
+void WriteFile::setFooter(const char* newFooter){
+	allocateAndCopyString(newFooter, &footer);
+}
+
+void WriteFile::sanitizeString(char* string){
+	for(int unsigned n = 0; n < strlen(string); n++){ //purge %'s from the string
+		if(string[n] == '%'){
+			string[n] = ' ';
+		}
+	}
+}
+
+void WriteFile::run(){
+	threadRunning = true;
+	writeAllHeaders();
+	while(threadShouldExit()==false){
+		writeAllOutputs();
+		usleep(sleepTimeMs*1000);
+	}
+	writeAllFooters(); // when ctrl-c is pressed, the last line is closed and the file is closed
+	threadRunning = false;
+}
+
+void WriteFile::allocateAndCopyString(const char* source, char** destination){
+	free(*destination);
+	*destination = (char*)malloc(sizeof(char) * (strlen(source) + 1));
+	strcpy(*destination, source);
+}