src_other/tuplebase/ZTupleIndex_T.h

00001 /*  @(#) $Id: ZTupleIndex_T.h,v 1.16 2007/02/14 23:26:48 agreen Exp $ */
00002 
00003 /* ------------------------------------------------------------
00004 Copyright (c) 2003 Andrew Green and Learning in Motion, Inc.
00005 http://www.zoolib.org
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a copy
00008 of this software and associated documentation files (the "Software"), to deal
00009 in the Software without restriction, including without limitation the rights
00010 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00011 copies of the Software, and to permit persons to whom the Software is
00012 furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00020 COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023 ------------------------------------------------------------ */
00024 
00025 #ifndef __ZTupleIndex_T__
00026 #define __ZTupleIndex_T__
00027 #include "zconfig.h"
00028 
00029 #include "ZTupleIndex.h"
00030 
00031 // =================================================================================================
00032 #pragma mark -
00033 #pragma mark * ZTupleIndex_T
00034 
00035 template <int kPropCount>
00036 class ZTupleIndex_T : public ZTupleIndex
00037         {
00038 private:
00039         class Key
00040                 {
00041         public:
00042                 bool operator<(const Key& iOther) const
00043                         {
00044                         // When called by lower_bound this is a key in the set, and iOther
00045                         // is a key that's being looked for. So when this has more entries
00046                         // than iOther then this is considered bigger than iOther.
00047 
00048                         // When called by upper_bound this is a key that's being looked for
00049                         // and iOther is a key in the set. So when this has fewer entries
00050                         // than iOther then this is considered bigger than iOther.
00051 
00052                         // The upshot being that when one or other vector of values is
00053                         // exhausted we return false, indicating that this is not smaller
00054                         // than iOther.
00055 
00056                         const ZTupleValue* const* otherIter = &iOther.fValues[0];
00057 
00058                         const ZTupleValue* const* thisIter = &fValues[0];
00059 
00060                         for (size_t x = kPropCount; x; --x)
00061                                 {
00062                                 if (!*otherIter || !*thisIter)
00063                                         {
00064                                         // Our vectors are of different lengths, so we return false as discussed above.
00065                                         return false;
00066                                         }
00067 
00068                                 if (int compare = (*thisIter)->Compare(**otherIter))
00069                                         return compare < 0;
00070                                 ++thisIter;
00071                                 ++otherIter;
00072                                 }
00073                         return fID < iOther.fID;
00074                         }
00075 
00076                 uint64 fID;
00077                 const ZTupleValue* fValues[kPropCount];
00078                 };
00079 
00080 public:
00081         ZTupleIndex_T(const ZTuplePropName* iPropNames)
00082                 {
00083                 std::copy(iPropNames, iPropNames + kPropCount, fPropNames);
00084                 }
00085 
00086         virtual void Add(uint64 iID, const ZTuple* iTuple)
00087                 {
00088                 Key theKey;
00089                 if (this->pKeyFromTuple(iID, iTuple, theKey))
00090                         fSet.insert(theKey);
00091                 }
00092 
00093         virtual void Remove(uint64 iID, const ZTuple* iTuple)
00094                 {
00095                 Key theKey;
00096                 if (this->pKeyFromTuple(iID, iTuple, theKey))
00097                         fSet.erase(theKey);
00098                 }
00099 
00100         virtual void Find(const std::set<uint64>& iSkipIDs,
00101                 std::vector<const ZTBSpec::Criterion*>& ioCriteria, std::vector<uint64>& oIDs)
00102                 {       
00103                 typename set<Key>::const_iterator lowerBound, upperBound;
00104                 if (this->pSetupIterators(ioCriteria, lowerBound, upperBound))
00105                         {
00106                         if (iSkipIDs.empty())
00107                                 {
00108                                 for (/*no init*/; lowerBound != upperBound; ++lowerBound)
00109                                         oIDs.push_back((*lowerBound).fID);
00110                                 }
00111                         else
00112                                 {
00113                                 for (/*no init*/; lowerBound != upperBound; ++lowerBound)
00114                                         {
00115                                         if (iSkipIDs.end() == iSkipIDs.find((*lowerBound).fID))
00116                                                 oIDs.push_back((*lowerBound).fID);
00117                                         }
00118                                 }
00119                         }
00120                 }
00121 
00122         virtual size_t CanHandle(const ZTBSpec::CriterionSect& iCriterionSect)
00123                 {
00124                 vector<const ZTBSpec::Criterion*> remainingCriteria;
00125                 remainingCriteria.reserve(iCriterionSect.size());
00126                 for (ZTBSpec::CriterionSect::const_iterator i = iCriterionSect.begin(),
00127                         theEnd = iCriterionSect.end();
00128                         i != theEnd; ++i)
00129                         {
00130                         remainingCriteria.push_back(&(*i));
00131                         }
00132 
00133                 size_t likelyResultSize = fSet.size();
00134 
00135                 size_t propertyCount = 0;
00136 
00137                 const ZTupleValue* valueEqual;
00138                 const ZTupleValue* bestValueLess;
00139                 const ZTupleValue* bestValueLessEqual;
00140                 const ZTupleValue* bestValueGreater;
00141                 const ZTupleValue* bestValueGreaterEqual;
00142 
00143                 // Walk through our properties, looking for and removing entries in
00144                 // remainingCriteria where where the effective constraint is equivalence.
00145                 for (const ZTuplePropName* propNameIter = fPropNames;
00146                         propertyCount < kPropCount; ++propertyCount)
00147                         {
00148                         if (!sGatherMergeConstraints(*propNameIter++, remainingCriteria,
00149                                 valueEqual,
00150                                 bestValueLess, bestValueLessEqual, bestValueGreater, bestValueGreaterEqual))
00151                                 {
00152                                 // We found a contradiction, so we can trivially handle this search.
00153                                 return 1;
00154                                 }
00155 
00156                         if (!valueEqual)
00157                                 break;
00158 
00159                         ZAssertStop(ZCONFIG_TupleIndex_Debug, !bestValueLess && !bestValueLessEqual
00160                                 && !bestValueGreater && !bestValueGreaterEqual);
00161 
00162                         likelyResultSize /= 2;
00163                         }
00164 
00165                 if (propertyCount != kPropCount)
00166                         {
00167                         // We still have properties on which we index not referenced by the criteria we've seen.
00168                         if (bestValueLess || bestValueLessEqual || bestValueGreater || bestValueGreaterEqual)
00169                                 {
00170                                 // We at least had a range check on the last item, so move on.
00171                                 likelyResultSize /= 2;
00172                                 ++propertyCount;
00173                                 }
00174                         }
00175 
00176                 if (!propertyCount)
00177                         {
00178                         // We didn't see any matching property names at all, so we can't help.
00179                         return 0;
00180                         }
00181 
00182                 // Add 1, so we can't return zero.
00183                 return likelyResultSize + 1;
00184                 }
00185 
00186 //      virtual void WriteDescription(const ZStrimW& s);
00187 
00188 private:
00189         bool pSetupIterators(std::vector<const ZTBSpec::Criterion*>& ioCriteria,
00190                 typename std::set<Key>::const_iterator& oLowerBound, typename std::set<Key>::const_iterator& oUpperBound)
00191                 {
00192                 Key theKey;
00193 
00194                 theKey.fValues[0] = nil;
00195 
00196                 if (kPropCount > 1)
00197                         theKey.fValues[1] = nil;
00198                 if (kPropCount > 2)
00199                         theKey.fValues[2] = nil;
00200                 if (kPropCount > 3)
00201                         theKey.fValues[3] = nil;
00202                 if (kPropCount > 4)
00203                         theKey.fValues[4] = nil;
00204                 if (kPropCount > 5)
00205                         {
00206                         for (size_t x = 5; x < kPropCount; ++x)
00207                                 theKey.fValues[x] = nil;
00208                         }
00209 
00210                 size_t keyPropCount = 0;
00211 
00212                 const ZTupleValue* valueEqual;
00213                 const ZTupleValue* bestValueLess;
00214                 const ZTupleValue* bestValueLessEqual;
00215                 const ZTupleValue* bestValueGreater;
00216                 const ZTupleValue* bestValueGreaterEqual;
00217 
00218                 // Walk through our properties, looking for and removing entries in
00219                 // ioCriteria where where the effective constraint is equivalence.
00220                 for (const ZTuplePropName* propNameIter = fPropNames;
00221                         keyPropCount < kPropCount; ++propNameIter)
00222                         {
00223                         if (!sGatherMergeConstraints(*propNameIter, ioCriteria,
00224                                 valueEqual,
00225                                 bestValueLess, bestValueLessEqual, bestValueGreater, bestValueGreaterEqual))
00226                                 {
00227                                 // We found a contradiction, so we have completed the search, with no results.
00228                                 return false;
00229                                 }
00230 
00231                         if (!valueEqual)
00232                                 break;
00233 
00234                         ZAssertStop(ZCONFIG_TupleIndex_Debug, !bestValueLess && !bestValueLessEqual
00235                                 && !bestValueGreater && !bestValueGreaterEqual);
00236                         theKey.fValues[keyPropCount++] = valueEqual;
00237                         }
00238 
00239                 if (bestValueGreater)
00240                         {
00241                         ZAssertStop(ZCONFIG_TupleIndex_Debug, !bestValueGreaterEqual);
00242                         theKey.fID = kMaxID;
00243                         theKey.fValues[keyPropCount] = bestValueGreater;
00244                         oLowerBound = fSet.upper_bound(theKey);
00245                         theKey.fValues[keyPropCount] = nil;
00246                         }
00247                 else if (bestValueGreaterEqual)
00248                         {
00249                         theKey.fID = 0;
00250                         theKey.fValues[keyPropCount] = bestValueGreaterEqual;
00251                         oLowerBound = fSet.lower_bound(theKey);
00252                         theKey.fValues[keyPropCount] = nil;
00253                         }
00254                 else
00255                         {
00256                         // Find the first entry greater than or equal to
00257                         // the (possibly empty) equals portion of the key.
00258                         theKey.fID = 0;
00259                         oLowerBound = fSet.lower_bound(theKey);
00260                         }
00261 
00262                 if (bestValueLess)
00263                         {
00264                         ZAssertStop(ZCONFIG_TupleIndex_Debug, !bestValueLessEqual);
00265                         theKey.fID = 0;
00266                         theKey.fValues[keyPropCount] = bestValueLess;
00267                         oUpperBound = fSet.lower_bound(theKey);
00268                         }
00269                 else if (bestValueLessEqual)
00270                         {
00271                         theKey.fID = kMaxID;
00272                         theKey.fValues[keyPropCount] = bestValueLessEqual;
00273                         oUpperBound = fSet.upper_bound(theKey);
00274                         }
00275                 else
00276                         {
00277                         // Find the first tuple greater than the (possibly
00278                         // empty) equals portion of the key.
00279                         theKey.fID = kMaxID;
00280                         oUpperBound = fSet.upper_bound(theKey);
00281                         }
00282 
00283                 return true;
00284                 }
00285 
00286         bool pKeyFromTuple(uint64 iID, const ZTuple* iTuple, Key& oKey)
00287                 {
00288                 ZTuple::const_iterator tupleIter = iTuple->IteratorOf(fPropNames[0]);
00289                 if (tupleIter == iTuple->end())
00290                         {
00291                         // The tuple does not have our first property, so there's no point
00292                         // in storing it -- no search we can do will help find this tuple.
00293                         return false;
00294                         }
00295 
00296                 oKey.fValues[0] = &iTuple->GetValue(tupleIter);
00297                 
00298                 for (size_t x = 1; x < kPropCount; ++x)
00299                         oKey.fValues[x] = &iTuple->GetValue(fPropNames[x]);
00300 
00301                 oKey.fID = iID;
00302                 return true;
00303                 }
00304 
00305         ZTuplePropName fPropNames[kPropCount];
00306         std::set<Key> fSet;
00307         };
00308 
00309 // =================================================================================================
00310 #pragma mark -
00311 #pragma mark * ZTupleIndexFactory_T
00312 
00313 template <int kPropCount>
00314 class ZTupleIndexFactory_T : public ZTupleIndexFactory
00315         {
00316 public:
00317         ZTupleIndexFactory_T(const std::string* iPropNames)
00318                 {
00319                 std::copy(iPropNames, iPropNames + kPropCount, fPropNames);
00320                 }
00321 
00322         // From ZTupleIndexFactory
00323         virtual ZTupleIndex* Make()
00324                 { return new ZTupleIndex_T<kPropCount>(fPropNames); }
00325 
00326 private:
00327         ZTuplePropName fPropNames[kPropCount];
00328         };
00329 
00330 #endif // __ZTupleIndex_T__

Generated on Thu Jul 26 11:21:59 2007 for ZooLib by  doxygen 1.4.7