Skip to content

Commit

Permalink
recordsNumber(): state check fix.
Browse files Browse the repository at this point in the history
  • Loading branch information
JulStrat committed Sep 2, 2021
1 parent 487845e commit a89f4d3
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 46 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@
# uCDB

Arduino library for querying [Constant DataBase](https://en.wikipedia.org/wiki/Cdb_(software)) (key, value) store.
Simple, fast and portable CDB file format was developed by D. J. Bernstein.
Simple, :cyclone: fast and portable CDB file format was developed by D. J. Bernstein.

Compatible storage libraries:
- official [Arduino SD](https://github.com/arduino-libraries/SD)
- [Greiman SdFat](https://github.com/greiman/SdFat)
- [SdFat - Adafruit fork](https://github.com/adafruit/SdFat)
- [Adafruit SPIFlash](https://github.com/adafruit/Adafruit_SPIFlash)

## API

```C++
cdbResult open(const char fileName[], unsigned long (*userHashFunc)(const void *key, unsigned long keyLen) = DJBHash);
cdbResult open(const char *fileName, unsigned long (*userHashFunc)(const void *key, unsigned long keyLen) = DJBHash);

cdbResult findKey(const void *key, unsigned long keyLen);

Expand Down
Binary file modified examples/airports/airports.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 9 additions & 12 deletions examples/benchmark/benchmark.ino
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/*
uCDB benchmark sketch
Write file bench.cdb ([0..5000000] divisible by 5) on SD card. Connect to Ardino board.
Compile and upload sketch. Open Serial Monitor.
Board: Arduino Uno
SD card: SDHC 7.31Gb FAT32, sectorsPerCluster - 64
SD chip select pin: 10
Arduino IDE Serial Monitors settings: 9600 baud, no line ending.
Created by Ioulianos Kakoulidis, 2021.
Released into the public domain.
Released into the public domain.
*/

//#define USE_SERIALFLASH_LIB
Expand All @@ -30,14 +30,12 @@ SdFat fat;
uCDB<SdFat, File> ucdb(fat);
#endif



void setup() {
Serial.begin(9600);
while (!Serial) {
;
}

if (!fat.begin(10)) {
Serial.println("SD card initialization failed!");
while (true) {
Expand All @@ -47,18 +45,17 @@ void setup() {
}

void loop() {

char str[16];
long key;
unsigned long startMillis;
unsigned long startMillis;
cdbResult rt;
int br;

Serial.println("Press any key to start test");
while (!Serial.available()) {
;
}

if (ucdb.open("bench.cdb") != CDB_OK) {
Serial.print("Invalid CDB: ");
Serial.println("bench.cdb");
Expand Down Expand Up @@ -106,7 +103,7 @@ void loop() {
}
Serial.print("Query millis: ");
Serial.println(millis() - startMillis);

Serial.println("Querying 1000 random keys with findNextValue() from interval [0, 5000000)...");
startMillis = millis();
for (int i = 0; i < 1000; ++i) {
Expand Down Expand Up @@ -136,7 +133,7 @@ void loop() {
}
Serial.print("Query millis: ");
Serial.println(millis() - startMillis);

Serial.println("Querying 1000 random keys with findNextValue() from interval [-5000000, 0)...");
startMillis = millis();
for (int i = 0; i < 1000; ++i) {
Expand Down Expand Up @@ -183,4 +180,4 @@ void loop() {
while (Serial.available()) {
Serial.read();
}
}
}
Binary file modified examples/benchmark/benchmark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=uCDB
version=0.4.3
version=0.5.0
author=Ioulianos Kakoulidis
maintainer=Ioulianos Kakoulidis <[email protected]>
sentence=API for querying Constant DataBase file store.
Expand Down
68 changes: 37 additions & 31 deletions src/uCDB.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
uCDB template implementation
@author Ioulianos Kakoulidis
@date 2021
@date 2021
@copyright Public Domain
*/

Expand Down Expand Up @@ -53,7 +53,7 @@ class uCDB
after successful finKey() or findNextValue() call
*/
int readValue(void *buff, unsigned int byteNum);

/**
Total records number in CDB
*/
Expand Down Expand Up @@ -120,7 +120,7 @@ static unsigned long unpack(const byte *buff);

template <class TFileSystem, class TFile>
uCDB<TFileSystem, TFile>::uCDB(TFileSystem& fs) : fs_(fs) {
zero();
zero();
state = CDB_CLOSED;
}

Expand All @@ -131,9 +131,9 @@ cdbResult uCDB<TFileSystem, TFile>::open(const char *fileName, unsigned long (*u

unsigned long dend;
unsigned long snum;

byte buff[CDB_DESCRIPTOR_SIZE];

zero();
if (cdb) {
cdb.close(); // Close previously opened CDB file
Expand All @@ -147,9 +147,9 @@ cdbResult uCDB<TFileSystem, TFile>::open(const char *fileName, unsigned long (*u
if (!cdb) {
return (state = CDB_CLOSED);
}

// CDB hash tables position and slots number integrity check

// CDB file size must be at least HEADER_SIZE bytes
if (cdb.size() < CDB_HEADER_SIZE) {
return (state = CDB_ERROR);
Expand All @@ -170,27 +170,27 @@ cdbResult uCDB<TFileSystem, TFile>::open(const char *fileName, unsigned long (*u
continue; // Empty hash table
}
if ((htPos < CDB_HEADER_SIZE) || (htPos > cdb.size())) {
return (state = CDB_ERROR); // Critical CDB format or data integrity error
return (state = CDB_ERROR); // Critical CDB format or data integrity error
}
if (((cdb.size() - htPos) >> 3) < htSlotsNum) {
return (state = CDB_ERROR); // Critical CDB format or data integrity error
return (state = CDB_ERROR); // Critical CDB format or data integrity error
}

// Adjust data end position and total slots number
if (htPos < dend) {
dend = htPos;
}
snum += htSlotsNum;

if (((cdb.size() - dend) >> 3) < snum) {
return (state = CDB_ERROR); // Critical CDB format or data integrity error
return (state = CDB_ERROR); // Critical CDB format or data integrity error
}
}
// Check total
if ((cdb.size() - dend) != 8 * snum){
return (state = CDB_ERROR); // Critical CDB format or data integrity error
return (state = CDB_ERROR); // Critical CDB format or data integrity error
}

dataEndPos = dend;
slotsNum = snum;
hashFunc = userHashFunc;
Expand Down Expand Up @@ -245,14 +245,14 @@ cdbResult uCDB<TFileSystem, TFile>::findNextValue() {
}

while (slotsToScan) {
rd = readDescriptor(buff, nextSlotPos);
rd = readDescriptor(buff, nextSlotPos);
// Adjust slotsToScan and next slot position
--slotsToScan;
nextSlotPos += CDB_DESCRIPTOR_SIZE;
if (nextSlotPos == hashTabEndPos) {
nextSlotPos = hashTabStartPos;
}

if (!rd) {
return (state = FILE_ERROR);
}
Expand All @@ -267,7 +267,7 @@ cdbResult uCDB<TFileSystem, TFile>::findNextValue() {

// Check data position
if ((dataPos < CDB_HEADER_SIZE) || (dataPos > (dataEndPos - CDB_DESCRIPTOR_SIZE))) {
return (state = CDB_ERROR); // Critical CDB format or data integrity error
return (state = CDB_ERROR); // Critical CDB format or data integrity error
}

if (slotHash == keyHash) {
Expand All @@ -277,27 +277,27 @@ cdbResult uCDB<TFileSystem, TFile>::findNextValue() {

dataKeyLen = unpack(buff);
dataValueLen = unpack(buff + 4);

//> key, value length check
unsigned long t = dataPos + CDB_DESCRIPTOR_SIZE;
if ((dataEndPos - t) < dataKeyLen) {
return (state = CDB_ERROR); // Critical CDB format or data integrity error
return (state = CDB_ERROR); // Critical CDB format or data integrity error
}
t += dataKeyLen;
if ((dataEndPos - t) < dataValueLen) {
return (state = CDB_ERROR); // Critical CDB format or data integrity error
return (state = CDB_ERROR); // Critical CDB format or data integrity error
}
//< key, value length check

if (keyLen_ == dataKeyLen) {
switch (compareKey()) {
case KEY_FOUND:
valueBytesAvail = dataValueLen;
return (state = KEY_FOUND);
valueBytesAvail = dataValueLen;
return (state = KEY_FOUND);
case FILE_ERROR:
return (state = FILE_ERROR);
return (state = FILE_ERROR);
default:
;
;
}
}
}
Expand Down Expand Up @@ -329,7 +329,7 @@ int uCDB<TFileSystem, TFile>::readValue(void *buff, unsigned int byteNum) {
}
int br = cdb.read(buff, byteNum);
if (br > 0) {
valueBytesAvail -= br;
valueBytesAvail -= br;
}
return br;
}
Expand All @@ -339,7 +339,15 @@ int uCDB<TFileSystem, TFile>::readValue(void *buff, unsigned int byteNum) {

template <class TFileSystem, class TFile>
unsigned long uCDB<TFileSystem, TFile>::recordsNumber() {
return (slotsNum >> 1);
// Check CDB state
switch (state) {
case CDB_CLOSED:
case CDB_NOT_FOUND:
case CDB_ERROR:
return 0;
default:
return (slotsNum >> 1);
}
}

template <class TFileSystem, class TFile>
Expand All @@ -349,7 +357,7 @@ unsigned long uCDB<TFileSystem, TFile>::valueAvailable() {

template <class TFileSystem, class TFile>
cdbResult uCDB<TFileSystem, TFile>::close() {
zero();
zero();
if (cdb) {
cdb.close();
}
Expand Down Expand Up @@ -386,10 +394,11 @@ cdbResult uCDB<TFileSystem, TFile>::compareKey() {

return KEY_FOUND;
}

template <class TFileSystem, class TFile>
bool uCDB<TFileSystem, TFile>::readDescriptor(byte *buff, unsigned long pos) {
if (cdb.position() != pos) {
cdb.seek(pos);
cdb.seek(pos);
if (pos != cdb.position()) {
return false;
}
Expand All @@ -400,14 +409,11 @@ bool uCDB<TFileSystem, TFile>::readDescriptor(byte *buff, unsigned long pos) {

template <class TFileSystem, class TFile>
void uCDB<TFileSystem, TFile>::zero() {
dataEndPos = 0;
slotsNum = 0;

slotsToScan = 0;
nextSlotPos = 0;
}

#define DJB_START_HASH 5381UL
#define DJB_START_HASH 5381UL
unsigned long DJBHash(const void *key, unsigned long keyLen) {
unsigned long h = DJB_START_HASH;
const byte *curr = static_cast<const byte *>(key);
Expand Down

0 comments on commit a89f4d3

Please sign in to comment.