pos/database/posdb.cpp

292 lines
6.7 KiB
C++
Raw Normal View History

2011-11-10 16:56:56 -05:00
#include "common.h"
2011-11-18 21:09:47 -05:00
#include "posdb.h"
2011-11-08 17:06:32 -05:00
#include "log.h"
#include "sha1.h"
#include <cassert>
#include <cstdlib>
#include <cstdio>
2011-11-08 20:38:06 -05:00
#include <cstring>
2011-11-08 17:06:32 -05:00
#include <ctime>
PosDb::PosDb(const char * fn)
: log(fn)
{
// read in the log
for(std::list<LogEntry>::const_iterator p = log.begin(); p != log.end(); ++p)
acceptLogEntry(*p);
}
void PosDb::acceptLogEntry(const LogEntry & l) {
2011-11-08 20:38:06 -05:00
serial_to_object[l.serial] = l;
2011-11-08 17:06:32 -05:00
switch(l.type) {
case ET_HASH: {
SHA1Hash h;
h.set((unsigned char *)l.HashChange.hash);
if(l.HashChange.add) {
// verify hash not associated with anything
2011-11-08 20:38:06 -05:00
for(ath_it p = account_to_hash.begin(); p != account_to_hash.end(); ++p) {
if(p->second == h) {
fprintf(stderr, "PosDb: Log associates a hash"
" with more than one account! Aborting.");
abort();
}
2011-11-08 17:06:32 -05:00
}
2011-11-08 20:38:06 -05:00
account_to_hash.insert(std::pair<uint32_t, SHA1Hash>(l.HashChange.uid, h));
2011-11-08 17:06:32 -05:00
} else {
// verify hash associated with something
2011-11-08 20:38:06 -05:00
ath_it p;
for(p = account_to_hash.begin(); p != account_to_hash.end(); ++p) {
if(p->second == h)
break;
}
if(p == account_to_hash.end()) {
2011-11-08 17:06:32 -05:00
fprintf(stderr, "PosDb: Log deassociates an"
"unassociated hash! Aborting.");
abort();
} else {
2011-11-08 20:38:06 -05:00
account_to_hash.erase(p);
2011-11-08 17:06:32 -05:00
}
}
break;
}
case ET_TRANS: {
2011-11-08 20:38:06 -05:00
atb_it q = account_to_balance.find(l.Transaction.uid);
if(q == account_to_balance.end())
account_to_balance[l.Transaction.uid] = l.Transaction.delta;
else
q->second += l.Transaction.delta;
break;
}
2011-11-08 17:06:32 -05:00
2011-11-08 20:38:06 -05:00
case ET_SALE: {
uts_it q = upc_to_stock.find(l.StockChange.upc);
if(q == upc_to_stock.end())
upc_to_stock[l.StockChange.upc] = l.StockChange.delta;
else
q->second += l.StockChange.delta;
break;
}
2011-11-08 17:06:32 -05:00
2011-11-11 00:49:18 -05:00
case ET_PRICE: {
upc_to_price[l.PriceChange.upc] = l.PriceChange.price;
break;
}
2011-11-10 15:17:17 -05:00
2011-11-11 00:49:18 -05:00
case ET_ADDUPC: {
upc_to_name[l.AddUPC.upc] = l.AddUPC.name;
break;
}
2011-11-08 20:38:06 -05:00
case ET_REVERT: {
sto_it q = serial_to_object.find(l.Revert.revert_serial);
if((q == serial_to_object.end()) || (q->second.type != ET_TRANS)) {
fprintf(stderr, "PosDb: Log reverts an invalid object! Aborting.");
2011-11-08 17:06:32 -05:00
abort();
} else {
2011-11-08 20:38:06 -05:00
account_to_balance[q->second.Transaction.uid] -= q->second.Transaction.delta;
2011-11-08 17:06:32 -05:00
}
break;
}
}
}
uint32_t PosDb::getAccountFromHash(const SHA1Hash & hash) {
2011-11-08 20:38:06 -05:00
ath_it p;
for(p = account_to_hash.begin(); p != account_to_hash.end(); ++p) {
if(p->second == hash)
break;
}
if(p == account_to_hash.end())
2011-11-08 17:06:32 -05:00
return 0;
2011-11-08 20:38:06 -05:00
else
return p->first;
2011-11-08 17:06:32 -05:00
}
std::list<std::string> PosDb::getHashesFromAccount(uint32_t account) {
std::list<std::string> result;
2011-11-08 20:38:06 -05:00
ath_it_r range = account_to_hash.equal_range(account);
for(ath_it p = range.first; p != range.second; ++p)
result.push_back(p->second.toHex());
2011-11-08 17:06:32 -05:00
return result;
}
2011-11-08 20:38:06 -05:00
std::list<std::string> PosDb::getHashesFromAccount(std::string account) {
return getHashesFromAccount(ns.get_id(account));
}
2011-11-08 17:06:32 -05:00
int32_t PosDb::getAccountBalance(const SHA1Hash & hash) {
2011-11-08 20:38:06 -05:00
uint32_t acct = getAccountFromHash(hash);
2011-11-08 17:06:32 -05:00
2011-11-08 20:38:06 -05:00
if(!acct)
2011-11-08 17:06:32 -05:00
return 0;
else {
2011-11-08 20:38:06 -05:00
atb_it p = account_to_balance.find(acct);
2011-11-08 17:06:32 -05:00
if(p == account_to_balance.end())
return 0;
else
return p->second;
}
}
int32_t PosDb::getAccountBalance(uint32_t account) {
2011-11-08 20:38:06 -05:00
atb_it p = account_to_balance.find(account);
2011-11-08 17:06:32 -05:00
if(p == account_to_balance.end())
return 0;
else
return p->second;
}
2011-11-08 20:38:06 -05:00
int32_t PosDb::getAccountBalance(std::string account) {
return getAccountBalance(ns.get_id(account));
}
2011-11-08 17:06:32 -05:00
uint64_t PosDb::associateHash(const SHA1Hash & hash, uint32_t account) {
// verify hash not associated with anything
2011-11-08 20:38:06 -05:00
if(getAccountFromHash(hash)) {
2011-11-08 17:06:32 -05:00
return 0;
} else {
2011-11-11 00:49:18 -05:00
LogEntry l = log.newLogEntry(ET_HASH);
2011-11-08 17:06:32 -05:00
l.HashChange.uid = account;
l.HashChange.add = true;
hash.get((unsigned char *)l.HashChange.hash);
acceptLogEntry(l);
return log.writeEntry(l);
}
}
2011-11-08 20:38:06 -05:00
uint64_t PosDb::associateHash(const SHA1Hash & hash, std::string account) {
return associateHash(hash, ns.get_id(account));
}
2011-11-08 17:06:32 -05:00
uint64_t PosDb::deassociateHash(const SHA1Hash & hash) {
// verify hash associated with something
2011-11-08 20:38:06 -05:00
uint32_t acct = getAccountFromHash(hash);
if(!acct) {
2011-11-08 17:06:32 -05:00
return 0;
} else {
2011-11-11 00:49:18 -05:00
LogEntry l = log.newLogEntry(ET_HASH);
l.HashChange.uid = acct;
l.HashChange.add = false;
hash.get((unsigned char *)l.HashChange.hash);
2011-11-11 00:49:18 -05:00
acceptLogEntry(l);
return log.writeEntry(l);
2011-11-08 17:06:32 -05:00
}
}
int32_t PosDb::getUPCPrice(uint64_t upc) {
2011-11-11 00:49:18 -05:00
uts_it it = upc_to_price.find(upc);
if (it == upc_to_price.end()) {
return 0;
}
return it->second;
2011-11-10 15:17:17 -05:00
}
uint64_t PosDb::setUPCPrice(uint64_t upc, int32_t price) {
2011-11-11 00:49:18 -05:00
LogEntry l = log.newLogEntry(ET_PRICE);
l.PriceChange.upc = upc;
l.PriceChange.price = price;
2011-11-11 00:49:18 -05:00
acceptLogEntry(l);
return log.writeEntry(l);
2011-11-10 15:17:17 -05:00
}
// NOTE: this in theory could be deprecated. The client should
// probably get the uid from the hash before doing a transaction.
2011-11-08 20:38:06 -05:00
uint64_t PosDb::doTransaction(const SHA1Hash & hash, int32_t delta) {
// verify hash associated with something
uint32_t acct = getAccountFromHash(hash);
if(!acct) {
return 0;
} else {
2011-11-11 00:49:18 -05:00
LogEntry l = log.newLogEntry(ET_TRANS);
2011-11-08 20:38:06 -05:00
l.Transaction.delta = delta;
l.Transaction.uid = acct;
acceptLogEntry(l);
return log.writeEntry(l);
}
}
uint64_t PosDb::doTransaction(const uint32_t account, int32_t delta) {
2011-11-11 00:49:18 -05:00
LogEntry l = log.newLogEntry(ET_TRANS);
2011-11-08 20:38:06 -05:00
l.Transaction.delta = delta;
l.Transaction.uid = account;
acceptLogEntry(l);
return log.writeEntry(l);
}
uint64_t PosDb::doTransaction(std::string account, int32_t delta) {
return doTransaction(ns.get_id(account), delta);
}
uint64_t PosDb::revertTransaction(uint64_t serial) {
if(serial_to_object.find(serial) == serial_to_object.end()) {
return 0;
} else {
// do not double-revert transactions
sto_it p;
for(p = serial_to_object.begin(); p != serial_to_object.end(); ++p) {
if((p->second.type == ET_REVERT) && (p->second.Revert.revert_serial == serial))
break;
}
if(p != serial_to_object.end())
return 0;
2011-11-11 00:49:18 -05:00
LogEntry l = log.newLogEntry(ET_REVERT);
2011-11-08 20:38:06 -05:00
l.Revert.revert_serial = serial;
acceptLogEntry(l);
return log.writeEntry(l);
}
}
int32_t PosDb::getStock(uint64_t upc) {
2011-11-08 20:38:06 -05:00
uts_it p = upc_to_stock.find(upc);
if(p == upc_to_stock.end())
return 0;
else
return p->second;
}
uint64_t PosDb::doStockChange(uint64_t upc, int32_t delta) {
2011-11-11 00:49:18 -05:00
LogEntry l = log.newLogEntry(ET_SALE);
2011-11-08 20:38:06 -05:00
l.StockChange.delta = delta;
l.StockChange.upc = upc;
acceptLogEntry(l);
return log.writeEntry(l);
}
std::string PosDb::getUPCName(uint64_t upc) {
std::map<uint64_t, std::string>::iterator it = upc_to_name.find(upc);
2011-11-11 00:49:18 -05:00
if(it == upc_to_name.end()) return "UNKNOWN UPC";
return upc_to_name[upc];
}
2011-11-10 17:21:53 -05:00
uint64_t PosDb::setUPCName (uint64_t upc, std::string name) {
2011-11-11 00:49:18 -05:00
LogEntry l = log.newLogEntry(ET_ADDUPC);
l.AddUPC.upc = upc;
strncpy(l.AddUPC.name, name.c_str(), 32);
l.AddUPC.name[32] = 0;
2011-11-11 00:49:18 -05:00
acceptLogEntry(l);
return log.writeEntry(l);
}
2011-11-11 00:49:18 -05:00
std::vector<std::string> PosDb::toString() {
2011-11-11 00:49:18 -05:00
return log.toString();
2011-11-10 16:56:56 -05:00
}
2011-11-11 00:49:18 -05:00