4 #include "FileLockFunctions.h"
10 #define LF_QUEUESIZE 20
15 #define LF_FILENAME "../PJONLocalFile.dat"
20 #define LF_POLLDELAY 10
24 #ifndef LF_RECEIVE_TIME
25 #define LF_RECEIVE_TIME 0
38 uint16_t lastRecordIdRead = 0;
40 uint16_t last_send_result = PJON_ACK;
44 uint8_t message[PJON_PACKET_MAX_LENGTH];
47 memset(
this, 0,
sizeof(Record));
51 void doOpen(
const bool create =
false)
57 permissions = S_IREAD | S_IWRITE;
62 mode |= O_RANDOM | O_BINARY;
63 _sopen_s(&fn, LF_FILENAME, mode, _SH_DENYNO, permissions);
65 permissions |= S_IRGRP | S_IWGRP | S_IROTH;
67 fn = open(LF_FILENAME, mode, permissions);
71 bool openContentFile()
76 bool file_exists = CheckIfFile(LF_FILENAME);
79 uint16_t lastRecordId = 0, index[LF_QUEUESIZE];
80 memset(index, 0, LF_QUEUESIZE *
sizeof(uint16_t));
84 write(fn, (
const char*)&lastRecordId,
sizeof(lastRecordId));
85 write(fn, (
const char*)index, LF_QUEUESIZE*
sizeof(uint16_t));
87 for(uint8_t i=0; i<LF_QUEUESIZE; i++) {
88 write(fn, (
const char*)&record,
sizeof(Record));
99 void closeContentFile()
107 bool readIndex(uint16_t &lastRecordId, uint16_t index[LF_QUEUESIZE])
109 lseek(fn, 0, SEEK_SET);
110 read(fn, (
char*)&lastRecordId,
sizeof(uint16_t));
111 read(fn, (
char *)index, LF_QUEUESIZE*
sizeof(uint16_t));
115 bool updateIndex(uint16_t recordId, uint8_t indexPos)
117 lseek(fn, 0, SEEK_SET);
118 write(fn, (
const char*)&recordId,
sizeof(uint16_t));
119 lseek(fn,
sizeof recordId + indexPos*
sizeof(uint16_t), SEEK_SET);
120 write(fn, (
const char*)&recordId,
sizeof(uint16_t));
127 LockFileSection(fn, 0, 1, 1, 1, 0);
134 LockFileSection(fn, 0, 1, 0, 1, 0);
138 bool writePacketToFile(
const Record &record)
140 bool success =
false;
142 uint16_t lastRecordId, index[LF_QUEUESIZE];
143 if(readIndex(lastRecordId, index)) {
145 uint8_t recordPos = findReusablePosition(lastRecordId, index);
146 if(recordPos != PJON_NOT_ASSIGNED) {
148 uint16_t diff = (uint16_t)(lastRecordId - index[recordPos]);
149 bool rollover = lastRecordId < index[recordPos];
151 (!rollover && (diff+1 != LF_QUEUESIZE)) ||
152 (rollover && (diff != LF_QUEUESIZE))
154 "countermismatch=%d/%d/%d/(%d) ",
163 LF_QUEUESIZE *
sizeof(uint16_t) +
164 recordPos *
sizeof(Record)
166 lseek(fn, filePos, SEEK_SET);
167 write(fn, (
const char*)&record,
sizeof(Record));
168 uint16_t nextRecordId = (uint16_t)(lastRecordId + 1);
169 if(nextRecordId == 0) {
172 success = updateIndex(nextRecordId, recordPos);
179 bool readNextPacketFromFile(Record &record)
181 bool success =
false;
182 uint16_t lastRecordId, index[LF_QUEUESIZE];
184 if(readIndex(lastRecordId, index)) {
186 if(lastRecordId != 0) {
187 uint8_t recordPos = findNextUnreadPosition(lastRecordId, index);
188 if(recordPos != PJON_NOT_ASSIGNED) {
191 LF_QUEUESIZE *
sizeof(uint16_t) +
192 recordPos *
sizeof(Record)
194 lseek(fn, filePos, SEEK_SET);
195 read(fn, (
char*)&record,
sizeof(Record));
196 lastRecordIdRead = index[recordPos];
205 uint8_t findReusablePosition(
206 const uint16_t lastRecordId,
207 const uint16_t index[LF_QUEUESIZE]
210 uint16_t maxDiff = 0;
211 uint8_t pos = PJON_NOT_ASSIGNED;
212 for(uint8_t i = 0; i < LF_QUEUESIZE; i++) {
216 uint16_t diff = (uint16_t)(lastRecordId - index[i]);
225 uint8_t findNextUnreadPosition(
226 const uint16_t lastRecordId,
227 const uint16_t index[LF_QUEUESIZE]
230 uint8_t pos = PJON_NOT_ASSIGNED;
231 if(lastRecordIdRead == 0) {
232 lastRecordIdRead = lastRecordId - LF_QUEUESIZE;
234 if(lastRecordId == lastRecordIdRead) {
237 uint16_t minDiff = 0xFFFF;
238 for(uint8_t i = 0; i < LF_QUEUESIZE; i++) {
239 if(index[i] == 0 || index[i] == lastRecordIdRead) {
242 uint16_t diff = (uint16_t)(index[i] - lastRecordIdRead);
243 if(diff < 0x8FFF && diff < minDiff) {
258 uint32_t back_off(uint8_t attempts)
260 return 1000 * attempts;
263 bool begin(uint8_t did)
265 return openContentFile();
268 void handle_collision()
281 uint8_t get_max_attempts()
286 static uint16_t get_receive_time()
288 return LF_RECEIVE_TIME;
291 uint16_t receive_frame(uint8_t *
data, uint16_t max_length)
294 if(readNextPacketFromFile(record)) {
296 record.length < max_length ? record.length : max_length;
297 memcpy(
data, record.message, length);
301 PJON_DELAY(LF_POLLDELAY);
306 uint16_t receive_response()
308 return last_send_result;
311 void send_response(uint8_t response) { };
313 void send_frame(uint8_t *
data, uint16_t length)
316 memcpy(&record.message,
data, length);
317 record.length = length;
318 bool ok = writePacketToFile(record);
319 last_send_result = ok ? PJON_ACK : PJON_FAIL;