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