RegisterReference.h

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/calculator/RegisterReference.h#3 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2004-2009 SQLstream, Inc.
00006 // Copyright (C) 2009-2009 LucidEra, Inc.
00007 //
00008 // This program is free software; you can redistribute it and/or modify it
00009 // under the terms of the GNU General Public License as published by the Free
00010 // Software Foundation; either version 2 of the License, or (at your option)
00011 // any later version approved by The Eigenbase Project.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 //
00022 // RegisterReference
00023 //
00024 */
00025 #ifndef Fennel_RegisterReference_Included
00026 #define Fennel_RegisterReference_Included
00027 
00028 #include "fennel/tuple/TupleData.h"
00029 #include "fennel/tuple/StandardTypeDescriptor.h"
00030 #include "fennel/exec/DynamicParam.h"
00031 #include "boost/lexical_cast.hpp"
00032 
00033 #include <strstream>
00034 
00035 FENNEL_BEGIN_NAMESPACE
00036 
00037 using namespace std;
00038 using boost::lexical_cast;
00039 
00040 class Calculator;
00041 class RegisterSetBinding;
00042 
00043 typedef RegisterSetBinding ** TRegisterSetP;
00044 typedef TupleDescriptor ** TRegisterSetDescP;
00045 typedef uint32_t TRegisterRefProp;
00046 
00047 
00049 class FENNEL_CALCULATOR_EXPORT RegisterSetBinding
00050 {
00051     const bool ownTheBase;              // we own (and will delete) the base
00052     uint ncols;
00053     TupleData *const base;              // the underlying data
00054     PConstBuffer *datumAddr;            // we allocate
00055     // In this set, the nth register is bound to TupleDatum d = (*base)[n].
00056     // Its length is d.cbLen, its location is d.pDatum.
00057     // However, d.pDatum = 0 indicates a null value.
00058     // At bind time, the datum location for the nth register is copied to
00059     // datumAddr[n]; saving this address lets the calculator overwrite a null
00060     // value. Changing the register value via the TupleDatum directly changes
00061     // base.
00062 
00063 public:
00064     ~RegisterSetBinding();
00065 
00069     RegisterSetBinding(TupleData* base, bool ownIt = false);
00070 
00077     RegisterSetBinding(
00078         TupleData* base,
00079         const TupleData* shadow,
00080         bool ownIt = false);
00081 
00083     const TupleData& asTupleData() const {
00084         return *base;
00085     }
00086 
00088     TupleDatum& operator[](int n) {
00089         assert((n >= 0) && (n < ncols));
00090         return (*base)[n];
00091     }
00092 
00094     PConstBuffer getTargetAddr(int n) {
00095         assert((n >= 0) && (n < ncols));
00096         return datumAddr[n];
00097     }
00098 };
00099 
00100 
00113 class FENNEL_CALCULATOR_EXPORT RegisterReference
00114 {
00115 public:
00117     enum ERegisterSet {
00118         EFirstSet = 0,
00119         ELiteral =  0,
00120         EInput =    1,
00121         EOutput =   2,
00122         ELocal =    3,
00123         EStatus =   4,
00124         ELastSet,           
00125         EUnknown =  1000
00126     };
00127 
00129     explicit
00130     RegisterReference()
00131         : mSetIndex(EUnknown),
00132           mIndex(0),
00133           mType(STANDARD_TYPE_END_NO_UNICODE),
00134           mPData(0),
00135           mCbData(0),
00136           mCbStorage(0),
00137           mPDynamicParamManager(0)
00138     {
00139         mProp = EPropNone;
00140     }
00141 
00147     explicit
00148     RegisterReference(
00149         ERegisterSet set,
00150         unsigned long index,
00151         StandardTypeDescriptorOrdinal datatype)
00152         : mSetIndex(set),
00153           mIndex(index),
00154           mType(datatype),
00155           mPData(0),
00156           mCbData(0),
00157           mCbStorage(0),
00158           mPDynamicParamManager(0)
00159     {
00160         assert(mSetIndex < ELastSet);
00161         assert(mSetIndex >= EFirstSet);
00162         setDefaultProperties();
00163     }
00164 
00165     virtual
00166     ~RegisterReference() {}
00167 
00168 
00172     enum EProperties {
00173         EPropNone         = 0,  
00174         EPropReadOnly     = 1,  
00175 
00176         EPropCachePointer = 2,  
00177 
00178         EPropPtrReset     = 4,  
00179         EPropByRefOnly    = 8   
00180 
00181 
00182     };
00183 
00184     // TODO: Replace with array indexed by ERegisterSet
00186     static const uint32_t KLiteralSetDefault =
00187         EPropReadOnly | EPropCachePointer;
00188 
00190     static const uint32_t KInputSetDefault   = EPropReadOnly;
00191 
00193     static const uint32_t KOutputSetDefault  = EPropNone;
00194 
00197     static const uint32_t KLocalSetDefault   =
00198         EPropCachePointer | EPropPtrReset;
00199 
00201     static const uint32_t KStatusSetDefault  = EPropNone;
00202 
00208     void setCalc(Calculator* calcP);
00209 
00214     void cachePointer();
00215 
00217     ERegisterSet setIndex() const
00218     {
00219         return mSetIndex;
00220     }
00222     unsigned long index() const
00223     {
00224         return mIndex;
00225     }
00227     bool isValid() const
00228     {
00229         return ((mSetIndex < ELastSet) ? true : false);
00230     }
00232     StandardTypeDescriptorOrdinal type() const {
00233         return mType;
00234     }
00235 
00237     static inline string getSetName(ERegisterSet set)
00238     {
00239         switch (set) {
00240         case ELiteral:
00241             return "C";
00242         case ELocal:
00243             return "L";
00244         case EInput:
00245             return "I";
00246         case EOutput:
00247             return "O";
00248         case EStatus:
00249             return "S";
00250         default:
00251             throw std::invalid_argument(
00252                 "fennel/calculator/RegisterReference::getSetName");
00253         }
00254     }
00255 
00256 
00259     static inline string toString(ERegisterSet set, unsigned long index)
00260     {
00261         ostringstream ostr("");
00262         ostr << getSetName(set) << index;
00263         return ostr.str();
00264     }
00265 
00267     string toString() const;
00269     virtual string valueToString() const = 0;
00271     virtual bool isNull() const = 0;
00272 
00274     inline DynamicParamManager* getDynamicParamManager() const {
00275         assert(mPDynamicParamManager);
00276         return mPDynamicParamManager;
00277     }
00278 
00282     TupleDatum* getBinding(bool resetFromNull = false) const {
00283         // validate indexes
00284         assert(mRegisterSetP);
00285         assert(mSetIndex < ELastSet);
00286         assert(mRegisterSetP[mSetIndex]);
00287         RegisterSetBinding* rsb = mRegisterSetP[mSetIndex];
00288         TupleDatum& bind = (*rsb)[mIndex];
00289         if (resetFromNull) {
00290             if (!bind.pData) {
00291                 bind.pData = mRegisterSetP[mSetIndex]->getTargetAddr(mIndex);
00292             }
00293         }
00294         return &bind;
00295     }
00296 
00297 protected:
00299     const ERegisterSet mSetIndex;
00300 
00302     const unsigned long mIndex;
00303 
00305     const StandardTypeDescriptorOrdinal mType;
00306 
00310     TRegisterSetP mRegisterSetP;
00311 
00315     TRegisterSetDescP mRegisterSetDescP;
00316 
00320     vector<RegisterReference *>*mResetP;
00321 
00323     bool mCachePtrModified;
00324 
00328     PBuffer mPData;
00329 
00333     TupleStorageByteLength mCbData;
00334 
00338     TupleStorageByteLength mCbStorage;
00339 
00341     TRegisterRefProp mProp;
00342 
00344     DynamicParamManager* mPDynamicParamManager;
00345 
00347     void setDefaultProperties();
00348 
00349 };
00350 
00352 template<typename TMPLT>
00353 class RegisterRef : public RegisterReference
00354 {
00355 public:
00356     explicit
00358     RegisterRef () : RegisterReference()
00359     {}
00360 
00366     explicit
00367     RegisterRef(
00368         ERegisterSet set,
00369         unsigned long index,
00370         StandardTypeDescriptorOrdinal datatype)
00371         : RegisterReference(set, index, datatype)
00372     {}
00373 
00377     TMPLT value() const {
00378         if (mProp & (EPropCachePointer | EPropPtrReset)) {
00379             assert(mPData);
00380             return *(reinterpret_cast<TMPLT*>(mPData));
00381         } else {
00382             TupleDatum *bind = getBinding();
00383             assert(bind->pData); // Cannot read from a NULL value.
00384             return *(reinterpret_cast<TMPLT*>(
00385                 const_cast<PBuffer>(bind->pData)));
00386         }
00387     }
00388 
00389 
00391     void
00392     value(TMPLT newV)
00393     {
00394         // JDF 06/19/06 Need to find out why output register used for
00395         // histogram support gets marked as ReadOnly.
00396         if (0) {
00397             assert(!(mProp & EPropReadOnly));
00398         }
00399 
00400         if (mProp & (EPropCachePointer | EPropPtrReset)) {
00401             assert(mPData);
00402             *(reinterpret_cast<TMPLT*>(mPData)) = newV;
00403         } else {
00404             TupleDatum *bind = getBinding(true); // reset when null
00405             assert(bind->pData);
00406             *(reinterpret_cast<TMPLT*>(
00407                 const_cast<PBuffer>(bind->pData))) = newV;
00408         }
00409     }
00410 
00412     bool isNullable()
00413     {
00414         return !(mProp & EPropReadOnly);
00415     }
00416 
00420     void toNull() {
00421         assert(!(mProp & EPropReadOnly));
00422         if (mProp & (EPropCachePointer | EPropPtrReset)) {
00423             if ((mProp & EPropPtrReset) && !mCachePtrModified) {
00424                 mCachePtrModified = true;
00425                 mResetP->push_back(this);
00426             }
00427             mPData = NULL;
00428             mCbData = 0;
00429         } else {
00430             TupleDatum *bind = getBinding();
00431             bind->pData = NULL;
00432         }
00433     }
00434 
00436     bool isNull() const {
00437         if (mProp & (EPropCachePointer | EPropPtrReset)) {
00438             return (mPData ? false : true);
00439         } else {
00440             TupleDatum *bind = getBinding();
00441             return (bind->pData ? false : true);
00442         }
00443     }
00444 
00450     TMPLT
00451     pointer() const {
00452         assert(StandardTypeDescriptor::isArray(mType));
00453         if (mProp & (EPropCachePointer | EPropPtrReset)) {
00454             assert(mPData);  // useful or harmful?
00455             return reinterpret_cast<TMPLT>(mPData);
00456         } else {
00457             TupleDatum *bind = getBinding();
00458             assert(bind->pData);
00459             return reinterpret_cast<TMPLT>(const_cast<PBuffer>(bind->pData));
00460         }
00461     }
00468     void
00469     pointer(TMPLT newP, TupleStorageByteLength len)
00470     {
00471         assert(!(mProp & EPropReadOnly));
00472         assert(newP);  // use toNull()
00473         assert(StandardTypeDescriptor::isArray(mType));
00474         if (mProp & (EPropCachePointer | EPropPtrReset)) {
00475             if ((mProp & EPropPtrReset) && !mCachePtrModified) {
00476                 mCachePtrModified = true;
00477                 mResetP->push_back(this);
00478             }
00479             mPData = reinterpret_cast<PBuffer>(newP);
00480             mCbData = len;
00481         } else {
00482             TupleDatum *bind = getBinding();
00483             bind->pData = reinterpret_cast<PConstBuffer>(newP);
00484             bind->cbData = len;
00485         }
00486     }
00488     TMPLT*
00489     refer() const {
00490         if (mProp & (EPropCachePointer | EPropPtrReset)) {
00491             return reinterpret_cast<TMPLT*>(const_cast<PBuffer>(mPData));
00492         } else {
00493             TupleDatum *bind = getBinding();
00494             return reinterpret_cast<TMPLT*>(const_cast<PBuffer>(bind->pData));
00495         }
00496     }
00503     void
00504     refer(RegisterRef<TMPLT>* from)
00505     {
00506         assert(!(mProp & (EPropCachePointer | EPropPtrReset)));
00507         TupleDatum *bind = getBinding();
00508         bind->pData = reinterpret_cast<PConstBuffer>(
00509             const_cast<TMPLT*>(from->refer()));
00510         bind->cbData = from->length();
00511     }
00512 
00518     TupleStorageByteLength
00519     length() const
00520     {
00521         if (mProp & (EPropCachePointer | EPropPtrReset)) {
00522             return mCbData;
00523         } else {
00524             TupleDatum *bind = getBinding();
00525             return bind->cbData;
00526         }
00527     }
00534     TupleStorageByteLength
00535     storage() const
00536     {
00537         if (mProp & (EPropCachePointer | EPropPtrReset)) {
00538             return mCbStorage;
00539         } else {
00540             assert(mRegisterSetP);
00541             assert(mSetIndex < ELastSet);
00542             assert(mRegisterSetDescP[mSetIndex]);
00543             //Next 3 lines clarify complex 4th line:
00544             //TupleDescriptor* tupleDescP = mRegisterSetDescP[mSetIndex];
00545             //TupleAttributeDescriptor* attrP = &((*tupleDescP)[mIndex]);
00546             //return attrP->cbStorage;
00547             return ((*(mRegisterSetDescP[mSetIndex]))[mIndex]).cbStorage;
00548         }
00549     }
00554     TupleStorageByteLength
00555     stringLength() const
00556     {
00557         assert(StandardTypeDescriptor::isArray(mType));
00558         if (StandardTypeDescriptor::isVariableLenArray(mType)) {
00559             return length();
00560         } else {
00561             return storage();
00562         }
00563     }
00569     void
00570     length(TupleStorageByteLength newLen)
00571     {
00572         if (mProp & (EPropCachePointer | EPropPtrReset)) {
00573             // useful or harmful?
00574             assert(newLen == 0 ? true : (mPData == 0 ? false : true));
00575             // useful or harmful?
00576             assert(newLen <= mCbStorage);
00577             mCbData = newLen;
00578         } else {
00579             assert(
00580                 newLen
00581                 <= ((*(mRegisterSetDescP[mSetIndex]))[mIndex]).cbStorage);
00582             TupleDatum *bind = getBinding();
00583             bind->cbData = newLen;
00584         }
00585     }
00590     void
00591     stringLength(TupleStorageByteLength newLen)
00592     {
00593         assert(StandardTypeDescriptor::isArray(mType));
00594         if (StandardTypeDescriptor::isVariableLenArray(mType)) {
00595             length(newLen);
00596         }
00597     }
00598 
00603     string
00604     valueToString() const {
00605         if (this->isNull()) { // does assert checking for us
00606             return "NULL";
00607         }
00608         if (StandardTypeDescriptor::isArray(mType)) {
00609 #if 0
00610             // Does not compile due to ptr/non-ptr compile issue
00611             // TODO: Make this work with VARBINARY and I18N
00612             // TODO: Remove the reinterpret_cast. Ugly.
00613             string ret((char *)(this->pointer()), this->getS());
00614             return ret;
00615 #endif
00616             return "Unimpl";
00617         } else {
00618             // TODO: Remove boost call, use stream instead
00619             return boost::lexical_cast<std::string>(this->value());
00620         }
00621     }
00622 protected:
00623 
00624 };
00625 
00626 FENNEL_END_NAMESPACE
00627 
00628 #endif
00629 
00630 // End RegisterReference.h

Generated on Mon Jun 22 04:00:17 2009 for Fennel by  doxygen 1.5.1