Mercurial > hg > beaglert
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 } |