annotate 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
rev   line source
giuliomoro@153 1 /*
giuliomoro@153 2 * WriteFile.cpp
giuliomoro@153 3 *
giuliomoro@153 4 * Created on: 5 Oct 2015
giuliomoro@153 5 * Author: giulio
giuliomoro@153 6 */
giuliomoro@153 7
giuliomoro@153 8 #include "WriteFile.h"
giuliomoro@153 9 //initialise static members
giuliomoro@153 10 bool WriteFile::staticConstructed=false;
giuliomoro@153 11 AuxiliaryTask WriteFile::writeAllFilesTask=NULL;
giuliomoro@153 12 std::vector<WriteFile *> WriteFile::objAddrs(0);
giuliomoro@153 13 bool WriteFile::threadRunning;
giuliomoro@153 14 bool WriteFile::threadIsExiting;
giuliomoro@153 15 int WriteFile::sleepTimeMs;
giuliomoro@153 16
giuliomoro@153 17 void WriteFile::staticConstructor(){
giuliomoro@153 18 if(staticConstructed==true)
giuliomoro@153 19 return;
giuliomoro@153 20 staticConstructed=true;
giuliomoro@153 21 threadIsExiting=false;
giuliomoro@153 22 threadRunning=false;
giuliomoro@153 23 writeAllFilesTask = BeagleRT_createAuxiliaryTask(WriteFile::run, 60, "writeAllFilesTask");
giuliomoro@153 24 }
giuliomoro@153 25
giuliomoro@153 26 WriteFile::WriteFile(){
giuliomoro@153 27 buffer = NULL;
giuliomoro@153 28 format = NULL;
giuliomoro@153 29 header = NULL;
giuliomoro@153 30 footer = NULL;
giuliomoro@153 31 stringBuffer = NULL;
giuliomoro@153 32 };
giuliomoro@153 33
giuliomoro@153 34 void WriteFile::init(const char* filename){ //if you do not call this before using the object, results are undefined
giuliomoro@153 35 file = fopen(filename, "w");
giuliomoro@153 36 variableOpen = false;
giuliomoro@153 37 lineLength = 0;
giuliomoro@153 38 echo = false;
giuliomoro@153 39 bufferLength = 0;
giuliomoro@153 40 readPointer = 0;
giuliomoro@153 41 writePointer = 0;
giuliomoro@153 42 sleepTimeMs = 1;
giuliomoro@153 43 stringBufferLength = 1000;
giuliomoro@153 44 stringBuffer = (char*)malloc(sizeof(char) * (stringBufferLength));
giuliomoro@153 45 setHeader("variable=[\n");
giuliomoro@153 46 setFooter("];\n");
giuliomoro@153 47 staticConstructor(); //TODO: this line should be in the constructor, but cannot because of a bug in BeagleRT
giuliomoro@153 48 objAddrs.push_back(this);
giuliomoro@153 49 }
giuliomoro@153 50
giuliomoro@153 51 void WriteFile::setEcho(bool newEcho){
giuliomoro@153 52 echo=newEcho;
giuliomoro@153 53 }
giuliomoro@153 54
giuliomoro@153 55 void WriteFile::print(const char* string){
giuliomoro@153 56 if(echo == true){
giuliomoro@153 57 printf("%s", string);
giuliomoro@153 58 }
giuliomoro@153 59 if(file != NULL){
giuliomoro@153 60 fprintf(file, "%s", string);
giuliomoro@153 61 }
giuliomoro@153 62 }
giuliomoro@153 63
giuliomoro@153 64 void WriteFile::writeLine(){
giuliomoro@153 65 int stringBufferPointer = 0;
giuliomoro@153 66 for(unsigned int n = 0; n < formatTokens.size(); n++){
giuliomoro@153 67 int numOfCharsWritten = snprintf( &stringBuffer[stringBufferPointer], stringBufferLength - stringBufferPointer,
giuliomoro@153 68 formatTokens[n], buffer[readPointer]);
giuliomoro@153 69 stringBufferPointer += numOfCharsWritten;
giuliomoro@153 70 readPointer++;
giuliomoro@153 71 if (readPointer >= bufferLength){
giuliomoro@153 72 readPointer -= bufferLength;
giuliomoro@153 73 }
giuliomoro@153 74 }
giuliomoro@153 75 print(stringBuffer);
giuliomoro@153 76 }
giuliomoro@153 77
giuliomoro@153 78 void WriteFile::setLineLength(int newLineLength){
giuliomoro@153 79 lineLength=newLineLength;
giuliomoro@153 80 free(buffer);
giuliomoro@153 81 bufferLength = lineLength * 10000; // circular buffer of length 10000 lineLenghts
giuliomoro@153 82 buffer = (float*)malloc(sizeof(float) * bufferLength);
giuliomoro@153 83 }
giuliomoro@153 84
giuliomoro@153 85 void WriteFile::log(float value){
giuliomoro@153 86 if(format == NULL || buffer == NULL)
giuliomoro@153 87 return;
giuliomoro@153 88 buffer[writePointer] = value;
giuliomoro@153 89 writePointer++;
giuliomoro@153 90 if(writePointer == bufferLength){
giuliomoro@153 91 writePointer = 0;
giuliomoro@153 92 }
giuliomoro@153 93 if(writePointer == readPointer){
giuliomoro@153 94 fprintf(stderr, "WriteFile: pointers crossed, you should probably write less data to disk\n");
giuliomoro@153 95 }
giuliomoro@153 96 if(threadRunning == false){
giuliomoro@153 97 startThread();
giuliomoro@153 98 }
giuliomoro@153 99 }
giuliomoro@153 100
giuliomoro@153 101 void WriteFile::log(float* array, int length){
giuliomoro@153 102 for(int n = 0; n < length; n++){
giuliomoro@153 103 log(array[n]);
giuliomoro@153 104 }
giuliomoro@153 105 }
giuliomoro@153 106
giuliomoro@153 107 WriteFile::~WriteFile() {
giuliomoro@153 108 free(format);
giuliomoro@153 109 free(buffer);
giuliomoro@153 110 free(header);
giuliomoro@153 111 free(footer);
giuliomoro@153 112 free(stringBuffer);
giuliomoro@153 113 }
giuliomoro@153 114
giuliomoro@153 115 void WriteFile::setFormat(const char* newFormat){
giuliomoro@153 116 allocateAndCopyString(newFormat, &format);
giuliomoro@153 117 for(unsigned int n = 0; n < formatTokens.size(); n++){
giuliomoro@153 118 free(formatTokens[n]);
giuliomoro@153 119 }
giuliomoro@153 120 formatTokens.clear();
giuliomoro@153 121 int tokenStart = 0;
giuliomoro@153 122 bool firstToken = true;
giuliomoro@153 123 for(unsigned int n = 0; n < strlen(format)+1; n++){
giuliomoro@153 124 if(format[n] == '%' && format[n + 1] == '%'){
giuliomoro@153 125 n++;
giuliomoro@153 126 } else if (format[n] == '%' || format[n] == 0){
giuliomoro@153 127 if(firstToken == true){
giuliomoro@153 128 firstToken = false;
giuliomoro@153 129 continue;
giuliomoro@153 130 }
giuliomoro@153 131 char* string;
giuliomoro@153 132 unsigned int tokenLength = n - tokenStart;
giuliomoro@153 133 if(tokenLength == 0)
giuliomoro@153 134 continue;
giuliomoro@153 135 string = (char*)malloc((1+tokenLength)*sizeof(char));
giuliomoro@153 136 for(unsigned int i = 0; i < tokenLength; i++){
giuliomoro@153 137 string[i] = format[tokenStart + i];
giuliomoro@153 138 }
giuliomoro@153 139 string[tokenLength] = 0;
giuliomoro@153 140 formatTokens.push_back(string);
giuliomoro@153 141 tokenStart = n;
giuliomoro@153 142 }
giuliomoro@153 143 }
giuliomoro@153 144 setLineLength(formatTokens.size());
giuliomoro@153 145 }
giuliomoro@153 146
giuliomoro@153 147 int WriteFile::getNumInstances(){
giuliomoro@153 148 return objAddrs.size();
giuliomoro@153 149 }
giuliomoro@153 150
giuliomoro@153 151 void WriteFile::startThread(){
giuliomoro@153 152 BeagleRT_scheduleAuxiliaryTask(writeAllFilesTask);
giuliomoro@153 153 }
giuliomoro@153 154
giuliomoro@153 155 void WriteFile::stopThread(){
giuliomoro@153 156 threadIsExiting=true;
giuliomoro@153 157 }
giuliomoro@153 158
giuliomoro@153 159 bool WriteFile::threadShouldExit(){
giuliomoro@153 160 return(gShouldStop || threadIsExiting);
giuliomoro@153 161 }
giuliomoro@153 162
giuliomoro@153 163 bool WriteFile::isThreadRunning(){
giuliomoro@153 164 return threadRunning;
giuliomoro@153 165 }
giuliomoro@153 166
giuliomoro@153 167 float WriteFile::getBufferStatus(){
giuliomoro@153 168 return 1-getOffset()/(float)bufferLength;
giuliomoro@153 169 }
giuliomoro@153 170
giuliomoro@153 171 int WriteFile::getOffset(){
giuliomoro@153 172 int offset = writePointer - readPointer;
giuliomoro@153 173 if( offset < 0)
giuliomoro@153 174 offset += bufferLength;
giuliomoro@153 175 return offset;
giuliomoro@153 176 }
giuliomoro@153 177
giuliomoro@153 178 void WriteFile::writeOutput(){
giuliomoro@153 179 while( getOffset() >= lineLength ){ //if there is less than one line worth of data to write, skip over.
giuliomoro@153 180 // So we make sure we always write full lines
giuliomoro@153 181 writeLine();
giuliomoro@153 182 }
giuliomoro@153 183 }
giuliomoro@153 184
giuliomoro@153 185 void WriteFile::writeAllOutputs(){
giuliomoro@153 186 for(unsigned int n = 0; n < objAddrs.size(); n++){
giuliomoro@153 187 objAddrs[n] -> writeOutput();
giuliomoro@153 188 }
giuliomoro@153 189 }
giuliomoro@153 190
giuliomoro@153 191 void WriteFile::writeAllHeaders(){
giuliomoro@153 192 for(unsigned int n = 0; n < objAddrs.size(); n++){
giuliomoro@153 193 objAddrs[n] -> writeHeader();
giuliomoro@153 194 }
giuliomoro@153 195 }
giuliomoro@153 196
giuliomoro@153 197 void WriteFile::writeAllFooters(){
giuliomoro@153 198 for(unsigned int n = 0; n < objAddrs.size(); n++){
giuliomoro@153 199 objAddrs[n] -> writeFooter();
giuliomoro@153 200 }
giuliomoro@153 201 }
giuliomoro@153 202
giuliomoro@153 203 void WriteFile::writeHeader(){
giuliomoro@153 204 print(header);
giuliomoro@153 205 }
giuliomoro@153 206
giuliomoro@153 207 void WriteFile::writeFooter(){
giuliomoro@153 208 print(footer);
giuliomoro@153 209 fflush(file);
giuliomoro@153 210 fclose(file);
giuliomoro@153 211 }
giuliomoro@153 212
giuliomoro@153 213 void WriteFile::setHeader(const char* newHeader){
giuliomoro@153 214 allocateAndCopyString(newHeader, &header);
giuliomoro@153 215 sanitizeString(header);
giuliomoro@153 216 }
giuliomoro@153 217
giuliomoro@153 218 void WriteFile::setFooter(const char* newFooter){
giuliomoro@153 219 allocateAndCopyString(newFooter, &footer);
giuliomoro@153 220 }
giuliomoro@153 221
giuliomoro@153 222 void WriteFile::sanitizeString(char* string){
giuliomoro@153 223 for(int unsigned n = 0; n < strlen(string); n++){ //purge %'s from the string
giuliomoro@153 224 if(string[n] == '%'){
giuliomoro@153 225 string[n] = ' ';
giuliomoro@153 226 }
giuliomoro@153 227 }
giuliomoro@153 228 }
giuliomoro@153 229
giuliomoro@153 230 void WriteFile::run(){
giuliomoro@153 231 threadRunning = true;
giuliomoro@153 232 writeAllHeaders();
giuliomoro@153 233 while(threadShouldExit()==false){
giuliomoro@153 234 writeAllOutputs();
giuliomoro@153 235 usleep(sleepTimeMs*1000);
giuliomoro@153 236 }
giuliomoro@153 237 writeAllFooters(); // when ctrl-c is pressed, the last line is closed and the file is closed
giuliomoro@153 238 threadRunning = false;
giuliomoro@153 239 }
giuliomoro@153 240
giuliomoro@153 241 void WriteFile::allocateAndCopyString(const char* source, char** destination){
giuliomoro@153 242 free(*destination);
giuliomoro@153 243 *destination = (char*)malloc(sizeof(char) * (strlen(source) + 1));
giuliomoro@153 244 strcpy(*destination, source);
giuliomoro@153 245 }