Update of /cvsroot/aolserver/knutil/src In directory sc8-pr-cvs11.sourceforge.net:/tmp/cvs-serv6393/src Added Files: atomicint.cpp atomicint.il counter.cpp kncircularmapping.cpp knconsistenthash.cpp kncrashhandler.cpp kncrypt.cpp knerror.cpp knhash.cpp knlog.cpp knmarkuputil.cpp knmemory.cpp knmutex.cpp knnetwork.cpp knnewdelete.cpp knpattern.cpp knperfstatistics.cpp knregex.cpp knrwlock.cpp knrwlogginglock.cpp knset.cpp knsleep.cpp knstring.cpp knstringtokenizer.cpp knsysutility_unix.cpp knsysutility_win32.cpp kntclerrors.cpp kntclfile.cpp kntclinterp.cpp kntemplateuri.cpp kntime.cpp knurl.cpp mtrand.cpp randomnumber.cpp shahash.cpp uuidgenerator.cpp Log Message: Added this library to the AOLServer.com repository. It contains a number of C/C++ utilities, some of which integrate into AOLServer, and many of which standalone. A portion of the library is required for the knregistration module, which will be checked in next. I believe this compiles fine in "native" AOLServer, but it has not been tested recently. --- NEW FILE: atomicint.cpp --- #include "knexportlibraryknutilmodule.h" /** * (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA * * @KNOWNOW_LICENSE_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not * be used to endorse or promote any product without prior written * permission from KnowNow, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @KNOWNOW_LICENSE_END@ **/ #include "knutil/atomicint.h" #ifndef WIN32 #include <unistd.h> #endif namespace { #ifdef WIN32 int getNumberOfProcessors() { SYSTEM_INFO si; memset(&si, 0, sizeof(si)); GetSystemInfo(&si); return si.dwNumberOfProcessors; } #else int getNumberOfProcessors() { return sysconf(_SC_NPROCESSORS_ONLN); } #endif /* WIN32 */ /* * Assume that the number of processors remains static during process * lifetime. This may be dicey if the superuser is using/abusing tools * such as Solaris's psradm. */ const int gNumberOfProcessors = getNumberOfProcessors(); #ifdef WIN32 #pragma warning(disable : 4035) /* * Return with the result in EAX. */ inline int atomicAdd(int *pcnt, int cnt) { if (gNumberOfProcessors == 1) { __asm { mov ecx, pcnt mov eax, cnt xadd dword ptr [ecx], eax add eax, cnt } } else { __asm { mov ecx, pcnt mov eax, cnt lock xadd dword ptr [ecx], eax add eax, cnt } } } #pragma warning(default : 4035) inline bool atomicCompareAndSwap(int *pcnt, int oval, int val) { unsigned char c; if (gNumberOfProcessors == 1) { __asm { mov ecx, pcnt mov eax, oval mov edx, val cmpxchg dword ptr [ecx], edx sete c } } else { __asm { mov ecx, pcnt mov eax, oval mov edx, val lock cmpxchg dword ptr [ecx], edx sete c } } return c != 0; } inline bool atomicDecrementAndTest(int *pcnt) { unsigned char c; if (gNumberOfProcessors == 1) { __asm { mov ecx, pcnt dec dword ptr [ecx] sete c } } else { __asm { mov ecx, pcnt lock dec dword ptr [ecx] sete c } } return c != 0; } inline bool atomicDoubleCompareAndSwap(int64_t *pcnt, int64_t oval, int64_t val) { unsigned char c; if (gNumberOfProcessors == 1) { __asm { mov esi, pcnt mov edx, dword ptr [oval + 4] mov eax, dword ptr [oval] mov ecx, dword ptr [val + 4] mov ebx, dword ptr [val] cmpxchg8b qword ptr [esi] sete c } } else { __asm { mov esi, pcnt mov edx, dword ptr [oval + 4] mov eax, dword ptr [oval] mov ecx, dword ptr [val + 4] mov ebx, dword ptr [val] lock cmpxchg8b qword ptr [esi] sete c } } return c != 0; } inline void atomicIncrement(int *pcnt) { if (gNumberOfProcessors == 1) { __asm { mov ecx, pcnt inc dword ptr [ecx] } } else { __asm { mov ecx, pcnt lock inc dword ptr [ecx] } } } inline void atomicReadBarrier() { /* * A read barrier is only necessary on a multiprocessor box. */ if (gNumberOfProcessors != 1) { __asm { lock add dword ptr [esp], 0 } } } inline void atomicWriteBarrier() { /* * Intel doesn't reorder writes. */ } #elif __linux inline int atomicAdd(int *pcnt, int cnt) { int rc; if (gNumberOfProcessors == 1) { __asm__ __volatile__( "xaddl %0,%2" : "=r" (rc) : "0" (cnt), "m" (*pcnt) : "memory"); } else { __asm__ __volatile__( "lock xaddl %0,%2" : "=r" (rc) : "0" (cnt), "m" (*pcnt) : "memory"); } return rc + cnt; } inline bool atomicCompareAndSwap(int *pcnt, int oval, int val) { unsigned char c; if (gNumberOfProcessors == 1) { __asm__ __volatile__( "cmpxchgl %2,%1; sete %0" : "=q" (c), "=m" (*pcnt) : "r" (val), "1" (*pcnt), "a" (oval)); } else { __asm__ __volatile__( "lock cmpxchgl %2,%1; sete %0" : "=q" (c), "=m" (*pcnt) : "r" (val), "1" (*pcnt), "a" (oval)); } return c != 0; } inline bool atomicDecrementAndTest(int *pcnt) { unsigned char c; if (gNumberOfProcessors == 1) { __asm__ __volatile__( "decl %1; sete %0" : "=q" (c) : "m" (*pcnt) : "memory"); } else { __asm__ __volatile__( "lock decl %1; sete %0" : "=q" (c) : "m" (*pcnt) : "memory" ); } return c != 0; } inline bool atomicDoubleCompareAndSwap(int64_t *pcnt, int64_t oval, int64_t val) { unsigned char c; if (gNumberOfProcessors == 1) { __asm__ __volatile__( "cmpxchg8b %1; sete %0" : "=q" (c), "=m" (*pcnt) : "1" (*pcnt), "A" (oval), "c" (static_cast<int>(val >> 32)), "b" (static_cast<int>(val))); } else { __asm__ __volatile__( "lock cmpxchg8b %1; sete %0" : "=q" (c), "=m" (*pcnt) : "1" (*pcnt), "A" (oval), "c" (static_cast<int>(val >> 32)), "b" (static_cast<int>(val))); } return c != 0; } inline void atomicIncrement(int *pcnt) { if (gNumberOfProcessors == 1) { __asm__ __volatile__( "incl %0" : "+m" (*pcnt) ); } else { __asm__ __volatile__( "lock incl %0" : "+m" (*pcnt) ); } } inline void atomicReadBarrier() { if (gNumberOfProcessors == 1) { __asm__ __volatile__( "" : : : "memory"); } else { int x = 0, y = 1; __asm__ __volatile__( "xchgl %0,%1" : "=r" (x) : "m" (y), "0" (x) : "memory"); } } inline void atomicWriteBarrier() { __asm__ __volatile__( "" : : : "memory"); } #elif __sun extern "C" int atomicAdd(int *, int); extern "C" bool atomicCompareAndSwap(int *, int, int); extern "C" bool atomicDoubleCompareAndSwap(int64_t *, int64_t *, int64_t *); extern "C" void atomicReadBarrier(); extern "C" void atomicWriteBarrier(); inline bool atomicDecrementAndTest(int *pcnt) { return atomicAdd(pcnt, -1) == 0; } inline bool atomicDoubleCompareAndSwap(int64_t *pcnt, int64_t oval, int64_t val) { return atomicDoubleCompareAndSwap(pcnt, &oval, &val); } inline void atomicIncrement(int *pcnt) { atomicAdd(pcnt, 1); } #endif /* WIN32 */ } //namespace int AtomicInt::operator+=(int cnt) { return atomicAdd(&m_cnt, cnt); } int AtomicInt::operator-=(int cnt) { return atomicAdd(&m_cnt, -cnt); } int AtomicInt::operator++() { return atomicAdd(&m_cnt, 1); } int AtomicInt::operator++(int) { return atomicAdd(&m_cnt, 1) - 1; } int AtomicInt::operator--() { return atomicAdd(&m_cnt, -1); } int AtomicInt::operator--(int) { return atomicAdd(&m_cnt, -1) + 1; } bool AtomicInt::decrementAndTest() { return atomicDecrementAndTest(&m_cnt); } void AtomicInt::increment() { atomicIncrement(&m_cnt); } --- NEW FILE: atomicint.il --- .inline atomicAdd,8 1: ld [%o0],%o2 add %o2,%o1,%o3 cas [%o0],%o2,%o3 cmp %o2,%o3 bne,pn %icc,1b nop add %o2,%o1,%o0 .end .inline atomicCompareAndSwap,12 cas [%o0],%o1,%o2 xor %o0,%o0,%o0 cmp %o1,%o2 bne,pn %icc,2f nop add %o0,1,%o0 2: .end .inline atomicDoubleCompareAndSwap,12 ldx [%o1],%o3 ldx [%o2],%o4 casx [%o0],%o3,%o4 xor %o0,%o0,%o0 cmp %o3,%o4 bne,pn %xcc,3f nop add %o0,1,%o0 3: .end .inline atomicReadBarrier,0 membar #LoadLoad .end .inline atomicWriteBarrier,0 membar #StoreStore .end --- NEW FILE: counter.cpp --- #include "knexportlibraryknutilmodule.h" /** * (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA * * @KNOWNOW_LICENSE_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not * be used to endorse or promote any product without prior written * permission from KnowNow, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @KNOWNOW_LICENSE_END@ **/ #include "knutil/counter.h" Counter::Counter(int c) : count(c) { } Counter::~Counter() { } --- NEW FILE: kncircularmapping.cpp --- #include <math.h> /** * (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA * * @KNOWNOW_LICENSE_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not * be used to endorse or promote any product without prior written * permission from KnowNow, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @KNOWNOW_LICENSE_END@ **/ #include <sstream> #include <algorithm> #include "knexportlibraryknutilmodule.h" #include "knutil/knerror.h" #include "knutil/knlog.h" #include "knutil/kncircularmapping.h" //-------------------------------------------------------------------------- // Bucket Class //-------------------------------------------------------------------------- class Bucket { public: Bucket(const std::string& bucketName, double weight) : m_name(bucketName), m_weight(weight) { } std::string m_name; double m_weight; std::vector<KnCircularMapping::PointT> m_replicaPoints; }; bool BucketComp(const Bucket* lhs, const Bucket* rhs) { return lhs->m_name < rhs->m_name; } bool insertSorted(std::vector<Bucket*>& v, Bucket* value) { std::pair<std::vector<Bucket*>::iterator, std::vector<Bucket*>::iterator> bounds; bounds = equal_range(v.begin(), v.end(), value, BucketComp); if(bounds.first == bounds.second) { if(bounds.first == v.end()) { v.push_back(value); return true; } v.insert(bounds.second, value); return true; } return false; } //-------------------------------------------------------------------------- // ReplicaPoint Class //-------------------------------------------------------------------------- class ReplicaPoint { public: ReplicaPoint(KnCircularMapping::PointT& point) : m_point(point) { } ~ReplicaPoint() { } Bucket* getFirstBucket() { if(!m_replicas.size()) { KnLog(KnLogError, "KnConsistentHash: replica point with no replicas."); return NULL; } Bucket* bucket = *m_replicas.begin(); return bucket; } bool addReplica(Bucket* bucket) // keep them sorted , return true if conflict { if(!m_replicas.size()) { m_replicas.push_back(bucket); return false; } bool result = insertSorted(m_replicas, bucket); if(!result) { KnLog(KnLogError, "KnConsistentHash: Bucket with same ID already present at replica"); } KnLog(KnLogWarning, "KnConsistentHash: conflict when adding bucket %s replica at point %u.", bucket->m_name.c_str(), m_point); return true; } KnCircularMapping::PointT m_point; std::vector<Bucket*> m_replicas; // should be just one or there are conflicts }; //-------------------------------------------------------------------------- // KnCircularMapping //-------------------------------------------------------------------------- KnCircularMapping::KnCircularMapping() { m_totalWeight = 0; } KnCircularMapping::~KnCircularMapping() { removeAllBuckets(); } bool KnCircularMapping::addBucket(const char* bucketName, std::vector<PointT>& replicas, double weight) { if (weight <= 0) return false; if (m_buckets.find(bucketName) != m_buckets.end()) return false; Bucket* bucket = new Bucket(bucketName, weight); m_buckets[bucketName] = bucket; ReplicaPoint* rp; bucket->m_replicaPoints = replicas; for (int i = 0; i < replicas.size(); i++) { rp = findOrAddReplicaPoint(replicas[i]); rp->addReplica(bucket); } m_totalWeight += weight; return true; } bool KnCircularMapping::removeBucket(const char* bucketName) { BucketMapIterator it = m_buckets.find(bucketName); if (it == m_buckets.end()) return false; Bucket* bucket = it->second; m_buckets.erase(it); double weight = bucket->m_weight; m_totalWeight -= weight; for (int i = 0; i < bucket->m_replicaPoints.size(); i++) { if(!removeReplicaPoint(bucket->m_replicaPoints[i], bucket)) { KnLog(KnLogError, "KnConsistentHash: could not remove replica point %u for bucket %s.", bucket->m_replicaPoints[i] ,bucket->m_name.c_str()); } } SAFE_DELETE(bucket); return true; } ReplicaPoint* KnCircularMapping::findOrAddReplicaPoint(PointT point) { ReplicaMapRange bounds; ReplicaPoint* result; bounds = m_replicaMap.equal_range(point); if(bounds.first == bounds.second) { // not found result = new ReplicaPoint(point); if(bounds.first == m_replicaMap.end()) { m_replicaMap[point] = result; return result; } m_replicaMap.insert(bounds.second, std::pair<const PointT, ReplicaPoint*>(point, result)); return result; } return (*bounds.first).second; } ReplicaPoint* KnCircularMapping::findReplicaPoint(PointT point) { ReplicaMapIterator it = m_replicaMap.find(point); if(it == m_replicaMap.end()) return NULL; return it->second; } bool KnCircularMapping::removeReplicaPoint(PointT point, Bucket* bucket) { ReplicaMapRange bounds; bounds = m_replicaMap.equal_range(point); if(bounds.first == bounds.second) return false; ReplicaPoint* rp = (*bounds.first).second; std::vector<Bucket*>& replicas = rp->m_replicas; std::vector<Bucket*>::iterator it = find(replicas.begin(), replicas.end(), bucket); if(it == replicas.end()) return false; replicas.erase(it); if(!replicas.size()) { m_replicaMap.erase(bounds.first); SAFE_DELETE(rp); } return true; } Bucket* KnCircularMapping::findBucketForPoint(PointT point) { if (m_replicaMap.empty() || m_buckets.empty()) return NULL; if (m_buckets.size() == 1) return (*m_replicaMap.begin()).second->getFirstBucket(); ReplicaMapRange bounds; bounds = m_replicaMap.equal_range(point); if(bounds.first == bounds.second) { // not found if(bounds.first == m_replicaMap.end()) { // point is after all replicas => assign to first replica return (*m_replicaMap.begin()).second->getFirstBucket(); } // assign to greater replica return (*bounds.second).second->getFirstBucket(); } // assign to this replica as it has the same point value return (*bounds.first).second->getFirstBucket(); } void KnCircularMapping::removeAllBuckets() { ReplicaMapIterator it; for(it = m_replicaMap.begin(); it != m_replicaMap.end(); it++) SAFE_DELETE(it->second); m_replicaMap.clear(); BucketMapIterator bmi = m_buckets.begin(); for(; bmi != m_buckets.end(); bmi++) SAFE_DELETE(bmi->second); m_buckets.clear(); } double KnCircularMapping::getWeight(const std::string& bucketName) { BucketMapIterator it = m_buckets.find(bucketName.c_str()); if(it != m_buckets.end()) return it->second->m_weight; return -1; } double KnCircularMapping::getTotalWeight() { return m_totalWeight; } bool KnCircularMapping::existsBucket(const std::string& bucketName) { return m_buckets.find(bucketName.c_str()) != m_buckets.end(); } std::string KnCircularMapping::assignPointToBucket(PointT point) { Bucket* bucket = findBucketForPoint(point); if(!bucket) return ""; return bucket->m_name; } int KnCircularMapping::bucketCount() { return m_buckets.size(); } --- NEW FILE: knconsistenthash.cpp --- #include <math.h> /** * (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA * * @KNOWNOW_LICENSE_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not * be used to endorse or promote any product without prior written * permission from KnowNow, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @KNOWNOW_LICENSE_END@ **/ #include <sstream> #include <algorithm> #include <vector> #include "knexportlibraryknutilmodule.h" #include "knutil/knerror.h" #include "knutil/knlog.h" #include "knutil/knhash.h" #include "knutil/mtrand.h" #include "knutil/knconsistenthash.h" //-------------------------------------------------------------------------- // KnConsistentHash //-------------------------------------------------------------------------- KnConsistentHash::KnConsistentHash(int replicasPerBucket, KnCircularMapping::PointT pointInterval) { m_replicasPerBucket = replicasPerBucket; m_pointInterval = pointInterval; } KnConsistentHash::~KnConsistentHash() { } KnConsistentHash::IDHash KnConsistentHash::computeHash(const char* identifier) { return hash32(identifier, strlen(identifier), 1492); } KnCircularMapping::PointT KnConsistentHash::computePointForResource(const char* identifier) { MTRand_int32 randGen( computeHash(identifier) ); return randGen() % m_pointInterval; } bool KnConsistentHash::addBucket(const char* bucketName, double weight) { return addBucketUnsafe(bucketName, computeHash(bucketName), weight); } bool KnConsistentHash::addBucket(const char* bucketName, IDHash bucketHash, double weight) { KnRWLock::KnWriteLock wlock(m_bucketLock); return addBucketUnsafe(bucketName, bucketHash, weight); } bool KnConsistentHash::addBucketUnsafe(const char* bucketName, IDHash bucketHash, double weight) { if (weight < 0.000001) return m_mapping.removeBucket(bucketName); if(m_mapping.existsBucket(bucketName)) { // Bucket already exists => remove before adding m_mapping.removeBucket(bucketName); } MTRand_int32 randGen(bucketHash); KnCircularMapping::PointT point; std::vector<KnCircularMapping::PointT> replicas; int replicaCount = floor(weight * m_replicasPerBucket); replicas.reserve(replicaCount); for (int i = 0; i < replicaCount; i++) { point = randGen() % m_pointInterval; replicas.push_back(point); } return m_mapping.addBucket(bucketName, replicas, weight); } bool KnConsistentHash::removeBucket(const char* bucketName) { KnRWLock::KnWriteLock wlock(m_bucketLock); return m_mapping.removeBucket(bucketName); } void KnConsistentHash::removeAllBuckets() { KnRWLock::KnWriteLock wlock(m_bucketLock); m_mapping.removeAllBuckets(); } std::string KnConsistentHash::assignPointToBucket(KnCircularMapping::PointT point) { KnRWLock::KnReadLock rlock(m_bucketLock); return m_mapping.assignPointToBucket(point); } std::string KnConsistentHash::assignResourceToBucket(const char* identifier) { KnRWLock::KnReadLock rlock(m_bucketLock); return m_mapping.assignPointToBucket( computePointForResource(identifier) ); } int KnConsistentHash::bucketCount() { return m_mapping.bucketCount(); } bool KnConsistentHash::addBucketsFromSet(const KnSet& bucketSet) { if(bucketSet.size() == 0) return true; KnRWLock::KnWriteLock wlock(m_bucketLock); return addBucketsFromSetUnsafe(bucketSet); } bool KnConsistentHash::setBucketsFromSet(const KnSet& bucketSet) { if(bucketSet.size() == 0) return true; KnRWLock::KnWriteLock wlock(m_bucketLock); m_mapping.removeAllBuckets(); return addBucketsFromSetUnsafe(bucketSet); } bool KnConsistentHash::addBucketsFromSetUnsafe(const KnSet& bucketSet) { if(bucketSet.size() == 0) return true; for (size_t ix = 0; ix < bucketSet.size(); ++ix) { KnSetElem entry = bucketSet[ix]; KnString bucketName = entry.m_key; if(entry.m_value == "") { // A delete bucket request m_mapping.removeBucket(bucketName.c_str()); continue; } double weight = entry.m_value.toDouble(); addBucketUnsafe(bucketName.c_str(), computeHash(bucketName.c_str()), weight); } return true; } double KnConsistentHash::getTotalWeight() { return m_mapping.getTotalWeight(); } --- NEW FILE: kncrashhandler.cpp --- #include "knexportlibraryknutilmodule.h" /** * (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA * * @KNOWNOW_LICENSE_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not * be used to endorse or promote any product without prior written * permission from KnowNow, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @KNOWNOW_LICENSE_END@ **/ #include "knutil/kncrashhandler.h" #include "knutil/knlog.h" #include "knutil/knmemory.h" #include "knutil/knmutex.h" #include "string" namespace { KnMutex gCrashHandlerMutex; std::string gDumpLocation; // For occasions when we change it. bool gDumpAtAll = true; // Avoid denial of service by running out of disk (Customer Support called for the default to be false for this reason). } #ifdef WIN32 #define _MSJDBG_H #include "BugslayerUtil.h" namespace { // From http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/minidumpwritedump.asp: // DumpType // [in] The type of information to be generated. This parameter can be // one or more of the values from the MINIDUMP_TYPE enumeration. unsigned int gMiniDumpType = static_cast<unsigned int>(MiniDumpNormal); char* gMiniDumpFile = "log/liveserver.dmp"; } LONG __stdcall KnCrashHandler( EXCEPTION_POINTERS * pExPtrs ) { // Count on the BugSlayer's OutputDebugString (annoying) if // we're out of stack; if we're a service, we'll have hung // before getting here. Unfortunately, it's not as rare for us as // for many other programs, since we're multithreaded (and have therefore // declared a stack size), but it's rare enough to have worked out OK for a while. // When we get hangs or crashes on Windows with no stack trace or minidump, then // we're probably looking at exactly that case. Try increasing the stack size // in knrouter.tcl. if ( EXCEPTION_STACK_OVERFLOW != pExPtrs->ExceptionRecord->ExceptionCode ) { // None of the BugSlayer routines are thread-safe. OTOH, it's hard // to bring myself to use another mutex at this point, since we deadlock // so often for mutex problems. Doing it anyway. KnMutex::KnLock lock(gCrashHandlerMutex); KnLog(KnLogBug,GetFaultReason(pExPtrs)); KnLog(KnLogNotice,GetRegisterString(pExPtrs)); // Want the ns_fatal call to have all the info about minidump so it's easy // to see in the Monitor Alarms view. char *miniDumpIntro = "No .dmp generated:"; char *miniDumpExtra = ""; char *miniDumpFile = gDumpLocation.length() ? const_cast<char*>(gDumpLocation.c_str()) : gMiniDumpFile; if (!gDumpAtAll) { miniDumpExtra = "disabled. See Configuration: Memory in the KSA"; } else if (IsMiniDumpFunctionAvailable()) { BSUMDRET problems = CreateCurrentProcessMiniDump( static_cast<MINIDUMP_TYPE>(gMiniDumpType), miniDumpFile, GetCurrentThreadId(), pExPtrs); switch (problems) { case eDUMP_SUCCEEDED: miniDumpIntro = "See minidump file"; miniDumpExtra = miniDumpFile; break; case eDBGHELP_NOT_FOUND: miniDumpExtra = "dbghelp.dll not found."; break; case eDBGHELP_MISSING_EXPORTS: miniDumpExtra = "dbghelp.dll missing functionality."; break; case eBAD_PARAM: miniDumpExtra = "Bad parameter."; break; case eOPEN_DUMP_FAILED: miniDumpIntro = "Could not open minidump file"; miniDumpExtra = miniDumpFile; // No guidance from Mr. Robbins on why in this case. break; case eMINIDUMPWRITEDUMP_FAILED: KnLog(KnLogNotice,"Couldn't write dump; GetLastError returns %d",GetLastError()); miniDumpExtra = "Dump writing failed."; break; case eDEATH_ERROR: miniDumpExtra = "Minidump thread could not be started."; break; case eINVALID_ERROR: miniDumpExtra = "Bad bugslayer code"; break; } } else { miniDumpExtra = "Minidump facility not available."; } KnLog(KnLogNotice,"Stack trace:"); DWORD dwOpts = GSTSO_SRCLINE | GSTSO_SYMBOL | GSTSO_PARAMS; for ( LPCSTR pStackMessage =GetFirstStackTraceString( dwOpts, pExPtrs ) ; 0 != pStackMessage ; pStackMessage = GetNextStackTraceString( dwOpts, pExPtrs ) ) { KnLog(KnLogNotice,pStackMessage); } KnMemory::logStatistics( KnLogNotice ) ; KnLog(KnLogNotice,"knownow: Memory available: %lu",KnMemory::getMemoryAvail()); Ns_Fatal("Exception shuts down server immediately. %s %s", miniDumpIntro, miniDumpExtra); } return EXCEPTION_EXECUTE_HANDLER ; }; // This routine should be called from DLLMAIN, but so far, we're doing // OK just installing it from nskn. Since we're not limiting ourselves // to just one dll, it works pretty nicely, without requiring changes in // AOLServer. If we ever integrate any DLL that sets its own in this way, // though, we will run into some conflicts, at which point we'll have to // BE_NICE_TO_OUR_MODULE_WRITERS and get this called from each of our .dlls. // // See Robbins; I'm using "Debugging Applications" (the VS 6 - era book) // // Separated KnSetCrashHandler from KnSetCrashInfo for two reasons (one // very minor) // // (1) didn't want to change an existing API [very minor, it's only called // in one place] // // (2) want it called *before* we try to do anything across dll boundaries // from nskn. // // OTOH, since it's going to be set before we even _can_ look at the defauls // from the nskn ns_section, we've set up the defaults here so we do get a // stack trace dump during that short time. That shouldn't be enough data // to cause a serious denial of service -- and is a huge win for debugging. /* bool KnSetCrashHandler() { if (! SetCrashHandlerFilter( KnCrashHandler ) ) { KnLog(KnLogError,"Could not set crash handler.\n"); return false ; } #if BE_NICE_TO_OUR_MODULE_WRITERS /* Get the handle for this DLL or module */ HMODULE hMyModule = GetModuleHandle(NULL) ; if (! AddCrashHandlerLimitModule( hMyModule )) { KnLog(KnLogError,"Could not limit crash handling\n"); return false ; } #endif return true; } #else #ifdef __sun #else #include "google/coredumper.h" #endif namespace { char* gCoreFile = "log/liveserver.core"; } bool KnDumpCore() { if (gDumpAtAll) { const char *coreFile = gDumpLocation.length() ? gDumpLocation.c_str() : gCoreFile; #ifdef __sun KnLog(KnLogNotice,"Core dumping currently not supported on Solaris."); #else return 0 == WriteCoreDump(coreFile); #endif } return true; } bool KnSetCrashHandler() { return true; } #endif bool KnSetCrashInfo(const char* dumpLocation, const char* dumpLevel) { if (dumpLocation != NULL) gDumpLocation = dumpLocation; std::string level(dumpLevel); if (level[0] == '0') { gDumpAtAll = false; } #ifdef WIN32 else if (level[0] == '1') { gDumpAtAll = true; gMiniDumpType = MiniDumpNormal; // Just the stacks, ma'am } else if (level[0] == '2') { gDumpAtAll = true; gMiniDumpType = MiniDumpWithDataSegs; } else if (level[0] == '3') { gDumpAtAll = true; gMiniDumpType = MiniDumpWithFullMemory | MiniDumpWithHandleData ; // Hope this also contains Full Data } else { KnLog(KnLogNotice,"Unrecognized dump level '%s'; will set to 'just the stacks' level",level.c_str()); gDumpAtAll = true; gMiniDumpType = MiniDumpNormal; } #else else if (level[0] == '1') { gDumpAtAll = true; } else { KnLog(KnLogNotice,"Unrecognized dump level '%s'; setting dump level to 'true'",level.c_str()); gDumpAtAll = true; } #endif return true; } // We wrote our own so we always get crash dumps the way we want 'em // (and get the assertion in the log) void KnAssert(char *exp, char *file, unsigned int line) { KnLog(KnLogBug,"%s @ %s:%u", exp, file, line); // I wanted something reasonably portable without working too hard, so here's the best I could do on short // notice. All attempts do it with kill (and any portable fault) were // caught by nsd and didn't give core dumps. char *p = 0; ++p; strcpy(p,"assertion failed"); } --- NEW FILE: kncrypt.cpp --- #include "knexportlibraryknutilmodule.h" /** * (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA * * @KNOWNOW_LICENSE_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not * be used to endorse or promote any product without prior written * permission from KnowNow, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @KNOWNOW_LICENSE_END@ **/ #include "knutil/kncrypt.h" KnError KnCrypt(KnString &buf, const KnString &key, const KnString &salt) { char tmp[NS_ENCRYPT_BUFSIZE]; /* * Copy the raw byte string into a KnString. */ buf = Ns_Encrypt(const_cast<char*>(key.c_str()), const_cast<char*>(salt.c_str()), tmp); return KnErrorSuccess; } --- NEW FILE: knerror.cpp --- /* Copyright 2004-2005 KnowNow, Inc */ /** * @KNOWNOW_LICENSE_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not * be used to endorse or promote any product without prior written * permission from KnowNow, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @KNOWNOW_LICENSE_END@ **/ #include "knexportlibraryknutilmodule.h" #include "knutil/knerror.h" #include "knutil/knmutex.h" #include "knutil/knstring.h" #include "knutil/knlog.h" #include "knutil/simpletraits.h" #include "knutil/simplemap.h" namespace { class KnErrorSingleton { public: static KnErrorSingleton& instance(); const KnString* get(KnError errEnum) { unsigned int err = static_cast<unsigned int>(errEnum); const KnString *val = m_map.get(err); if (0 == val) { err &= 0xFF00; val = m_map.get(err); } if (0 == val) { KnString *unknown = new KnString("Unregistered error "); unknown->printf("%u",err); m_map.put(err,unknown); val = m_map.get(err); } if (0 == val) { Ns_Fatal("knerror: Can't map error %d",err); } return val; } private: // Not implemented KnErrorSingleton(const KnErrorSingleton &); KnErrorSingleton &operator=(const KnErrorSingleton &); // Implemented KnErrorSingleton() ; SimpleMap<unsigned int,const KnString *> m_map; static KnErrorSingleton *m_instance ; static KnMutex m_lock; }; KnErrorSingleton* KnErrorSingleton::m_instance = 0 ; KnMutex KnErrorSingleton::m_lock ; KnErrorSingleton& KnErrorSingleton::instance( void ) { if ( 0 == m_instance ) { KnMutex::KnLock guard(m_lock) ; if ( 0 == m_instance ) { m_instance = new KnErrorSingleton ; if (0 == m_instance) { KnLog(KnLogFatal,"knerror: Can't allocate instance"); } } } return *m_instance ; } KnErrorSingleton::KnErrorSingleton() { m_map.put(KnErrorSuccess, &KnStringConstants::success); m_map.put(KnErrorUnauthorized, &KnStringConstants::unauthorized); m_map.put(KnErrorForbidden, &KnStringConstants::forbidden); m_map.put(KnErrorNotFound, &KnStringConstants::notspacefound); m_map.put(KnErrorFailure, &KnStringConstants::failed); /* m_map.put(KnErrorNotFound_Event, new KnString("event not found")); m_map.put(KnErrorNotFound_Route, new KnString("route not found")); m_map.put(KnErrorNotFound_Topic, new KnString("topic not found")); m_map.put(KnErrorNotFound_Journal, new KnString("journal not found")); m_map.put(KnErrorNotFound_Parent, new KnString("parent topic not found")); m_map.put(KnErrorNotFound_SubTopic, new KnString("subtopic not found")); m_map.put(KnErrorNotFound_User, new KnString("user not found")); m_map.put(KnErrorNotFound_Group, new KnString("group not found")); */ } } // Namespace const KnString& KnError_AsString( const KnError err ) { return *KnErrorSingleton::instance().get(err); } const int KnError_AsHTTP(const KnError err) { return err >> 8; } #if 0 KnError KnError_Register(unsigned int err, KnString string) { if (err > 65500 || err < 256) { return KnError_OutOfRange; } return KnErrorSingleton::instance().put(err,string); } #endif --- NEW FILE: knhash.cpp --- #include "knexportlibraryknutilmodule.h" /** * (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA * * @KNOWNOW_LICENSE_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not * be used to endorse or promote any product without prior written * permission from KnowNow, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @KNOWNOW_LICENSE_END@ **/ #include "knutil/knhash.h" #define ind32(value, bits) \ (static_cast<uint32_t>(value) << (bits)) #define ind64(value, bits) \ (static_cast<uint64_t>(value) << (bits)) #define mix32(a, b, c) \ { \ a -= b; a -= c; a ^= (c >> 13); \ b -= c; b -= a; b ^= (a << 8); \ c -= a; c -= b; c ^= (b >> 13); \ a -= b; a -= c; a ^= (c >> 12); \ b -= c; b -= a; b ^= (a << 16); \ c -= a; c -= b; c ^= (b >> 5); \ a -= b; a -= c; a ^= (c >> 3); \ b -= c; b -= a; b ^= (a << 10); \ c -= a; c -= b; c ^= (b >> 15); \ } #define mix64(a, b, c) \ { \ a -= b; a -= c; a ^= (c >> 43); \ b -= c; b -= a; b ^= (a << 9); \ c -= a; c -= b; c ^= (b >> 8); \ a -= b; a -= c; a ^= (c >> 38); \ b -= c; b -= a; b ^= (a << 23); \ c -= a; c -= b; c ^= (b >> 5); \ a -= b; a -= c; a ^= (c >> 35); \ b -= c; b -= a; b ^= (a << 49); \ c -= a; c -= b; c ^= (b >> 11); \ a -= b; a -= c; a ^= (c >> 12); \ b -= c; b -= a; b ^= (a << 18); \ c -= a; c -= b; c ^= (b >> 22); \ } extern "C" { uint32_t hash32(const void *buf, uint32_t len, uint32_t seed) { const uint8_t *p = static_cast<const uint8_t *>(buf); uint32_t a = 0x9E3779B9; uint32_t b = 0x9E3779B9; uint32_t c = seed; uint32_t d = len; for (; d >= 12; d -= 12, p += 12) { a += ind32(p[ 0], 0) + ind32(p[ 1], 8) + ind32(p[ 2], 16) + ind32(p[ 3], 24); b += ind32(p[ 4], 0) + ind32(p[ 5], 8) + ind32(p[ 6], 16) + ind32(p[ 7], 24); c += ind32(p[ 8], 0) + ind32(p[ 9], 8) + ind32(p[10], 16) + ind32(p[11], 24); mix32(a, b, c); } c += len; /* * Duff's Device lives! The first byte of c is reserved for the length. */ switch (d) { case 11: c += ind32(p[10], 24); case 10: c += ind32(p[ 9], 16); case 9: c += ind32(p[ 8], 8); case 8: b += ind32(p[ 7], 24); case 7: b += ind32(p[ 6], 16); case 6: b += ind32(p[ 5], 8); case 5: b += ind32(p[ 4], 0); case 4: a += ind32(p[ 3], 24); case 3: a += ind32(p[ 2], 16); case 2: a += ind32(p[ 1], 8); case 1: a += ind32(p[ 0], 0); } mix32(a, b, c); return c; } uint64_t hash64(const void *buf, uint64_t len, uint64_t seed) { const uint8_t *p = static_cast<const uint8_t *>(buf); uint64_t a = seed; uint64_t b = seed; uint64_t c = 0x9E3779B97F4A7C13ULL; uint64_t d = len; for (; d >= 24; d -= 24, p += 24) { a += ind64(p[ 0], 0) + ind64(p[ 1], 8) + ind64(p[ 2], 16) + ind64(p[ 3], 24) + ind64(p[ 4], 32) + ind64(p[ 5], 40) + ind64(p[ 6], 48) + ind64(p[ 7], 56); b += ind64(p[ 8], 0) + ind64(p[ 9], 8) + ind64(p[10], 16) + ind64(p[11], 24) + ind64(p[12], 32) + ind64(p[13], 40) + ind64(p[14], 48) + ind64(p[15], 56); c += ind64(p[16], 0) + ind64(p[17], 8) + ind64(p[18], 16) + ind64(p[19], 24) + ind64(p[20], 32) + ind64(p[21], 40) + ind64(p[22], 48) + ind64(p[23], 56); mix64(a, b, c); } c += len; /* * Duff's Device lives! The first byte of c is reserved for the length. */ switch (d) { case 23: c += ind64(p[22], 56); case 22: c += ind64(p[21], 48); case 21: c += ind64(p[20], 40); case 20: c += ind64(p[19], 32); case 19: c += ind64(p[18], 24); case 18: c += ind64(p[17], 16); case 17: c += ind64(p[16], 8); case 16: b += ind64(p[15], 56); case 15: b += ind64(p[14], 48); case 14: b += ind64(p[13], 40); case 13: b += ind64(p[12], 32); case 12: b += ind64(p[11], 24); case 11: b += ind64(p[10], 16); case 10: b += ind64(p[ 9], 8); case 9: b += ind64(p[ 8], 0); case 8: a += ind64(p[ 7], 56); case 7: a += ind64(p[ 6], 48); case 6: a += ind64(p[ 5], 40); case 5: a += ind64(p[ 4], 32); case 4: a += ind64(p[ 3], 24); case 3: a += ind64(p[ 2], 16); case 2: a += ind64(p[ 1], 8); case 1: a += ind64(p[ 0], 0); } mix64(a, b, c); return c; } } // extern "C" --- NEW FILE: knlog.cpp --- #include "knexportlibraryknutilmodule.h" /** * (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA * * @KNOWNOW_LICENSE_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not * be used to endorse or promote any product without prior written * permission from KnowNow, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @KNOWNOW_LICENSE_END@ **/ #include "knutil/kntypes.h" #include "knutil/knlog.h" #include <cstdarg> KnError KnLog(KnLogSeverity severity, const KnString &msg) { /* * Reuse existing interface. */ return KnLog(severity, "%.*s", (int)msg.length(), msg.c_str()); } KnError KnLog(KnLogSeverity severity, const char *fmt, ...) { va_list ap; /* * Grab the arguments off the stack. */ va_start(ap, fmt); /* * Note the C-style cast for converting between unrelated enums. */ Ns_ServerLog(Ns_LogSeverity(severity), const_cast<char*>(fmt), &ap); /* * Restore the stack. */ va_end(ap); return KnErrorSuccess; } --- NEW FILE: knmarkuputil.cpp --- ////////////////////////////////////////////////////// /** * (c) Copyright 2008 KnowNow, Inc., Sunnyvale CA * * @KNOWNOW_LICENSE_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "KnowNow" is a trademark of KnowNow, Inc. and may not * be used to endorse or promote any product without prior written * permission from KnowNow, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL KNOWNOW, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @KNOWNOW_LICENSE_END@ **/ // knmarkuputil.cpp // // (c)2002-2006, KnowNow, Inc. All Rights Reserved. #include "knexportlibraryknutilmodule.h" #include "knutil/knmarkuputil.h" #include "knutil/knlog.h" template class EXPORT_LIBRARY_KNUTIL SimpleMap<char*, char*>; KnMarkupUtil::KnMarkupUtil() { buildHtlmEntity(); buildHtlmTags(); } KnMarkupUtil::~KnMarkupUtil() { } void KnMarkupUtil::buildHtlmEntity() { // http://www.w3schools.com/tags/ref_entities.asp // http://www.utoronto.ca/webdocs/HTMLdocs/NewHTML/iso_table.html entityMap.put("#32"," "); entityMap.put("#0x0020"," "); entityMap.put("nbsp"," "); entityMap.put("#33","!"); entityMap.put("#0x0021","!"); entityMap.put("#34","\""); entityMap.put("#0x0022","\""); entityMap.put("quot","\""); entityMap.put("#35","#"); entityMap.put("#0x0023","#"); entityMap.put("#36","$"); entityMap.put("#0x0024","$"); entityMap.put("#37","%"); entityMap.put("#0x0025","%"); entityMap.put("#38","&"); entityMap.put("#0x0026","&"); entityMap.put("amp","&"); entityMap.put("#39","'"); entityMap.put("#0x0027","'"); entityMap.put("#40","("); entityMap.put("#0x0028","("); entityMap.put("#41",")"); entityMap.put("#0x0029",")"); entityMap.put("#42","*"); entityMap.put("#0x002a","*"); entityMap.put("#43","+"); entityMap.put("#0x002b","+"); entityMap.put("#44",","); entityMap.put("#0x002c",","); entityMap.put("#45","-"); entityMap.put("#0x002d","-"); entityMap.put("#46","."); entityMap.put("#0x002e","."); entityMap.put("#47","/"); entityMap.put("#0x002f","/"); entityMap.put("#48","0"); entityMap.put("#0x0030","0"); entityMap.put("#49","1"); entityMap.put("#0x0031","1"); entityMap.put("#50","2"); entityMap.put("#0x0032","2"); entityMap.put("#51","3"); entityMap.put("#0x0033","3"); entityMap.put("#52","4"); entityMap.put("#0x0034","4"); entityMap.put("#53","5"); entityMap.put("#0x0035","5"); entityMap.put("#54","6"); entityMap.put("#0x0036","6"); entityMap.put("#55","7"); entityMap.put("#0x0037","7"); entityMap.put("#56","8"); entityMap.put("#0x0038","8"); entityMap.put("#57","9"); entityMap.put("#0x0039","9"); entityMap.put("#58",":"); entityMap.put("#0x003a",":"); entityMap.put("#59",";"); entityMap.put("#0x003b",";"); entityMap.put("#60","<"); entityMap.put("#0x003c","<"); entityMap.put("lt","<"); entityMap.put("#61","="); entityMap.put("#0x003d","="); entityMap.put("#62",">"); entityMap.put("#0x003e",">"); entityMap.put("gt",">"); entityMap.put("#63","?"); entityMap.put("#0x003f","?"); entityMap.put("#64","@"); entityMap.put("#0x0040","@"); entityMap.put("#65","A"); entityMap.put("#0x0041","A"); entityMap.put("#66","B"); entityMap.put("#0x0042","B"); entityMap.put("#67","C"); entityMap.put("#0x0043","C"); entityMap.put("#68","D"); entityMap.put("#0x0044","D"); entityMap.put("#69","E"); entityMap.put("#0x0045","E"); entityMap.put("#70","F"); entityMap.put("#0x0046","F"); entityMap.put("#71","G"); entityMap.put("#0x0047","G"); entityMap.put("#72","H"); entityMap.put("#0x0048","H"); entityMap.put("#73","I"); entityMap.put("#0x0049","I"); entityMap.put("#74","J"); entityMap.put("#0x004a","J"); entityMap.put("#75","K"); entityMap.put("#0x004b","K"); entityMap.put("#76","L"); entityMap.put("#0x004c","L"); entityMap.put("#77","M"); entityMap.put("#0x004d","M"); entityMap.put("#78","N"); entityMap.put("#0x004e","N"); entityMap.put("#79","O"); entityMap.put("#0x004f","O"); entityMap.put("#80","P"); entityMap.put("#0x0050","P"); entityMap.put("#81","Q"); entityMap.put("#0x0051","Q"); entityMap.put("#82","R"); entityMap.put("#0x0052","R"); entityMap.put("#83","S"); entityMap.put("#0x0053","S"); entityMap.put("#84","T"); entityMap.put("#0x0054","T"); entityMap.put("#85","U"); entityMap.put("#0x0055","U"); entityMap.put("#86","V"); entityMap.put("#0x0056","V"); entityMap.put("#87","W"); entityMap.put("#0x0057","W"); entityMap.put("#88","X"); entityMap.put("#0x0058","X"); entityMap.put("#89","Y"); entityMap.put("#0x0059","Y"); entityMap.put("#90","Z"); entityMap.put("#0x005a","Z"); entityMap.put("#91","["); entityMap.put("#0x005b","["); entityMap.put("#92","\\"); entityMap.put("#0x005c","\\"); entityMap.put("#93","]"); entityMap.put("#0x005d","]"); entityMap.put("#94","^"); entityMap.put("#0x005e","^"); entityMap.put("#95","_"); entityMap.put("#0x005e","_"); entityMap.put("#96","`"); entityMap.put("#0x0060","`"); entityMap.put("#97","a"); entityMap.put("#0x0061","a"); entityMap.put("#98","b"); entityMap.put("#0x0062","b"); entityMap.put("#99","c"); entityMap.put("#0x0063","c"); entityMap.put("#100","d"); entityMap.put("#0x0064","d"); entityMap.put("#101","e"); entityMap.put("#0x0065","e"); entityMap.put("#102","f"); entityMap.put("#0x0066","f"); entityMap.put("#103","g"); entityMap.put("#0x0067","g"); entityMap.put("#104","h"); entityMap.put("#0x0068","h"); entityMap.put("#105","i"); entityMap.put("#0x0069","i"); entityMap.put("#106","j"); entityMap.put("#0x006a","j"); entityMap.put("#107","k"); entityMap.put("#0x006b","k"); entityMap.put("#108","l"); entityMap.put("#0x006c","l"); entityMap.put("#109","m"); entityMap.put("#0x006d","m"); entityMap.put("#110","n"); entityMap.put("#0x006e","n"); entityMap.put("#111","o"); entityMap.put("#0x006f","o"); entityMap.put("#112","p"); entityMap.put("#0x0070","p"); entityMap.put("#113","q"); entityMap.put("#0x0071","q"); entityMap.put("#114","r"); entityMap.put("#0x0072","r"); entityMap.put("#115","s"); entityMap.put("#0x0073","s"); entityMap.put("#116","t"); entityMap.put("#0x0074","t"); entityMap.put("#117","u"); entityMap.put("#0x0075","u"); entityMap.put("#118","v"); entityMap.put("#0x0076","v"); entityMap.put("#119","w"); entityMap.put("#0x0077","w"); entityMap.put("#120","x"); entityMap.put("#0x0078","x"); entityMap.put("#121","y"); entityMap.put("#0x0079","y"); entityMap.put("#122","z"); entityMap.put("#0x007a","z"); entityMap.put("#123","{"); entityMap.put("#0x007b","{"); entityMap.put("#124","|"); entityMap.put("#0x007c","|"); entityMap.put("#125","}"); entityMap.put("#0x007d","}"); entityMap.put("#126","~"); entityMap.put("#0x007e","~"); // ---------------------------- END ASCII ----------------------------- entityMap.put("#160"," "); ... [truncated message content] |