merge 5.0 preview from commercial

This commit is contained in:
Michael Iedema 2014-07-16 04:32:22 +02:00
parent 00d91e90bb
commit 88311c0670
51 changed files with 596 additions and 296 deletions

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.
@ -348,6 +349,7 @@ float SoftVector::getSNR() const
}
ostream& operator<<(ostream& os, const SoftVector& sv)
{
for (size_t i=0; i<sv.size(); i++) {

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
@ -123,7 +124,7 @@ class BitVector : public VectorBase<char>
//@{
/**@name Casts of Vector constructors. */
BitVector(VectorDataType wData, char* wStart, char* wEnd) : VectorBase(wData, wStart, wEnd) {}
BitVector(VectorDataType wData, char* wStart, char* wEnd) : VectorBase<char>(wData, wStart, wEnd) {}
// The one and only copy-constructor.
BitVector(const BitVector&other) : VectorBase<char>() {

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.

View File

@ -3,7 +3,6 @@
* Copyright 2010 Kestrel Signal Processing, Inc.
* Copyright 2011, 2012, 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*

View File

@ -371,33 +371,34 @@ class ConfigurationKey {
BOOLEAN,
CHOICE_OPT,
CHOICE,
CIDR_OPT,
CIDR_OPT, // (pat) IP Route, eg: "xxx.xxx.xxx.xxx/yy"
CIDR,
FILEPATH_OPT,
FILEPATH,
HOSTANDPORT_OPT,
HOSTANDPORT,
HOSTANDPORT, // (pat) hostname is allowed.
IPADDRESS_OPT,
IPADDRESS,
IPADDRESS, // (pat) IP Address but hostnames not allowed.
IPANDPORT,
MIPADDRESS_OPT,
MIPADDRESS,
MIPADDRESS, // (pat) List of IP addresses + optional ports, used only for the Neighbors config option.
PORT_OPT,
PORT,
PORT, // (pat) An IP port.
REGEX_OPT,
REGEX,
STRING_OPT,
STRING,
VALRANGE // (pat) string format is: <min_value> ':' <max_value> [ '(' <step> ')' ]
// step is not currently enforced.
// To allow floating point add a decimal point to the range, eg: "0.0:10.0"
};
enum Scope
{
GLOBALLYUNIQUE = 1,
GLOBALLYSAME = 2,
NEIGHBORSUNIQUE = 4,
NEIGHBORSSAME = 8,
GLOBALLYUNIQUE = 1, // (pat) value must be unique on all nodes.
GLOBALLYSAME = 2, // (pat) value must be the same on all nodes.
NEIGHBORSUNIQUE = 4, // (pat) value must be unique on all neighbors
NEIGHBORSSAME = 8, // (pat) value must be the same on all neighbors
NODESPECIFIC = 16
};

View File

@ -1,6 +1,7 @@
/*
* Copyright 2009, 2010 Free Software Foundation, Inc.
* Copyright 2010 Kestrel Signal Processing, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.

View File

@ -1,3 +1,27 @@
/*
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Pat added this file.
// We need an include file that is included before any other include files.
// Might I suggest that Range Networks specific global #defines be prefixed with RN_

2
Exit.h
View File

@ -4,7 +4,7 @@
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribuion.
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

1
F16.h
View File

@ -1,5 +1,6 @@
/*
* Copyright 2009 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.

View File

@ -1,5 +1,6 @@
/*
* Copyright 2009 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008, 2011 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
@ -43,122 +44,6 @@
//@{
/** Pointer FIFO for interthread operations. */
// (pat) The elements in the queue are type T*, and
// the Fifo class implements the underlying queue.
// The default is class PointerFIFO, which does not place any restrictions on the type of T,
// and is implemented by allocating auxilliary structures for the queue,
// or SingleLinkedList, which implements the queue using an internal pointer in type T,
// which must implement the functional interface of class SingleLinkListNode,
// namely: functions T*next() and void setNext(T*).
#if UNUSED
//template <class T, class Fifo=PointerFIFO> class InterthreadQueue {
//
// protected:
//
// Fifo mQ;
// mutable Mutex mLock;
// mutable Signal mWriteSignal;
//
// public:
//
// /** Delete contents. */
// void clear()
// {
// ScopedLock lock(mLock);
// while (mQ.size()>0) delete (T*)mQ.get();
// }
//
// /** Empty the queue, but don't delete. */
// void flushNoDelete()
// {
// ScopedLock lock(mLock);
// while (mQ.size()>0) mQ.get();
// }
//
//
// ~InterthreadQueue()
// { clear(); }
//
//
// size_t size() const
// {
// ScopedLock lock(mLock);
// return mQ.size();
// }
//
// size_t totalSize() const // pat added
// {
// ScopedLock lock(mLock);
// return mQ.totalSize();
// }
//
// /**
// Blocking read.
// @return Pointer to object (will not be NULL).
// */
// T* read()
// {
// ScopedLock lock(mLock);
// T* retVal = (T*)mQ.get();
// while (retVal==NULL) {
// mWriteSignal.wait(mLock);
// retVal = (T*)mQ.get();
// }
// return retVal;
// }
//
// /** Non-blocking peek at the first element; returns NULL if empty. */
// T* front()
// {
// ScopedLock lock(mLock);
// return (T*) mQ.front();
// }
//
// /**
// Blocking read with a timeout.
// @param timeout The read timeout in ms.
// @return Pointer to object or NULL on timeout.
// */
// T* read(unsigned timeout)
// {
// if (timeout==0) return readNoBlock();
// Timeval waitTime(timeout);
// ScopedLock lock(mLock);
// while ((mQ.size()==0) && (!waitTime.passed()))
// mWriteSignal.wait(mLock,waitTime.remaining());
// T* retVal = (T*)mQ.get();
// return retVal;
// }
//
// /**
// Non-blocking read.
// @return Pointer to object or NULL if FIFO is empty.
// */
// T* readNoBlock()
// {
// ScopedLock lock(mLock);
// return (T*)mQ.get();
// }
//
// /** Non-blocking write. */
// void write(T* val)
// {
// ScopedLock lock(mLock);
// mQ.put(val);
// mWriteSignal.signal();
// }
//
// /** Non-block write to the front of the queue. */
// void write_front(T* val) // pat added
// {
// ScopedLock lock(mLock);
// mQ.push_front(val);
// mWriteSignal.signal();
// }
//};
#endif
// A list designed for pointers so we can use get methods that return NULL on error.
template<class T>
class PtrList : public std::list<T*> {
@ -365,7 +250,7 @@ template <class T, class Fifo=PtrList<T> > class InterthreadQueue {
T* front()
{
ScopedLock lock(*mLockPointer);
return (T*) mQ.front();
return (T*) (mQ.size() ? mQ.front() : NULL);
}
/**
@ -380,7 +265,7 @@ template <class T, class Fifo=PtrList<T> > class InterthreadQueue {
ScopedLock lock(*mLockPointer);
while (mQ.size()==0) {
long remaining = waitTime.remaining();
// (pat) How high to we expect the precision here to be? I dont think they are used a precision timers,
// (pat) How high do we expect the precision here to be? I dont think they used precision timers,
// so dont try to wait if the remainder is just a few msecs.
if (remaining < 2) { return NULL; }
mWriteSignalPointer->wait(*mLockPointer,remaining);
@ -496,7 +381,7 @@ template <class T> class InterthreadQueueWithWait {
// mWriteSignal.wait(mLock,waitTime.remaining());
while (mQ.size()==0) {
long remaining = waitTime.remaining();
// (pat) How high to we expect the precision here to be? I dont think they are used a precision timers,
// (pat) How high do we expect the precision here to be? I dont think they are used as precision timers,
// so dont try to wait if the remainder is just a few msecs.
if (remaining < 2) { return NULL; }
mWriteSignal.wait(mLock,remaining);
@ -521,9 +406,10 @@ template <class T> class InterthreadQueueWithWait {
/** Non-blocking write. */
void write(T* val)
{
// (pat) 8-14: Taking out the threading problem fix temporarily for David to use in the field.
ScopedLock lock(mLock);
mQ.put(val);
{
ScopedLock lock(mLock);
mQ.put(val);
}
mWriteSignal.signal();
}
@ -541,51 +427,44 @@ template <class T> class InterthreadQueueWithWait {
};
/** Thread-safe map of pointers to class D, keyed by class K. */
template <class K, class D > class InterthreadMap
// (pat) Same as an InterthreadMap but the mapped type is "D" instead of "D*";
// the only difference is that we cannot automatically delete the content on destruction (no clear method).
template <class K, class D > class InterthreadMap1
{
public:
typedef std::map<K,D*> Map; // (pat) It would be more generally useful if this were D instead of D*
typedef std::map<K,D> Map;
protected:
Map mMap;
mutable Mutex mLock;
//mutable Mutex mModificationLock; // (pat) Lock prevents deletion from the map while an iterator is active.
Signal mWriteSignal;
public:
// User can over-ride this method if they want to delete type D elements.
virtual void vdelete(D) {}
void clear()
{
// Delete everything in the map.
//ScopedLock lock1(mModificationLock); // Lock this first!
~InterthreadMap1() {
ScopedLock lock(mLock);
typename Map::iterator iter = mMap.begin();
while (iter != mMap.end()) {
delete iter->second;
vdelete(iter->second);
++iter;
}
mMap.clear();
}
~InterthreadMap() { clear(); }
/**
Non-blocking write. WARNING: This deletes any pre-existing element!
@param key The index to write to.
@param wData Pointer to data, not to be deleted until removed from the map.
*/
void write(const K &key, D * wData)
void write(const K &key, D wData)
{
//ScopedLock lock1(mModificationLock); // Lock this first!
ScopedLock lock(mLock);
typename Map::iterator iter = mMap.find(key);
if (iter!=mMap.end()) {
delete iter->second;
vdelete(iter->second);
iter->second = wData;
} else {
mMap[key] = wData;
@ -598,14 +477,14 @@ public:
@param key Key to read from.
@return Pointer at key or NULL if key not found, to be deleted by caller.
*/
D* getNoBlock(const K& key, bool bRemove = true)
bool getNoBlock(const K& key, D &result, bool bRemove = true)
{
ScopedLock lock(mLock);
typename Map::iterator iter = mMap.find(key);
if (iter==mMap.end()) return NULL;
D* retVal = iter->second;
if (iter==mMap.end()) return false;
result = iter->second;
if (bRemove) { mMap.erase(iter); }
return retVal;
return true;
}
/**
@ -614,30 +493,20 @@ public:
@param timeout The blocking timeout in ms.
@return Pointer at key or NULL on timeout, to be deleted by caller.
*/
D* get(const K &key, unsigned timeout, bool bRemove = true)
bool get(const K &key, D &result, unsigned timeout, bool bRemove = true)
{
if (timeout==0) return getNoBlock(key,bRemove);
if (timeout==0) return getNoBlock(key,result,bRemove);
ScopedLock lock(mLock);
Timeval waitTime(timeout);
// (pat 8-2013) This commented out code suffered from a deadlock problem.
//typename Map::iterator iter = mMap.find(key);
//while ((iter==mMap.end()) && (!waitTime.passed())) {
// mWriteSignal.wait(mLock,waitTime.remaining());
// iter = mMap.find(key);
//}
//if (iter==mMap.end()) return NULL;
//D* retVal = iter->second;
//mMap.erase(iter);
//return retVal;
while (1) {
typename Map::iterator iter = mMap.find(key);
if (iter!=mMap.end()) {
D* retVal = iter->second;
result = iter->second;
if (bRemove) { mMap.erase(iter); }
return retVal;
return true;
}
long remaining = waitTime.remaining();
if (remaining < 2) { return NULL; }
if (remaining < 2) { return false; }
mWriteSignal.wait(mLock,remaining);
}
}
@ -646,8 +515,9 @@ public:
Blocking read with and element removal.
@param key The key to read from.
@return Pointer at key, to be deleted by caller.
This always returns true.
*/
D* get(const K &key, bool bRemove = true)
bool get(const K &key, D &result, bool bRemove = true)
{
ScopedLock lock(mLock);
typename Map::iterator iter = mMap.find(key);
@ -655,9 +525,9 @@ public:
mWriteSignal.wait(mLock);
iter = mMap.find(key);
}
D* retVal = iter->second;
result = iter->second;
if (bRemove) { mMap.erase(iter); }
return retVal;
return true;
}
@ -669,11 +539,13 @@ public:
*/
bool remove(const K &key )
{
//ScopedLock lock(mModificationLock);
D* val = getNoBlock(key);
if (!val) return false;
delete val;
return true;
D val;
if (getNoBlock(key,val,true)) {
vdelete(val);
return true;
} else {
return false;
}
}
@ -682,15 +554,11 @@ public:
@param key Key to read from.
@return Pointer at key or NULL if key not found.
*/
D* readNoBlock(const K& key) const
D readNoBlock(const K& key) const
{
return Unconst(this)->getNoBlock(key,false);
// (pat 8-2013) Lets use common code.
//D* retVal=NULL;
//ScopedLock lock(mLock);
//typename Map::const_iterator iter = mMap.find(key);
//if (iter!=mMap.end()) retVal = iter->second;
//return retVal;
D result = NULL;
Unconst(this)->getNoBlock(key,result,false);
return result;
}
/**
@ -699,21 +567,11 @@ public:
@param timeout The blocking timeout in ms.
@return Pointer at key or NULL on timeout.
*/
D* read(const K &key, unsigned timeout) const
D read(const K &key, unsigned timeout) const
{
return Unconst(this)->get(key,timeout,false);
// (pat 8-2013) This commented out code suffered from a deadlock problem.
//if (timeout==0) return readNoBlock(key);
//ScopedLock lock(mLock);
//Timeval waitTime(timeout);
//typename Map::const_iterator iter = mMap.find(key);
//while ((iter==mMap.end()) && (!waitTime.passed())) {
// mWriteSignal.wait(mLock,waitTime.remaining());
// iter = mMap.find(key);
//}
//if (iter==mMap.end()) return NULL;
//D* retVal = iter->second;
//return retVal;
D result = NULL;
Unconst(this)->get(key,result,timeout,false);
return result;
}
/**
@ -721,32 +579,18 @@ public:
@param key The key to read from.
@return Pointer at key.
*/
D* read(const K &key) const
D read(const K &key) const
{
return Unconst(this)->get(key,false);
// (pat 8-2013) Lets use common code.
//ScopedLock lock(mLock);
//typename Map::const_iterator iter = mMap.find(key);
//while (iter==mMap.end()) {
// mWriteSignal.wait(mLock);
// iter = mMap.find(key);
//}
//D* retVal = iter->second;
//return retVal;
D result;
Unconst(this)->get(key,result,false);
return result;
}
// pat added.
unsigned size() const { return mMap.size(); }
unsigned size() const { ScopedLock(mLock); return mMap.size(); }
//Mutex &getModificationLock() { return mModificationLock; }
//void iterLock() { mModificationLock.lock(); }
//void iterUnlock() { mModificationLock.unlock(); }
#if USE_SCOPED_ITERATORS
typedef ScopedIteratorTemplate<Map,InterthreadMap<K,D>,std::pair<const K,D*> > ScopedIterator;
#endif
// WARNING: These iterators are not intrinsically thread safe.
// Caller must use ScopiedIterator or the modification lock or enclose the entire iteration in some higher level lock.
// Caller must use ScopedIterator or the modification lock or enclose the entire iteration in some higher level lock.
Mutex &qGetLock() { return mLock; }
typedef typename Map::iterator iterator;
typename Map::iterator begin() { return mMap.begin(); }
@ -755,11 +599,22 @@ public:
// (pat) The original InterthreadMap works only for pointers; now it is derived from the more general version above.
/** Thread-safe map of pointers to class D, keyed by class K. */
template <class K, class D > class InterthreadMap : public InterthreadMap1<K,D*>
{
void vdelete(D* foo) { delete foo; }
};
/** This class is used to provide pointer-based comparison in priority_queues. */
// The priority_queue sorts the largest element to the 'top' of the priority_queue, which is the back of the underlying vector.
template <class T> class PointerCompare {
public:
@ -776,7 +631,8 @@ template <class T> class PointerCompare {
Priority queue for interthread operations.
Passes pointers to objects.
*/
template <class T, class C = std::vector<T*>, class Cmp = PointerCompare<T> > class InterthreadPriorityQueue {
template <class T, class C = std::vector<T*>, class Cmp = PointerCompare<T> > class InterthreadPriorityQueue
{
protected:
@ -784,6 +640,14 @@ template <class T, class C = std::vector<T*>, class Cmp = PointerCompare<T> > cl
mutable Mutex mLock;
mutable Signal mWriteSignal;
// Assumes caller holds the lock.
T*ipqGet() {
if (!mQ.size()) { return NULL; }
T*result = mQ.top();
mQ.pop();
return result;
}
public:
@ -815,31 +679,45 @@ template <class T, class C = std::vector<T*>, class Cmp = PointerCompare<T> > cl
T* readNoBlock()
{
ScopedLock lock(mLock);
T* retVal = NULL;
if (mQ.size()!=0) {
retVal = mQ.top();
mQ.pop();
}
return retVal;
return ipqGet();
}
/** Blocking read. */
T* read()
{
ScopedLock lock(mLock);
T* retVal;
while (mQ.size()==0) mWriteSignal.wait(mLock);
retVal = mQ.top();
mQ.pop();
return retVal;
return ipqGet();
}
T* read(unsigned timeout)
{
if (timeout==0) return readNoBlock();
Timeval waitTime(timeout);
ScopedLock lock(mLock);
while (mQ.size()==0) {
long remaining = waitTime.remaining();
// (pat) How high do we expect the precision here to be? I dont think they used precision timers,
// so dont try to wait if the remainder is just a few msecs.
if (remaining < 2) { return NULL; }
mWriteSignal.wait(mLock,remaining);
}
return ipqGet();
}
// pat added 4-2014. Return but do not pop the top element, if any, or NULL.
T* peek()
{
ScopedLock lock(mLock);
return mQ.size() ? mQ.top() : NULL;
}
/** Non-blocking write. */
void write(T* val)
{
// (pat) 8-14: Taking out the threading problem fix temporarily for David to use in the field.
ScopedLock lock(mLock);
mQ.push(val);
{ ScopedLock lock(mLock);
mQ.push(val);
}
mWriteSignal.signal();
}

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.

View File

@ -1,7 +1,8 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribuion.
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribution.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.

View File

@ -1,6 +1,7 @@
/*
* Copyright 2009 Free Software Foundation, Inc.
* Copyright 2010 Kestrel Signal Processing, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.

View File

@ -262,7 +262,6 @@ ostringstream& Log::get()
}
// Allow applications to also pass in a filename. Filename should come from the database
void gLogInitWithFile(const char* name, const char* level, int facility, char * LogFilePath)
{
@ -301,9 +300,9 @@ void gLogInit(const char* name, const char* level, int facility)
gPid = getpid();
// Pat added, tired of the syslog facility.
// Both the transceiver and OpenBTS use this same facility, but only OpenBTS/OpenNodeB may use this log file:
// Both the transceiver and OpenBTS use this same Logger class, but only RMSC/OpenBTS/OpenNodeB may use this log file:
string str = gConfig.getStr("Log.File");
if (gLogToFile==0 && str.length() && 0==strncmp(gCmdName,"Open",4)) {
if (gLogToFile==0 && str.length() && (0==strncmp(gCmdName,"Open",4) || 0==strncmp(gCmdName,"RMSC",4))) {
const char *fn = str.c_str();
if (fn && *fn && strlen(fn)>3) { // strlen because a garbage char is getting in sometimes.
gLogToFile = fopen(fn,"w"); // New log file each time we start.
@ -365,6 +364,7 @@ void LogGroup::LogGroupInit()
for (unsigned g = 0; g < _NumberOfLogGroups; g++) {
mDebugLevel[g] = 0;
mWatchLevel[g] = 0;
}
#if 0
@ -377,26 +377,39 @@ void LogGroup::LogGroupInit()
#endif
}
static const char *LogGroupPrefix = "Log.Group.";
static const char*getNonEmptyStrIfDefined(string param)
{
if (! gConfig.defines(param)) { return NULL; }
string result = gConfig.getStr(param);
// (pat) The "unconfig" command does not remove the value, it just gives it an empty value, so check for that.
return result.size() ? result.c_str() : NULL;
}
// Set all the Log.Group debug levels based on database settings
void LogGroup::setAll()
{
LOG(DEBUG);
string prefix = string(LogGroupPrefix);
string groupprefix = string("Log.Group.");
string watchprefix = string("Log.Watch.");
for (unsigned g = 0; g < _NumberOfLogGroups; g++) {
{
string param = groupprefix + mGroupNames[g];
int level = 0;
string param = prefix + mGroupNames[g];
if (gConfig.defines(param)) {
string levelName = gConfig.getStr(param);
// (pat) The "unconfig" command does not remove the value, it just gives it an empty value, so check for that.
if (levelName.size()) {
//LOG(DEBUG) << "Setting "<<LOGVAR(param)<<LOGVAR(levelName);
level = lookupLevel2(param,levelName);
}
if (const char*levelName = getNonEmptyStrIfDefined(param)) {
level = lookupLevel2(param,levelName);
}
mDebugLevel[g] = level;
}
{
string watchparam = watchprefix + mGroupNames[g];
int watchlevel = 0;
if (const char*levelName = getNonEmptyStrIfDefined(watchparam)) {
watchlevel = lookupLevel2(watchparam,levelName);
}
mWatchLevel[g] = watchlevel;
}
}
}

View File

@ -62,7 +62,9 @@ extern pid_t gPid;
//#define CHECK_GROUP_LOG_LEVEL(groupname,loglevel) gCheckGroupLogLevel(#groupname,loglevel)
//#define IS_LOG_LEVEL(wLevel) (CHECK_GROUP_LOG_LEVEL(LOG_GROUP,LOG_##wLevel) || gGetLoggingLevel(__FILE__)>=LOG_##wLevel)
#define IS_LOG_LEVEL(wLevel) (gCheckGroupLogLevel(LOG_GROUP,LOG_##wLevel) || gGetLoggingLevel(__FILE__)>=LOG_##wLevel)
#define IS_WATCH_LEVEL(wLevel) gCheckGroupWatchLevel(LOG_GROUP,LOG_##wLevel)
#else
#define IS_WATCH_LEVEL(wLevel) (gGetLoggingLevel(__FILE__)>=LOG_##wLevel)
#define IS_LOG_LEVEL(wLevel) (gGetLoggingLevel(__FILE__)>=LOG_##wLevel)
#endif
@ -89,10 +91,11 @@ extern pid_t gPid;
#define LOGVAR2(name,val) " " << name << "=" << (val)
#define LOGVAR(var) (" " #var "=") << var
#define LOGVARM(var) " " << &#var[1] << "=" << var // Strip the first char ("m") off the var name when printing.
#define LOGVARP(var) (" " #var "=(") << var <<")" // Put value in parens; used for classes.
#define LOGVARP2(name,val) (" " name "=(") << val <<")" // Put value in parens; used for classes.
#define LOGVARP(var) LOGVARP2(#var,var) // Put value in parens; used for classes.
// (pat) 3-2014: Use (unsigned long) for LOGHEX so it can be used for pointers with 64-bit compiler. What a choke.
#define LOGHEX(var) (" " #var "=0x") << hex << ((unsigned long)var) << dec
#define LOGHEX2(name,val) " " << name << "=0x" << hex << ((unsigned long)(val)) << dec
#define LOGHEX(var) (" " #var "=0x") << std::hex << ((unsigned long long)var) << std::dec
#define LOGHEX2(name,val) " " << name << "=0x" << std::hex << ((unsigned long)(val)) << std::dec
// These are kind of cheesy, but you can use for bitvector
#define LOGBV2(name,val) " " << name << "=(" << val<<" size:"<<val.size()<<")"
#define LOGBV(bv) LOGBV2(#bv,bv)
@ -107,9 +110,9 @@ extern pid_t gPid;
// (pat) The WATCH and WATCHF macros print only to the console. Pat uses them for debugging.
// The WATCHINFO macro prints an INFO level message that is also printed to the console if the log level is DEBUG.
// Beware that the arguments are evaluated multiple times.
#define WATCHF(...) if (IS_LOG_LEVEL(DEBUG)) { printf("%s ",timestr(7).c_str()); printf(__VA_ARGS__); LOG(DEBUG)<<format(__VA_ARGS__); }
#define WATCH(...) if (IS_LOG_LEVEL(DEBUG)) { std::cout << timestr(7)<<" "<<__VA_ARGS__ << endl; LOG(DEBUG)<<__VA_ARGS__; }
#define WATCHINFO(...) { if (IS_LOG_LEVEL(DEBUG)) { std::cout << timestr(7)<<" "<<__VA_ARGS__ << endl; } LOG(INFO)<<__VA_ARGS__; }
#define WATCHF(...) { LOG(DEBUG)<<format(__VA_ARGS__); if (IS_WATCH_LEVEL(DEBUG)) {printf("%s ",timestr(7).c_str()); printf(__VA_ARGS__);} }
#define WATCH(...) { LOG(DEBUG)<<__VA_ARGS__; if (IS_WATCH_LEVEL(DEBUG)) {std::cout << timestr(7)<<" "<<__VA_ARGS__ << endl;} }
#define WATCHINFO(...) { LOG(INFO)<<__VA_ARGS__; if (IS_WATCH_LEVEL(INFO)) {std::cout << timestr(7)<<" "<<__VA_ARGS__ << endl;} }
//#include "Threads.h" // must be after defines above, if these files are to be allowed to use LOG()
@ -168,6 +171,7 @@ class LogGroup {
void setAll(); // Update mDebugLevel from the Log.Group.... config database options.
int8_t mDebugLevel[_NumberOfLogGroups]; // use int in case a -1 value gets in here.
int8_t mWatchLevel[_NumberOfLogGroups]; // use int in case a -1 value gets in here.
LogGroup();
void LogGroupInit();
private:
@ -182,6 +186,11 @@ static __inline__ bool gCheckGroupLogLevel(LogGroup::Group group, unsigned level
//_LOG(DEBUG) << LOGVAR(group)<<LOGVAR(level)<<LOGVAR2("stashed",(unsigned) gLogGroup.mDebugLevel[group]);
return gLogGroup.mDebugLevel[group] >= (int) level;
}
static __inline__ bool gCheckGroupWatchLevel(LogGroup::Group group, unsigned level) {
assert(group < LogGroup::_NumberOfLogGroups);
//_LOG(DEBUG) << LOGVAR(group)<<LOGVAR(level)<<LOGVAR2("stashed",(unsigned) gLogGroup.mDebugLevel[group]);
return gLogGroup.mWatchLevel[group] >= (int) level;
}

View File

@ -1,6 +1,6 @@
#
# Copyright 2008, 2009 Free Software Foundation, Inc.
# Copyright 2011, 2012 Range Networks, Inc.
# Copyright 2011, 2012, 2014 Range Networks, Inc.
#
# This software is distributed under the terms of the GNU Public License.
# See the COPYING file in the main directory for details.
@ -22,7 +22,7 @@
include $(top_srcdir)/Makefile.common
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES)
AM_CXXFLAGS = -Wall -O3 -g -ldl -lpthread
AM_CXXFLAGS = -Wall -O3 -g -ldl -lpthread -lsqlite3
EXTRA_DIST = \
example.config \
@ -47,6 +47,8 @@ libcommon_la_SOURCES = \
Utils.cpp
noinst_PROGRAMS = \
UtilsTest \
ThreadTest \
BitVectorTest \
InterthreadTest \
SelfDetectTest \
@ -83,6 +85,9 @@ noinst_HEADERS = \
Logger.h \
sqlite3util.h
ThreadTest_SOURCES = ThreadTest.cpp
ThreadTest_LDADD = libcommon.la $(SQLITE_LA)
URLEncodeTest_SOURCES = URLEncodeTest.cpp
URLEncodeTest_LDADD = libcommon.la
@ -123,6 +128,9 @@ LogTest_LDADD = libcommon.la $(SQLITE_LA)
F16Test_SOURCES = F16Test.cpp
UtilsTest_SOURCES = UtilsTest.cpp
UtilsTest_LDADD = libcommon.la
MOSTLYCLEANFILES += testSource testDestination

View File

@ -1,10 +1,10 @@
/*
* Copyright 2011 Range Networks, Inc.
* Copyright 2011, 2014 Range Networks, Inc.
* All Rights Reserved.
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribuion.
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

16
README Normal file
View File

@ -0,0 +1,16 @@
This directory contains common-use classes, most of which are not specific to GSM.
```
Vector A vector class (NOT std::vector<>) that supports aliased subvectors. Not resizable.
BitVector Bit-indexable vectors based on Vector.
Interthread A set of C++ wrappers for pthread facilities.
Sockets A set of C++ wrappers for Unix sockets.
Timeval A C++ wraper for struct timeval.
LinkLists Classes for simple linked lists of pointers.
Logger A logging interface based on syslogd.
Configuration A key-value configuration table.
Regexp A C++ wrapper on stdlib regular expressions.
```
Do "make tests" to build a series of unit tests for these classes.

View File

@ -1,15 +0,0 @@
This directory contains common-use classes, most of which are not specific to GSM.
Vector A vector class (NOT std::vector<>) that supports
aliased subvectors. Not resizable.
BitVector Bit-indexable vectors based on Vector.
Interthread A set of C++ wrappers for pthread facilities.
Sockets A set of C++ wrappers for Unix sockets.
Timeval A C++ wraper for struct timeval.
LinkLists Classes for simple linked lists of pointers.
Logger A logging interface based on syslogd.
Configuration A key-value configuration table.
Regexp A C++ wrapper on stdlib regular expressions.
Do "make tests" to build a series of unit tests for these classes.

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.

View File

@ -1,6 +1,6 @@
/**@file Module for performance-reporting mechanisms. */
/*
* Copyright 2012, 2013 Range Networks, Inc.
* Copyright 2012, 2013, 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.

View File

@ -1,6 +1,6 @@
/**@file Module for performance-reporting mechanisms. */
/*
* Copyright 2012, 2013 Range Networks, Inc.
* Copyright 2012, 2013, 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
@ -98,6 +98,7 @@ class ReportingTable {
/** Periodically triggers ReportingTable::commit(). */
void* reportingBatchCommitter(void*);
extern ReportingTable gReports;
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012 Range Networks, Inc.
* Copyright 2012, 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.

View File

@ -1,10 +1,10 @@
/*
* Copyright 2011 Range Networks, Inc.
* Copyright 2011, 2014 Range Networks, Inc.
* All Rights Reserved.
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribuion.
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

View File

@ -1,6 +1,6 @@
/**@file Module for preventing two instances of a program from running. */
/*
* Copyright 2013 Range Networks, Inc.
* Copyright 2013, 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
@ -96,6 +96,7 @@ void SelfDetect::RegisterProgram(const char *argv0)
// openbts: NOTICE 3031243584 05:03:50.4 OpenBTS.cpp:165:startTransceiver: starting transceiver ./transceiver w/ 1 ARFCNs and Args:
// openbts: NOTICE 3073816320 05:03:50.4 SelfDetect.cpp:98:Exit: *** Terminating ./OpenBTS
// openbts: NOTICE 3073816320 05:03:50.4 SelfDetect.cpp:105:Exit: *** Removing pid file /var/run/OpenBTS.pid
case SIGCONT:
case SIGCHLD:
break;
default:

View File

@ -1,10 +1,10 @@
/*
* Copyright 2013 Range Networks, Inc.
* Copyright 2013, 2014 Range Networks, Inc.
* All Rights Reserved.
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribuion.
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2013 Range Networks, Inc.
* Copyright 2013, 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008, 2010, 2014 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008, 2010 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.

140
ThreadTest.cpp Normal file
View File

@ -0,0 +1,140 @@
/*
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "Threads.h"
#include "Utils.h"
using namespace Utils;
// We must have a gConfig now to include BitVector.
#include "Configuration.h"
ConfigurationTable gConfig;
// pat 6-2014: Check how many threads we can create.
#define NUM_THREADS 100000
// Overwrite Thread::start() so we can see what is going on.
class ThreadTest {
protected:
pthread_t mThread;
pthread_attr_t mAttrib;
// FIXME -- Can this be reduced now?
size_t mStackSize;
public:
/** Create a thread in a non-running state. */
ThreadTest(size_t wStackSize = (65536*4)):mThread((pthread_t)0) {
pthread_attr_init(&mAttrib); // (pat) moved this here.
mStackSize=wStackSize;
}
/**
Destroy the Thread.
It should be stopped and joined.
*/
// (pat) If the Thread is destroyed without being started, then mAttrib is undefined. Oops.
~ThreadTest() { pthread_attr_destroy(&mAttrib); }
/** Start the thread on a task. */
void start( void*(*task)(void*), void *arg) {
assert(mThread==((pthread_t)0));
int res;
res = pthread_attr_setstacksize(&mAttrib, mStackSize);
if (res) { fprintf(stderr,"pthread_setstacksize(%u) failed: error=%d %s\n",mStackSize,res,strerror(res)); }
assert(!res);
//res = pthread_create(&mThread, &mAttrib, &thread_main, p);
res = pthread_create(&mThread, &mAttrib, task, arg);
if (res) { LOG(ALERT) << "pthread_create failed, error:" <<strerror(res); }
//if (res) { fprintf(stderr,"pthread_create failed: error=%d %s\n",res,strerror(res)); }
assert(!res);
}
/** Join a thread that will stop on its own. */
void join() { int s = pthread_join(mThread,NULL); assert(!s); mThread = 0; }
};
ThreadTest *threads[NUM_THREADS];
int outputs[NUM_THREADS];
void *serviceLoop(void *arg)
{
int myid = *(int*)arg;
outputs[myid]++;
return NULL;
}
// The maximum number of threads is 32K, even though the RLIMIT_PROC is 65K. Dont know why.
int main(int argc, char **argv)
{
// Note: The Thread library sets the default stack size using pthread_attr_setstacksize
memset(outputs,0,sizeof(outputs));
// Check system limit.
printf("System thread limit:"); fflush(stdout);
system("cat /proc/sys/kernel/threads-max");
// Check rlimit.
struct rlimit limits;
if (0 != getrlimit(RLIMIT_NPROC,&limits)) {
perror("getrlimit failed");
exit(2);
}
printf("RLIMIT_PROC = %lu / %lu\n",limits.rlim_cur,limits.rlim_max);
double start = timef();
double chunktime = timef();
long stacksize = 65000;
long long totalmem = 0;
for (int i = 0; i < NUM_THREADS; i++) {
// Minimum stack size is evidently 16K.
// On my 8G system: With default stack size (65K*4) I can only create 7000 threads (2G)
//threads[i] = new ThreadTest(17000);
threads[i] = new ThreadTest(stacksize);
totalmem += stacksize;
threads[i]->start( (void*(*)(void*)) serviceLoop,&i);
if (i && i % 1000 == 0) {
printf("%d\n",i); fflush(stdout);
printf("Created %d (%d total) threads in %.2g seconds mem=%lldM\n",1000,i,timef()-chunktime,totalmem/1000000);
chunktime = timef();
}
}
double elapsed = timef() - start;
printf("Created %d threads in %.2g seconds\n",NUM_THREADS,elapsed);
}

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008, 2014 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.
@ -256,9 +257,17 @@ void Thread::start(void *(*task)(void*), void *arg)
p->task = task;
p->arg = arg;
res = pthread_create(&mThread, &mAttrib, &thread_main, p);
// (pat) Note: the error is returned and is not placed in errno.
if (res) { LOG(ALERT) << "pthread_create failed, error:" <<strerror(res); }
assert(!res);
}
void Thread::start2(void *(*task)(void*), void *arg, int stacksize)
{
mStackSize = stacksize;
start(task,arg);
}
// vim: ts=4 sw=4

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008, 2011, 2014 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
@ -241,6 +242,7 @@ class Thread {
/** Start the thread on a task. */
void start(void *(*task)(void*), void *arg);
void start2(void *(*task)(void*), void *arg, int stacksize);
/** Join a thread that will stop on its own. */
void join() { int s = pthread_join(mThread,NULL); assert(!s); mThread = 0; }

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.

View File

@ -1,4 +1,26 @@
/* Copyright 2011, Range Networks, Inc. */
/*
* Copyright 2011, 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <URLEncode.h>
#include <string>

View File

@ -1,5 +1,6 @@
/*
* Copyright 2011 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.

View File

@ -1,3 +1,26 @@
/*
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "URLEncode.h"
#include <string>

View File

@ -4,7 +4,7 @@
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribuion.
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

View File

@ -4,7 +4,7 @@
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribuion.
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
@ -41,8 +41,10 @@ int RefCntBase::decRefCnt()
} // Must not keep locked during the delete, since the Mutex itself will be deleted.
// The typeid(this).name() doesnt add anything because it is just the name of the class here, not the derived class.
LOG(DEBUG) <<" "<<(void*)this <<" " <<LOGVAR2("refcnt after",saveRefCnt);
//printf("decRefCnt %p mRefCnt=%d\n",this,mRefCnt);
// The refcnt is created with a value of zero, so when the last one is deleted it will come in with a value of zero.
if (saveRefCnt <= 0) {
//printf("decRefCnt %p deleting refcnted pointer\n",this);
LOG(DEBUG) << "deleting refcnted pointer "<<typeid(this).name();
delete this;
}
@ -51,6 +53,7 @@ int RefCntBase::decRefCnt()
void RefCntBase::incRefCnt()
{
ScopedLock lock(mRefMutex);
//printf("incRefCnt %p before=%d\n",this,mRefCnt);
LOG(DEBUG) <<" "<<(void*)this <<" " <<LOGVAR2("refcnt before",mRefCnt);
assert(mRefCnt >= 0);
mRefCnt++;
@ -555,4 +558,19 @@ string uintToString(uint32_t x)
os << hex << x;
return os.str();
}
// Return the first n lines of a string.
string firstlines(string msgstr, int n) { // n must be >=1
size_t pos = msgstr.find('\n');
if (pos < msgstr.size()) pos++;
//printf("firstlines pos=%d\n",(int)pos);
while (--n > 0 && pos < msgstr.size()) {
pos = msgstr.find('\n',pos);
//printf("firstlines n=%d pos=%d\n",n,(int)pos);
if (pos < msgstr.size()) pos++;
}
//printf("firstlines return n=%d pos=%d\n",n,(int)pos);
return msgstr.substr(0,pos);
}
};

19
Utils.h
View File

@ -4,7 +4,7 @@
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribuion.
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
@ -194,9 +194,11 @@ extern void stringToUint(string strRAND, uint64_t *hRAND, uint64_t *lRAND);
extern string uintToString(uint64_t h, uint64_t l);
extern string uintToString(uint32_t x);
//template <class Type> class RefCntPointer;
// The class is created with a RefCnt of 0. The caller must assign the constructed result to a pointer
// of type RefCntPointer. When the last RefCntPointer is freed, this struct is too.
class RefCntBase {
template <class Type> friend class RefCntPointer;
Mutex mRefMutex;
mutable short mRefCnt; // signed, not unsigned!
int setRefCnt(int val) { return mRefCnt = val; }
@ -206,14 +208,20 @@ class RefCntBase {
RefCntBase(RefCntBase &) { assert(0); }
RefCntBase(const RefCntBase &) { assert(0); }
RefCntBase operator=(RefCntBase &) {assert(0); mRefCnt = 0; return *this; }
int decRefCnt(); // Only RefCntPointer is permitted to use incRefCnt and decRefCnt.
void incRefCnt();
public:
virtual ~RefCntBase();
RefCntBase() : mRefCnt(0) {}
int getRefCnt() const { return mRefCnt; }
int decRefCnt();
void incRefCnt();
};
// This is basically the same as a C++11 shared_ptr, but we cannot use C++ 11 yet.
// The basic idea is that once you put an object into a RefCntPointer, then destruction of that
// object is controlled by and assured by RefCntPointer using reference counts; when the last
// RefCntPointer referring to the object is destroyed, the object is too.
// You can use RefCntPointer<object> similarly to an object* for most data-access purposes.
// The auto-destruction should be optional - there should be a version that just maintains reference counts for you.
// Semantics:
// SomeDescendentOfRefCntBase foo;
// RefCntPointer<SomeDescendentOfRefCntBase> ptrToFoo;
@ -244,7 +252,8 @@ class RefCntPointer {
// The operator=(Type*) is called if the argument is NULL, so we dont need int.
//Type* operator=(int value) { assert(value == 0); rcDec(); rcPointer = 0; return rcPointer; }
// We increment before decrement if possible so that a = a; does not crash.
RefCntPointer<Type>& operator=(RefCntPointer &other) { other.rcInc(); rcDec(); rcPointer = other.rcPointer; return *this; }
RefCntPointer<Type>& operator=(RefCntPointer other) { other.rcInc(); rcDec(); rcPointer = other.rcPointer; return *this; }
// The old is the previous value of this pointer. We do not decrement the refcnt in the other that we are taking charge of.
RefCntPointer<Type>& operator=(Type* other) { Type *old = rcPointer; rcPointer = other; rcInc(); if (old) {old->decRefCnt();} return *this; }
bool operator==(const RefCntPointer &other) const { return rcPointer == other.rcPointer; }
bool operator==(const Type* other) const { return rcPointer == other; }
@ -265,6 +274,8 @@ class RefCntPointer {
bool isNULL() const { return self() == NULL; }
};
extern string firstlines(string msgstr, int n=2);
}; // namespace
using namespace Utils;

71
UtilsTest.cpp Normal file
View File

@ -0,0 +1,71 @@
#include <string>
#include <stdio.h>
#include "Configuration.h"
#include "Utils.h"
ConfigurationTable gConfig; // Needed for logger.
using namespace std;
struct foo : public RefCntBase {
string id;
foo(string wid) : id(wid) { printf("create foo %s %p\n",id.c_str(),this); }
~foo() { printf("delete foo %s %p\n",id.c_str(),this); }
};
typedef RefCntPointer<foo> fooref;
RefCntPointer<foo> refize(foo*f)
{
fooref ref(f);
return ref;
}
void test1() // Basic test.
{
foo *b = new foo("b");
fooref bref(b);
bref.free(); // Should free b.
}
void test2() // assignment
{
foo *c = new foo("c");
fooref cref = refize(c);
foo *d = new foo("d");
fooref dref = d;
fooref dref2 = d;
dref = c;
printf("here\n");
// d and c deleted when test2 returns.
}
void test3() // assignment
{
foo *c = new foo("c");
fooref cref = refize(c);
foo *d = new foo("d");
fooref dref = d;
dref = c;
printf("here\n");
// d and c deleted when test2 returns.
}
void refcntpointertest()
{
test1();
test2();
test3();
}
int main(int argc, char **argv)
{
printf("Utils Test starting.\n");
refcntpointertest();
}

View File

@ -4,7 +4,7 @@
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribuion.
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

View File

@ -1,6 +1,7 @@
/**@file Simplified Vector template with aliases. */
/*
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008 Free Software Foundation, Inc.
* Copyright 2014 Range Networks, Inc.
*
*
* This software is distributed under the terms of the GNU Affero Public License.

View File

@ -1,10 +1,29 @@
/*
* Copyright 2010 Kestrel Signal Processing, Inc.
* All rights reserved.
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sqlite3.h"
#include "sqlite3util.h"
#include "Logger.h"
@ -342,17 +361,21 @@ bool sqlite3_single_lookup(sqlite3* DB, const char* tableName,
bool sqlite_set_attr(sqlite3*db,const char *attr_name,const char*attr_value)
{
if (! sqlite3_command(db,"CREATE TABLE IF NOT EXISTS ATTR_TABLE (ATTR_NAME TEXT PRIMARY KEY, ATTR_VALUE TEXT)")) {
const char *fn = sqlite3_db_filename(db,"main");
// (mike) 2014-06: to free ourselves of the in-tree sqlite3 code, the system library must be used.
// However, sqlite3_db_filename is not available in Ubuntu 12.04. Removing dependence for now.
//const char *fn = sqlite3_db_filename(db,"main");
// (pat) You must not call LOG() from this file because it causes infinite recursion through gGetLoggingLevel and ConfigurationTable::lookup
_LOG(WARNING) << "Could not create ATTR_TABLE in database file " <<(fn?fn:"");
_LOG(WARNING) << "Could not create ATTR_TABLE in database file ";// <<(fn?fn:"");
return false;
}
char query[100];
snprintf(query,100,"REPLACE INTO ATTR_TABLE (ATTR_NAME,ATTR_VALUE) VALUES('%s','%s')",attr_name,attr_value);
if (! sqlite3_command(db,query)) {
const char *fn = sqlite3_db_filename(db,"main");
// (mike) 2014-06: to free ourselves of the in-tree sqlite3 code, the system library must be used.
// However, sqlite3_db_filename is not available in Ubuntu 12.04. Removing dependence for now.
//const char *fn = sqlite3_db_filename(db,"main");
// (pat) You must not call LOG() from this file because it causes infinite recursion through gGetLoggingLevel and ConfigurationTable::lookup
_LOG(WARNING) << "Could not set attribute: "<<attr_name<<"="<<attr_value <<" in database "<<(fn?fn:"");
_LOG(WARNING) << "Could not set attribute: "<<attr_name<<"="<<attr_value <<" in database ";//<<(fn?fn:"");
return false;
}
return true;

View File

@ -1,3 +1,27 @@
/*
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SQLITE3UTIL_H
#define SQLITE3UTIL_H