cleanup pendingdata vector

This commit is contained in:
Nic Limper
2023-04-27 22:37:33 +02:00
parent a46678386e
commit 9158549cb3
6 changed files with 90 additions and 134 deletions

View File

@@ -1,23 +0,0 @@
#include <Arduino.h>
#include <vector>
#pragma pack(push, 1)
#pragma once
class pendingdata {
public:
String filename;
uint64_t ver;
uint32_t timeout;
uint8_t datatimeout;
uint8_t* data = nullptr;
uint32_t len;
static pendingdata* findByVer(uint64_t ver);
static void garbageCollection();
};
void garbageCollection(void* parameter);
extern std::vector<pendingdata*> pendingfiles;
#pragma pack(pop)

View File

@@ -18,7 +18,8 @@
class tagRecord {
public:
uint16_t nextCheckinpending;
tagRecord() : mac{0}, alias(""), lastseen(0), nextupdate(0), contentMode(0), pending(false), md5{0}, md5pending{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false) {}
tagRecord() : mac{0}, alias(""), lastseen(0), nextupdate(0), contentMode(0), pending(false), md5{0}, md5pending{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false),
filename(""), data(nullptr), len(0) {}
uint8_t mac[6];
String alias;
@@ -39,6 +40,11 @@ class tagRecord {
uint8_t capabilities;
uint32_t lastfullupdate;
bool isExternal;
String filename;
uint8_t* data;
uint32_t len;
static tagRecord* findByMAC(uint8_t mac[6]);
};
@@ -48,5 +54,7 @@ bool deleteRecord(uint8_t mac[6]);
void fillNode(JsonObject &tag, tagRecord* &taginfo);
void saveDB(String filename);
void loadDB(String filename);
uint8_t getTagCount();
void clearPending(tagRecord* taginfo);
#pragma pack(pop)

View File

@@ -7,7 +7,6 @@
#include "flasher.h"
//#include "hal/wdt_hal.h"
#include "makeimage.h"
#include "pendingdata.h"
#include "serial.h"
#include "settings.h"
#include "tag_db.h"
@@ -28,7 +27,7 @@ void timeTask(void* parameter) {
if (!getLocalTime(&tm)) {
Serial.println("Waiting for valid time from NTP-server");
} else {
if (now % 10 == 0) wsSendSysteminfo();
if (now % 5 == 0) wsSendSysteminfo();
if (now % 30 == 3) Ping();
if (now % 300 == 6) saveDB("/current/tagDB.json");
@@ -71,7 +70,6 @@ void setup() {
loadDB("/current/tagDB.json");
xTaskCreate(zbsRxTask, "zbsRX Process", 10000, NULL, 2, NULL);
xTaskCreate(garbageCollection, "pending-data cleanup", 5000, NULL, 1, NULL);
xTaskCreate(webSocketSendProcess, "ws", 5000, NULL, configMAX_PRIORITIES - 10, NULL);
xTaskCreate(timeTask, "timed tasks", 10000, NULL, 2, NULL);
xTaskCreate(ledTask, "handles leds", 5000, NULL, 10, NULL);

View File

@@ -10,7 +10,6 @@
#include "LittleFS.h"
#include "commstructs.h"
#include "pendingdata.h"
#include "serial.h"
#include "settings.h"
#include "tag_db.h"
@@ -39,6 +38,7 @@ bool checkCRC(void* p, uint8_t len) {
uint8_t* getDataForFile(fs::File* file) {
uint8_t* ret = nullptr;
ret = (uint8_t*)malloc(file->size());
Serial.println("malloc " + String(file->size()));
if (ret) {
file->seek(0);
file->readBytes((char*)ret, file->size());
@@ -48,10 +48,24 @@ uint8_t* getDataForFile(fs::File* file) {
return ret;
}
void prepareCancelPending(uint64_t ver) {
void prepareCancelPending(uint8_t dst[8]) {
struct pendingData pending = {0};
pending.availdatainfo.dataVer = ver;
memcpy(pending.targetMac, dst, 8);
sendCancelPending(&pending);
uint8_t src[8];
*((uint64_t*)src) = swap64(*((uint64_t*)dst));
uint8_t mac[6];
memcpy(mac, src + 2, sizeof(mac));
tagRecord* taginfo = nullptr;
taginfo = tagRecord::findByMAC(mac);
if (taginfo == nullptr) {
wsErr("Tag not found, this shouldn't happen.");
return;
}
clearPending(taginfo);
wsSendTaginfo(mac);
}
void prepareIdleReq(uint8_t* dst, uint16_t nextCheckin) {
@@ -146,15 +160,19 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t
wsLog("new image: " + String(dst_path));
time_t now;
time(&now);
taginfo->pending = true;
taginfo->expectedNextCheckin = now + nextCheckin * 60 + 60;
taginfo->filename = *filename;
taginfo->len = filesize;
clearPending(taginfo);
taginfo->pending = true;
memcpy(taginfo->md5pending, md5bytes, sizeof(md5bytes));
} else {
wsLog("firmware upload pending");
taginfo->filename = *filename;
taginfo->len = filesize;
}
// the message that will be sent to the AP to tell the tag there is data pending
struct pendingData pending = {0};
memcpy(pending.targetMac, dst, 8);
pending.availdatainfo.dataType = dataType;
@@ -169,16 +187,6 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t
udpsync.netSendDataAvail(&pending);
}
// data for the cache on the esp32; needs to hold the data longer than the maximum timeout on the AP
pendingdata* pendinginfo = nullptr;
pendinginfo = new pendingdata;
pendinginfo->filename = *filename;
pendinginfo->ver = pending.availdatainfo.dataVer;
pendinginfo->len = pending.availdatainfo.dataSize;
pendinginfo->data = nullptr;
pendinginfo->timeout = PENDING_TIMEOUT;
pendingfiles.push_back(pendinginfo);
wsSendTaginfo(mac);
return true;
@@ -232,15 +240,9 @@ void prepareExternalDataAvail(struct pendingData* pending, IPAddress remoteIP) {
file.close();
sendDataAvail(pending);
pendingdata* pendinginfo = nullptr;
pendinginfo = new pendingdata;
pendinginfo->filename = filename;
pendinginfo->ver = *((uint64_t*)md5bytes);
pendinginfo->len = filesize;
pendinginfo->data = nullptr;
pendinginfo->timeout = PENDING_TIMEOUT;
pendingfiles.push_back(pendinginfo);
taginfo->filename = filename;
taginfo->len = filesize;
clearPending(taginfo);
taginfo->pending = true;
memcpy(taginfo->md5pending, md5bytes, sizeof(md5bytes));
taginfo->contentMode = 12;
@@ -256,43 +258,44 @@ void processBlockRequest(struct espBlockRequest* br) {
return;
}
pendingdata* pd = pendingdata::findByVer(br->ver);
if (pd == nullptr) {
prepareCancelPending(br->ver);
Serial.printf("Couldn't find pendingdata info for ver %llu", br->ver);
uint8_t src[8];
*((uint64_t*)src) = swap64(*((uint64_t*)br->src));
uint8_t mac[6];
memcpy(mac, src + 2, sizeof(mac));
tagRecord* taginfo = nullptr;
taginfo = tagRecord::findByMAC(mac);
if (taginfo == nullptr) {
prepareCancelPending(br->src);
Serial.printf("blockrequest: couldn't find taginfo %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", br->src[7], br->src[6], br->src[5], br->src[4], br->src[3], br->src[2], br->src[1], br->src[0]);
return;
} else {
if (pd->data == nullptr) {
// not cached. open file, cache the data
fs::File file = LittleFS.open(pd->filename);
if (!file) {
Serial.print("Dunno how this happened... File pending but deleted in the meantime?\n");
prepareCancelPending(br->ver);
return;
}
pd->data = getDataForFile(&file);
pd->datatimeout = PENDING_DATA_TIMEOUT;
file.close();
} else {
// file is already cached, refresh the timeout
//pd->datatimeout = PENDING_DATA_TIMEOUT;
}
}
if (taginfo->data == nullptr) {
// not cached. open file, cache the data
fs::File file = LittleFS.open(taginfo->filename);
if (!file) {
Serial.print("Dunno how this happened... File pending but deleted in the meantime?\n");
prepareCancelPending(br->src);
return;
}
taginfo->data = getDataForFile(&file);
file.close();
}
// check if we're not exceeding max blocks (to prevent sendBlock from exceeding its boundary)
uint8_t totalblocks = (pd->len / BLOCK_DATA_SIZE);
if (pd->len % BLOCK_DATA_SIZE) totalblocks++;
uint8_t totalblocks = (taginfo->len / BLOCK_DATA_SIZE);
if (taginfo->len % BLOCK_DATA_SIZE) totalblocks++;
if (br->blockId >= totalblocks) {
br->blockId = totalblocks - 1;
}
uint32_t len = pd->len - (BLOCK_DATA_SIZE * br->blockId);
uint32_t len = taginfo->len - (BLOCK_DATA_SIZE * br->blockId);
if (len > BLOCK_DATA_SIZE) len = BLOCK_DATA_SIZE;
uint16_t checksum = sendBlock(pd->data + (br->blockId * BLOCK_DATA_SIZE), len);
uint16_t checksum = sendBlock(taginfo->data + (br->blockId * BLOCK_DATA_SIZE), len);
char buffer[150];
sprintf(buffer, "< Block Request received for file %s block %d, len %d checksum %u\0", pd->filename.c_str(), br->blockId, len, checksum);
sprintf(buffer, "< Block Request received for file %s block %d, len %d checksum %u\0", taginfo->filename.c_str(), br->blockId, len, checksum);
wsLog((String)buffer);
Serial.printf("< Block Request received for MD5 %llu, file %s block %d, len %d checksum %u", br->ver, pd->filename.c_str(), br->blockId, len, checksum);
Serial.printf(" from mac %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", br->src[7],br->src[6],br->src[5],br->src[4],br->src[3],br->src[2],br->src[1],br->src[0]);
Serial.printf("< Block Request received for file %s block %d, len %d checksum %u\0", taginfo->filename.c_str(), br->blockId, len, checksum);
}
void processXferComplete(struct espXferComplete* xfc) {
@@ -332,7 +335,7 @@ void processXferComplete(struct espXferComplete* xfc) {
taginfo->expectedNextCheckin = now + 60;
}
taginfo->pending = false;
clearPending(taginfo);
memcpy(taginfo->md5, taginfo->md5pending, sizeof(taginfo->md5pending));
}
wsSendTaginfo(mac);
@@ -354,8 +357,8 @@ void processXferTimeout(struct espXferComplete* xfc) {
taginfo = tagRecord::findByMAC(mac);
if (taginfo != nullptr) {
taginfo->expectedNextCheckin = now + 60;
taginfo->pending = false;
memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t));
clearPending(taginfo);
}
wsSendTaginfo(mac);
}
@@ -422,7 +425,7 @@ void refreshAllPending() {
tagRecord* taginfo = nullptr;
taginfo = tagDB.at(c);
if (taginfo->pending) {
taginfo->pending = false;
clearPending(taginfo);
taginfo->nextupdate = 0;
memset(taginfo->md5, 0, 16 * sizeof(uint8_t));
memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t));

View File

@@ -1,53 +0,0 @@
#include "pendingdata.h"
#include <Arduino.h>
#include <vector>
#include "settings.h"
std::vector<pendingdata*> pendingfiles;
void garbageCollection(void* parameter) {
while (1) {
vTaskDelay(1000 / portTICK_PERIOD_MS);
pendingdata::garbageCollection();
}
}
pendingdata* pendingdata::findByVer(uint64_t ver) {
for (int16_t c = 0; c < pendingfiles.size(); c++) {
pendingdata* pending = nullptr;
pending = pendingfiles.at(c);
if (pending->ver == ver) {
return pending;
}
}
return nullptr;
}
void pendingdata::garbageCollection() {
for (int16_t c = 0; c < pendingfiles.size(); c++) {
pendingdata* pending = pendingfiles.at(c);
if (pending->datatimeout > 1) {
pending->datatimeout--;
} else if (pending->datatimeout == 1) {
if (pending->data != nullptr) {
free(pending->data);
}
pending->data = nullptr;
pending->datatimeout == 0;
}
if (pending->timeout) {
pending->timeout--;
} else {
if (pending->data != nullptr) {
free(pending->data);
}
pending->data = nullptr;
delete pending;
pendingfiles.erase(pendingfiles.begin() + c);
}
}
}

View File

@@ -25,6 +25,10 @@ bool deleteRecord(uint8_t mac[6]) {
tagRecord* tag = nullptr;
tag = tagDB.at(c);
if (memcmp(tag->mac, mac, 6) == 0) {
if (tag->data != nullptr) {
free(tag->data);
}
tag->data = nullptr;
delete tagDB[c];
tagDB.erase(tagDB.begin() + c);
return true;
@@ -198,3 +202,22 @@ void loadDB(String filename) {
return;
}
uint8_t getTagCount() {
uint8_t tagcount = 0;
for (int16_t c = 0; c < tagDB.size(); c++) {
tagRecord* taginfo = nullptr;
taginfo = tagDB.at(c);
if (taginfo->isExternal == false) tagcount++;
}
return tagcount;
}
void clearPending(tagRecord* taginfo) {
if (taginfo->data != nullptr) {
free(taginfo->data);
Serial.println("free taginfo->data");
taginfo->data = nullptr;
}
taginfo->pending = false;
}