/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#ifndef POLYGRAPH__BASE_UNIQID_H
#define POLYGRAPH__BASE_UNIQID_H
#include "xstd/h/iosfwd.h"
class Area;
class String;
class OLog;
class ILog;
class OBStream;
class IBStream;
// we often need an id with these characteristics:
// - truly unique across hosts, processes, time (within ttl), etc
// - at least one year ttl
// - compact to store
// - fast to produce [possibly in huge quantaties!]
// - fast to compare on equality
// - has one and only one "permutated" value that
// cannot be generated by means other than "mutating" an id
class UniqId {
public:
static UniqId Create() { return UniqId().create(); }
static void Space(int id); // generate ids in a given space
static UniqId FromStr(const Area &area);
public:
UniqId();
UniqId(int aSecs, int aMix, int aCnt);
void clear() { theCnt = 0; }
UniqId &create(); // returns itself
operator void*() const { return theCnt > 0 ? (void*)-1 : 0; } // created?
bool mutant() const { return theCnt & 1; } // is a mutatant?
inline bool myMutant(const UniqId &mid) const;
inline UniqId genMutant() const; // produce a mutant
// returns a not so unique integer
int hash() const;
String str() const;
inline bool operator ==(const UniqId &id) const;
inline bool operator !=(const UniqId &id) const;
inline bool operator <(const UniqId &id) const; // arbirtary order
ostream &print(ostream &os) const;
OLog &store(OLog &ol) const;
ILog &load(ILog &il);
OBStream &store(OBStream &os) const;
IBStream &load(IBStream &is);
protected:
void RefreshSessionId();
protected:
int theSecs; // seconds since Nov 29 06:21:18 MST 1998 (or space XXX)
int theMix; // usec and process id
int theCnt; // instance
};
/* inline definitions */
inline
ostream &operator <<(ostream &os, const UniqId &id) { return id.print(os); }
inline
OLog &operator <<(OLog &ol, const UniqId &id) { return id.store(ol); }
inline
ILog &operator >>(ILog &il, UniqId &id) { return id.load(il); }
inline
OBStream &operator <<(OBStream &os, const UniqId &id) { return id.store(os); }
inline
IBStream &operator >>(IBStream &is, UniqId &id) { return id.load(is); }
inline
UniqId UniqId::genMutant() const {
return UniqId(theSecs, theMix, ~theCnt & 0x7fffffff);
}
inline
bool UniqId::myMutant(const UniqId &m) const {
return (m.theCnt == (~theCnt & 0x7fffffff)) &&
theMix == m.theMix &&
theSecs == m.theSecs;
}
inline
bool UniqId::operator ==(const UniqId &id) const {
return theCnt == id.theCnt && // most selective first
theMix == id.theMix &&
theSecs == id.theSecs;
}
inline
bool UniqId::operator !=(const UniqId &id) const {
return !(*this == id);
}
inline
bool UniqId::operator <(const UniqId &id) const {
if (theCnt < id.theCnt)
return true;
if (theCnt > id.theCnt)
return false;
if (theMix < id.theMix)
return true;
if (theMix > id.theMix)
return false;
return theSecs < id.theSecs;
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1