Implementation of journaling
This commit is contained in:
parent
aa8beace98
commit
abbb2f2cc2
|
@ -23,7 +23,7 @@ HashTable::htNode *HashTable::Retrieve(const char *key)
|
|||
return _FindNode(key);
|
||||
}
|
||||
|
||||
//Adds an entry into the hash table
|
||||
//Adds an entry into the hash table with current time
|
||||
void HashTable::Store(const char *key, const char *value, bool temporary)
|
||||
{
|
||||
time_t stamp = 0;
|
||||
|
@ -34,6 +34,22 @@ void HashTable::Store(const char *key, const char *value, bool temporary)
|
|||
_Insert(key, value, stamp);
|
||||
}
|
||||
|
||||
//Adds an entry into the hash table with preset time
|
||||
void HashTable::Store(const char *key, const char *value, time_t stamp)
|
||||
{
|
||||
_Insert(key, value, stamp);
|
||||
}
|
||||
|
||||
//Erases a key
|
||||
void HashTable::EraseKey(const char *key)
|
||||
{
|
||||
HashTable::htNodeSet *set = _FindNodeSet(key);
|
||||
HashTable::htNode *node = _FindNode(key, false);
|
||||
|
||||
if (set && node)
|
||||
_Unlink(set, node);
|
||||
}
|
||||
|
||||
//Deletes all keys between the two times.
|
||||
// 0 specifies "match all"
|
||||
//All specifies whether permanent keys (time_t = 0) are erased
|
||||
|
@ -106,7 +122,20 @@ void HashTable::Clear()
|
|||
|
||||
bool HashTable::KeyExists(const char *key)
|
||||
{
|
||||
return _FindNode(key, false);
|
||||
return (_FindNode(key, false) != NULL);
|
||||
}
|
||||
|
||||
size_t HashTable::UsedHashes()
|
||||
{
|
||||
size_t num = 0;
|
||||
|
||||
for (uint32_t i=0; i<HT_SIZE; i++)
|
||||
{
|
||||
if (m_Table[i])
|
||||
num++;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
////////////////////
|
||||
|
|
|
@ -34,15 +34,19 @@ public: //STRUCTORS
|
|||
public: //PRE-DEF
|
||||
class iterator;
|
||||
struct htNode;
|
||||
friend class Vault;
|
||||
private: //PRE-DEF
|
||||
struct htNodeSet;
|
||||
public: //PUBLIC FUNCTIONS
|
||||
void Store(const char *key, const char *value, bool temporary=true);
|
||||
void Store(const char *key, const char *value, time_t stamp);
|
||||
htNode *Retrieve(const char *key);
|
||||
iterator Enumerate();
|
||||
size_t Prune(time_t begin, time_t end, bool all=false);
|
||||
void Clear();
|
||||
bool KeyExists(const char *key);
|
||||
size_t UsedHashes();
|
||||
void EraseKey(const char *key);
|
||||
public: //PUBLIC CLASSES
|
||||
class iterator
|
||||
{
|
||||
|
|
328
dlls/nvault/journal.cpp
Executable file
328
dlls/nvault/journal.cpp
Executable file
|
@ -0,0 +1,328 @@
|
|||
#include <stdlib.h>
|
||||
#include "journal.h"
|
||||
#include "sdk/CVector.h"
|
||||
|
||||
struct j_info
|
||||
{
|
||||
int id;
|
||||
Vault *vault;
|
||||
};
|
||||
|
||||
Journal::Journal(const char *file)
|
||||
{
|
||||
m_File.assign(file);
|
||||
m_Fp = NULL;
|
||||
m_LastId = 0;
|
||||
}
|
||||
|
||||
#define rd(v,s) if (fread(&v, sizeof(s), 1, m_Fp) != 1) { \
|
||||
fclose(m_Fp); \
|
||||
m_Fp = NULL; \
|
||||
goto _error; }
|
||||
#define rds(v,l) if (fread(v, sizeof(char), l, m_Fp) != l) { \
|
||||
fclose(m_Fp); \
|
||||
m_Fp = NULL; \
|
||||
goto _error; } else { \
|
||||
v[l] = '\0'; }
|
||||
|
||||
bool Journal::Replay(size_t &files, size_t &ops)
|
||||
{
|
||||
m_Fp = fopen(m_File.c_str(), "rb");
|
||||
|
||||
files = 0;
|
||||
ops = 0;
|
||||
|
||||
if (!m_Fp)
|
||||
return false;
|
||||
|
||||
//this must come before the first jump...
|
||||
CVector<j_info *> table;
|
||||
uint32_t magic;
|
||||
|
||||
rd(magic, uint32_t);
|
||||
if (magic != JOURNAL_MAGIC)
|
||||
return false;
|
||||
|
||||
j_info *j;
|
||||
uint8_t op, klen;
|
||||
uint16_t vlen;
|
||||
uint32_t id;
|
||||
size_t i;
|
||||
char *key=NULL, *val=NULL;
|
||||
while (!feof(m_Fp))
|
||||
{
|
||||
if (fread(&op, sizeof(uint8_t), 1, m_Fp) != 1)
|
||||
{
|
||||
if (feof(m_Fp))
|
||||
break;
|
||||
else
|
||||
goto _error;
|
||||
}
|
||||
switch (op)
|
||||
{
|
||||
case Journal_Nop:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case Journal_Name:
|
||||
{
|
||||
rd(id, uint32_t);
|
||||
rd(klen, uint8_t);
|
||||
key = new char[klen+1];
|
||||
rds(key, klen);
|
||||
j = new j_info;
|
||||
j->id = id;
|
||||
j->vault = new Vault(key);
|
||||
j->vault->ReadFromFile();
|
||||
table.push_back(j);
|
||||
files++;
|
||||
delete [] key;
|
||||
key = NULL;
|
||||
break;
|
||||
}
|
||||
case Journal_Store:
|
||||
{
|
||||
//Stores key/val (id,time,klen,vlen,[],[])
|
||||
uint32_t stamp;
|
||||
rd(id, uint32_t);
|
||||
rd(stamp, uint32_t);
|
||||
rd(klen, uint8_t);
|
||||
rd(vlen, uint16_t);
|
||||
key = new char[klen+1];
|
||||
val = new char[vlen+1];
|
||||
rds(key, klen);
|
||||
rds(val, vlen);
|
||||
for (i=0; i<table.size(); i++)
|
||||
{
|
||||
if (table.at(i)->id == id)
|
||||
{
|
||||
table.at(i)->vault->Store(key, val, (time_t)stamp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete [] key;
|
||||
delete [] val;
|
||||
key = NULL;
|
||||
val = NULL;
|
||||
break;
|
||||
}
|
||||
case Journal_Erase:
|
||||
{
|
||||
//Erases key (id,klen,[])
|
||||
rd(id, uint32_t);
|
||||
rd(klen, uint8_t);
|
||||
key = new char[klen+1];
|
||||
rds(key, klen);
|
||||
for (i=0; i<table.size(); i++)
|
||||
{
|
||||
if (table.at(i)->id == id)
|
||||
{
|
||||
table.at(i)->vault->EraseKey(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete [] key;
|
||||
key = NULL;
|
||||
break;
|
||||
}
|
||||
case Journal_Clear:
|
||||
{
|
||||
//Clears (id)
|
||||
rd(id, uint32_t);
|
||||
for (i=0; i<table.size(); i++)
|
||||
{
|
||||
if (table.at(i)->id == id)
|
||||
{
|
||||
table.at(i)->vault->Clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Journal_Prune:
|
||||
{
|
||||
//Prunes (id,t1,t2,all)
|
||||
rd(id, uint32_t);
|
||||
uint32_t begin, end;
|
||||
uint8_t all;
|
||||
rd(begin, uint32_t);
|
||||
rd(end, uint32_t);
|
||||
rd(all, uint8_t);
|
||||
for (i=0; i<table.size(); i++)
|
||||
{
|
||||
if (table.at(i)->id == id)
|
||||
{
|
||||
table.at(i)->vault->Prune((time_t)begin, (time_t)end, all?true:false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
goto _error;
|
||||
}
|
||||
} //end while
|
||||
ops++;
|
||||
}
|
||||
|
||||
for (uint32_t i=0; i<table.size(); i++)
|
||||
{
|
||||
j = table.at(i);
|
||||
j->vault->WriteToFile();
|
||||
delete j->vault;
|
||||
delete j;
|
||||
}
|
||||
|
||||
fclose(m_Fp);
|
||||
|
||||
return true;
|
||||
_error:
|
||||
for (uint32_t i=0; i<table.size(); i++)
|
||||
{
|
||||
j = table.at(i);
|
||||
j->vault->WriteToFile();
|
||||
delete j->vault;
|
||||
delete j;
|
||||
}
|
||||
if (key)
|
||||
{
|
||||
delete [] key;
|
||||
key = NULL;
|
||||
}
|
||||
if (val)
|
||||
{
|
||||
delete [] val;
|
||||
val = NULL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Journal::ClearJournal()
|
||||
{
|
||||
m_Fp = fopen(m_File.c_str(), "wb");
|
||||
|
||||
if (m_Fp)
|
||||
{
|
||||
fclose(m_Fp);
|
||||
m_Fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool Journal::StartJournal()
|
||||
{
|
||||
m_Fp = fopen(m_File.c_str(), "wb");
|
||||
|
||||
if (!m_Fp)
|
||||
return false;
|
||||
|
||||
uint32_t magic = JOURNAL_MAGIC;
|
||||
|
||||
fwrite(&magic, sizeof(uint32_t), 1, m_Fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Journal::EndJournal()
|
||||
{
|
||||
if (m_Fp)
|
||||
{
|
||||
fclose(m_Fp);
|
||||
m_Fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//Stores key/val (id,time,klen,vlen,[],[]
|
||||
void Journal::Store(const char *name, const char *key, const char *val, time_t stamp)
|
||||
{
|
||||
uint32_t time32 = (uint32_t)stamp;
|
||||
uint16_t vlen = (uint16_t)strlen(val);
|
||||
uint8_t klen = (uint8_t)strlen(key);
|
||||
|
||||
BeginOp(name, Journal_Store);
|
||||
WriteInt(time32);
|
||||
WriteByte(klen);
|
||||
WriteShort(vlen);
|
||||
WriteString(key);
|
||||
WriteString(val);
|
||||
EndOp();
|
||||
}
|
||||
|
||||
//Erases key (id,klen,[])
|
||||
void Journal::Erase(const char *name, const char *key)
|
||||
{
|
||||
uint8_t klen = (uint8_t)strlen(key);
|
||||
|
||||
BeginOp(name, Journal_Erase);
|
||||
WriteByte(klen);
|
||||
WriteString(key);
|
||||
EndOp();
|
||||
}
|
||||
|
||||
//Clears (id)
|
||||
void Journal::Clear(const char *name)
|
||||
{
|
||||
BeginOp(name, Journal_Clear);
|
||||
EndOp();
|
||||
}
|
||||
|
||||
//Prunes (id,t1,t2,all)
|
||||
void Journal::Prune(const char *name, time_t begin, time_t end, bool all)
|
||||
{
|
||||
uint32_t begin32 = (uint32_t)begin;
|
||||
uint32_t end32 = (uint32_t)end;
|
||||
uint8_t all8 = (uint8_t)all;
|
||||
|
||||
BeginOp(name, Journal_Prune);
|
||||
WriteInt(begin32);
|
||||
WriteInt(end32);
|
||||
WriteByte(all8);
|
||||
EndOp();
|
||||
}
|
||||
|
||||
void Journal::BeginOp(const char *name, JournalOp jop)
|
||||
{
|
||||
uint32_t id;
|
||||
|
||||
if (!m_Names.KeyExists(name))
|
||||
{
|
||||
char name_buf[12];
|
||||
id = ++m_LastId;
|
||||
sprintf(name_buf, "%d", id);
|
||||
m_Names.Store(name, name_buf, false);
|
||||
WriteByte(Journal_Name);
|
||||
WriteInt(id);
|
||||
WriteByte(strlen(name));
|
||||
WriteString(name);
|
||||
} else {
|
||||
id = atoi(m_Names.Retrieve(name)->val.c_str());
|
||||
}
|
||||
|
||||
WriteByte(jop);
|
||||
WriteInt(id);
|
||||
}
|
||||
|
||||
void Journal::WriteByte(uint8_t num)
|
||||
{
|
||||
fwrite(&num, sizeof(uint8_t), 1, m_Fp);
|
||||
}
|
||||
|
||||
void Journal::WriteShort(uint16_t num)
|
||||
{
|
||||
fwrite(&num, sizeof(uint16_t), 1, m_Fp);
|
||||
}
|
||||
|
||||
void Journal::WriteInt(uint32_t num)
|
||||
{
|
||||
fwrite(&num, sizeof(uint32_t), 1, m_Fp);
|
||||
}
|
||||
|
||||
void Journal::WriteString(const char *str)
|
||||
{
|
||||
fwrite(str, sizeof(char), strlen(str), m_Fp);
|
||||
}
|
||||
|
||||
size_t Journal::EndOp()
|
||||
{
|
||||
return 1;
|
||||
}
|
46
dlls/nvault/journal.h
Executable file
46
dlls/nvault/journal.h
Executable file
|
@ -0,0 +1,46 @@
|
|||
#ifndef _INCLUDE_JOURNAL_H
|
||||
#define _INCLUDE_JOURNAL_H
|
||||
|
||||
#include "nvault.h"
|
||||
|
||||
#define JOURNAL_MAGIC 0x6E564A4C
|
||||
|
||||
class Journal
|
||||
{
|
||||
public:
|
||||
enum JournalOp
|
||||
{
|
||||
Journal_Nop, //Nothing
|
||||
Journal_Name, //Maps name to Id (id,len,[])
|
||||
Journal_Store, //Stores key/val (id,time,klen,vlen,[],[])
|
||||
Journal_Erase, //Erases key (id,klen,[])
|
||||
Journal_Clear, //Clears (id)
|
||||
Journal_Prune //Prunes (id,t1,t2,all)
|
||||
};
|
||||
public:
|
||||
Journal(const char *file);
|
||||
public:
|
||||
bool Replay(size_t &files, size_t &ops);
|
||||
void ClearJournal();
|
||||
bool StartJournal();
|
||||
void EndJournal();
|
||||
public:
|
||||
void Store(const char *name, const char *key, const char *val, time_t stamp);
|
||||
void Erase(const char *name, const char *key);
|
||||
void Clear(const char *name);
|
||||
void Prune(const char *name, time_t begin, time_t end, bool all);
|
||||
private:
|
||||
void BeginOp(const char *name, JournalOp jop);
|
||||
void WriteByte(uint8_t num);
|
||||
void WriteShort(uint16_t num);
|
||||
void WriteInt(uint32_t num);
|
||||
void WriteString(const char *str);
|
||||
size_t EndOp();
|
||||
private:
|
||||
String m_File;
|
||||
FILE *m_Fp;
|
||||
HashTable m_Names;
|
||||
uint32_t m_LastId;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_JOURNAL_H
|
|
@ -1,2 +1,206 @@
|
|||
#include "nvault.h"
|
||||
|
||||
Vault::Vault(const char *name)
|
||||
{
|
||||
m_File.assign(name);
|
||||
m_Vault = NULL;
|
||||
}
|
||||
|
||||
Vault::~Vault()
|
||||
{
|
||||
if (m_Vault)
|
||||
{
|
||||
delete m_Vault;
|
||||
m_Vault = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Vault::Clear()
|
||||
{
|
||||
if (m_Vault)
|
||||
m_Vault->Clear();
|
||||
}
|
||||
|
||||
void Vault::EraseKey(const char *key)
|
||||
{
|
||||
if (m_Vault)
|
||||
m_Vault->EraseKey(key);
|
||||
}
|
||||
|
||||
HashTable::htNode *Vault::Find(const char *key)
|
||||
{
|
||||
if (m_Vault)
|
||||
return m_Vault->Retrieve(key);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Vault::KeyExists(const char *key)
|
||||
{
|
||||
if (m_Vault)
|
||||
return m_Vault->KeyExists(key);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t Vault::Prune(time_t begin, time_t end, bool all)
|
||||
{
|
||||
if (m_Vault)
|
||||
return m_Vault->Prune(begin, end, all);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Vault::Store(const char *key, const char *value, bool temporary)
|
||||
{
|
||||
if (m_Vault)
|
||||
m_Vault->Store(key, value, temporary);
|
||||
}
|
||||
|
||||
void Vault::Store(const char *key, const char *value, time_t stamp)
|
||||
{
|
||||
if (m_Vault)
|
||||
m_Vault->Store(key, value, stamp);
|
||||
}
|
||||
|
||||
#define wr(v,s) fwrite(&v, sizeof(s), 1, fp)
|
||||
|
||||
bool Vault::WriteToFile()
|
||||
{
|
||||
FILE *fp = fopen(m_File.c_str(), "wb");
|
||||
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
uint32_t hashes = m_Vault->UsedHashes();
|
||||
|
||||
_WriteHeaders(fp, hashes);
|
||||
|
||||
HashTable::htNode *node;
|
||||
uint32_t keys, stamp;
|
||||
uint16_t vChars;
|
||||
uint8_t kChars;
|
||||
for (uint32_t i=0; i<HT_SIZE; i++)
|
||||
{
|
||||
if (m_Vault->m_Table[i])
|
||||
{
|
||||
keys = 0;
|
||||
node = m_Vault->m_Table[i]->head;;
|
||||
while (node != NULL)
|
||||
{
|
||||
keys++;
|
||||
node = node->next;
|
||||
}
|
||||
wr(i, uint32_t);
|
||||
wr(keys, uint32_t);
|
||||
node = m_Vault->m_Table[i]->head;
|
||||
while (node != NULL)
|
||||
{
|
||||
stamp = (uint32_t)(node->stamp);
|
||||
wr(stamp, uint32_t);
|
||||
kChars = (uint8_t)(node->key.size());
|
||||
vChars = (uint16_t)(node->val.size());
|
||||
wr(kChars, uint8_t);
|
||||
wr(vChars, uint16_t);
|
||||
fwrite(node->key.c_str(), sizeof(char), kChars, fp);
|
||||
fwrite(node->val.c_str(), sizeof(char), vChars, fp);
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define rd(v,s) if (fread(&v, sizeof(s), 1, fp) != 1) { \
|
||||
fclose(fp); \
|
||||
return Vault_ReadFail; }
|
||||
|
||||
Vault::VaultError Vault::ReadFromFile()
|
||||
{
|
||||
FILE *fp = fopen(m_File.c_str(), "rb");
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
fp = fopen(m_File.c_str(), "wb");
|
||||
if (!fp)
|
||||
return Vault_ReadFail;
|
||||
_WriteHeaders(fp, 0);
|
||||
fclose(fp);
|
||||
m_Vault = new HashTable();
|
||||
return Vault_Ok;
|
||||
}
|
||||
|
||||
uint32_t magic, keysize, hashes;
|
||||
uint8_t timesize;
|
||||
|
||||
rd(magic, uint32_t);
|
||||
if (magic != VAULT_MAGIC)
|
||||
{
|
||||
fclose(fp);
|
||||
return Vault_BadMagic;
|
||||
}
|
||||
rd(timesize, uint8_t);
|
||||
rd(keysize, uint32_t);
|
||||
rd(hashes, uint32_t);
|
||||
|
||||
m_Vault = new HashTable();
|
||||
|
||||
uint32_t hash, keys, stamp;
|
||||
uint16_t vChars;
|
||||
uint8_t kChars;
|
||||
char *key, *value;
|
||||
for (uint32_t i=0; i<hashes; i++)
|
||||
{
|
||||
rd(hash, uint32_t);
|
||||
rd(keys, uint32_t);
|
||||
for (uint32_t d=0; d<keys; d++)
|
||||
{
|
||||
rd(stamp, uint32_t);
|
||||
rd(kChars, uint8_t);
|
||||
rd(vChars, uint16_t);
|
||||
key = new char[kChars+1];
|
||||
if (fread(key, sizeof(char), kChars, fp) != kChars)
|
||||
{
|
||||
delete [] key;
|
||||
fclose(fp);
|
||||
return Vault_ReadFail;
|
||||
}
|
||||
value = new char[vChars+1];
|
||||
if (fread(value, sizeof(char), vChars, fp) != vChars)
|
||||
{
|
||||
delete [] key;
|
||||
delete [] value;
|
||||
return Vault_ReadFail;
|
||||
}
|
||||
key[kChars] = '\0';
|
||||
value[vChars] = '\0';
|
||||
m_Vault->Store(key, value, (time_t)stamp);
|
||||
delete [] key;
|
||||
delete [] value;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return Vault_Ok;
|
||||
}
|
||||
|
||||
///////////////////
|
||||
// Private stuff //
|
||||
///////////////////
|
||||
|
||||
void Vault::_WriteHeaders(FILE *fp, uint32_t keys)
|
||||
{
|
||||
uint32_t magic = VAULT_MAGIC;
|
||||
uint32_t keysize = (1<<11);
|
||||
uint8_t timesize = sizeof(time_t);
|
||||
|
||||
fwrite(&magic, sizeof(uint32_t), 1, fp);
|
||||
fwrite(×ize, sizeof(uint8_t), 1, fp);
|
||||
fwrite(&keysize, sizeof(uint32_t), 1, fp);
|
||||
fwrite(&keys, sizeof(uint32_t), 1, fp);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,47 +4,50 @@
|
|||
#include "sdk/CString.h"
|
||||
#include "hash.h"
|
||||
|
||||
class Journal
|
||||
/**
|
||||
* Vault file format:
|
||||
* Headers
|
||||
* uint32_t - nVLT
|
||||
* uint8_t - sizeof(time_t)
|
||||
* uint32_t - key size (will be used in future maybe)
|
||||
* uint32_t - number of hashes stored
|
||||
* Data
|
||||
* uint32_t - key hash
|
||||
* uint32_t - # of keys in this hash
|
||||
* Data
|
||||
* uint32_t - Time
|
||||
* uint8_t - Characters in key
|
||||
* uint16_t - Characters in value
|
||||
* char[] - Key
|
||||
* char[] - Value
|
||||
*/
|
||||
|
||||
#define VAULT_MAGIC 0x6E564C54
|
||||
|
||||
class Vault
|
||||
{
|
||||
public:
|
||||
enum JournalOp
|
||||
Vault(const char *name);
|
||||
~Vault();
|
||||
enum VaultError
|
||||
{
|
||||
Journal_Store,
|
||||
Journal_Erase,
|
||||
Journal_Clear,
|
||||
Journal_Prune
|
||||
Vault_Ok=0,
|
||||
Vault_ReadFail,
|
||||
Vault_BadMagic,
|
||||
};
|
||||
public:
|
||||
Journal(const char *file);
|
||||
public:
|
||||
bool Replay(size_t &files, size_t &ops);
|
||||
void Clear();
|
||||
public:
|
||||
void Begin(const char *name, JournalOp jop);
|
||||
void WriteByte(uint8_t num);
|
||||
void WriteInt(uint32_t num);
|
||||
void WriteTime(time_t n);
|
||||
void WriteString(const char *str);
|
||||
size_t End();
|
||||
private:
|
||||
String m_File;
|
||||
FILE *m_Fp;
|
||||
size_t m_WriteSize;
|
||||
};
|
||||
|
||||
class nVault
|
||||
{
|
||||
public:
|
||||
nVault(const char *name);
|
||||
public:
|
||||
bool WriteToFile();
|
||||
bool ReadFromFile();
|
||||
VaultError ReadFromFile();
|
||||
public:
|
||||
void Store(const char *key, const char *value, bool temporary=true);
|
||||
void Store(const char *key, const char *value, time_t stamp);
|
||||
size_t Prune(time_t begin, time_t end, bool all=false);
|
||||
HashTable::htNode *Find(const char *key);
|
||||
bool KeyExists(const char *key);
|
||||
void Clear();
|
||||
void EraseKey(const char *key);
|
||||
private:
|
||||
void _WriteHeaders(FILE *fp, uint32_t hashes);
|
||||
private:
|
||||
String m_File;
|
||||
HashTable *m_Vault;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
|
@ -117,9 +117,24 @@
|
|||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\hash.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\journal.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\nvault.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Detect64BitPortabilityProblems="FALSE"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
|
@ -129,6 +144,9 @@
|
|||
<File
|
||||
RelativePath=".\hash.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\journal.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\nvault.h">
|
||||
</File>
|
||||
|
|
444
dlls/nvault/sdk/CVector.h
Executable file
444
dlls/nvault/sdk/CVector.h
Executable file
|
@ -0,0 +1,444 @@
|
|||
/* AMX Mod X
|
||||
*
|
||||
* by the AMX Mod X Development Team
|
||||
* originally developed by OLO
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*/
|
||||
|
||||
#ifndef __CVECTOR_H__
|
||||
#define __CVECTOR_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
// Vector
|
||||
template <class T> class CVector
|
||||
{
|
||||
bool Grow()
|
||||
{
|
||||
// automatic grow
|
||||
size_t newSize = m_Size * 2;
|
||||
if (newSize == 0)
|
||||
newSize = 8; // a good init value
|
||||
T *newData = new T[newSize];
|
||||
if (!newData)
|
||||
return false;
|
||||
if (m_Data)
|
||||
{
|
||||
memcpy(newData, m_Data, m_Size * sizeof(T));
|
||||
delete [] m_Data;
|
||||
}
|
||||
m_Data = newData;
|
||||
m_Size = newSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrowIfNeeded()
|
||||
{
|
||||
if (m_CurrentUsedSize >= m_Size)
|
||||
return Grow();
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChangeSize(size_t size)
|
||||
{
|
||||
// change size
|
||||
if (size == m_Size)
|
||||
return true;
|
||||
T *newData = new T[size];
|
||||
if (!newData)
|
||||
return false;
|
||||
if (m_Data)
|
||||
{
|
||||
memcpy(newData, m_Data, (m_Size < size) ? (m_Size * sizeof(T)) : (size * sizeof(T)));
|
||||
delete [] m_Data;
|
||||
}
|
||||
if (m_Size < size)
|
||||
m_CurrentSize = size;
|
||||
m_Data = newData;
|
||||
m_Size = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FreeMemIfPossible()
|
||||
{
|
||||
|
||||
}
|
||||
protected:
|
||||
T *m_Data;
|
||||
size_t m_Size;
|
||||
size_t m_CurrentUsedSize;
|
||||
size_t m_CurrentSize;
|
||||
public:
|
||||
class iterator
|
||||
{
|
||||
protected:
|
||||
T *m_Ptr;
|
||||
public:
|
||||
// constructors / destructors
|
||||
iterator()
|
||||
{
|
||||
m_Ptr = NULL;
|
||||
}
|
||||
|
||||
iterator(T * ptr)
|
||||
{
|
||||
m_Ptr = ptr;
|
||||
}
|
||||
|
||||
// member functions
|
||||
T * base()
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
const T * base() const
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
// operators
|
||||
T & operator*()
|
||||
{
|
||||
return *m_Ptr;
|
||||
}
|
||||
|
||||
T * operator->()
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
iterator & operator++() // preincrement
|
||||
{
|
||||
++m_Ptr;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator operator++(int) // postincrement
|
||||
{
|
||||
iterator tmp = *this;
|
||||
++m_Ptr;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator & operator--() // predecrement
|
||||
{
|
||||
--m_Ptr;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator operator--(int) // postdecrememnt
|
||||
{
|
||||
iterator tmp = *this;
|
||||
--m_Ptr;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(T * right) const
|
||||
{
|
||||
return (m_Ptr == right);
|
||||
}
|
||||
|
||||
bool operator==(const iterator & right) const
|
||||
{
|
||||
return (m_Ptr == right.m_Ptr);
|
||||
}
|
||||
|
||||
bool operator!=(T * right) const
|
||||
{
|
||||
return (m_Ptr != right);
|
||||
}
|
||||
|
||||
bool operator!=(const iterator & right) const
|
||||
{
|
||||
return (m_Ptr != right.m_Ptr);
|
||||
}
|
||||
|
||||
iterator & operator+=(size_t offset)
|
||||
{
|
||||
m_Ptr += offset;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator & operator-=(size_t offset)
|
||||
{
|
||||
m_Ptr += offset;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
iterator operator+(size_t offset) const
|
||||
{
|
||||
iterator tmp(*this);
|
||||
tmp.m_Ptr += offset;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator operator-(size_t offset) const
|
||||
{
|
||||
iterator tmp(*this);
|
||||
tmp.m_Ptr += offset;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
T & operator[](size_t offset)
|
||||
{
|
||||
return (*(*this + offset));
|
||||
}
|
||||
|
||||
const T & operator[](size_t offset) const
|
||||
{
|
||||
return (*(*this + offset));
|
||||
}
|
||||
|
||||
bool operator<(const iterator & right) const
|
||||
{
|
||||
return m_Ptr < right.m_Ptr;
|
||||
}
|
||||
|
||||
bool operator>(const iterator & right) const
|
||||
{
|
||||
return m_Ptr > right.m_Ptr;
|
||||
}
|
||||
|
||||
bool operator<=(const iterator & right) const
|
||||
{
|
||||
return m_Ptr <= right.m_Ptr;
|
||||
}
|
||||
|
||||
bool operator>=(const iterator & right) const
|
||||
{
|
||||
return m_Ptr >= right.m_Ptr;
|
||||
}
|
||||
|
||||
size_t operator-(const iterator & right) const
|
||||
{
|
||||
return m_Ptr - right.m_Ptr;
|
||||
}
|
||||
};
|
||||
|
||||
// constructors / destructors
|
||||
CVector<T>()
|
||||
{
|
||||
m_Size = 0;
|
||||
m_CurrentUsedSize = 0;
|
||||
m_Data = NULL;
|
||||
}
|
||||
|
||||
CVector<T>(const CVector<T> & other)
|
||||
{
|
||||
// copy data
|
||||
m_Data = new T [other.m_Size];
|
||||
m_Size = other.m_Size;
|
||||
m_CurrentUsedSize = other.m_CurrentUsedSize;
|
||||
memcpy(m_Data, other.m_Data, m_CurrentUsedSize * sizeof(T));
|
||||
}
|
||||
|
||||
~CVector<T>()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
// interface
|
||||
size_t size() const
|
||||
{
|
||||
return m_CurrentUsedSize;
|
||||
}
|
||||
|
||||
size_t capacity() const
|
||||
{
|
||||
return m_Size;
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(m_Data);
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return iterator(m_Data + m_CurrentUsedSize);
|
||||
}
|
||||
|
||||
iterator iterAt(size_t pos)
|
||||
{
|
||||
if (pos > m_CurrentUsedSize)
|
||||
assert(0);
|
||||
return iterator(m_Data + pos);
|
||||
}
|
||||
|
||||
bool reserve(size_t newSize)
|
||||
{
|
||||
return ChangeSize(newSize);
|
||||
}
|
||||
|
||||
bool push_back(const T & elem)
|
||||
{
|
||||
++m_CurrentUsedSize;
|
||||
if (!GrowIfNeeded())
|
||||
{
|
||||
--m_CurrentUsedSize;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Data[m_CurrentUsedSize - 1] = elem;
|
||||
return true;
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
--m_CurrentUsedSize;
|
||||
if (m_CurrentUsedSize < 0)
|
||||
m_CurrentUsedSize = 0;
|
||||
// :TODO: free memory sometimes
|
||||
}
|
||||
|
||||
bool resize(size_t newSize)
|
||||
{
|
||||
if (!ChangeSize(newSize))
|
||||
return false;
|
||||
FreeMemIfPossible();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return (m_CurrentUsedSize == 0);
|
||||
}
|
||||
|
||||
T & at(size_t pos)
|
||||
{
|
||||
if (pos > m_CurrentUsedSize)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[pos];
|
||||
}
|
||||
|
||||
const T & at(size_t pos) const
|
||||
{
|
||||
if (pos > m_CurrentUsedSize)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[pos];
|
||||
}
|
||||
|
||||
T & operator[](size_t pos)
|
||||
{
|
||||
return at(pos);
|
||||
}
|
||||
|
||||
const T & operator[](size_t pos) const
|
||||
{
|
||||
return at(pos);
|
||||
}
|
||||
|
||||
T & front()
|
||||
{
|
||||
if (m_CurrentUsedSize < 1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[0];
|
||||
}
|
||||
|
||||
const T & front() const
|
||||
{
|
||||
if (m_CurrentUsedSize < 1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[0];
|
||||
}
|
||||
|
||||
T & back()
|
||||
{
|
||||
if (m_CurrentUsedSize < 1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[m_CurrentUsedSize - 1];
|
||||
}
|
||||
|
||||
const T & back() const
|
||||
{
|
||||
if (m_CurrentUsedSize < 1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
return m_Data[m_CurrentUsedSize - 1];
|
||||
}
|
||||
|
||||
bool insert(iterator where, const T & value)
|
||||
{
|
||||
// we have to insert before
|
||||
// if it is begin, don't decrement
|
||||
if (where != m_Data)
|
||||
--where;
|
||||
// validate iter
|
||||
if (where < m_Data || where >= (m_Data + m_CurrentUsedSize))
|
||||
return false;
|
||||
|
||||
++m_CurrentUsedSize;
|
||||
if (!GrowIfNeeded())
|
||||
{
|
||||
--m_CurrentUsedSize;
|
||||
return false;
|
||||
}
|
||||
|
||||
memmove(where.base() + 1, where.base(), m_CurrentUsedSize - (where - m_Data));
|
||||
memcpy(where.base(), &value, sizeof(T));
|
||||
return true;
|
||||
}
|
||||
|
||||
void erase(iterator where)
|
||||
{
|
||||
// validate iter
|
||||
if (where < m_Data || where >= (m_Data + m_CurrentUsedSize))
|
||||
return false;
|
||||
|
||||
if (m_CurrentUsedSize > 1)
|
||||
{
|
||||
// move
|
||||
memmove(where.base(), where.base() + 1, m_CurrentUsedSize - 1);
|
||||
}
|
||||
|
||||
--m_CurrentUsedSize;
|
||||
// :TODO: free memory sometimes
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_Size = 0;
|
||||
m_CurrentUsedSize = 0;
|
||||
delete [] m_Data;
|
||||
m_Data = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __CVECTOR_H__
|
||||
|
Loading…
Reference in New Issue
Block a user