mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-08-21 04:18:23 -04:00
Merged branch v0.5-gxs-b1 into trunk (from -r 5351 -> 5995)
This brings a huge amount of goodness into the trunk, but there is still a big chunk todo before it can be released. * GXS Backend. * GXS Services: - Identities. - Circles - Photos - Wiki - GxsForums - Posted. * SSH no-gui server. See branch commits for more info. To switch on GXS stuff, enable CONFIG += gxs in both libretroshare.pro and retroshare-gui.pro git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@5996 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
commit
069b72e0b2
549 changed files with 111171 additions and 25579 deletions
312
libretroshare/src/util/contentvalue.cc
Normal file
312
libretroshare/src/util/contentvalue.cc
Normal file
|
@ -0,0 +1,312 @@
|
|||
|
||||
/*
|
||||
* util/contentvalue.cc, key val container
|
||||
*
|
||||
* Copyright 2012 Christopher Evi-Parker
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <memory.h>
|
||||
|
||||
#include "contentvalue.h"
|
||||
|
||||
|
||||
|
||||
|
||||
const uint8_t ContentValue::BOOL_TYPE = 1;
|
||||
const uint8_t ContentValue::DATA_TYPE = 2;
|
||||
const uint8_t ContentValue::STRING_TYPE = 3;
|
||||
const uint8_t ContentValue::DOUBLE_TYPE = 4;
|
||||
const uint8_t ContentValue::INT32_TYPE = 5;
|
||||
const uint8_t ContentValue::INT64_TYPE = 6;
|
||||
|
||||
|
||||
/**************** content value implementation ******************/
|
||||
|
||||
typedef std::pair<std::string, uint8_t> KeyTypePair;
|
||||
|
||||
ContentValue::ContentValue(){
|
||||
|
||||
}
|
||||
|
||||
ContentValue::~ContentValue(){
|
||||
// release resources held in data
|
||||
clearData();
|
||||
}
|
||||
|
||||
ContentValue::ContentValue(ContentValue &from){
|
||||
|
||||
std::map<std::string, uint8_t> keyTypeMap;
|
||||
from.getKeyTypeMap(keyTypeMap);
|
||||
std::map<std::string, uint8_t>::const_iterator cit =
|
||||
keyTypeMap.begin();
|
||||
|
||||
uint8_t type = 0;
|
||||
std::string currKey;
|
||||
std::string val = "";
|
||||
char *src = NULL;
|
||||
uint32_t data_len = 0;
|
||||
|
||||
for(; cit != keyTypeMap.end(); cit++){
|
||||
|
||||
type = cit->second;
|
||||
currKey = cit->first;
|
||||
|
||||
switch(type){
|
||||
|
||||
case INT32_TYPE:
|
||||
{
|
||||
int32_t value;
|
||||
from.getAsInt32(currKey, value);
|
||||
put(currKey, value);
|
||||
break;
|
||||
}
|
||||
case INT64_TYPE:
|
||||
{
|
||||
int64_t value;
|
||||
from.getAsInt64(currKey, value);
|
||||
put(currKey, value);
|
||||
break;
|
||||
}
|
||||
case STRING_TYPE:
|
||||
{
|
||||
from.getAsString(currKey, val);
|
||||
put(currKey, val);
|
||||
break;
|
||||
}
|
||||
case BOOL_TYPE:
|
||||
{
|
||||
bool value;
|
||||
from.getAsBool(currKey, value);
|
||||
put(currKey, value);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE:
|
||||
{
|
||||
from.getAsData(currKey, data_len, src);
|
||||
put(currKey, data_len, src);
|
||||
break;
|
||||
}
|
||||
case DOUBLE_TYPE:
|
||||
double value;
|
||||
from.getAsDouble(currKey, value);
|
||||
put(currKey, value);
|
||||
break;
|
||||
default:
|
||||
std::cerr << "ContentValue::ContentValue(ContentValue &from):"
|
||||
<< "Error! Unrecognised data type!" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContentValue::put(const std::string &key, bool value){
|
||||
|
||||
if(mKvSet.find(key) != mKvSet.end())
|
||||
removeKeyValue(key);
|
||||
|
||||
mKvSet.insert(KeyTypePair(key, BOOL_TYPE));
|
||||
mKvBool.insert(std::pair<std::string, bool>(key, value));
|
||||
}
|
||||
|
||||
void ContentValue::put(const std::string &key, const std::string &value){
|
||||
|
||||
if(mKvSet.find(key) != mKvSet.end())
|
||||
removeKeyValue(key);
|
||||
|
||||
mKvSet.insert(KeyTypePair(key, STRING_TYPE));
|
||||
mKvString.insert(std::pair<std::string, std::string>(key, value));
|
||||
}
|
||||
|
||||
void ContentValue::put(const std::string &key, double value){
|
||||
|
||||
if(mKvSet.find(key) != mKvSet.end())
|
||||
removeKeyValue(key);
|
||||
|
||||
mKvSet.insert(KeyTypePair(key,DOUBLE_TYPE));
|
||||
mKvDouble.insert(std::pair<std::string, double>(key, value));
|
||||
}
|
||||
|
||||
void ContentValue::put(const std::string &key, int32_t value){
|
||||
|
||||
if(mKvSet.find(key) != mKvSet.end())
|
||||
removeKeyValue(key);
|
||||
|
||||
mKvSet.insert(KeyTypePair(key, INT32_TYPE));
|
||||
mKvInt32.insert(std::pair<std::string, int32_t>(key, value));
|
||||
}
|
||||
|
||||
void ContentValue::put(const std::string &key, int64_t value){
|
||||
|
||||
if(mKvSet.find(key) != mKvSet.end())
|
||||
removeKeyValue(key);
|
||||
|
||||
mKvSet.insert(KeyTypePair(key, INT64_TYPE));
|
||||
mKvInt64.insert(std::pair<std::string, int64_t>(key, value));
|
||||
}
|
||||
|
||||
void ContentValue::put(const std::string &key, uint32_t len, const char* value){
|
||||
|
||||
|
||||
// release memory from old key value if key
|
||||
// exists
|
||||
if(mKvSet.find(key) != mKvSet.end()) {
|
||||
removeKeyValue(key);
|
||||
}
|
||||
|
||||
mKvSet.insert(KeyTypePair(key, DATA_TYPE));
|
||||
char* dest = NULL;
|
||||
|
||||
// len is zero then just put a NULL entry
|
||||
if(len != 0){
|
||||
dest = new char[len];
|
||||
memcpy(dest, value, len);
|
||||
}
|
||||
|
||||
mKvData.insert(std::pair<std::string, std::pair<uint32_t, char*> >
|
||||
(key, std::pair<uint32_t, char*>(len, dest)));
|
||||
}
|
||||
|
||||
bool ContentValue::getAsBool(const std::string &key, bool& value) const{
|
||||
|
||||
std::map<std::string, bool>::const_iterator it;
|
||||
if((it = mKvBool.find(key)) == mKvBool.end())
|
||||
return false;
|
||||
|
||||
value = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContentValue::getAsInt32(const std::string &key, int32_t& value) const{
|
||||
|
||||
std::map<std::string, int32_t>::const_iterator it;
|
||||
if((it = mKvInt32.find(key)) == mKvInt32.end())
|
||||
return false;
|
||||
|
||||
value = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContentValue::getAsInt64(const std::string &key, int64_t& value) const{
|
||||
|
||||
std::map<std::string, int64_t>::const_iterator it;
|
||||
if((it = mKvInt64.find(key)) == mKvInt64.end())
|
||||
return false;
|
||||
|
||||
value = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContentValue::getAsString(const std::string &key, std::string &value) const{
|
||||
|
||||
std::map<std::string, std::string>::const_iterator it;
|
||||
if((it = mKvString.find(key)) == mKvString.end())
|
||||
return false;
|
||||
|
||||
value = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContentValue::getAsData(const std::string& key, uint32_t &len, char*& value) const{
|
||||
|
||||
std::map<std::string, std::pair<uint32_t, char*> >::const_iterator it;
|
||||
if((it = mKvData.find(key)) == mKvData.end())
|
||||
return false;
|
||||
|
||||
const std::pair<uint32_t, char*> &kvRef = it->second;
|
||||
|
||||
len = kvRef.first;
|
||||
value = kvRef.second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContentValue::getAsDouble(const std::string &key, double& value) const{
|
||||
|
||||
std::map<std::string, double>::const_iterator it;
|
||||
if((it = mKvDouble.find(key)) == mKvDouble.end())
|
||||
return false;
|
||||
|
||||
value = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContentValue::removeKeyValue(const std::string &key){
|
||||
|
||||
std::map<std::string, uint8_t>::iterator mit;
|
||||
|
||||
if((mit = mKvSet.find(key)) == mKvSet.end())
|
||||
return false;
|
||||
|
||||
if(mit->second == BOOL_TYPE)
|
||||
mKvBool.erase(key);
|
||||
|
||||
if(mit->second == INT64_TYPE)
|
||||
mKvInt64.erase(key);
|
||||
|
||||
if(mit->second == DATA_TYPE){
|
||||
delete[] (mKvData[key].second);
|
||||
mKvData.erase(key);
|
||||
}
|
||||
|
||||
if(mit->second == DOUBLE_TYPE)
|
||||
mKvDouble.erase(key);
|
||||
|
||||
if(mit->second == STRING_TYPE)
|
||||
mKvString.erase(key);
|
||||
|
||||
if(mit->second == INT32_TYPE)
|
||||
mKvInt32.erase(key);
|
||||
|
||||
|
||||
mKvSet.erase(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ContentValue::getKeyTypeMap(std::map<std::string, uint8_t> &keySet) const {
|
||||
keySet = mKvSet;
|
||||
}
|
||||
|
||||
void ContentValue::clear(){
|
||||
mKvSet.clear();
|
||||
mKvBool.clear();
|
||||
mKvDouble.clear();
|
||||
mKvString.clear();
|
||||
mKvInt32.clear();
|
||||
mKvInt64.clear();
|
||||
clearData();
|
||||
}
|
||||
|
||||
void ContentValue::clearData(){
|
||||
|
||||
std::map<std::string, std::pair<uint32_t, char*> >::iterator
|
||||
mit = mKvData.begin();
|
||||
|
||||
for(; mit != mKvData.end(); mit++){
|
||||
|
||||
if(mit->second.first != 0)
|
||||
delete[] (mit->second.second);
|
||||
}
|
||||
|
||||
mKvData.clear();
|
||||
}
|
||||
|
||||
|
||||
|
183
libretroshare/src/util/contentvalue.h
Normal file
183
libretroshare/src/util/contentvalue.h
Normal file
|
@ -0,0 +1,183 @@
|
|||
#ifndef CONTENTVALUE_H
|
||||
#define CONTENTVALUE_H
|
||||
|
||||
/*
|
||||
* util/contentvalue.h, key val container
|
||||
*
|
||||
* Copyright 2012 Christopher Evi-Parker
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
/*!
|
||||
* @brief Convenience container for making additions to databases
|
||||
* This class provides a means of holding column values to insert into a database
|
||||
*/
|
||||
class ContentValue {
|
||||
|
||||
public:
|
||||
|
||||
static const uint8_t INT32_TYPE;
|
||||
static const uint8_t INT64_TYPE;
|
||||
static const uint8_t DOUBLE_TYPE;
|
||||
static const uint8_t STRING_TYPE;
|
||||
static const uint8_t DATA_TYPE;
|
||||
static const uint8_t BOOL_TYPE;
|
||||
|
||||
ContentValue();
|
||||
|
||||
/*!
|
||||
* copy constructor that copys the key value set from another \n
|
||||
* ContentValue object to this one
|
||||
* makes a deep copy of raw data
|
||||
* @param from ContentValue instance to copy key value set from
|
||||
*/
|
||||
ContentValue(ContentValue& from);
|
||||
|
||||
/*!
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
~ContentValue();
|
||||
|
||||
/*!
|
||||
* Adds a value to the set
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
* @warning cast string literals explicitly as string, observed string literal \n
|
||||
* being casted to bool instead e.g. string("hello") rather than "hello"
|
||||
*/
|
||||
void put(const std::string& key, const std::string& value);
|
||||
|
||||
/*!
|
||||
* Adds a value to the set
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
void put(const std::string& key, bool value);
|
||||
|
||||
/*!
|
||||
* Adds a value to the set
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
void put(const std::string& key, int64_t value);
|
||||
|
||||
/*!
|
||||
* Adds a value to the set
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
void put(const std::string& key, int32_t value);
|
||||
|
||||
/*!
|
||||
* Adds a value to the set
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
void put(const std::string& key, double value);
|
||||
|
||||
/*!
|
||||
* Adds a value to the set
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
void put(const std::string& key, uint32_t len, const char* value);
|
||||
|
||||
|
||||
/*!
|
||||
* get value as 32 bit signed integer
|
||||
* @param key the value to get
|
||||
*/
|
||||
bool getAsInt32(const std::string& key, int32_t& value) const;
|
||||
|
||||
/*!
|
||||
* get value as 64 bit signed integer
|
||||
* @param key the value to get
|
||||
*/
|
||||
bool getAsInt64(const std::string& key, int64_t& value) const;
|
||||
|
||||
/*!
|
||||
* get value as bool
|
||||
* @param key the value to get
|
||||
*/
|
||||
bool getAsBool(const std::string& key, bool& value) const;
|
||||
|
||||
/*!
|
||||
* get as value double
|
||||
* @param key the value to get
|
||||
*/
|
||||
bool getAsDouble(const std::string& key, double& value) const;
|
||||
|
||||
/*!
|
||||
* get as value as string
|
||||
* @param key the value to get
|
||||
* @param value the data retrieved
|
||||
*/
|
||||
bool getAsString(const std::string& key, std::string& value) const;
|
||||
|
||||
/*!
|
||||
* get as value as raw data
|
||||
* @warning Deep copy of data reference should be made, if this instance ContentValue \n
|
||||
* is destroyed pointer returned (value) is pointing to invalid memory
|
||||
* @param key the value to get
|
||||
*/
|
||||
bool getAsData(const std::string&, uint32_t& len, char*& value) const;
|
||||
|
||||
/*!
|
||||
* @param keySet the is set with key to type pairs contained in the ContentValue instance
|
||||
*/
|
||||
void getKeyTypeMap(std::map<std::string, uint8_t>& keySet) const;
|
||||
|
||||
/*!
|
||||
* @param key the key of the key value pair to remove
|
||||
* @return true if key was found and removed, false otherwise
|
||||
*/
|
||||
bool removeKeyValue(const std::string& key);
|
||||
|
||||
/*!
|
||||
* clears this data structure of all its key value pairs held
|
||||
*/
|
||||
void clear();
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
* release memory resource associated with mKvData
|
||||
*/
|
||||
void clearData();
|
||||
|
||||
private:
|
||||
|
||||
std::map<std::string, int32_t> mKvInt32;
|
||||
std::map<std::string, int64_t> mKvInt64;
|
||||
std::map<std::string, double> mKvDouble;
|
||||
std::map<std::string, std::string> mKvString;
|
||||
std::map<std::string, std::pair<uint32_t, char*> > mKvData;
|
||||
std::map<std::string, bool> mKvBool;
|
||||
|
||||
std::map<std::string, uint8_t> mKvSet;
|
||||
|
||||
};
|
||||
|
||||
#endif // CONTENTVALUE_H
|
|
@ -6,7 +6,6 @@
|
|||
#include <cstdio>
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
#include "util/rswin.h"
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
|
||||
//#define RETRODB_DEBUG
|
||||
|
||||
|
||||
|
||||
void free_blob(void* dat){
|
||||
|
||||
char* c = (char*) dat;
|
||||
|
@ -40,13 +42,6 @@ void free_blob(void* dat){
|
|||
|
||||
}
|
||||
|
||||
const uint8_t ContentValue::BOOL_TYPE = 1;
|
||||
const uint8_t ContentValue::DATA_TYPE = 2;
|
||||
const uint8_t ContentValue::STRING_TYPE = 3;
|
||||
const uint8_t ContentValue::DOUBLE_TYPE = 4;
|
||||
const uint8_t ContentValue::INT32_TYPE = 5;
|
||||
const uint8_t ContentValue::INT64_TYPE = 6;
|
||||
|
||||
const int RetroDb::OPEN_READONLY = SQLITE_OPEN_READONLY;
|
||||
const int RetroDb::OPEN_READWRITE = SQLITE_OPEN_READWRITE;
|
||||
const int RetroDb::OPEN_READWRITE_CREATE = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||
|
@ -234,25 +229,23 @@ bool RetroDb::sqlInsert(const std::string &table, const std::string& nullColumnH
|
|||
uint8_t type = mit->second;
|
||||
std::string key = mit->first;
|
||||
|
||||
switch(type){
|
||||
|
||||
case ContentValue::BOOL_TYPE:
|
||||
|
||||
if(ContentValue::BOOL_TYPE == type)
|
||||
{
|
||||
bool value;
|
||||
cv.getAsBool(key, value);
|
||||
oStrStream << value;
|
||||
qValues += oStrStream.str();
|
||||
break;
|
||||
}
|
||||
case ContentValue::DOUBLE_TYPE:
|
||||
else if( ContentValue::DOUBLE_TYPE == type)
|
||||
{
|
||||
double value;
|
||||
cv.getAsDouble(key, value);
|
||||
oStrStream << value;
|
||||
qValues += oStrStream.str();
|
||||
break;
|
||||
}
|
||||
case ContentValue::DATA_TYPE:
|
||||
else if( ContentValue::DATA_TYPE == type)
|
||||
{
|
||||
char* value;
|
||||
uint32_t len;
|
||||
|
@ -263,32 +256,28 @@ bool RetroDb::sqlInsert(const std::string &table, const std::string& nullColumnH
|
|||
b.index = ++index;
|
||||
blobL.push_back(b);
|
||||
qValues += "?"; // parameter
|
||||
break;
|
||||
}
|
||||
case ContentValue::STRING_TYPE:
|
||||
else if ( ContentValue::STRING_TYPE == type)
|
||||
{
|
||||
std::string value;
|
||||
cv.getAsString(key, value);
|
||||
qValues += "'" + value +"'";
|
||||
break;
|
||||
}
|
||||
case ContentValue::INT32_TYPE:
|
||||
else if ( ContentValue::INT32_TYPE == type)
|
||||
{
|
||||
int32_t value;
|
||||
cv.getAsInt32(key, value);
|
||||
oStrStream << value;
|
||||
qValues += oStrStream.str();
|
||||
break;
|
||||
}
|
||||
case ContentValue::INT64_TYPE:
|
||||
else if( ContentValue::INT64_TYPE == type)
|
||||
{
|
||||
int64_t value;
|
||||
cv.getAsInt64(key, value);
|
||||
oStrStream << value;
|
||||
qValues += oStrStream.str();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mit++;
|
||||
if(mit != keyTypeMap.end()){ // add comma if more columns left
|
||||
|
@ -419,57 +408,48 @@ bool RetroDb::sqlUpdate(const std::string &tableName, std::string whereClause, c
|
|||
uint8_t type = mit->second;
|
||||
std::string key = mit->first;
|
||||
|
||||
switch(type){
|
||||
|
||||
case ContentValue::BOOL_TYPE:
|
||||
if( ContentValue::BOOL_TYPE == type)
|
||||
{
|
||||
bool value;
|
||||
cv.getAsBool(key, value);
|
||||
oStrStream << value;
|
||||
qValues += key + "='" + oStrStream.str();
|
||||
break;
|
||||
}
|
||||
case ContentValue::DOUBLE_TYPE:
|
||||
else if( ContentValue::DOUBLE_TYPE == type)
|
||||
{
|
||||
double value;
|
||||
cv.getAsDouble(key, value);
|
||||
oStrStream << value;
|
||||
qValues += key + "='" + oStrStream.str();
|
||||
break;
|
||||
}
|
||||
case ContentValue::DATA_TYPE:
|
||||
else if( ContentValue::DATA_TYPE == type)
|
||||
{
|
||||
char* value;
|
||||
uint32_t len;
|
||||
cv.getAsData(key, len, value);
|
||||
oStrStream.write(value, len);
|
||||
qValues += key + "='" + oStrStream.str() + "' ";
|
||||
break;
|
||||
}
|
||||
case ContentValue::STRING_TYPE:
|
||||
else if( ContentValue::STRING_TYPE == type)
|
||||
{
|
||||
std::string value;
|
||||
cv.getAsString(key, value);
|
||||
qValues += key + "='" + value + "' ";
|
||||
break;
|
||||
}
|
||||
case ContentValue::INT32_TYPE:
|
||||
else if( ContentValue::INT32_TYPE == type)
|
||||
{
|
||||
int32_t value;
|
||||
cv.getAsInt32(key, value);
|
||||
oStrStream << value;
|
||||
qValues += key + "='" + oStrStream.str() + "' ";
|
||||
break;
|
||||
}
|
||||
case ContentValue::INT64_TYPE:
|
||||
else if( ContentValue::INT64_TYPE == type)
|
||||
{
|
||||
int64_t value;
|
||||
cv.getAsInt64(key, value);
|
||||
oStrStream << value;
|
||||
qValues += key + "='" + oStrStream.str() + "' ";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mit++;
|
||||
if(mit != keyTypeMap.end()){ // add comma if more columns left
|
||||
|
@ -496,7 +476,6 @@ bool RetroDb::sqlUpdate(const std::string &tableName, std::string whereClause, c
|
|||
|
||||
// execute query
|
||||
return execSQL(sqlQuery);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -715,276 +694,3 @@ const void* RetroCursor::getData(int columnIndex, uint32_t &datSize){
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**************** content value implementation ******************/
|
||||
|
||||
typedef std::pair<std::string, uint8_t> KeyTypePair;
|
||||
|
||||
ContentValue::ContentValue(){
|
||||
|
||||
}
|
||||
|
||||
ContentValue::~ContentValue(){
|
||||
// release resources held in data
|
||||
clearData();
|
||||
}
|
||||
|
||||
ContentValue::ContentValue(ContentValue &from){
|
||||
|
||||
std::map<std::string, uint8_t> keyTypeMap;
|
||||
from.getKeyTypeMap(keyTypeMap);
|
||||
std::map<std::string, uint8_t>::const_iterator cit =
|
||||
keyTypeMap.begin();
|
||||
|
||||
uint8_t type = 0;
|
||||
std::string currKey;
|
||||
std::string val = "";
|
||||
char *src = NULL;
|
||||
uint32_t data_len = 0;
|
||||
|
||||
for(; cit != keyTypeMap.end(); cit++){
|
||||
|
||||
type = cit->second;
|
||||
currKey = cit->first;
|
||||
|
||||
switch(type){
|
||||
|
||||
case INT32_TYPE:
|
||||
{
|
||||
int32_t value;
|
||||
from.getAsInt32(currKey, value);
|
||||
put(currKey, value);
|
||||
break;
|
||||
}
|
||||
case INT64_TYPE:
|
||||
{
|
||||
int64_t value;
|
||||
from.getAsInt64(currKey, value);
|
||||
put(currKey, value);
|
||||
break;
|
||||
}
|
||||
case STRING_TYPE:
|
||||
{
|
||||
from.getAsString(currKey, val);
|
||||
put(currKey, val);
|
||||
break;
|
||||
}
|
||||
case BOOL_TYPE:
|
||||
{
|
||||
bool value;
|
||||
from.getAsBool(currKey, value);
|
||||
put(currKey, value);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE:
|
||||
{
|
||||
from.getAsData(currKey, data_len, src);
|
||||
put(currKey, data_len, src);
|
||||
break;
|
||||
}
|
||||
case DOUBLE_TYPE:
|
||||
double value;
|
||||
from.getAsDouble(currKey, value);
|
||||
put(currKey, value);
|
||||
break;
|
||||
default:
|
||||
std::cerr << "ContentValue::ContentValue(ContentValue &from):"
|
||||
<< "Error! Unrecognised data type!" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContentValue::put(const std::string &key, bool value){
|
||||
|
||||
if(mKvSet.find(key) != mKvSet.end())
|
||||
removeKeyValue(key);
|
||||
|
||||
mKvSet.insert(KeyTypePair(key, BOOL_TYPE));
|
||||
mKvBool.insert(std::pair<std::string, bool>(key, value));
|
||||
}
|
||||
|
||||
void ContentValue::put(const std::string &key, const std::string &value){
|
||||
|
||||
if(mKvSet.find(key) != mKvSet.end())
|
||||
removeKeyValue(key);
|
||||
|
||||
mKvSet.insert(KeyTypePair(key, STRING_TYPE));
|
||||
mKvString.insert(std::pair<std::string, std::string>(key, value));
|
||||
}
|
||||
|
||||
void ContentValue::put(const std::string &key, double value){
|
||||
|
||||
if(mKvSet.find(key) != mKvSet.end())
|
||||
removeKeyValue(key);
|
||||
|
||||
mKvSet.insert(KeyTypePair(key,DOUBLE_TYPE));
|
||||
mKvDouble.insert(std::pair<std::string, double>(key, value));
|
||||
}
|
||||
|
||||
void ContentValue::put(const std::string &key, int32_t value){
|
||||
|
||||
if(mKvSet.find(key) != mKvSet.end())
|
||||
removeKeyValue(key);
|
||||
|
||||
mKvSet.insert(KeyTypePair(key, INT32_TYPE));
|
||||
mKvInt32.insert(std::pair<std::string, int32_t>(key, value));
|
||||
}
|
||||
|
||||
void ContentValue::put(const std::string &key, int64_t value){
|
||||
|
||||
if(mKvSet.find(key) != mKvSet.end())
|
||||
removeKeyValue(key);
|
||||
|
||||
mKvSet.insert(KeyTypePair(key, INT64_TYPE));
|
||||
mKvInt64.insert(std::pair<std::string, int64_t>(key, value));
|
||||
}
|
||||
|
||||
void ContentValue::put(const std::string &key, uint32_t len, const char* value){
|
||||
|
||||
|
||||
// release memory from old key value if key
|
||||
// exists
|
||||
if(mKvSet.find(key) != mKvSet.end()) {
|
||||
removeKeyValue(key);
|
||||
}
|
||||
|
||||
mKvSet.insert(KeyTypePair(key, DATA_TYPE));
|
||||
char* dest = NULL;
|
||||
|
||||
// len is zero then just put a NULL entry
|
||||
if(len != 0){
|
||||
dest = new char[len];
|
||||
memcpy(dest, value, len);
|
||||
}
|
||||
|
||||
mKvData.insert(std::pair<std::string, std::pair<uint32_t, char*> >
|
||||
(key, std::pair<uint32_t, char*>(len, dest)));
|
||||
}
|
||||
|
||||
bool ContentValue::getAsBool(const std::string &key, bool& value) const{
|
||||
|
||||
std::map<std::string, bool>::const_iterator it;
|
||||
if((it = mKvBool.find(key)) == mKvBool.end())
|
||||
return false;
|
||||
|
||||
value = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContentValue::getAsInt32(const std::string &key, int32_t& value) const{
|
||||
|
||||
std::map<std::string, int32_t>::const_iterator it;
|
||||
if((it = mKvInt32.find(key)) == mKvInt32.end())
|
||||
return false;
|
||||
|
||||
value = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContentValue::getAsInt64(const std::string &key, int64_t& value) const{
|
||||
|
||||
std::map<std::string, int64_t>::const_iterator it;
|
||||
if((it = mKvInt64.find(key)) == mKvInt64.end())
|
||||
return false;
|
||||
|
||||
value = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContentValue::getAsString(const std::string &key, std::string &value) const{
|
||||
|
||||
std::map<std::string, std::string>::const_iterator it;
|
||||
if((it = mKvString.find(key)) == mKvString.end())
|
||||
return false;
|
||||
|
||||
value = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContentValue::getAsData(const std::string& key, uint32_t &len, char*& value) const{
|
||||
|
||||
std::map<std::string, std::pair<uint32_t, char*> >::const_iterator it;
|
||||
if((it = mKvData.find(key)) == mKvData.end())
|
||||
return false;
|
||||
|
||||
const std::pair<uint32_t, char*> &kvRef = it->second;
|
||||
|
||||
len = kvRef.first;
|
||||
value = kvRef.second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContentValue::getAsDouble(const std::string &key, double& value) const{
|
||||
|
||||
std::map<std::string, double>::const_iterator it;
|
||||
if((it = mKvDouble.find(key)) == mKvDouble.end())
|
||||
return false;
|
||||
|
||||
value = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContentValue::removeKeyValue(const std::string &key){
|
||||
|
||||
std::map<std::string, uint8_t>::iterator mit;
|
||||
|
||||
if((mit = mKvSet.find(key)) == mKvSet.end())
|
||||
return false;
|
||||
|
||||
if(mit->second == BOOL_TYPE)
|
||||
mKvBool.erase(key);
|
||||
|
||||
if(mit->second == INT64_TYPE)
|
||||
mKvInt64.erase(key);
|
||||
|
||||
if(mit->second == DATA_TYPE){
|
||||
delete[] (mKvData[key].second);
|
||||
mKvData.erase(key);
|
||||
}
|
||||
|
||||
if(mit->second == DOUBLE_TYPE)
|
||||
mKvDouble.erase(key);
|
||||
|
||||
if(mit->second == STRING_TYPE)
|
||||
mKvString.erase(key);
|
||||
|
||||
if(mit->second == INT32_TYPE)
|
||||
mKvInt32.erase(key);
|
||||
|
||||
|
||||
mKvSet.erase(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ContentValue::getKeyTypeMap(std::map<std::string, uint8_t> &keySet) const {
|
||||
keySet = mKvSet;
|
||||
}
|
||||
|
||||
void ContentValue::clear(){
|
||||
mKvSet.clear();
|
||||
mKvBool.clear();
|
||||
mKvDouble.clear();
|
||||
mKvString.clear();
|
||||
mKvInt32.clear();
|
||||
mKvInt64.clear();
|
||||
clearData();
|
||||
}
|
||||
|
||||
void ContentValue::clearData(){
|
||||
|
||||
std::map<std::string, std::pair<uint32_t, char*> >::iterator
|
||||
mit = mKvData.begin();
|
||||
|
||||
for(; mit != mKvData.end(); mit++){
|
||||
|
||||
if(mit->second.first != 0)
|
||||
delete[] (mit->second.second);
|
||||
}
|
||||
|
||||
mKvData.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "contentvalue.h"
|
||||
|
||||
class ContentValue;
|
||||
class RetroCursor;
|
||||
|
||||
/*!
|
||||
|
@ -288,157 +288,7 @@ private:
|
|||
};
|
||||
|
||||
|
||||
/*!
|
||||
* @brief Convenience container for making additions to databases
|
||||
* This class provides a means of holding column values to insert into a database
|
||||
*/
|
||||
class ContentValue {
|
||||
|
||||
public:
|
||||
|
||||
static const uint8_t INT32_TYPE;
|
||||
static const uint8_t INT64_TYPE;
|
||||
static const uint8_t DOUBLE_TYPE;
|
||||
static const uint8_t STRING_TYPE;
|
||||
static const uint8_t DATA_TYPE;
|
||||
static const uint8_t BOOL_TYPE;
|
||||
|
||||
ContentValue();
|
||||
|
||||
/*!
|
||||
* copy constructor that copys the key value set from another \n
|
||||
* ContentValue object to this one
|
||||
* makes a deep copy of raw data
|
||||
* @param from ContentValue instance to copy key value set from
|
||||
*/
|
||||
ContentValue(ContentValue& from);
|
||||
|
||||
/*!
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
~ContentValue();
|
||||
|
||||
/*!
|
||||
* Adds a value to the set
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
* @warning cast string literals explicitly as string, observed string literal \n
|
||||
* being casted to bool instead e.g. string("hello") rather than "hello"
|
||||
*/
|
||||
void put(const std::string& key, const std::string& value);
|
||||
|
||||
/*!
|
||||
* Adds a value to the set
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
void put(const std::string& key, bool value);
|
||||
|
||||
/*!
|
||||
* Adds a value to the set
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
void put(const std::string& key, int64_t value);
|
||||
|
||||
/*!
|
||||
* Adds a value to the set
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
void put(const std::string& key, int32_t value);
|
||||
|
||||
/*!
|
||||
* Adds a value to the set
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
void put(const std::string& key, double value);
|
||||
|
||||
/*!
|
||||
* Adds a value to the set
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
void put(const std::string& key, uint32_t len, const char* value);
|
||||
|
||||
|
||||
/*!
|
||||
* get value as 32 bit signed integer
|
||||
* @param key the value to get
|
||||
*/
|
||||
bool getAsInt32(const std::string& key, int32_t& value) const;
|
||||
|
||||
/*!
|
||||
* get value as 64 bit signed integer
|
||||
* @param key the value to get
|
||||
*/
|
||||
bool getAsInt64(const std::string& key, int64_t& value) const;
|
||||
|
||||
/*!
|
||||
* get value as bool
|
||||
* @param key the value to get
|
||||
*/
|
||||
bool getAsBool(const std::string& key, bool& value) const;
|
||||
|
||||
/*!
|
||||
* get as value double
|
||||
* @param key the value to get
|
||||
*/
|
||||
bool getAsDouble(const std::string& key, double& value) const;
|
||||
|
||||
/*!
|
||||
* get as value as string
|
||||
* @param key the value to get
|
||||
* @param value the data retrieved
|
||||
*/
|
||||
bool getAsString(const std::string& key, std::string& value) const;
|
||||
|
||||
/*!
|
||||
* get as value as raw data
|
||||
* @warning Deep copy of data reference should be made, if this instance ContentValue \n
|
||||
* is destroyed pointer returned (value) is pointing to invalid memory
|
||||
* @param key the value to get
|
||||
*/
|
||||
bool getAsData(const std::string&, uint32_t& len, char*& value) const;
|
||||
|
||||
/*!
|
||||
* @param keySet the is set with key to type pairs contained in the ContentValue instance
|
||||
*/
|
||||
void getKeyTypeMap(std::map<std::string, uint8_t>& keySet) const;
|
||||
|
||||
/*!
|
||||
* @param key the key of the key value pair to remove
|
||||
* @return true if key was found and removed, false otherwise
|
||||
*/
|
||||
bool removeKeyValue(const std::string& key);
|
||||
|
||||
/*!
|
||||
* clears this data structure of all its key value pairs held
|
||||
*/
|
||||
void clear();
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
* release memory resource associated with mKvData
|
||||
*/
|
||||
void clearData();
|
||||
|
||||
private:
|
||||
|
||||
std::map<std::string, int32_t> mKvInt32;
|
||||
std::map<std::string, int64_t> mKvInt64;
|
||||
std::map<std::string, double> mKvDouble;
|
||||
std::map<std::string, std::string> mKvString;
|
||||
std::map<std::string, std::pair<uint32_t, char*> > mKvData;
|
||||
std::map<std::string, bool> mKvBool;
|
||||
|
||||
std::map<std::string, uint8_t> mKvSet;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // RSSQLITE_H
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
// Warning: never store references to a t_RsGenericIdType accross threads, since the
|
||||
// cached string convertion is not thread safe.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdexcept>
|
||||
|
@ -63,6 +64,14 @@ template<uint32_t ID_SIZE_IN_BYTES> class t_RsGenericIdType
|
|||
return !operator==(fp) ;
|
||||
}
|
||||
|
||||
bool operator<(const t_RsGenericIdType<ID_SIZE_IN_BYTES>& fp) const
|
||||
{
|
||||
for(uint32_t i=0;i<ID_SIZE_IN_BYTES;++i)
|
||||
if(fp.bytes[i] != bytes[i])
|
||||
return (bytes[i] < fp.bytes[i]);
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned char bytes[ID_SIZE_IN_BYTES] ;
|
||||
};
|
||||
|
|
380
libretroshare/src/util/rsmemcache.h
Normal file
380
libretroshare/src/util/rsmemcache.h
Normal file
|
@ -0,0 +1,380 @@
|
|||
/*
|
||||
* libretroshare/src/util: rsmemcache.h
|
||||
*
|
||||
* Identity interface for RetroShare.
|
||||
*
|
||||
* Copyright 2012-2012 by Robert Fernie.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
#ifndef RS_UTIL_MEM_CACHE
|
||||
#define RS_UTIL_MEM_CACHE
|
||||
|
||||
#include <map>
|
||||
#include <time.h>
|
||||
#include <iostream>
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
|
||||
/************************************************************************************/
|
||||
/************************************************************************************/
|
||||
/************************************************************************************/
|
||||
|
||||
/* Generic Memoory Cache
|
||||
*
|
||||
* This is probably crude and crap to start with.
|
||||
* Want Least Recently Used (LRU) discard policy, without having to search whole cache.
|
||||
* Use two maps:
|
||||
* - mDataMap[key] => data.
|
||||
* - mLruMap[AccessTS] => key (multimap)
|
||||
*/
|
||||
|
||||
#define DEFAULT_MEM_CACHE_SIZE 100
|
||||
|
||||
template<class Key, class Value> class RsMemCache
|
||||
{
|
||||
public:
|
||||
|
||||
RsMemCache(uint32_t max_size = DEFAULT_MEM_CACHE_SIZE, std::string name = "UnknownMemCache")
|
||||
:mDataCount(0), mMaxSize(max_size), mName(name)
|
||||
{
|
||||
clearStats();
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_cached(const Key &key) const;
|
||||
bool fetch(const Key &key, Value &data);
|
||||
Value &ref(const Key &key); // like map[] installs empty one if non-existent.
|
||||
bool store(const Key &key, const Value &data);
|
||||
|
||||
bool resize(); // should be called periodically to cleanup old entries.
|
||||
|
||||
private:
|
||||
|
||||
bool update_lrumap(const Key &key, time_t old_ts, time_t new_ts);
|
||||
bool discard_LRU(int count_to_clear);
|
||||
|
||||
// internal class.
|
||||
class cache_data
|
||||
{
|
||||
public:
|
||||
cache_data() { return; }
|
||||
cache_data(Key in_key, Value in_data, time_t in_ts)
|
||||
:key(in_key), data(in_data), ts(in_ts) { return; }
|
||||
Key key;
|
||||
Value data;
|
||||
time_t ts;
|
||||
};
|
||||
|
||||
|
||||
std::map<Key, cache_data > mDataMap;
|
||||
std::multimap<time_t, Key> mLruMap;
|
||||
uint32_t mDataCount;
|
||||
uint32_t mMaxSize;
|
||||
std::string mName;
|
||||
|
||||
// some statistics.
|
||||
void printStats(std::ostream &out);
|
||||
void clearStats();
|
||||
|
||||
mutable uint32_t mStats_inserted;
|
||||
mutable uint32_t mStats_dropped;
|
||||
mutable uint32_t mStats_iscached;
|
||||
mutable uint32_t mStats_cachemiss;
|
||||
mutable uint32_t mStats_access;
|
||||
mutable uint32_t mStats_accessmiss;
|
||||
};
|
||||
|
||||
|
||||
template<class Key, class Value> bool RsMemCache<Key, Value>::is_cached(const Key &key) const
|
||||
{
|
||||
typename std::map<Key,cache_data>::const_iterator it;
|
||||
it = mDataMap.find(key);
|
||||
if (it == mDataMap.end())
|
||||
{
|
||||
std::cerr << "RsMemCache::is_cached(" << key << ") false";
|
||||
std::cerr << std::endl;
|
||||
|
||||
mStats_cachemiss++;
|
||||
return false;
|
||||
}
|
||||
std::cerr << "RsMemCache::is_cached(" << key << ") false";
|
||||
std::cerr << std::endl;
|
||||
mStats_iscached++;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<class Key, class Value> bool RsMemCache<Key, Value>::fetch(const Key &key, Value &data)
|
||||
{
|
||||
printStats(std::cerr);
|
||||
typename std::map<Key, cache_data>::iterator it;
|
||||
it = mDataMap.find(key);
|
||||
if (it == mDataMap.end())
|
||||
{
|
||||
std::cerr << "RsMemCache::fetch(" << key << ") false";
|
||||
std::cerr << std::endl;
|
||||
|
||||
mStats_accessmiss++;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cerr << "RsMemCache::fetch(" << key << ") OK";
|
||||
std::cerr << std::endl;
|
||||
|
||||
data = it->second.data;
|
||||
|
||||
/* update ts on data */
|
||||
time_t old_ts = it->second.ts;
|
||||
time_t new_ts = time(NULL);
|
||||
it->second.ts = new_ts;
|
||||
|
||||
update_lrumap(key, old_ts, new_ts);
|
||||
|
||||
mStats_access++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Key, class Value> Value &RsMemCache<Key, Value>::ref(const Key &key)
|
||||
{
|
||||
printStats(std::cerr);
|
||||
typename std::map<Key, cache_data>::iterator it;
|
||||
it = mDataMap.find(key);
|
||||
if (it == mDataMap.end())
|
||||
{
|
||||
std::cerr << "RsMemCache::ref(" << key << ") ERROR missing Key inserting Empty Data in LRU slot";
|
||||
std::cerr << std::endl;
|
||||
|
||||
// insert operation.
|
||||
time_t new_ts = 0;
|
||||
Value data;
|
||||
mDataMap[key] = cache_data(key, data, new_ts);
|
||||
mDataCount++;
|
||||
|
||||
update_lrumap(key, 0, new_ts);
|
||||
it = mDataMap.find(key);
|
||||
|
||||
mStats_accessmiss++;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "RsMemCache::ref(" << key << ") OK";
|
||||
std::cerr << std::endl;
|
||||
|
||||
/* update ts on data */
|
||||
time_t old_ts = it->second.ts;
|
||||
time_t new_ts = time(NULL);
|
||||
it->second.ts = new_ts;
|
||||
|
||||
update_lrumap(key, old_ts, new_ts);
|
||||
|
||||
mStats_access++;
|
||||
}
|
||||
return it->second.data;
|
||||
}
|
||||
|
||||
template<class Key, class Value> bool RsMemCache<Key, Value>::store(const Key &key, const Value &data)
|
||||
{
|
||||
std::cerr << "RsMemCache::store()";
|
||||
std::cerr << std::endl;
|
||||
printStats(std::cerr);
|
||||
|
||||
/* update lrumap entry */
|
||||
time_t old_ts = 0;
|
||||
time_t new_ts = time(NULL);
|
||||
|
||||
// For consistency
|
||||
typename std::map<Key, cache_data>::const_iterator it;
|
||||
it = mDataMap.find(key);
|
||||
if (it != mDataMap.end())
|
||||
{
|
||||
// ERROR.
|
||||
std::cerr << "RsMemCache::store() WARNING overriding existing entry";
|
||||
std::cerr << std::endl;
|
||||
|
||||
old_ts = it->second.ts;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDataCount++;
|
||||
}
|
||||
|
||||
mDataMap[key] = cache_data(key, data, new_ts);
|
||||
|
||||
update_lrumap(key, old_ts, new_ts);
|
||||
|
||||
mStats_inserted++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Key, class Value> bool RsMemCache<Key, Value>::update_lrumap(const Key &key, time_t old_ts, time_t new_ts)
|
||||
{
|
||||
if (old_ts == 0)
|
||||
{
|
||||
std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") just insert!";
|
||||
std::cerr << std::endl;
|
||||
|
||||
/* new insertion */
|
||||
mLruMap.insert(std::make_pair(new_ts, key));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* find old entry */
|
||||
typename std::multimap<time_t, Key>::iterator mit;
|
||||
typename std::multimap<time_t, Key>::iterator sit = mLruMap.lower_bound(old_ts);
|
||||
typename std::multimap<time_t, Key>::iterator eit = mLruMap.upper_bound(old_ts);
|
||||
|
||||
for(mit = sit; mit != eit; mit++)
|
||||
{
|
||||
if (mit->second == key)
|
||||
{
|
||||
mLruMap.erase(mit);
|
||||
std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") rm old";
|
||||
std::cerr << std::endl;
|
||||
|
||||
if (new_ts != 0) // == 0, means remove.
|
||||
{
|
||||
std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") added new_ts";
|
||||
std::cerr << std::endl;
|
||||
mLruMap.insert(std::make_pair(new_ts, key));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
std::cerr << "p3IdService::locked_cache_update_lrumap(" << key << ") ERROR";
|
||||
std::cerr << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class Key, class Value> bool RsMemCache<Key, Value>::resize()
|
||||
{
|
||||
std::cerr << "RsMemCache::resize()";
|
||||
std::cerr << std::endl;
|
||||
printStats(std::cerr);
|
||||
|
||||
int count_to_clear = 0;
|
||||
{
|
||||
// consistency check.
|
||||
if ((mDataMap.size() != mDataCount) ||
|
||||
(mLruMap.size() != mDataCount))
|
||||
{
|
||||
// ERROR.
|
||||
std::cerr << "RsMemCache::resize() CONSISTENCY ERROR";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
if (mDataCount > mMaxSize)
|
||||
{
|
||||
count_to_clear = mDataCount - mMaxSize;
|
||||
std::cerr << "RsMemCache::resize() to_clear: " << count_to_clear;
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (count_to_clear > 0)
|
||||
{
|
||||
discard_LRU(count_to_clear);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class Key, class Value> bool RsMemCache<Key, Value>::discard_LRU(int count_to_clear)
|
||||
{
|
||||
while(count_to_clear > 0)
|
||||
{
|
||||
typename std::multimap<time_t, Key>::iterator mit = mLruMap.begin();
|
||||
if (mit != mLruMap.end())
|
||||
{
|
||||
Key key = mit->second;
|
||||
mLruMap.erase(mit);
|
||||
|
||||
/* now clear from real cache */
|
||||
//std::map<Key, cache_data<Key, Value> >::iterator it;
|
||||
typename std::map<Key, cache_data>::iterator it;
|
||||
it = mDataMap.find(key);
|
||||
if (it == mDataMap.end())
|
||||
{
|
||||
// ERROR
|
||||
std::cerr << "RsMemCache::discard_LRU(): ERROR Missing key: " << key;
|
||||
std::cerr << std::endl;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "RsMemCache::discard_LRU() removing: " << key;
|
||||
std::cerr << std::endl;
|
||||
mDataMap.erase(it);
|
||||
mDataCount--;
|
||||
mStats_dropped++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No More Data, ERROR.
|
||||
std::cerr << "RsMemCache::discard_LRU(): INFO more more cache data";
|
||||
std::cerr << std::endl;
|
||||
return true;
|
||||
}
|
||||
count_to_clear--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// These aren't templated functions.
|
||||
template<class Key, class Value> void RsMemCache<Key, Value>::printStats(std::ostream &out)
|
||||
{
|
||||
typename std::multimap<time_t, Key>::iterator mit = mLruMap.begin();
|
||||
time_t age = 0;
|
||||
if (mit != mLruMap.end())
|
||||
{
|
||||
age = time(NULL) - mit->first;
|
||||
}
|
||||
|
||||
out << "RsMemCache<" << mName << ">::printStats() Size: " << mDataCount << " Size2: " << mDataMap.size() << " Size3: " << mLruMap.size() << " MaxSize: " << mMaxSize << " LRU Age: " << age;
|
||||
out << std::endl;
|
||||
|
||||
out << "\tInsertions: " << mStats_inserted << " Drops: " << mStats_dropped;
|
||||
out << std::endl;
|
||||
|
||||
out << "\tCache Hits: " << mStats_iscached << " Misses: " << mStats_cachemiss;
|
||||
out << std::endl;
|
||||
|
||||
out << "\tAccess Hits: " << mStats_access << " Misses: " << mStats_accessmiss;
|
||||
out << std::endl;
|
||||
}
|
||||
|
||||
template<class Key, class Value> void RsMemCache<Key, Value>::clearStats()
|
||||
{
|
||||
mStats_inserted = 0;
|
||||
mStats_dropped = 0;
|
||||
mStats_iscached = 0;
|
||||
mStats_cachemiss = 0;
|
||||
mStats_access = 0;
|
||||
mStats_accessmiss = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // RS_UTIL_MEM_CACHE
|
|
@ -44,10 +44,8 @@
|
|||
|
||||
#else
|
||||
|
||||
#include "util/rswin.h"
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#include <stdio.h> /* for ssize_t */
|
||||
//typedef uint32_t socklen_t;
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
*/
|
||||
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
#include "util/rswin.h"
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
|
@ -119,7 +115,7 @@ class RsThread
|
|||
RsThread();
|
||||
virtual ~RsThread() {}
|
||||
|
||||
virtual void start() { createThread(*this); }
|
||||
virtual void start() { mIsRunning = true; createThread(*this); }
|
||||
virtual void run() = 0; /* called once the thread is started */
|
||||
virtual void join(); /* waits for the the mTid thread to stop */
|
||||
virtual void stop(); /* calls pthread_exit() */
|
||||
|
|
198
libretroshare/src/util/rstickevent.cc
Normal file
198
libretroshare/src/util/rstickevent.cc
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* libretroshare/src/util: rstickevent.cc
|
||||
*
|
||||
* Identity interface for RetroShare.
|
||||
*
|
||||
* Copyright 2012-2012 by Robert Fernie.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "util/rstickevent.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
//#define DEBUG_EVENTS 1
|
||||
|
||||
void RsTickEvent::tick_events()
|
||||
{
|
||||
#ifdef DEBUG_EVENTS
|
||||
std::cerr << "RsTickEvent::tick_events() Event List:";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
time_t now = time(NULL);
|
||||
{
|
||||
RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
#ifdef DEBUG_EVENTS
|
||||
if (!mEvents.empty())
|
||||
{
|
||||
std::multimap<time_t, uint32_t>::iterator it;
|
||||
|
||||
for(it = mEvents.begin(); it != mEvents.end(); it++)
|
||||
{
|
||||
std::cerr << "\tEvent type: ";
|
||||
std::cerr << it->second << " in " << it->first - now << " secs";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mEvents.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* all events in the future */
|
||||
if (mEvents.begin()->first > now)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::list<EventData> toProcess;
|
||||
std::list<EventData>::iterator it;
|
||||
|
||||
{
|
||||
RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/
|
||||
while((!mEvents.empty()) && (mEvents.begin()->first <= now))
|
||||
{
|
||||
std::multimap<time_t, EventData>::iterator it = mEvents.begin();
|
||||
uint32_t event_type = it->second.mEventType;
|
||||
toProcess.push_back(it->second);
|
||||
mEvents.erase(it);
|
||||
|
||||
count_adjust_locked(event_type, -1);
|
||||
}
|
||||
}
|
||||
|
||||
for(it = toProcess.begin(); it != toProcess.end(); it++)
|
||||
{
|
||||
std::cerr << "RsTickEvent::tick_events() calling handle_event(";
|
||||
std::cerr << it->mEventType << ", " << it->mEventLabel << ")";
|
||||
std::cerr << std::endl;
|
||||
handle_event(it->mEventType, it->mEventLabel);
|
||||
}
|
||||
}
|
||||
|
||||
void RsTickEvent::schedule_now(uint32_t event_type)
|
||||
{
|
||||
std::string elabel;
|
||||
RsTickEvent::schedule_in(event_type, 0, elabel);
|
||||
}
|
||||
|
||||
|
||||
void RsTickEvent::schedule_now(uint32_t event_type, const std::string &elabel)
|
||||
{
|
||||
RsTickEvent::schedule_in(event_type, 0, elabel);
|
||||
}
|
||||
|
||||
void RsTickEvent::schedule_event(uint32_t event_type, time_t when, const std::string &elabel)
|
||||
{
|
||||
RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/
|
||||
mEvents.insert(std::make_pair(when, EventData(event_type, elabel)));
|
||||
|
||||
count_adjust_locked(event_type, 1);
|
||||
}
|
||||
|
||||
void RsTickEvent::schedule_in(uint32_t event_type, uint32_t in_secs)
|
||||
{
|
||||
std::string elabel;
|
||||
RsTickEvent::schedule_in(event_type, in_secs, elabel);
|
||||
}
|
||||
|
||||
|
||||
void RsTickEvent::schedule_in(uint32_t event_type, uint32_t in_secs, const std::string &elabel)
|
||||
{
|
||||
std::cerr << "RsTickEvent::schedule_in(" << event_type << ", " << elabel << ") in " << in_secs << " secs";
|
||||
std::cerr << std::endl;
|
||||
|
||||
time_t event_time = time(NULL) + in_secs;
|
||||
RsTickEvent::schedule_event(event_type, event_time, elabel);
|
||||
}
|
||||
|
||||
|
||||
void RsTickEvent::handle_event(uint32_t event_type, const std::string &elabel)
|
||||
{
|
||||
std::cerr << "RsTickEvent::handle_event(" << event_type << ", " << elabel;
|
||||
std::cerr << ") ERROR Not Handled";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
|
||||
int32_t RsTickEvent::event_count(uint32_t event_type)
|
||||
{
|
||||
RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/
|
||||
std::map<uint32_t, int32_t>::iterator it;
|
||||
|
||||
it = mEventCount.find(event_type);
|
||||
if (it == mEventCount.end())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
|
||||
bool RsTickEvent::prev_event_ago(uint32_t event_type, int32_t &age)
|
||||
{
|
||||
RsStackMutex stack(mEventMtx); /********** STACK LOCKED MTX ******/
|
||||
std::map<uint32_t, time_t>::iterator it;
|
||||
|
||||
it = mPreviousEvent.find(event_type);
|
||||
if (it == mPreviousEvent.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
age = time(NULL) - it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void RsTickEvent::count_adjust_locked(uint32_t event_type, int32_t change)
|
||||
{
|
||||
std::map<uint32_t, int32_t>::iterator it;
|
||||
|
||||
it = mEventCount.find(event_type);
|
||||
if (it == mEventCount.end())
|
||||
{
|
||||
mEventCount[event_type] = 0;
|
||||
it = mEventCount.find(event_type);
|
||||
}
|
||||
|
||||
it->second += change;
|
||||
if (it->second < 0)
|
||||
{
|
||||
std::cerr << "RsTickEvent::count_adjust() ERROR: COUNT < 0";
|
||||
std::cerr << std::endl;
|
||||
|
||||
it->second = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RsTickEvent::note_event_locked(uint32_t event_type)
|
||||
{
|
||||
mPreviousEvent[event_type] = time(NULL);
|
||||
}
|
||||
|
||||
|
84
libretroshare/src/util/rstickevent.h
Normal file
84
libretroshare/src/util/rstickevent.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* libretroshare/src/util: rstickevent.h
|
||||
*
|
||||
* Identity interface for RetroShare.
|
||||
*
|
||||
* Copyright 2012-2012 by Robert Fernie.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
#ifndef RS_UTIL_TICK_EVENT
|
||||
#define RS_UTIL_TICK_EVENT
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* A simple event queue... to avoid having to continually write separate one.
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include <time.h>
|
||||
|
||||
#include "util/rsthreads.h"
|
||||
|
||||
class RsTickEvent
|
||||
{
|
||||
public:
|
||||
RsTickEvent():mEventMtx("TickEventMtx") { return; }
|
||||
|
||||
void tick_events();
|
||||
|
||||
void schedule_now(uint32_t event_type);
|
||||
void schedule_now(uint32_t event_type, const std::string &elabel);
|
||||
|
||||
void schedule_event(uint32_t event_type, time_t when, const std::string &elabel);
|
||||
|
||||
void schedule_in(uint32_t event_type, uint32_t in_secs);
|
||||
void schedule_in(uint32_t event_type, uint32_t in_secs, const std::string &elabel);
|
||||
|
||||
int32_t event_count(uint32_t event_type);
|
||||
bool prev_event_ago(uint32_t event_type, int32_t &age);
|
||||
|
||||
protected:
|
||||
|
||||
// Overloaded to handle the events.
|
||||
virtual void handle_event(uint32_t event_type, const std::string &event_label);
|
||||
|
||||
private:
|
||||
|
||||
class EventData
|
||||
{
|
||||
public:
|
||||
EventData() :mEventType(0) { return; }
|
||||
EventData(uint32_t etype) :mEventType(etype) { return; }
|
||||
EventData(uint32_t etype, std::string elabel) :mEventLabel(elabel), mEventType(etype) { return; }
|
||||
|
||||
std::string mEventLabel;
|
||||
uint32_t mEventType;
|
||||
};
|
||||
|
||||
void count_adjust_locked(uint32_t event_type, int32_t change);
|
||||
void note_event_locked(uint32_t event_type);
|
||||
|
||||
RsMutex mEventMtx;
|
||||
std::map<uint32_t, int32_t> mEventCount;
|
||||
std::map<uint32_t, time_t> mPreviousEvent;
|
||||
std::multimap<time_t, EventData> mEvents;
|
||||
};
|
||||
|
||||
#endif // RS_UTIL_TICK_EVENT
|
Loading…
Add table
Add a link
Reference in a new issue