merge 5.0 preview from commercial
This commit is contained in:
parent
00d91e90bb
commit
88311c0670
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
|
* 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.
|
* 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)
|
ostream& operator<<(ostream& os, const SoftVector& sv)
|
||||||
{
|
{
|
||||||
for (size_t i=0; i<sv.size(); i++) {
|
for (size_t i=0; i<sv.size(); i++) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
|
* 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.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
@ -123,7 +124,7 @@ class BitVector : public VectorBase<char>
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
/**@name Casts of Vector constructors. */
|
/**@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.
|
// The one and only copy-constructor.
|
||||||
BitVector(const BitVector&other) : VectorBase<char>() {
|
BitVector(const BitVector&other) : VectorBase<char>() {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 Free Software Foundation, Inc.
|
* Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
* Copyright 2010 Kestrel Signal Processing, Inc.
|
* Copyright 2010 Kestrel Signal Processing, Inc.
|
||||||
* Copyright 2011, 2012, 2014 Range Networks, Inc.
|
* Copyright 2011, 2012, 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
*
|
*
|
||||||
|
|
|
@ -371,33 +371,34 @@ class ConfigurationKey {
|
||||||
BOOLEAN,
|
BOOLEAN,
|
||||||
CHOICE_OPT,
|
CHOICE_OPT,
|
||||||
CHOICE,
|
CHOICE,
|
||||||
CIDR_OPT,
|
CIDR_OPT, // (pat) IP Route, eg: "xxx.xxx.xxx.xxx/yy"
|
||||||
CIDR,
|
CIDR,
|
||||||
FILEPATH_OPT,
|
FILEPATH_OPT,
|
||||||
FILEPATH,
|
FILEPATH,
|
||||||
HOSTANDPORT_OPT,
|
HOSTANDPORT_OPT,
|
||||||
HOSTANDPORT,
|
HOSTANDPORT, // (pat) hostname is allowed.
|
||||||
IPADDRESS_OPT,
|
IPADDRESS_OPT,
|
||||||
IPADDRESS,
|
IPADDRESS, // (pat) IP Address but hostnames not allowed.
|
||||||
IPANDPORT,
|
IPANDPORT,
|
||||||
MIPADDRESS_OPT,
|
MIPADDRESS_OPT,
|
||||||
MIPADDRESS,
|
MIPADDRESS, // (pat) List of IP addresses + optional ports, used only for the Neighbors config option.
|
||||||
PORT_OPT,
|
PORT_OPT,
|
||||||
PORT,
|
PORT, // (pat) An IP port.
|
||||||
REGEX_OPT,
|
REGEX_OPT,
|
||||||
REGEX,
|
REGEX,
|
||||||
STRING_OPT,
|
STRING_OPT,
|
||||||
STRING,
|
STRING,
|
||||||
VALRANGE // (pat) string format is: <min_value> ':' <max_value> [ '(' <step> ')' ]
|
VALRANGE // (pat) string format is: <min_value> ':' <max_value> [ '(' <step> ')' ]
|
||||||
// step is not currently enforced.
|
// step is not currently enforced.
|
||||||
|
// To allow floating point add a decimal point to the range, eg: "0.0:10.0"
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Scope
|
enum Scope
|
||||||
{
|
{
|
||||||
GLOBALLYUNIQUE = 1,
|
GLOBALLYUNIQUE = 1, // (pat) value must be unique on all nodes.
|
||||||
GLOBALLYSAME = 2,
|
GLOBALLYSAME = 2, // (pat) value must be the same on all nodes.
|
||||||
NEIGHBORSUNIQUE = 4,
|
NEIGHBORSUNIQUE = 4, // (pat) value must be unique on all neighbors
|
||||||
NEIGHBORSSAME = 8,
|
NEIGHBORSSAME = 8, // (pat) value must be the same on all neighbors
|
||||||
NODESPECIFIC = 16
|
NODESPECIFIC = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2009, 2010 Free Software Foundation, Inc.
|
* Copyright 2009, 2010 Free Software Foundation, Inc.
|
||||||
* Copyright 2010 Kestrel Signal Processing, 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.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
|
24
Defines.h
24
Defines.h
|
@ -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.
|
// Pat added this file.
|
||||||
// We need an include file that is included before any other include files.
|
// 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_
|
// Might I suggest that Range Networks specific global #defines be prefixed with RN_
|
||||||
|
|
2
Exit.h
2
Exit.h
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* This software is distributed under multiple licenses;
|
* This software is distributed under multiple licenses;
|
||||||
* see the COPYING file in the main directory for licensing
|
* 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.
|
* This use of this software may be subject to additional restrictions.
|
||||||
* See the LEGAL file in the main directory for details.
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
1
F16.h
1
F16.h
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2009 Free Software Foundation, Inc.
|
* Copyright 2009 Free Software Foundation, Inc.
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2009 Free Software Foundation, Inc.
|
* Copyright 2009 Free Software Foundation, Inc.
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
|
322
Interthread.h
322
Interthread.h
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008, 2011 Free Software Foundation, Inc.
|
* 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.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* 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.
|
// A list designed for pointers so we can use get methods that return NULL on error.
|
||||||
template<class T>
|
template<class T>
|
||||||
class PtrList : public std::list<T*> {
|
class PtrList : public std::list<T*> {
|
||||||
|
@ -365,7 +250,7 @@ template <class T, class Fifo=PtrList<T> > class InterthreadQueue {
|
||||||
T* front()
|
T* front()
|
||||||
{
|
{
|
||||||
ScopedLock lock(*mLockPointer);
|
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);
|
ScopedLock lock(*mLockPointer);
|
||||||
while (mQ.size()==0) {
|
while (mQ.size()==0) {
|
||||||
long remaining = waitTime.remaining();
|
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.
|
// so dont try to wait if the remainder is just a few msecs.
|
||||||
if (remaining < 2) { return NULL; }
|
if (remaining < 2) { return NULL; }
|
||||||
mWriteSignalPointer->wait(*mLockPointer,remaining);
|
mWriteSignalPointer->wait(*mLockPointer,remaining);
|
||||||
|
@ -496,7 +381,7 @@ template <class T> class InterthreadQueueWithWait {
|
||||||
// mWriteSignal.wait(mLock,waitTime.remaining());
|
// mWriteSignal.wait(mLock,waitTime.remaining());
|
||||||
while (mQ.size()==0) {
|
while (mQ.size()==0) {
|
||||||
long remaining = waitTime.remaining();
|
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.
|
// so dont try to wait if the remainder is just a few msecs.
|
||||||
if (remaining < 2) { return NULL; }
|
if (remaining < 2) { return NULL; }
|
||||||
mWriteSignal.wait(mLock,remaining);
|
mWriteSignal.wait(mLock,remaining);
|
||||||
|
@ -521,9 +406,10 @@ template <class T> class InterthreadQueueWithWait {
|
||||||
/** Non-blocking write. */
|
/** Non-blocking write. */
|
||||||
void write(T* val)
|
void write(T* val)
|
||||||
{
|
{
|
||||||
// (pat) 8-14: Taking out the threading problem fix temporarily for David to use in the field.
|
{
|
||||||
ScopedLock lock(mLock);
|
ScopedLock lock(mLock);
|
||||||
mQ.put(val);
|
mQ.put(val);
|
||||||
|
}
|
||||||
mWriteSignal.signal();
|
mWriteSignal.signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,51 +427,44 @@ template <class T> class InterthreadQueueWithWait {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// (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
|
||||||
/** Thread-safe map of pointers to class D, keyed by class K. */
|
|
||||||
template <class K, class D > class InterthreadMap
|
|
||||||
{
|
{
|
||||||
public:
|
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:
|
protected:
|
||||||
|
|
||||||
Map mMap;
|
Map mMap;
|
||||||
mutable Mutex mLock;
|
mutable Mutex mLock;
|
||||||
//mutable Mutex mModificationLock; // (pat) Lock prevents deletion from the map while an iterator is active.
|
|
||||||
Signal mWriteSignal;
|
Signal mWriteSignal;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// User can over-ride this method if they want to delete type D elements.
|
||||||
|
virtual void vdelete(D) {}
|
||||||
|
|
||||||
void clear()
|
~InterthreadMap1() {
|
||||||
{
|
|
||||||
// Delete everything in the map.
|
|
||||||
//ScopedLock lock1(mModificationLock); // Lock this first!
|
|
||||||
ScopedLock lock(mLock);
|
ScopedLock lock(mLock);
|
||||||
typename Map::iterator iter = mMap.begin();
|
typename Map::iterator iter = mMap.begin();
|
||||||
while (iter != mMap.end()) {
|
while (iter != mMap.end()) {
|
||||||
delete iter->second;
|
vdelete(iter->second);
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
mMap.clear();
|
mMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
~InterthreadMap() { clear(); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Non-blocking write. WARNING: This deletes any pre-existing element!
|
Non-blocking write. WARNING: This deletes any pre-existing element!
|
||||||
@param key The index to write to.
|
@param key The index to write to.
|
||||||
@param wData Pointer to data, not to be deleted until removed from the map.
|
@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);
|
ScopedLock lock(mLock);
|
||||||
typename Map::iterator iter = mMap.find(key);
|
typename Map::iterator iter = mMap.find(key);
|
||||||
if (iter!=mMap.end()) {
|
if (iter!=mMap.end()) {
|
||||||
delete iter->second;
|
vdelete(iter->second);
|
||||||
iter->second = wData;
|
iter->second = wData;
|
||||||
} else {
|
} else {
|
||||||
mMap[key] = wData;
|
mMap[key] = wData;
|
||||||
|
@ -598,14 +477,14 @@ public:
|
||||||
@param key Key to read from.
|
@param key Key to read from.
|
||||||
@return Pointer at key or NULL if key not found, to be deleted by caller.
|
@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);
|
ScopedLock lock(mLock);
|
||||||
typename Map::iterator iter = mMap.find(key);
|
typename Map::iterator iter = mMap.find(key);
|
||||||
if (iter==mMap.end()) return NULL;
|
if (iter==mMap.end()) return false;
|
||||||
D* retVal = iter->second;
|
result = iter->second;
|
||||||
if (bRemove) { mMap.erase(iter); }
|
if (bRemove) { mMap.erase(iter); }
|
||||||
return retVal;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -614,30 +493,20 @@ public:
|
||||||
@param timeout The blocking timeout in ms.
|
@param timeout The blocking timeout in ms.
|
||||||
@return Pointer at key or NULL on timeout, to be deleted by caller.
|
@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);
|
ScopedLock lock(mLock);
|
||||||
Timeval waitTime(timeout);
|
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) {
|
while (1) {
|
||||||
typename Map::iterator iter = mMap.find(key);
|
typename Map::iterator iter = mMap.find(key);
|
||||||
if (iter!=mMap.end()) {
|
if (iter!=mMap.end()) {
|
||||||
D* retVal = iter->second;
|
result = iter->second;
|
||||||
if (bRemove) { mMap.erase(iter); }
|
if (bRemove) { mMap.erase(iter); }
|
||||||
return retVal;
|
return true;
|
||||||
}
|
}
|
||||||
long remaining = waitTime.remaining();
|
long remaining = waitTime.remaining();
|
||||||
if (remaining < 2) { return NULL; }
|
if (remaining < 2) { return false; }
|
||||||
mWriteSignal.wait(mLock,remaining);
|
mWriteSignal.wait(mLock,remaining);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -646,8 +515,9 @@ public:
|
||||||
Blocking read with and element removal.
|
Blocking read with and element removal.
|
||||||
@param key The key to read from.
|
@param key The key to read from.
|
||||||
@return Pointer at key, to be deleted by caller.
|
@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);
|
ScopedLock lock(mLock);
|
||||||
typename Map::iterator iter = mMap.find(key);
|
typename Map::iterator iter = mMap.find(key);
|
||||||
|
@ -655,9 +525,9 @@ public:
|
||||||
mWriteSignal.wait(mLock);
|
mWriteSignal.wait(mLock);
|
||||||
iter = mMap.find(key);
|
iter = mMap.find(key);
|
||||||
}
|
}
|
||||||
D* retVal = iter->second;
|
result = iter->second;
|
||||||
if (bRemove) { mMap.erase(iter); }
|
if (bRemove) { mMap.erase(iter); }
|
||||||
return retVal;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -669,11 +539,13 @@ public:
|
||||||
*/
|
*/
|
||||||
bool remove(const K &key )
|
bool remove(const K &key )
|
||||||
{
|
{
|
||||||
//ScopedLock lock(mModificationLock);
|
D val;
|
||||||
D* val = getNoBlock(key);
|
if (getNoBlock(key,val,true)) {
|
||||||
if (!val) return false;
|
vdelete(val);
|
||||||
delete val;
|
return true;
|
||||||
return true;
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -682,15 +554,11 @@ public:
|
||||||
@param key Key to read from.
|
@param key Key to read from.
|
||||||
@return Pointer at key or NULL if key not found.
|
@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);
|
D result = NULL;
|
||||||
// (pat 8-2013) Lets use common code.
|
Unconst(this)->getNoBlock(key,result,false);
|
||||||
//D* retVal=NULL;
|
return result;
|
||||||
//ScopedLock lock(mLock);
|
|
||||||
//typename Map::const_iterator iter = mMap.find(key);
|
|
||||||
//if (iter!=mMap.end()) retVal = iter->second;
|
|
||||||
//return retVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -699,21 +567,11 @@ public:
|
||||||
@param timeout The blocking timeout in ms.
|
@param timeout The blocking timeout in ms.
|
||||||
@return Pointer at key or NULL on timeout.
|
@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);
|
D result = NULL;
|
||||||
// (pat 8-2013) This commented out code suffered from a deadlock problem.
|
Unconst(this)->get(key,result,timeout,false);
|
||||||
//if (timeout==0) return readNoBlock(key);
|
return result;
|
||||||
//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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -721,32 +579,18 @@ public:
|
||||||
@param key The key to read from.
|
@param key The key to read from.
|
||||||
@return Pointer at key.
|
@return Pointer at key.
|
||||||
*/
|
*/
|
||||||
D* read(const K &key) const
|
D read(const K &key) const
|
||||||
{
|
{
|
||||||
return Unconst(this)->get(key,false);
|
D result;
|
||||||
// (pat 8-2013) Lets use common code.
|
Unconst(this)->get(key,result,false);
|
||||||
//ScopedLock lock(mLock);
|
return result;
|
||||||
//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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pat added.
|
// 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.
|
// 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; }
|
Mutex &qGetLock() { return mLock; }
|
||||||
typedef typename Map::iterator iterator;
|
typedef typename Map::iterator iterator;
|
||||||
typename Map::iterator begin() { return mMap.begin(); }
|
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. */
|
/** 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 {
|
template <class T> class PointerCompare {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -776,7 +631,8 @@ template <class T> class PointerCompare {
|
||||||
Priority queue for interthread operations.
|
Priority queue for interthread operations.
|
||||||
Passes pointers to objects.
|
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:
|
protected:
|
||||||
|
|
||||||
|
@ -784,6 +640,14 @@ template <class T, class C = std::vector<T*>, class Cmp = PointerCompare<T> > cl
|
||||||
mutable Mutex mLock;
|
mutable Mutex mLock;
|
||||||
mutable Signal mWriteSignal;
|
mutable Signal mWriteSignal;
|
||||||
|
|
||||||
|
// Assumes caller holds the lock.
|
||||||
|
T*ipqGet() {
|
||||||
|
if (!mQ.size()) { return NULL; }
|
||||||
|
T*result = mQ.top();
|
||||||
|
mQ.pop();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
@ -815,31 +679,45 @@ template <class T, class C = std::vector<T*>, class Cmp = PointerCompare<T> > cl
|
||||||
T* readNoBlock()
|
T* readNoBlock()
|
||||||
{
|
{
|
||||||
ScopedLock lock(mLock);
|
ScopedLock lock(mLock);
|
||||||
T* retVal = NULL;
|
return ipqGet();
|
||||||
if (mQ.size()!=0) {
|
|
||||||
retVal = mQ.top();
|
|
||||||
mQ.pop();
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Blocking read. */
|
/** Blocking read. */
|
||||||
T* read()
|
T* read()
|
||||||
{
|
{
|
||||||
ScopedLock lock(mLock);
|
ScopedLock lock(mLock);
|
||||||
T* retVal;
|
|
||||||
while (mQ.size()==0) mWriteSignal.wait(mLock);
|
while (mQ.size()==0) mWriteSignal.wait(mLock);
|
||||||
retVal = mQ.top();
|
return ipqGet();
|
||||||
mQ.pop();
|
}
|
||||||
return retVal;
|
|
||||||
|
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. */
|
/** Non-blocking write. */
|
||||||
void write(T* val)
|
void write(T* val)
|
||||||
{
|
{
|
||||||
// (pat) 8-14: Taking out the threading problem fix temporarily for David to use in the field.
|
{ ScopedLock lock(mLock);
|
||||||
ScopedLock lock(mLock);
|
mQ.push(val);
|
||||||
mQ.push(val);
|
}
|
||||||
mWriteSignal.signal();
|
mWriteSignal.signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 Free Software Foundation, Inc.
|
* Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 Free Software Foundation, Inc.
|
* Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 Free Software Foundation, Inc.
|
* 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.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2009 Free Software Foundation, Inc.
|
* Copyright 2009 Free Software Foundation, Inc.
|
||||||
* Copyright 2010 Kestrel Signal Processing, 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.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
|
39
Logger.cpp
39
Logger.cpp
|
@ -262,7 +262,6 @@ ostringstream& Log::get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Allow applications to also pass in a filename. Filename should come from the database
|
// 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)
|
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();
|
gPid = getpid();
|
||||||
|
|
||||||
// Pat added, tired of the syslog facility.
|
// 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");
|
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();
|
const char *fn = str.c_str();
|
||||||
if (fn && *fn && strlen(fn)>3) { // strlen because a garbage char is getting in sometimes.
|
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.
|
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++) {
|
for (unsigned g = 0; g < _NumberOfLogGroups; g++) {
|
||||||
mDebugLevel[g] = 0;
|
mDebugLevel[g] = 0;
|
||||||
|
mWatchLevel[g] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -377,26 +377,39 @@ void LogGroup::LogGroupInit()
|
||||||
#endif
|
#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
|
// Set all the Log.Group debug levels based on database settings
|
||||||
void LogGroup::setAll()
|
void LogGroup::setAll()
|
||||||
{
|
{
|
||||||
LOG(DEBUG);
|
LOG(DEBUG);
|
||||||
string prefix = string(LogGroupPrefix);
|
string groupprefix = string("Log.Group.");
|
||||||
|
string watchprefix = string("Log.Watch.");
|
||||||
for (unsigned g = 0; g < _NumberOfLogGroups; g++) {
|
for (unsigned g = 0; g < _NumberOfLogGroups; g++) {
|
||||||
|
{
|
||||||
|
string param = groupprefix + mGroupNames[g];
|
||||||
int level = 0;
|
int level = 0;
|
||||||
string param = prefix + mGroupNames[g];
|
if (const char*levelName = getNonEmptyStrIfDefined(param)) {
|
||||||
if (gConfig.defines(param)) {
|
level = lookupLevel2(param,levelName);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mDebugLevel[g] = level;
|
mDebugLevel[g] = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
string watchparam = watchprefix + mGroupNames[g];
|
||||||
|
int watchlevel = 0;
|
||||||
|
if (const char*levelName = getNonEmptyStrIfDefined(watchparam)) {
|
||||||
|
watchlevel = lookupLevel2(watchparam,levelName);
|
||||||
|
}
|
||||||
|
mWatchLevel[g] = watchlevel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
Logger.h
21
Logger.h
|
@ -62,7 +62,9 @@ extern pid_t gPid;
|
||||||
//#define CHECK_GROUP_LOG_LEVEL(groupname,loglevel) gCheckGroupLogLevel(#groupname,loglevel)
|
//#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) (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_LOG_LEVEL(wLevel) (gCheckGroupLogLevel(LOG_GROUP,LOG_##wLevel) || gGetLoggingLevel(__FILE__)>=LOG_##wLevel)
|
||||||
|
#define IS_WATCH_LEVEL(wLevel) gCheckGroupWatchLevel(LOG_GROUP,LOG_##wLevel)
|
||||||
#else
|
#else
|
||||||
|
#define IS_WATCH_LEVEL(wLevel) (gGetLoggingLevel(__FILE__)>=LOG_##wLevel)
|
||||||
#define IS_LOG_LEVEL(wLevel) (gGetLoggingLevel(__FILE__)>=LOG_##wLevel)
|
#define IS_LOG_LEVEL(wLevel) (gGetLoggingLevel(__FILE__)>=LOG_##wLevel)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -89,10 +91,11 @@ extern pid_t gPid;
|
||||||
#define LOGVAR2(name,val) " " << name << "=" << (val)
|
#define LOGVAR2(name,val) " " << name << "=" << (val)
|
||||||
#define LOGVAR(var) (" " #var "=") << var
|
#define LOGVAR(var) (" " #var "=") << var
|
||||||
#define LOGVARM(var) " " << &#var[1] << "=" << var // Strip the first char ("m") off the var name when printing.
|
#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.
|
// (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 LOGHEX(var) (" " #var "=0x") << std::hex << ((unsigned long long)var) << std::dec
|
||||||
#define LOGHEX2(name,val) " " << name << "=0x" << hex << ((unsigned long)(val)) << 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
|
// These are kind of cheesy, but you can use for bitvector
|
||||||
#define LOGBV2(name,val) " " << name << "=(" << val<<" size:"<<val.size()<<")"
|
#define LOGBV2(name,val) " " << name << "=(" << val<<" size:"<<val.size()<<")"
|
||||||
#define LOGBV(bv) LOGBV2(#bv,bv)
|
#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.
|
// (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.
|
// 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.
|
// 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 WATCHF(...) { LOG(DEBUG)<<format(__VA_ARGS__); if (IS_WATCH_LEVEL(DEBUG)) {printf("%s ",timestr(7).c_str()); printf(__VA_ARGS__);} }
|
||||||
#define WATCH(...) if (IS_LOG_LEVEL(DEBUG)) { std::cout << timestr(7)<<" "<<__VA_ARGS__ << endl; LOG(DEBUG)<<__VA_ARGS__; }
|
#define WATCH(...) { LOG(DEBUG)<<__VA_ARGS__; if (IS_WATCH_LEVEL(DEBUG)) {std::cout << timestr(7)<<" "<<__VA_ARGS__ << endl;} }
|
||||||
#define WATCHINFO(...) { if (IS_LOG_LEVEL(DEBUG)) { std::cout << timestr(7)<<" "<<__VA_ARGS__ << endl; } LOG(INFO)<<__VA_ARGS__; }
|
#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()
|
//#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.
|
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 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();
|
LogGroup();
|
||||||
void LogGroupInit();
|
void LogGroupInit();
|
||||||
private:
|
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]);
|
//_LOG(DEBUG) << LOGVAR(group)<<LOGVAR(level)<<LOGVAR2("stashed",(unsigned) gLogGroup.mDebugLevel[group]);
|
||||||
return gLogGroup.mDebugLevel[group] >= (int) level;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
12
Makefile.am
12
Makefile.am
|
@ -1,6 +1,6 @@
|
||||||
#
|
#
|
||||||
# Copyright 2008, 2009 Free Software Foundation, Inc.
|
# 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.
|
# This software is distributed under the terms of the GNU Public License.
|
||||||
# See the COPYING file in the main directory for details.
|
# See the COPYING file in the main directory for details.
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
include $(top_srcdir)/Makefile.common
|
include $(top_srcdir)/Makefile.common
|
||||||
|
|
||||||
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES)
|
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES)
|
||||||
AM_CXXFLAGS = -Wall -O3 -g -ldl -lpthread
|
AM_CXXFLAGS = -Wall -O3 -g -ldl -lpthread -lsqlite3
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
example.config \
|
example.config \
|
||||||
|
@ -47,6 +47,8 @@ libcommon_la_SOURCES = \
|
||||||
Utils.cpp
|
Utils.cpp
|
||||||
|
|
||||||
noinst_PROGRAMS = \
|
noinst_PROGRAMS = \
|
||||||
|
UtilsTest \
|
||||||
|
ThreadTest \
|
||||||
BitVectorTest \
|
BitVectorTest \
|
||||||
InterthreadTest \
|
InterthreadTest \
|
||||||
SelfDetectTest \
|
SelfDetectTest \
|
||||||
|
@ -83,6 +85,9 @@ noinst_HEADERS = \
|
||||||
Logger.h \
|
Logger.h \
|
||||||
sqlite3util.h
|
sqlite3util.h
|
||||||
|
|
||||||
|
ThreadTest_SOURCES = ThreadTest.cpp
|
||||||
|
ThreadTest_LDADD = libcommon.la $(SQLITE_LA)
|
||||||
|
|
||||||
URLEncodeTest_SOURCES = URLEncodeTest.cpp
|
URLEncodeTest_SOURCES = URLEncodeTest.cpp
|
||||||
URLEncodeTest_LDADD = libcommon.la
|
URLEncodeTest_LDADD = libcommon.la
|
||||||
|
|
||||||
|
@ -123,6 +128,9 @@ LogTest_LDADD = libcommon.la $(SQLITE_LA)
|
||||||
|
|
||||||
F16Test_SOURCES = F16Test.cpp
|
F16Test_SOURCES = F16Test.cpp
|
||||||
|
|
||||||
|
UtilsTest_SOURCES = UtilsTest.cpp
|
||||||
|
UtilsTest_LDADD = libcommon.la
|
||||||
|
|
||||||
MOSTLYCLEANFILES += testSource testDestination
|
MOSTLYCLEANFILES += testSource testDestination
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Range Networks, Inc.
|
* Copyright 2011, 2014 Range Networks, Inc.
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
*
|
*
|
||||||
* This software is distributed under multiple licenses;
|
* This software is distributed under multiple licenses;
|
||||||
* see the COPYING file in the main directory for licensing
|
* 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.
|
* This use of this software may be subject to additional restrictions.
|
||||||
* See the LEGAL file in the main directory for details.
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
|
||||||
|
|
1
Regexp.h
1
Regexp.h
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 Free Software Foundation, Inc.
|
* Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 Free Software Foundation, Inc.
|
* Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**@file Module for performance-reporting mechanisms. */
|
/**@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.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**@file Module for performance-reporting mechanisms. */
|
/**@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.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
@ -98,6 +98,7 @@ class ReportingTable {
|
||||||
|
|
||||||
/** Periodically triggers ReportingTable::commit(). */
|
/** Periodically triggers ReportingTable::commit(). */
|
||||||
void* reportingBatchCommitter(void*);
|
void* reportingBatchCommitter(void*);
|
||||||
|
extern ReportingTable gReports;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -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.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Range Networks, Inc.
|
* Copyright 2011, 2014 Range Networks, Inc.
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
*
|
*
|
||||||
* This software is distributed under multiple licenses;
|
* This software is distributed under multiple licenses;
|
||||||
* see the COPYING file in the main directory for licensing
|
* 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.
|
* This use of this software may be subject to additional restrictions.
|
||||||
* See the LEGAL file in the main directory for details.
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**@file Module for preventing two instances of a program from running. */
|
/**@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.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* 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 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:98:Exit: *** Terminating ./OpenBTS
|
||||||
// openbts: NOTICE 3073816320 05:03:50.4 SelfDetect.cpp:105:Exit: *** Removing pid file /var/run/OpenBTS.pid
|
// openbts: NOTICE 3073816320 05:03:50.4 SelfDetect.cpp:105:Exit: *** Removing pid file /var/run/OpenBTS.pid
|
||||||
|
case SIGCONT:
|
||||||
case SIGCHLD:
|
case SIGCHLD:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2013 Range Networks, Inc.
|
* Copyright 2013, 2014 Range Networks, Inc.
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
*
|
*
|
||||||
* This software is distributed under multiple licenses;
|
* This software is distributed under multiple licenses;
|
||||||
* see the COPYING file in the main directory for licensing
|
* 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.
|
* This use of this software may be subject to additional restrictions.
|
||||||
* See the LEGAL file in the main directory for details.
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
|
@ -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.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008, 2010, 2014 Free Software Foundation, Inc.
|
* 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.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008, 2010 Free Software Foundation, Inc.
|
* 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.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 Free Software Foundation, Inc.
|
* Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008, 2014 Free Software Foundation, Inc.
|
* 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.
|
* 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->task = task;
|
||||||
p->arg = arg;
|
p->arg = arg;
|
||||||
res = pthread_create(&mThread, &mAttrib, &thread_main, p);
|
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);
|
assert(!res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Thread::start2(void *(*task)(void*), void *arg, int stacksize)
|
||||||
|
{
|
||||||
|
mStackSize = stacksize;
|
||||||
|
start(task,arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// vim: ts=4 sw=4
|
// vim: ts=4 sw=4
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008, 2011, 2014 Free Software Foundation, Inc.
|
* 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.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
@ -241,6 +242,7 @@ class Thread {
|
||||||
|
|
||||||
/** Start the thread on a task. */
|
/** Start the thread on a task. */
|
||||||
void start(void *(*task)(void*), void *arg);
|
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. */
|
/** Join a thread that will stop on its own. */
|
||||||
void join() { int s = pthread_join(mThread,NULL); assert(!s); mThread = 0; }
|
void join() { int s = pthread_join(mThread,NULL); assert(!s); mThread = 0; }
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 Free Software Foundation, Inc.
|
* Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 Free Software Foundation, Inc.
|
* Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 Free Software Foundation, Inc.
|
* Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
|
|
@ -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 <URLEncode.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2011 Free Software Foundation, Inc.
|
* Copyright 2011 Free Software Foundation, Inc.
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
|
|
@ -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 "URLEncode.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* This software is distributed under multiple licenses;
|
* This software is distributed under multiple licenses;
|
||||||
* see the COPYING file in the main directory for licensing
|
* 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.
|
* This use of this software may be subject to additional restrictions.
|
||||||
* See the LEGAL file in the main directory for details.
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
20
Utils.cpp
20
Utils.cpp
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* This software is distributed under multiple licenses;
|
* This software is distributed under multiple licenses;
|
||||||
* see the COPYING file in the main directory for licensing
|
* 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.
|
* This use of this software may be subject to additional restrictions.
|
||||||
* See the LEGAL file in the main directory for details.
|
* 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.
|
} // 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.
|
// 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);
|
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.
|
// 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) {
|
if (saveRefCnt <= 0) {
|
||||||
|
//printf("decRefCnt %p deleting refcnted pointer\n",this);
|
||||||
LOG(DEBUG) << "deleting refcnted pointer "<<typeid(this).name();
|
LOG(DEBUG) << "deleting refcnted pointer "<<typeid(this).name();
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
@ -51,6 +53,7 @@ int RefCntBase::decRefCnt()
|
||||||
void RefCntBase::incRefCnt()
|
void RefCntBase::incRefCnt()
|
||||||
{
|
{
|
||||||
ScopedLock lock(mRefMutex);
|
ScopedLock lock(mRefMutex);
|
||||||
|
//printf("incRefCnt %p before=%d\n",this,mRefCnt);
|
||||||
LOG(DEBUG) <<" "<<(void*)this <<" " <<LOGVAR2("refcnt before",mRefCnt);
|
LOG(DEBUG) <<" "<<(void*)this <<" " <<LOGVAR2("refcnt before",mRefCnt);
|
||||||
assert(mRefCnt >= 0);
|
assert(mRefCnt >= 0);
|
||||||
mRefCnt++;
|
mRefCnt++;
|
||||||
|
@ -555,4 +558,19 @@ string uintToString(uint32_t x)
|
||||||
os << hex << x;
|
os << hex << x;
|
||||||
return os.str();
|
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
19
Utils.h
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* This software is distributed under multiple licenses;
|
* This software is distributed under multiple licenses;
|
||||||
* see the COPYING file in the main directory for licensing
|
* 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.
|
* This use of this software may be subject to additional restrictions.
|
||||||
* See the LEGAL file in the main directory for details.
|
* 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(uint64_t h, uint64_t l);
|
||||||
extern string uintToString(uint32_t x);
|
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
|
// 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.
|
// of type RefCntPointer. When the last RefCntPointer is freed, this struct is too.
|
||||||
class RefCntBase {
|
class RefCntBase {
|
||||||
|
template <class Type> friend class RefCntPointer;
|
||||||
Mutex mRefMutex;
|
Mutex mRefMutex;
|
||||||
mutable short mRefCnt; // signed, not unsigned!
|
mutable short mRefCnt; // signed, not unsigned!
|
||||||
int setRefCnt(int val) { return mRefCnt = val; }
|
int setRefCnt(int val) { return mRefCnt = val; }
|
||||||
|
@ -206,14 +208,20 @@ class RefCntBase {
|
||||||
RefCntBase(RefCntBase &) { assert(0); }
|
RefCntBase(RefCntBase &) { assert(0); }
|
||||||
RefCntBase(const RefCntBase &) { assert(0); }
|
RefCntBase(const RefCntBase &) { assert(0); }
|
||||||
RefCntBase operator=(RefCntBase &) {assert(0); mRefCnt = 0; return *this; }
|
RefCntBase operator=(RefCntBase &) {assert(0); mRefCnt = 0; return *this; }
|
||||||
|
int decRefCnt(); // Only RefCntPointer is permitted to use incRefCnt and decRefCnt.
|
||||||
|
void incRefCnt();
|
||||||
public:
|
public:
|
||||||
virtual ~RefCntBase();
|
virtual ~RefCntBase();
|
||||||
RefCntBase() : mRefCnt(0) {}
|
RefCntBase() : mRefCnt(0) {}
|
||||||
int getRefCnt() const { return mRefCnt; }
|
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:
|
// Semantics:
|
||||||
// SomeDescendentOfRefCntBase foo;
|
// SomeDescendentOfRefCntBase foo;
|
||||||
// RefCntPointer<SomeDescendentOfRefCntBase> ptrToFoo;
|
// RefCntPointer<SomeDescendentOfRefCntBase> ptrToFoo;
|
||||||
|
@ -244,7 +252,8 @@ class RefCntPointer {
|
||||||
// The operator=(Type*) is called if the argument is NULL, so we dont need int.
|
// 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; }
|
//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.
|
// 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; }
|
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 RefCntPointer &other) const { return rcPointer == other.rcPointer; }
|
||||||
bool operator==(const Type* other) const { return rcPointer == other; }
|
bool operator==(const Type* other) const { return rcPointer == other; }
|
||||||
|
@ -265,6 +274,8 @@ class RefCntPointer {
|
||||||
bool isNULL() const { return self() == NULL; }
|
bool isNULL() const { return self() == NULL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern string firstlines(string msgstr, int n=2);
|
||||||
|
|
||||||
}; // namespace
|
}; // namespace
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
*
|
*
|
||||||
* This software is distributed under multiple licenses;
|
* This software is distributed under multiple licenses;
|
||||||
* see the COPYING file in the main directory for licensing
|
* 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.
|
* This use of this software may be subject to additional restrictions.
|
||||||
* See the LEGAL file in the main directory for details.
|
* See the LEGAL file in the main directory for details.
|
||||||
|
|
1
Vector.h
1
Vector.h
|
@ -1,6 +1,7 @@
|
||||||
/**@file Simplified Vector template with aliases. */
|
/**@file Simplified Vector template with aliases. */
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 Free Software Foundation, Inc.
|
* Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 Free Software Foundation, Inc.
|
* Copyright 2008 Free Software Foundation, Inc.
|
||||||
|
* Copyright 2014 Range Networks, Inc.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
|
|
@ -1,10 +1,29 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2010 Kestrel Signal Processing, Inc.
|
* 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 "sqlite3util.h"
|
||||||
#include "Logger.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)
|
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)")) {
|
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
|
// (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;
|
return false;
|
||||||
}
|
}
|
||||||
char query[100];
|
char query[100];
|
||||||
snprintf(query,100,"REPLACE INTO ATTR_TABLE (ATTR_NAME,ATTR_VALUE) VALUES('%s','%s')",attr_name,attr_value);
|
snprintf(query,100,"REPLACE INTO ATTR_TABLE (ATTR_NAME,ATTR_VALUE) VALUES('%s','%s')",attr_name,attr_value);
|
||||||
if (! sqlite3_command(db,query)) {
|
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
|
// (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 false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -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
|
#ifndef SQLITE3UTIL_H
|
||||||
#define SQLITE3UTIL_H
|
#define SQLITE3UTIL_H
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue