RTBKit  0.9
Open-source framework to create real-time ad bidding systems.
soa/types/id.h
00001 /* id.h                                                            -*- C++ -*-
00002    Jeremy Barnes, 17 February 2012
00003    Copyright (c) 2012 Datacratic.  All rights reserved.
00004 
00005    Basic ID type for binary IDs of all types.
00006 */
00007 
00008 #pragma once
00009 
00010 #include "city.h" // Google city hash function
00011 #include <string>
00012 #include "jml/utils/unnamed_bool.h"
00013 #include "jml/db/persistent_fwd.h"
00014 #include "jml/utils/less.h"
00015 #include "jml/arch/exception.h"
00016 
00017 namespace Json {
00018 struct Value;
00019 } // namespace Json
00020 
00021 namespace Datacratic {
00022 
00023 /* 
00024    JTzfCLBhlbWSsdZjcJ4wO4
00025    
00026    Google ID: --> CAESEAYra3NIxLT9C8twKrzqaA
00027    AGID: --> 0828398c-5965-11e0-84c8-0026b937c8e1
00028    ANID: --> 7394206091425759590
00029 
00030    
00031    0828398c-5965-11e0-84c8-0026b937c8e1
00032    32       16   16   16   48
00033    
00034    AYra3NIxLT9C8twKrzqaA
00035    
00036    21 * 6 = 126 bits so 128 bits
00037 */
00038 
00039 /*****************************************************************************/
00040 /* ID                                                                        */
00041 /*****************************************************************************/
00042 
00046 struct Id {
00047 
00048     enum Type {
00049         NONE = 0,
00050         NULLID = 1,
00051         UUID = 2,        
00052         GOOG128 = 3,     
00053         BIGDEC = 4,      
00054         BASE64_96 = 5,   
00055 
00056         // other integer-encoded values go here
00057 
00058         STR = 192,       
00059         //CUSTOM = 6       /// custom type with custom handlers
00060 
00061         COMPOUND2 = 193,  
00062         
00063         // other string-encoded values go here
00064 
00065         UNKNOWN = 255
00066     };
00067 
00068     Id()
00069         : type(NONE), val1(0), val2(0)
00070     {
00071     }
00072 
00073     ~Id()
00074     {
00075         if (type >= STR)
00076             complexDestroy();
00077     }
00078 
00079     explicit Id(const std::string & value,
00080                 Type type = UNKNOWN)
00081         : type(NONE), val1(0), val2(0)
00082     {
00083         parse(value, type);
00084     }
00085     
00086     explicit Id(uint64_t value):
00087             type(BIGDEC),
00088             val1(value),val2(0)
00089     {
00090     }
00091 
00092 
00093     // Construct a compound ID from two others
00094     Id(const Id & underlying1, const Id & underlying2)
00095         : type(COMPOUND2),
00096           cmp1(new Id(underlying1)),
00097           cmp2(new Id(underlying2))
00098     {
00099     }
00100 
00101     Id(Id && other)
00102         : type(other.type),
00103           val1(other.val1), val2(other.val2)
00104     {
00105         other.type = NONE;
00106     }
00107 
00108     Id(const Id & other)
00109         : type(other.type),
00110           val1(other.val1), val2(other.val2)
00111     {
00112         if (other.type >= STR)
00113             complexFinishCopy();
00114     }
00115 
00116     Id & operator = (Id && other)
00117     {
00118         if (type >= STR)
00119             complexDestroy();
00120         type = other.type;
00121         val1 = other.val1;
00122         val2 = other.val2;
00123         other.type = NONE;
00124         return *this;
00125     }
00126 
00127     Id & operator = (const Id & other)
00128     {
00129         if (type >= STR)
00130             complexDestroy();
00131         type = other.type;
00132         val1 = other.val1;
00133         val2 = other.val2;
00134         if (other.type >= STR)
00135             complexFinishCopy();
00136         return *this;
00137     }
00138 
00139     void parse(const std::string & value, Type type = UNKNOWN);
00140     
00141     std::string toString() const;
00142 
00143     uint64_t toInt() const
00144     {
00145         if (type != BIGDEC)
00146             throw ML::Exception("can't convert non-BIGDEC to int");
00147         return val1;
00148     }
00149 
00150     //operator std::string () const
00151     //{
00152     //    return toString();
00153     //}
00154 
00155     bool notNull() const
00156     {
00157         return type >= NULLID
00158             && val != 0;
00159     }
00160 
00161     JML_IMPLEMENT_OPERATOR_BOOL(notNull());
00162 
00163     bool operator == (const Id & other) const
00164     {
00165         if (type != other.type) return false;
00166         if (type == NONE || type == NULLID) return true;
00167         if (JML_UNLIKELY(type >= STR)) return complexEqual(other);
00168         return val == other.val;
00169     }
00170 
00171     bool operator != (const Id & other) const
00172     {
00173         return ! operator == (other);
00174     }
00175     
00176     bool operator < (const Id & other) const
00177     {
00178         if (type < other.type) return true;
00179         if (other.type < type) return false;
00180         if (JML_UNLIKELY(type >= STR)) return complexLess(other);
00181         return val < other.val;
00182     }
00183 
00184     uint64_t hash() const
00185     {
00186         if (type == NONE || type == NULLID) return 0;
00187         if (JML_UNLIKELY(type >= STR)) return complexHash();
00188         return Hash128to64(std::make_pair(val1, val2));
00189     }
00190 
00191     bool complexEqual(const Id & other) const;
00192     bool complexLess(const Id & other) const;
00193     uint64_t complexHash() const;
00194     void complexDestroy();
00195     void complexFinishCopy();
00196 
00197     uint8_t type;
00198     uint8_t unused[3];
00199 
00200     union {
00201         // 128 byte integer
00202         struct {
00203             uint64_t val1;
00204             uint64_t val2;
00205         };
00206 
00207         struct {
00208             uint32_t v1h, v1l;
00209             uint32_t v2h, v2l;
00210         };
00211 
00212         __uint128_t val;
00213 
00214         // uuid
00215         struct {
00216             uint64_t f1:32;
00217             uint64_t f2:16;
00218             uint64_t f3:16;
00219             uint64_t f4:16;
00220             uint64_t f5:48;
00221         };
00222 
00223         // string
00224         struct {
00225             uint64_t len:56;
00226             uint64_t ownstr:8;
00227             const char * str;
00228         };
00229 
00230         // compound2
00231         struct {
00232             Id * cmp1;
00233             Id * cmp2;
00234         };
00235 #if 0
00236         // custom
00237         struct {
00238             void * data;
00239             uint64_t (*controlFn) (int, Id *, Id *);
00240         };
00241 #endif
00242     };
00243 
00245     const Id & compoundId1() const;
00246 
00248     const Id & compoundId2() const;
00249     
00250     void serialize(ML::DB::Store_Writer & store) const;
00251     void reconstitute(ML::DB::Store_Reader & store);
00252 
00253     Json::Value toJson() const;
00254     static Id fromJson(const Json::Value & val);
00255 } JML_PACKED;
00256 
00257 IMPL_SERIALIZE_RECONSTITUTE(Id);
00258 
00259 inline std::ostream & operator << (std::ostream & stream, const Id & id)
00260 {
00261     return stream << id.toString();
00262 }
00263 
00264 inline std::istream & operator >> (std::istream & stream, Id & id)
00265 {
00266     std::string s;
00267     stream >> s;
00268     id.parse(s);
00269     return stream;
00270 }
00271 
00272 } // namespace Datacratic
00273 
00274 namespace std {
00275 
00276 template<typename T> struct hash;
00277 
00278 template<>
00279 struct hash<Datacratic::Id> : public std::unary_function<Datacratic::Id, size_t>
00280 {
00281     size_t operator()(const Datacratic::Id & id) const { return id.hash(); }
00282 };
00283 
00284 } // namespace std
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator