UnalignedAttributeAccessor.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/tuple/UnalignedAttributeAccessor.cpp#8 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2006-2009 The Eigenbase Project
00005 // Copyright (C) 2006-2009 SQLstream, Inc.
00006 // Copyright (C) 2006-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 
00023 #include "fennel/common/CommonPreamble.h"
00024 #include "fennel/tuple/UnalignedAttributeAccessor.h"
00025 #include "fennel/tuple/TupleData.h"
00026 
00027 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/tuple/UnalignedAttributeAccessor.cpp#8 $");
00028 
00029 UnalignedAttributeAccessor::UnalignedAttributeAccessor()
00030 {
00031     cbStorage = MAXU;
00032 }
00033 
00034 UnalignedAttributeAccessor::UnalignedAttributeAccessor(
00035     TupleAttributeDescriptor const &attrDescriptor)
00036 {
00037     compute(attrDescriptor);
00038 }
00039 
00040 void UnalignedAttributeAccessor::compute(
00041     TupleAttributeDescriptor const &attrDescriptor)
00042 {
00043     cbStorage = attrDescriptor.cbStorage;
00044     StoredTypeDescriptor::Ordinal typeOrdinal =
00045         attrDescriptor.pTypeDescriptor->getOrdinal();
00046     isCompressedInt64 =
00047         (typeOrdinal == STANDARD_TYPE_INT_64) ||
00048         (typeOrdinal == STANDARD_TYPE_UINT_64);
00049     omitLengthIndicator =
00050         !attrDescriptor.isNullable
00051         && !isCompressedInt64
00052         && (typeOrdinal != STANDARD_TYPE_VARCHAR)
00053         && (typeOrdinal != STANDARD_TYPE_VARBINARY)
00054         && (typeOrdinal != STANDARD_TYPE_UNICODE_VARCHAR);
00055 }
00056 
00057 bool UnalignedAttributeAccessor::isInitialized() const
00058 {
00059     return !isMAXU(cbStorage);
00060 }
00061 
00062 inline void UnalignedAttributeAccessor::compressInt64(
00063     TupleDatum const &datum,
00064     PBuffer pDest) const
00065 {
00066     // NOTE jvs 22-Oct-2006:  Although it may not be obvious,
00067     // this correctly handles both STANDARD_TYPE_INT_64
00068     // and STANDARD_TYPE_UINT_64 (very large unsigned values
00069     // are handled as if they were negative here, but
00070     // the consumer of the TupleDatum won't be aware of that,
00071     // and the sign-extension in uncompress will be a no-op).
00072 
00073     assert(datum.cbData == 8);
00074     int64_t intVal = *reinterpret_cast<int64_t const *> (datum.pData);
00075     uint len;
00076 
00077     if (intVal >= 0) {
00078         FixedBuffer tmpBuf[8];
00079         PBuffer pTmpBuf = tmpBuf + 8;
00080         len = 0;
00081         do {
00082             *(--pTmpBuf) = intVal & 0xff;
00083             len++;
00084             intVal >>= 8;
00085         } while (intVal);
00086 
00087         // if the high bit is set, add an extra zero byte to distinguish this
00088         // value from a negative one
00089         if (*pTmpBuf & 0x80) {
00090             *(--pTmpBuf) = 0;
00091             len++;
00092         }
00093         *pDest = static_cast<uint8_t>(len);
00094         memcpy(pDest + 1, pTmpBuf, len);
00095     } else {
00096         // negative case -- calculate the number of bytes based on the value
00097         if (intVal >= -(0x80)) {
00098             len = 1;
00099         } else if (intVal >= -(0x8000)) {
00100             len = 2;
00101         } else if (intVal >= -(0x800000)) {
00102             len = 3;
00103         } else if (intVal >= -(0x80000000LL)) {
00104             len = 4;
00105         } else if (intVal >= -(0x8000000000LL)) {
00106             len = 5;
00107         } else if (intVal >= -(0x800000000000LL)) {
00108             len = 6;
00109         } else if (intVal >= -(0x80000000000000LL)) {
00110             len = 7;
00111         } else {
00112             len = 8;
00113         }
00114         *pDest = static_cast<uint8_t>(len);
00115         PBuffer pTmpBuf = pDest + 1 + len;
00116         while (len--) {
00117             *(--pTmpBuf) = intVal & 0xff;
00118             intVal >>= 8;
00119         }
00120     }
00121 }
00122 
00123 inline void UnalignedAttributeAccessor::uncompressInt64(
00124     TupleDatum &datum,
00125     PConstBuffer pDataWithLen) const
00126 {
00127     uint len = *pDataWithLen;
00128     assert(len != 0);
00129     PConstBuffer pSrcBuf = pDataWithLen + 1;
00130     uint signByte = *(pSrcBuf++);
00131     // sign extend the high order byte if it's a negative number
00132     int64_t intVal =
00133         int64_t(signByte) | ((signByte & 0x80) ? 0xffffffffffffff00LL : 0);
00134     while (--len > 0) {
00135         intVal <<= 8;
00136         intVal |= *(pSrcBuf++);
00137     }
00138     datum.cbData = 8;
00139 
00140     // REVIEW jvs 25-Oct-2006:  Do we really need memcpy here?  I
00141     // think datum.pDatum is guaranteed to be aligned.
00142     memcpy(const_cast<PBuffer>(datum.pData), &intVal, 8);
00143 }
00144 
00145 void UnalignedAttributeAccessor::storeValue(
00146     TupleDatum const &datum,
00147     PBuffer pDataWithLen) const
00148 {
00149     assert(isInitialized());
00150 
00151     PBuffer tmpDataPtr = pDataWithLen;
00152 
00153     if (!datum.pData) {
00154         /*
00155          * NULL is stored as a special one-byte length: 0x00
00156          */
00157         *tmpDataPtr = 0x00;
00158     } else {
00159         /*
00160          * Note:
00161          * This storage format can only encode values shorter than 0x7fff bytes.
00162          */
00163         assert(datum.cbData <= TWO_BYTE_MAX_LENGTH);
00164 
00165         if (isCompressedInt64) {
00166             // strip off leading zeros from 8-byte ints
00167             compressInt64(datum, tmpDataPtr);
00168         } else {
00169             // for varying-length data and data that is nullable, store
00170             // a length byte in either 1 or 2 bytes, depending on the length
00171             if (!omitLengthIndicator) {
00172                 if (datum.cbData && (datum.cbData <= ONE_BYTE_MAX_LENGTH)) {
00173                     *tmpDataPtr = static_cast<uint8_t>(datum.cbData);
00174                     tmpDataPtr++;
00175                 } else {
00176                     uint8_t higherByte =
00177                         (datum.cbData & TWO_BYTE_LENGTH_MASK1) >> 8 |
00178                             TWO_BYTE_LENGTH_BIT;
00179                     uint8_t lowerByte  = datum.cbData & TWO_BYTE_LENGTH_MASK2;
00180                     *tmpDataPtr = higherByte;
00181                     tmpDataPtr++;
00182                     *tmpDataPtr = lowerByte;
00183                     tmpDataPtr++;
00184                 }
00185             }
00186 
00187             // store the value
00188             memcpy(tmpDataPtr, datum.pData, datum.cbData);
00189         }
00190     }
00191 }
00192 
00193 void UnalignedAttributeAccessor::loadValue(
00194     TupleDatum &datum,
00195     PConstBuffer pDataWithLen) const
00196 {
00197     assert(isInitialized());
00198     assert(datum.pData);
00199 
00200     // fixed width, non-nullable data is stored without leading length byte(s)
00201     if (omitLengthIndicator) {
00202         datum.cbData = cbStorage;
00203         memcpy(const_cast<PBuffer>(datum.pData), pDataWithLen, datum.cbData);
00204     } else {
00205         uint8_t firstByte = *pDataWithLen;
00206         if (!firstByte) {
00207             // null value
00208             datum.pData = NULL;
00209         } else if (firstByte & TWO_BYTE_LENGTH_BIT) {
00210             // not null, so must have a length that requires 2 bytes to
00211             // store
00212             datum.cbData =
00213                 ((firstByte & ONE_BYTE_LENGTH_MASK) << 8)
00214                 | *(pDataWithLen + 1);
00215             memcpy(
00216                 const_cast<PBuffer>(datum.pData),
00217                 pDataWithLen + 2,
00218                 datum.cbData);
00219         } else {
00220             if (isCompressedInt64) {
00221                 // 8-byte integers are stored with leading zeros stripped off
00222                 uncompressInt64(datum, pDataWithLen);
00223             } else {
00224                 // data that requires 1 byte to store the length
00225                 datum.cbData = firstByte;
00226                 memcpy(
00227                     const_cast<PBuffer>(datum.pData),
00228                     pDataWithLen + 1,
00229                     datum.cbData);
00230             }
00231         }
00232     }
00233 }
00234 
00235 TupleStorageByteLength UnalignedAttributeAccessor::getStoredByteCount(
00236     PConstBuffer pDataWithLen) const
00237 {
00238     assert(isInitialized());
00239     assert(pDataWithLen);
00240 
00241     if (omitLengthIndicator) {
00242         return cbStorage;
00243     }
00244 
00245     if (*pDataWithLen & TWO_BYTE_LENGTH_BIT) {
00246         return
00247             (((*pDataWithLen & ONE_BYTE_LENGTH_MASK) << 8)
00248                 | *(pDataWithLen + 1))
00249             + 2;
00250     } else {
00251         return (*pDataWithLen + 1);
00252     }
00253 }
00254 
00255 TupleStorageByteLength UnalignedAttributeAccessor::getMaxByteCount() const
00256 {
00257     assert(isInitialized());
00258 
00259     if (omitLengthIndicator) {
00260         return cbStorage;
00261     } else {
00262         return cbStorage + 2;
00263     }
00264 }
00265 
00266 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/tuple/UnalignedAttributeAccessor.cpp#8 $");
00267 
00268 // End UnalignedAttributeAccessor.cpp

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