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:
drbob 2012-12-16 19:17:11 +00:00
commit 069b72e0b2
549 changed files with 111171 additions and 25579 deletions

View 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();
}

View 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

View file

@ -6,7 +6,6 @@
#include <cstdio>
#ifdef WINDOWS_SYS
#include "util/rswin.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

View file

@ -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();
}

View file

@ -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

View file

@ -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] ;
};

View 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

View file

@ -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;

View file

@ -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() */

View 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);
}

View 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