M1-nw-project/dataStore.cpp

142 lines
3.0 KiB
C++

/***************************************************************************
* By Théophile Bastian, 2017
* M1 Network course project at ENS Cachan, Juliusz Chroboczek.
* License: WTFPL v2 <http://www.wtfpl.net/>
**************************************************************************/
#include "dataStore.h"
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
DataStore::DataStore(Protocol* proto) :
proto(proto), myData(0), hasOwnData(false)
{}
DataStore::~DataStore() {
}
void DataStore::update() {
while(!expireEvents.empty()) {
TimeEvent evt = expireEvents.front();
if(evt.time > time(NULL)) // We're done for now.
break;
expireEvents.pop();
handleExpire(evt.id, evt.seqno);
}
if(hasOwnData) {
if(time(NULL) - recvTime[myData] > csts::TIME_REPUBLISH_DATA)
handleRepublish(myData);
}
}
void DataStore::addData(Bytes pck, u32 seqno, u64 id, bool mine) {
if(curSeqno.find(id) != curSeqno.end() && curSeqno[id] >= seqno)
return;
data[id] = Data(pck, mine);
curSeqno[id] = seqno;
if(mine) {
hasOwnData = true;
myData = id;
}
else {
expireEvents.push(TimeEvent(
time(NULL) + csts::TIMEOUT_DATA,
seqno, id));
// If it is not renewed, it will expire.
}
recvTime[id] = time(NULL);
fprintf(stderr, "[INFO] Storing data %lX (%u)\n", id, seqno);
handleFlood(id);
}
ssize_t DataStore::dataSize(u64 id) {
if(data.find(id) == data.end())
return -1;
return data[id].data.size();
}
ssize_t DataStore::readData(u64 id, char* buffer, size_t size) {
if(data.find(id) == data.end())
return -1;
ssize_t len = min((ssize_t)size, dataSize(id));
data[id].data.writeToBuffer(buffer, size);
return len;
}
void DataStore::ids(std::vector<u64>& out) {
for(auto& dat : data)
out.push_back(dat.first);
}
void DataStore::setFlooded(u64 id) {
toFlood_.erase(id);
}
void DataStore::dump() {
for(auto it=data.begin(); it != data.end(); ++it) {
Bytes dat = it->second.data;
while(dat.size() >= 2) {
printf(">> DATA %lX (%u, %ld sec) ",
it->first, curSeqno[it->first],
time(NULL)-recvTime[it->first]);
if(dat.size() < 2) {
printf("INVALID\n");
continue;
}
u8 type, len;
dat >> type >> len;
if(dat.size() < len) {
printf("INVALID\n");
continue;
}
if(type == csts::TLV_DATA_TEXT) {
string val;
for(int i=0; i < len; i++) {
u8 c;
dat >> c;
val += c;
}
printf("'%s'\n", val.c_str());
}
else
printf("type=%d\n", type);
}
}
}
void DataStore::handleExpire(u64 id, u32 seqno) {
if(seqno < curSeqno[id])
return; // Was updated in time
cleanData(id);
}
void DataStore::handleRepublish(u64 datId) {
if(data.find(datId) == data.end() || !data[datId].isMine) {
return;
}
curSeqno[datId] = time(NULL);
recvTime[datId] = time(NULL);
handleFlood(datId);
}
void DataStore::handleFlood(u64 id) {
toFlood_.insert(id);
}
void DataStore::cleanData(u64 id) {
curSeqno.erase(id);
recvTime.erase(id);
data.erase(id); // Deletes the Bytes as well
}