| |
| /********************************************************************** |
| // @@@ START COPYRIGHT @@@ |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| // @@@ END COPYRIGHT @@@ |
| **********************************************************************/ |
| #ifndef SQL_BUFFER_H |
| #define SQL_BUFFER_H |
| |
| /* -*-C++-*- |
| ***************************************************************************** |
| * |
| * File: sql_buffer.h |
| * Description: SQL buffers are containers for tupps. SQL buffer pools |
| * manage the allocation and deallocation of sql buffers. |
| * |
| * Created: 7/10/95 |
| * Language: C++ |
| * |
| * |
| ***************************************************************************** |
| */ |
| |
| // |
| // NOTE: Some of the code in this file is excluded from the UDR server |
| // build using the UDRSERV_BUILD macro. The excluded code is: |
| // - All of the sql_buffer_pool, SqlBufferOlt, and SqlBufferOltSmallcode |
| // - Code in the SqlBuffer class that deals with ATPs, expression |
| // evaluation, and statistics |
| // |
| |
| #include "ExpSqlTupp.h" |
| #include "ex_io_control.h" |
| #ifndef UDRSERV_BUILD |
| #include "ex_god.h" |
| #endif // UDRSERV_BUILD |
| |
| // Defining SQL_BUFFER_SIGNATURE gives each sql_buffer a unique |
| // sequence number and a process ID. The seq number is unique within |
| // the process. It's useful for tracing sql_buffers to/from |
| // executor<-->exe-in-dp2 via the ArkFs. But, it changes the size of |
| // the sql_buffer, and thus really should be used only if guarded by |
| // an EIDVersion change, because EID must know about this signature |
| // too. Coordination w/ EIDVersion change is not done unfortunately. |
| // So if you use this, be sure to remember to rebuild dp2. |
| |
| //#define SQL_BUFFER_SIGNATURE |
| |
| #ifdef SQL_BUFFER_SIGNATURE |
| #include "Int64.h" |
| #endif |
| |
| // Integrity checking -- do this for debug builds only. Can also be enabled |
| // for testing release code, but should not be enabled for customers or |
| // Performance testing. |
| #if defined(_DEBUG) |
| #define DO_INTEGRITY_CHECK |
| #endif |
| |
| #include "ComDefs.h" // pick up ROUND8 macro |
| #define NO_INVALID_TUPLES USHRT_MAX // 0xffff, maximum unsigned short value, defined in limits.h |
| ///////////////////////////////////////////////////////////////////// |
| // contents of this file |
| //////////////////////////////////////////////////////////////////// |
| |
| class sql_buffer_pool; |
| class ExStatisticsArea; |
| class atp_struct; |
| class ex_expr; |
| |
| ///////////////////////////////////////////////////////////////////// |
| // forward references |
| //////////////////////////////////////////////////////////////////// |
| class Queue; |
| class SqlBufferOlt; |
| class SqlBufferDense; |
| class SqlBufferNormal; |
| class SqlBuffer; |
| |
| typedef ex_expr ex_expr_base; |
| |
| // this class used in SqlDenseBuffer |
| class TupleDescInfo : public tupp_descriptor |
| { |
| public: |
| |
| tupp_descriptor * tupleDesc() { return (tupp_descriptor*)this; }; |
| |
| |
| ULng32 getNextTDIOffset() { return nextTDIOffset(); }; |
| |
| ULng32 getPrevTDIOffset() { return prevTDIOffset(); }; |
| |
| void setNextTDIOffset(ULng32 tdiOffset) |
| { |
| nextTDIOffset() = (short)tdiOffset; |
| } |
| |
| void setPrevTDIOffset(ULng32 tdiOffset) |
| { |
| prevTDIOffset() = (short)tdiOffset; |
| } |
| |
| |
| void pack(Long base); |
| |
| void unpack(Long base); |
| }; |
| |
| ///////////////////////////////////////////////////////////////////////////// |
| // |
| // SqlBufferHeader |
| // / \ |
| // / \ |
| // / \ |
| // SqlBufferBase SqlBufferOltSmall |
| // / \ |
| // / \ |
| // SqlBuffer SqlBufferOlt |
| // / \ |
| // / \ |
| // SqlBufferNormal SqlBufferDense |
| // |
| // |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // class SqlBufferHeader |
| // |
| // NOTE**** DO NOT add any member fields or virtual methods to this class. |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| class SqlBufferHeader |
| { |
| public: |
| enum BufferType |
| { |
| NORMAL_ = 0, |
| DENSE_ = 1, |
| OLT_ = 2, |
| OLT_SMALL_ = 3 |
| }; |
| |
| // Buffer status |
| enum buffer_status_type |
| { |
| FULL = 1, // no more space in buffer |
| EMPTY = 2, // no records in buffer |
| PARTIAL = 3, // some records in buffer |
| IN_USE = 4 // buffer is being transferred from/to FS2 or DP2 |
| }; |
| |
| enum moveStatus |
| { |
| BUFFER_FULL, |
| MOVE_SUCCESS, |
| MOVE_ERROR |
| }; |
| |
| SqlBufferHeader(BufferType bufType) |
| : bufType_(bufType) |
| { |
| init(); |
| }; |
| |
| void init() |
| { |
| sendFlags_ = 0; |
| }; |
| |
| |
| NABoolean denseBuffer() { return ((bufType_ == DENSE_) != 0); }; |
| |
| |
| void setDenseBuffer(NABoolean v) |
| { ( v ? bufType_ = DENSE_ : bufType_ = NORMAL_ ); } |
| |
| |
| NABoolean oltBuffer() { return ((bufType_ == OLT_) != 0); }; |
| |
| |
| void setOltBuffer(NABoolean v) |
| { ( v ? bufType_ = OLT_ : bufType_ = NORMAL_ ); } |
| |
| |
| BufferType bufType() { return (BufferType)bufType_; }; |
| |
| |
| void setBufType(BufferType bt) { bufType_ = bt; }; |
| |
| |
| NABoolean statsEnabled() { return ((sendFlags_ & STATS_ENABLED) != 0); }; |
| |
| |
| void setStatsEnabled(NABoolean v) |
| { (v ? sendFlags_ |= STATS_ENABLED : sendFlags_ &= ~STATS_ENABLED); }; |
| |
| protected: |
| unsigned char& sendFlags() { return sendFlags_; } |
| unsigned char& replyFlags() { return replyFlags_; } |
| |
| private: |
| enum SendFlags |
| { |
| // The kind of stats to be collected is set at compile time based |
| // on a CQD. This could be overridden at runtime by the next flag. |
| // If set to 1, stats collection is enabled at runtime. If 0, it is not. |
| // Set whenever an input sql buffer is sent from exe->esp or fs->dp2. |
| // Currently being used to enable or disable measure stats collection |
| // at runtime based on whether measure is enabled. |
| STATS_ENABLED = 0x80 |
| }; |
| unsigned char bufType_; |
| union |
| { |
| unsigned char sendFlags_; |
| unsigned char replyFlags_; |
| }; |
| }; |
| |
| class SqlBufferBase : public SqlBufferHeader |
| { |
| public: |
| friend class sql_buffer_pool; |
| friend class SqlTable; |
| |
| SqlBufferBase(BufferType bufType); |
| |
| // fixup vtbl ptr and inits. |
| void driveInit(ULng32 in_size_in_bytes, |
| NABoolean clear, |
| BufferType bt); |
| |
| // fixup vtbl ptr and inits. |
| void driveInit(); |
| |
| // fixup vtbl ptr and unpacks. |
| void driveUnpack(); |
| |
| // packs. |
| void drivePack(); |
| |
| // fixup vtbl ptr and calls the verify() method |
| NABoolean driveVerify(ULng32 maxBytes); |
| |
| void fixupVTblPtr(); |
| |
| // ------------------------------------------------------------------- |
| // returns sizeof the clase. Used at initialization time to |
| // compute free space, etc. |
| // All subclasses MUST redefine this method to return the correct |
| // object sizes. |
| // ------------------------------------------------------------------- |
| virtual Lng32 getClassSize(){return sizeof(SqlBufferBase);}; |
| |
| // initialize data members after allocation, given the total length |
| // in bytes of the allocated sql_buffer |
| virtual void init(ULng32 in_size_in_bytes, |
| NABoolean clear = FALSE); |
| |
| // reinitialize data members; note that this version of init() |
| // can only be used after a buffer has been initialized via |
| // init(unsigned long). |
| virtual void init(); |
| |
| // converts all pointers in tuple descriptors to offset relative |
| // to the beginning of sql_buffer. NOTE: sql_buffer is not derived |
| // from the ExGod class but has similar pack and unpack methods. |
| virtual void pack(); |
| |
| virtual void unpack(); |
| |
| // A method to call before unpacking to verify the internal |
| // consistency of a packed object. The main concern is to make sure |
| // that after we convert offsets to pointers, we are not referencing |
| // memory outside the bounds of the incoming message |
| // buffer. Currently verify() is only called by the ExUdrTcb class |
| // when it receives a data reply from the non-trusted UDR server. |
| virtual NABoolean verify(ULng32 maxBytes) const; |
| |
| virtual ULng32 get_used_size() |
| { return 0; } |
| |
| // number of bytes to be sent across processes. From FS to EID, |
| // or from Send Top to Send Bottom. |
| // For SqlBufferDense, |
| // this method is redefined to return the actual number of bytes to |
| // be sent. |
| virtual ULng32 getSendBufferSize() |
| { return 0; } |
| |
| // number of bytes to be replied across processes. From EID to FS, |
| // of from Send Bottom to Send Top. |
| // For SqlBufferDense, |
| // this method is redefined to return the actual number of bytes to |
| // be sent. |
| virtual ULng32 getReplyBufferSize() |
| { return getSendBufferSize(); } |
| |
| |
| NABoolean packed() { return ((baseFlags_ & PACKED) != 0); }; |
| |
| |
| void setPacked(NABoolean v) { (v ? baseFlags_ |= PACKED : baseFlags_ &= ~PACKED); }; |
| |
| |
| void * operator new(size_t size, char * s); |
| |
| |
| // set the buffer status |
| inline void bufferInUse() {bufferStatus_ = IN_USE;} |
| inline void bufferFull() {bufferStatus_ = FULL;} |
| inline void setBufferStatus(buffer_status_type buf_stat) |
| {bufferStatus_ = buf_stat;} |
| |
| // get the buffer status |
| inline Int32 isFull() const {return (bufferStatus_ == FULL);} |
| inline Int32 isEmpty() const {return (bufferStatus_ == EMPTY);} |
| |
| |
| |
| virtual moveStatus |
| moveInSendOrReplyData(NABoolean isSend, // TRUE = send |
| NABoolean doMoveControl, // TRUE = move |
| // control always |
| NABoolean doMoveData, // TRUE = move data. |
| void * currQState, // up_state(reply) or |
| // down_state(send) |
| ULng32 controlInfoLen, |
| ControlInfo ** controlInfo, |
| ULng32 projRowLen, |
| tupp_descriptor ** outTdesc, |
| ComDiagsArea * diagsArea, |
| tupp_descriptor ** diagsDesc, |
| ex_expr_base * expr = NULL, |
| atp_struct * atp1 = NULL, |
| atp_struct * workAtp = NULL, |
| atp_struct * destAtp = NULL, |
| unsigned short tuppIndex = 0, |
| NABoolean doMoveStats = FALSE, // if TRUE & statsArea |
| // is passed in, |
| // move in stats |
| ExStatisticsArea * statsArea = NULL, |
| tupp_descriptor ** statsDesc = NULL, |
| NABoolean useExternalDA = FALSE, |
| NABoolean callerHasExternalDA = FALSE, |
| tupp_descriptor * defragTd = NULL |
| #if (defined(_DEBUG)) |
| ,ex_tcb * tcb = NULL |
| #endif |
| ,NABoolean noMoveWarnings = FALSE |
| ); |
| |
| |
| virtual NABoolean moveOutSendOrReplyData(NABoolean isSend, |
| void * currQState, |
| tupp &outTupp, |
| ControlInfo ** controlInfo, |
| ComDiagsArea ** diagsArea, |
| ExStatisticsArea ** statsArea = NULL, |
| Int64 * numStatsBytes = NULL, |
| NABoolean noStateChange = FALSE, |
| NABoolean unpackDA = FALSE, |
| CollHeap * heap = NULL); |
| |
| virtual SqlBuffer * castToSqlBuffer() { return NULL; } |
| |
| |
| virtual SqlBufferNormal * castToSqlBufferNormal() { return NULL; } |
| |
| |
| virtual SqlBufferDense * castToSqlBufferDense() { return NULL; } |
| |
| |
| virtual SqlBufferOlt * castToSqlBufferOlt() { return NULL; } |
| |
| // total size in bytes |
| inline ULng32 get_buffer_size() const |
| { return sizeInBytes_; } |
| |
| void setBufferSize(ULng32 s) |
| { |
| sizeInBytes_ = s; |
| } |
| |
| // positions to the first tupp descriptor in the buffer. |
| virtual void position(); |
| |
| // positions to the "tupp_desc_num"th tupp descriptor. |
| virtual void position(Lng32 tupp_desc_num); |
| |
| // returns the 'next' tupp descriptor. Increments the |
| // position. Returns null, if none found. |
| virtual tupp_descriptor * getNext(); |
| |
| // returns the 'current' tupp descriptor. Does not increment |
| // position. Returns null, if none found. |
| virtual tupp_descriptor * getCurr(); |
| |
| // advances the current tupp descriptor |
| virtual void advance(); |
| |
| // add a new tuple descriptor to the end of the buffer |
| virtual tupp_descriptor *add_tuple_desc(Lng32 tup_data_size); |
| |
| // remove the tuple desc with the highest number from the buffer |
| virtual void remove_tuple_desc(); |
| |
| // is space for a tuple with the given length available? |
| virtual short space_available(Lng32 tup_data_size) |
| { |
| return 0; |
| } |
| |
| // Next method checks integrity of a reply sql buffer when it |
| // leaves exe-in-dp2 and arrives at a partition access. |
| // TBD -- 1) enhance this to be usable for reply buffers |
| // from producer ESPs (which send diags and stats externally) |
| // and 2) enhance to be usabe for buffers sent to exe-in-dp2 and |
| // producer ESPs. |
| // This is a no-op for the OLT subclasses of sql buffer, and in |
| // release code. |
| #ifdef DO_INTEGRITY_CHECK |
| virtual void integrityCheck( NABoolean ignore_omm_check=FALSE) { return; }; |
| #else |
| // Cannot afford to check reply_buffer for release code. |
| inline void integrityCheck( NABoolean ignore_omm_check=FALSE) { return; }; |
| #endif |
| |
| protected: |
| enum Flags |
| { |
| IGNORE_CONTROL_FLAG = 0x0001, |
| PACKED = 0x0002, |
| CURR_HAS_EDA = 0x0004, // current entry associated w/ external diags area |
| RETURN_ROWCOUNT = 0x0008, |
| ROWCOUNT_RETURNED = 0x0010, |
| SAME_EXECUTION = 0x0020, |
| VAR_LEN_ROWS = 0x0040, // currently only set for normal buffers |
| FIRST_EXECUTION = 0x0080 |
| }; |
| |
| unsigned char baseFlags_; |
| char bufferStatus_; |
| Lng32 sizeInBytes_; // total size of the buffer |
| |
| }; |
| |
| /* |
| unsigned long SqlBufferNeededSize(long numTuples = 0, |
| long recordLength = 0, |
| SqlBufferHeader::BufferType bufType = SqlBufferHeader::NORMAL_); |
| |
| |
| */ |
| //////////////////////////////////////////////////////////////// |
| // class SqlBuffer |
| //////////////////////////////////////////////////////////////// |
| class SqlBuffer : public SqlBufferBase |
| { |
| public: |
| SqlBuffer(BufferType bufType) |
| : SqlBufferBase(bufType) |
| {}; |
| |
| |
| virtual SqlBuffer * castToSqlBuffer() { return this; } |
| |
| // initialize data members after allocation, given the total length |
| // in bytes of the allocated SqlBuffer |
| virtual void init(ULng32 in_size_in_bytes, |
| NABoolean clear = FALSE); |
| |
| // reinitialize data members; note that this version of init() |
| // can only be used after a buffer has been initialized via |
| // init(unsigned long). |
| virtual void init(); |
| |
| // find or allocate a free tuple_descriptor with the specified length |
| virtual tupp_descriptor *allocate_tuple_desc(Lng32 tup_data_size) |
| {return NULL;}; |
| |
| // returns whether this buffer is free |
| virtual short isFree() |
| {return 0;}; |
| |
| // returns whether this buffer is free (reinitializes the buffer if |
| // it no longer contains referenced tupps) |
| short freeBuffer(); |
| |
| // deallocate space from nonused tuples (noop for now) |
| void compactBuffer(); |
| |
| // is space for a tuple with the given length available? |
| virtual short space_available(Lng32 tup_data_size); |
| |
| // change a queue_entry to GET_NOMORE before it is sent. |
| NABoolean findAndCancel( queue_index pindex, |
| NABoolean startAtBeginning); |
| |
| ///////////////////////////////////////////////////////////// |
| // Methods to retrieve tupp_descriptors from this buffer. |
| ///////////////////////////////////////////////////////////// |
| |
| // returns maximum number of tupps in this buffer |
| Lng32 getTotalTuppDescs(){return maxTuppDesc_;} |
| |
| unsigned short getTotalValidTuppDescs(){return maxValidTuppDesc_;} |
| |
| void setTotalValidTuppDescs(Lng32 val) |
| { |
| ex_assert(val < USHRT_MAX, "total valid tupps in buffer is larger than USHRT_MAX"); |
| maxValidTuppDesc_ = (unsigned short) val; |
| } |
| |
| // returns the number of tupp descriptors that have been |
| // processed, that is, they have been returned via one |
| // of the get* calls. |
| Lng32 getProcessedTuppDescs(){return tuppDescIndex_;} |
| |
| void setProcessedTuppDescs(unsigned short tupp_desc_num) |
| { |
| tuppDescIndex_ = tupp_desc_num; |
| } |
| |
| // Returns the "tupp_desc_num"th tupp descriptor. |
| // Returns NULL, if tupp_desc_num is greater than maxTupleDesc_. |
| virtual tupp_descriptor * getTuppDescriptor(Lng32 tupp_desc_num); |
| |
| // returns the 'prev' tupp descriptor. Decrements the |
| // position. Returns null, if none found. |
| virtual tupp_descriptor * getPrev(); |
| |
| // atEOTD (At End Of Tupp Descriptors) |
| // returns -1, if all tupp descriptors have been returned |
| short atEOTD() const |
| { |
| if ((tuppDescIndex_ < maxTuppDesc_) || |
| (flags_ & IGNORE_CONTROL_FLAG)) |
| return 0; |
| else |
| return -1; |
| } |
| |
| // print buffer info. For debugging |
| void printInfo(); |
| |
| virtual void resize_tupp_desc(UInt32 tup_data_size, char *dataPointer) { }; |
| |
| NABoolean varLenRows() { return (flags_ & VAR_LEN_ROWS) != 0; }; |
| |
| void setVarLenRows(NABoolean v) |
| {(v ? flags_ |= VAR_LEN_ROWS : flags_ &= ~VAR_LEN_ROWS);} |
| |
| virtual SqlBuffer::moveStatus |
| moveInSendOrReplyData(NABoolean isSend, // TRUE = send |
| NABoolean doMoveControl, // TRUE = move |
| // control always |
| NABoolean doMoveData, // TRUE = move data. |
| void * currQState, // up_state(reply) or |
| // down_state(send) |
| ULng32 controlInfoLen, |
| ControlInfo ** controlInfo, |
| ULng32 projRowLen, |
| tupp_descriptor ** outTdesc, |
| ComDiagsArea * diagsArea, |
| tupp_descriptor ** diagsDesc, |
| ex_expr_base * expr = NULL, |
| atp_struct * atp1 = NULL, |
| atp_struct * workAtp = NULL, |
| atp_struct * destAtp = NULL, |
| unsigned short tuppIndex = 0, |
| NABoolean doMoveStats = FALSE, // if TRUE & statsArea |
| // is passed in, |
| // move in stats |
| ExStatisticsArea * statsArea = NULL, |
| tupp_descriptor ** statsDesc = NULL, |
| NABoolean useExternalDA = FALSE, |
| NABoolean callerHasExternalDA = FALSE, |
| tupp_descriptor * defragTd = NULL |
| #if (defined(_DEBUG)) |
| ,ex_tcb * tcb = NULL // for debuggin |
| #endif |
| ,NABoolean noMoveWarnings = FALSE |
| ); |
| |
| |
| virtual NABoolean moveOutSendOrReplyData(NABoolean isSend, |
| void * currQState, |
| tupp &outTupp, |
| ControlInfo ** controlInfo, |
| ComDiagsArea ** diagsArea, |
| ExStatisticsArea ** statsArea = NULL, |
| Int64 * numStatsBytes = NULL, |
| NABoolean noStateChange = FALSE, |
| NABoolean unpackDA = FALSE, |
| CollHeap * heap = NULL); |
| |
| |
| ControlInfo * getControlInfo() {return &srControlInfo_;}; |
| |
| // To get more info if sql_buffer received twice. |
| void setSignature(); |
| inline void setInvalidSignature() |
| { |
| signature_ = (Int64) INVALID_SIGNATURE; |
| } |
| inline Int64 getSignature(void) const |
| { |
| return signature_; |
| } |
| NABoolean checkSignature(const Int32 nid, const Int32 pid, |
| Int64 *signature, const Int32 action); |
| |
| //////////////////////////////////////////////////////////////////////// |
| // SEND* requests: These flags set by sender which sends input requests |
| // (down request entries). |
| // SEND_SAME_REQUEST: |
| // Each down entry has the same queue downState. One control |
| // entry is moved to buffer followed by multiple data entries. If |
| // any queue downState is 'different' than the previous one, then |
| // a new controlInfo tuple is moved in. Multiple input entries with |
| // the same parentIndex could happen for cases when rows are being |
| // sent from top, ex. for an "INSERT...SELECT", the tupleFlow operator |
| // sends multiple rows belonging to the same INSERT...SELECT request. |
| // |
| // SEND_CONSECUTIVE_REQUEST: |
| // Each input request has a downState that is different in only |
| // the parentIndex and each subsequent parentIndex is one greater |
| // than the previous one. Ex. inputs to right child of a nested |
| // join. |
| // |
| // REPLY* requests: The flags are set by the replier which returns |
| // reply rows (up reply entries). |
| // REPLY_GET_UNIQUE_REQUEST: |
| // Each reply entry either returns exactly one row or no rows. |
| // And each up entry's parentIndex is one greater than the previous |
| // one. One control tuple is moved followed by data tuples, as long |
| // as their parentIndex are one greater than the previous one. An |
| // empty data tuple of length zero is put in for those requests that |
| // do not return any rows. |
| // |
| // REPLY_GET_SUBSET_REQUEST: |
| // Each input entry has multiple reply data rows. Each reply row |
| // has the same parentIndex as input request but the matchNo value |
| // is one greater than the previous one. |
| // |
| // REPLY_VSBB_INSERT_REQUEST: |
| // For buffered inserts, each input buffer sent from exe to eid |
| // contains one 'row'. This 'row' is actually a vsbb insert buffer |
| // (class SqlBuffer) and contains multiple data rows. The reply to |
| // these input 'rows' contain the number of inserted rows in the |
| // matchNo field of the upState. |
| // |
| //////////////////////////////////////////////////////////////////////// |
| enum SRFlags |
| { |
| SEND_SAME_REQUEST = 0, SEND_CONSECUTIVE_REQUEST, |
| SEND_VSBB_WITH_EOD, |
| REPLY_GET_UNIQUE_REQUEST, REPLY_GET_SUBSET_REQUEST, |
| REPLY_VSBB_INSERT_REQUEST, DEFAULT_ |
| }; |
| |
| SRFlags srFlags() {return (SRFlags)srFlags_;}; |
| void setSRFlags(SRFlags srf) |
| { |
| srFlags_ = (unsigned short)srf; |
| }; |
| |
| Lng32 getFreeSpace() { return freeSpace_; } |
| |
| virtual NABoolean hasEnoughFreeSpace( Lng32 neededSpace) |
| { |
| return FALSE; |
| } |
| |
| virtual unsigned short getNumInvalidTuplesUptoNow(); |
| |
| virtual void setNumInvalidTuplesUptoNow(Lng32 val); |
| |
| virtual void incNumInvalidTuplesUptoNow(); |
| |
| virtual void decNumInvalidTuplesUptoNow(); |
| |
| virtual void advanceToNextValidTuple(); |
| |
| void sameExecution(bool s) { |
| if (s) |
| flags_ |= SAME_EXECUTION; |
| } |
| |
| inline bool isSameExecution() const { |
| if (flags_ & SAME_EXECUTION) |
| return true; |
| else |
| return false; |
| } |
| |
| void firstExecution(bool s) { |
| if (s) |
| flags_ |= FIRST_EXECUTION; |
| } |
| |
| inline bool isFirstExecution() const { |
| if (flags_ & FIRST_EXECUTION) |
| return true; |
| else |
| return false; |
| } |
| |
| #ifdef DO_INTEGRITY_CHECK |
| // Redefine from no-op in base class to a real integrity check |
| // for SqlBuffer and derived classes. |
| virtual void integrityCheck( NABoolean ignore_omm_check=FALSE); |
| #else |
| // Cannot afford to check reply_buffer for release code. |
| #endif |
| |
| enum SIGNATURE_MODE |
| { |
| INITIAL_SIGNATURE, // not used yet |
| INVALID_SIGNATURE = -5555555 |
| }; |
| |
| protected: |
| Lng32 freeSpace_; // free space in the buffer |
| ULng32 maxTuppDesc_; // max tupp desc allocated. Some of |
| // them may have a reference count of 0. |
| // used to read all tuple descriptors from the buffer. |
| // See position() and getNext(). |
| ULng32 tuppDescIndex_; |
| |
| // send/receive flags will be unioned with maxValidTuppDesc |
| // as maxValidTuppDesc is used only in VSBBInsert node between the |
| // from the SETUP state to DONE state. This data member is reset in the |
| // DONE state if it was ever used as maxValidTuppDesc_ |
| union { |
| //send/receive flags. |
| unsigned short srFlags_; |
| |
| // number of valid rows in this buffer. Rows become invalid if they |
| // raise a setup error during non-atomic insert |
| unsigned short maxValidTuppDesc_; |
| }; |
| |
| // See IGNORE_CONTROL_FLAG, CURR_HAS_EDA etc. |
| short flags_; |
| |
| // To get more info if sql_buffer received twice. |
| Int64 signature_; |
| |
| // this variable is used to keep track of the control info associated |
| // with the 'current' send or reply data tuple that is being added |
| // or accessed. See methods moveInSendOrReplyData and moveOutSendOrReplyData |
| // for details on how this variable is used. |
| ControlInfo srControlInfo_; |
| |
| |
| virtual tupp_descriptor * tupleDesc(Int32 i) |
| { return 0; } |
| |
| |
| private: |
| enum PROCEED_OR_DEFER |
| { |
| DEFER_MORE_TUPPS, // related to REPLY_VSBB_INSERT_REQUEST |
| PROCEED_MORE_TUPPS |
| }; |
| |
| Int32 setupSrControlInfo( NABoolean isSend, tupp_descriptor *tuppDesc ); |
| |
| }; |
| |
| ///////////////////////////////////////////////////////////////////// |
| // class SqlBufferNormal |
| // |
| // An SqlBuffer is a C++ class with variable length. Instead of |
| // using a constructor, it is allocated with the method |
| // sql_buffer_pool::addBuffer(). An SQL buffer looks like this: |
| // |
| // +-----------------------------+ |
| // | SqlBuffer data members | |
| // | (# of tupp_descriptors, | |
| // | data offset, free space, | |
| // | total length, ...) | |
| // +-----------------------------+ |
| // | tupp data 1 | |
| // +-----------------------------+ |
| // | tupp data 2 | |
| // +-----------------------------+ |
| // | ... | |
| // +-----------------------------+ |
| // | tupp data n | |
| // +-----------------------------+ |
| // | | |
| // | free space | |
| // | | |
| // +-----------------------------+ |
| // | tupp_descriptor n | |
| // +-----------------------------+ |
| // | ... | |
| // +-----------------------------+ |
| // | tupp_descriptor 2 | |
| // +-----------------------------+ |
| // | tupp_descriptor 1 | |
| // +-----------------------------+ |
| // |
| // Tupp descriptors are allocated from the end of the buffer. The |
| // data space is allocated from the top of the buffer to facilitate |
| // resizing of the tupp data. |
| // |
| // Data for each tupp_descriptor begins on an 8 byte boundary. Data |
| // for the tupp_descriptors does not necessarily have to be laid out |
| // in the way shown, and not all tupp_descriptors have to have the |
| // same data length. There may be holes in the tupp_descriptors and |
| // in the tupp data. Holes are not counted as free space. |
| // |
| // |
| //////////////////////////////////////////////////////////////////// |
| class SqlBufferNormal : public SqlBuffer |
| { |
| friend class sql_buffer_pool; |
| friend class SqlTable; |
| friend class SimSqlTable; |
| |
| #ifdef SQL_BUFFER_SIGNATURE |
| friend class ExEIDRootTcb; |
| #endif |
| |
| public: |
| |
| SqlBufferNormal() |
| : SqlBuffer(NORMAL_) |
| { |
| }; |
| |
| virtual Lng32 getClassSize(){return sizeof(SqlBufferNormal);}; |
| |
| // initialize data members after allocation, given the total length |
| // in bytes of the allocated sql_buffer |
| virtual void init(ULng32 in_size_in_bytes, |
| NABoolean clear = FALSE); |
| |
| // reinitialize data members; note that this version of init() |
| // can only be used after a buffer has been initialized via |
| // init(unsigned long). |
| virtual void init(); |
| |
| // find or allocate a free tuple_descriptor with the specified length |
| virtual tupp_descriptor *allocate_tuple_desc(Lng32 tup_data_size); |
| |
| // add a new tuple descriptor to the end of the buffer |
| virtual tupp_descriptor *add_tuple_desc(Lng32 tup_data_size); |
| |
| // remove the tuple desc with the highest number from the buffer |
| virtual void remove_tuple_desc(); |
| |
| // returns whether this buffer is free |
| virtual short isFree(); |
| |
| // total size in bytes |
| virtual ULng32 get_used_size() |
| { return (sizeInBytes_ - freeSpace_); } |
| |
| // number of bytes to be sent across processes. For SqlBufferDense, |
| // this method is redefined to return the actual number of bytes to |
| // be sent. |
| virtual ULng32 getSendBufferSize() |
| { return get_buffer_size(); } |
| |
| // converts all pointers in tuple descriptors to offset relative |
| // to the beginning of sql_buffer. NOTE: sql_buffer is not derived |
| // from the ExGod class but has similar pack and unpack methods. |
| virtual void pack(); |
| |
| virtual void unpack(); |
| |
| // A method to call before unpacking to verify the internal |
| // consistency of a packed object. The main concern is to make sure |
| // that after we convert offsets to pointers, we are not referencing |
| // memory outside the bounds of the incoming message |
| // buffer. Currently verify() is only called by the ExUdrTcb class |
| // when it receives a data reply from the non-trusted UDR server. |
| virtual NABoolean verify(ULng32 maxBytes) const; |
| |
| ///////////////////////////////////////////////////////////// |
| // Methods to retrieve tupp_descriptors from this buffer. |
| ///////////////////////////////////////////////////////////// |
| |
| // positions to the first tupp descriptor in the buffer. |
| virtual void position(); |
| |
| // positions to the "tupp_desc_num"th tupp descriptor. |
| virtual void position(Lng32 tupp_desc_num); |
| |
| // returns the 'next' tupp descriptor. Increments the |
| // position. Returns null, if none found. |
| virtual tupp_descriptor * getNext(); |
| |
| // returns the 'prev' tupp descriptor. Decrements the |
| // position. Returns null, if none found. |
| virtual tupp_descriptor * getPrev(); |
| |
| // returns the 'current' tupp descriptor. Does not increment |
| // position. Returns null, if none found. |
| virtual tupp_descriptor * getCurr() { return getCurrNormal(); }; |
| tupp_descriptor * getCurrNormal() { |
| if (tuppDescIndex_ < maxTuppDesc_) |
| return tupleDesc((Int32)tuppDescIndex_); |
| else |
| return 0; |
| } |
| |
| // advances the current tupp descriptor |
| virtual void advance() { advanceNormal(); }; |
| void advanceNormal() { |
| tuppDescIndex_++; |
| } |
| |
| // Returns the "tupp_desc_num"th tupp descriptor. |
| // Returns NULL, if tupp_desc_num is greater than maxTupleDesc_. |
| virtual tupp_descriptor * getTuppDescriptor(Lng32 tupp_desc_num); |
| |
| virtual unsigned short getNumInvalidTuplesUptoNow(); |
| |
| virtual void setNumInvalidTuplesUptoNow(Lng32 val); |
| |
| virtual void incNumInvalidTuplesUptoNow(); |
| |
| virtual void decNumInvalidTuplesUptoNow(); |
| |
| // print buffer info. For debugging |
| void printInfo(); |
| |
| virtual void resize_tupp_desc(UInt32 tup_data_size, char *dataPointer); |
| |
| ////////////////////////////////////////////////// |
| |
| |
| virtual SqlBufferNormal * castToSqlBufferNormal() { return this; } |
| |
| private: |
| ULng32 dataOffset_; // offset from where data space is to be |
| // to be allocated. |
| Lng32 tupleDescOffset_; |
| // this is also the end of the buffer as |
| // tupp descs are allocated in reverse order. |
| |
| // number of invalid rows upto (not including) the current position of buffer. |
| // intialized to NO_INVALID_TUPLES. The value 0 means that this buffer |
| // has invalid tuples, but not before the current position. |
| unsigned short numInvalidTuplesUptoCurrentPosition_; |
| |
| unsigned short normalBufFlags_; |
| |
| virtual tupp_descriptor * tupleDesc(Int32 i) |
| { // tuple descs are allocated in reverse order, from the end of the buffer. |
| return &((tupp_descriptor*)((char *)this + tupleDescOffset_))[-(i+1)]; |
| }; |
| |
| }; |
| |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // class SqlBufferDense |
| ///////////////////////////////////////////////////////////////////////// |
| class SqlBufferDense : public SqlBuffer |
| { |
| friend class SqlBuffer; |
| |
| public: |
| |
| SqlBufferDense(); |
| |
| virtual Lng32 getClassSize(){return sizeof(SqlBufferDense);}; |
| |
| // initialize data members after allocation, given the total length |
| // in bytes of the allocated sql_buffer |
| virtual void init(ULng32 in_size_in_bytes, |
| NABoolean clear = FALSE); |
| |
| // reinitialize data members; note that this version of init() |
| // can only be used after a buffer has been initialized via |
| // init(unsigned long). |
| virtual void init(); |
| |
| // find or allocate a free tuple_descriptor with the specified length |
| virtual tupp_descriptor *allocate_tuple_desc(Lng32 tup_data_size); |
| |
| // add a new tuple descriptor to the end of the buffer |
| virtual tupp_descriptor *add_tuple_desc(Lng32 tup_data_size); |
| |
| // remove the tuple desc with the highest number from the buffer |
| virtual void remove_tuple_desc(); |
| |
| // returns whether this buffer is free |
| virtual short isFree(); |
| |
| // positions to the first tupp descriptor in the buffer. |
| virtual void position(); |
| |
| // positions to the "tupp_desc_num"th tupp descriptor. |
| virtual void position(Lng32 tupp_desc_num); |
| |
| // returns the 'next' tupp descriptor. Increments the |
| // position. Returns null, if none found. |
| virtual tupp_descriptor * getNext(); |
| |
| // returns the 'prev' tupp descriptor. Decrements the |
| // position. Returns null, if none found. |
| virtual tupp_descriptor * getPrev(); |
| |
| // returns the 'current' tupp descriptor. Does not increment |
| // position. Returns null, if none found. |
| virtual tupp_descriptor * getCurr() { return getCurrDense(); }; |
| tupp_descriptor * getCurrDense() { |
| if (tuppDescIndex_ < maxTuppDesc_) |
| return currTupleDesc()->tupleDesc(); |
| else |
| return NULL; |
| } |
| |
| // advances the current tupp descriptor |
| virtual void advance() { advanceDense(); }; |
| void advanceDense() { |
| tuppDescIndex_++; |
| currTupleDesc() = getNextTupleDesc(currTupleDesc()); |
| } |
| |
| // Returns the "tupp_desc_num"th tupp descriptor. |
| // Returns NULL, if tupp_desc_num is greater than maxTupleDesc_. |
| virtual tupp_descriptor * getTuppDescriptor(Lng32 tupp_desc_num); |
| |
| virtual ULng32 get_used_size() |
| { return getSendBufferSize(); } |
| |
| virtual ULng32 getSendBufferSize() |
| { |
| // dataOffset_ points to the first free byte in this buffer. |
| //return ((char *)lastTupleDesc() - (char *)this); |
| |
| // must be unpacked of lastTupleDesc() will not be a valid address. |
| // return the total buffer size in this case. |
| // Could also do a temporary unpack of lasttupledesc and return it. |
| if ((packed()) && (lastTupleDesc())) |
| return get_buffer_size(); |
| |
| if (lastTupleDesc()) |
| return |
| (Lng32) |
| ((char *)(lastTupleDesc()->tupleDesc()->getTupleAddress() |
| + ROUND8(lastTupleDesc()->tupleDesc()->getAllocatedSize())) |
| - (char *)this); |
| else |
| return (Lng32)((char *)firstTupleDesc() - (char *)this); |
| |
| } |
| |
| virtual unsigned short getNumInvalidTuplesUptoNow(); |
| |
| virtual void setNumInvalidTuplesUptoNow(Lng32 val); |
| |
| virtual void incNumInvalidTuplesUptoNow(); |
| |
| virtual void decNumInvalidTuplesUptoNow(); |
| |
| moveStatus moveInVsbbEOD(void * down_q_state); |
| |
| virtual void pack(); |
| |
| virtual void unpack(); |
| |
| |
| virtual SqlBufferDense * castToSqlBufferDense() { return this; }; |
| |
| virtual void resize_tupp_desc(UInt32 tup_data_size, char *dataPointer); |
| |
| private: |
| TupleDescInfo * lastTupleDesc_; |
| TupleDescInfo * currTupleDesc_; |
| // number of invalid rows upto (not including) the current position of buffer. |
| // intialized to NO_INVALID_TUPLES. The value 0 means that this buffer |
| // has invalid tuples, but not before the current position. |
| unsigned short numInvalidTuplesUptoCurrentPosition_; |
| |
| char filler_[2]; |
| |
| |
| TupleDescInfo * firstTupleDesc() |
| { |
| return (TupleDescInfo*)((char *)this + ROUND8(sizeof(*this))); |
| } |
| |
| |
| TupleDescInfo * &lastTupleDesc() { return lastTupleDesc_; }; |
| |
| TupleDescInfo * &currTupleDesc() { return currTupleDesc_; }; |
| |
| |
| virtual tupp_descriptor * tupleDesc(Int32 i) |
| { |
| if (i >= maxTuppDesc_) |
| return NULL; |
| |
| TupleDescInfo * tdi = firstTupleDesc(); |
| for (Int32 j = 0; j < i; j++) |
| { |
| setNextTupleDesc(tdi, getNextTupleDesc(tdi)); |
| } |
| |
| return tdi->tupleDesc(); |
| }; |
| |
| |
| TupleDescInfo * getNextTupleDesc(TupleDescInfo * tdi) |
| { |
| if (tdi->getNextTDIOffset() > 0) |
| return ((TupleDescInfo*)((char *)this + tdi->getNextTDIOffset())); |
| else |
| return NULL; |
| }; |
| |
| |
| TupleDescInfo * getPrevTupleDesc(TupleDescInfo * tdi) |
| { |
| if (tdi->getPrevTDIOffset() > 0) |
| return ((TupleDescInfo*)((char *)this + tdi->getPrevTDIOffset())); |
| else |
| return NULL; |
| }; |
| |
| |
| void setNextTupleDesc(TupleDescInfo * tdi, TupleDescInfo * nextTdi) |
| { |
| if (nextTdi) |
| tdi->setNextTDIOffset((char *)nextTdi - (char *)this); |
| else |
| tdi->setNextTDIOffset(0); |
| } |
| |
| |
| void setPrevTupleDesc(TupleDescInfo * tdi, TupleDescInfo * prevTdi) |
| { |
| if (prevTdi) |
| tdi->setPrevTDIOffset((char *)prevTdi - (char *)this); |
| else |
| tdi->setPrevTDIOffset(0); |
| } |
| |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // class SqlBufferOltSmall |
| // This class is a very special purpose class. It is used for queries which |
| // use olt optimization. It is use to send request/data from fs to eid, |
| // and for reply from eid/dp2 to fs. Max one row of data for either send |
| // or reply. |
| // For send, this class is used for request and/or data. |
| // For reply, this class is used to receive reply with |
| // or without data, and with or without stats(PERTABLE or ACCUMULATED). |
| // For olt optimization cases where an error, warning, rowcount, or anything |
| // else is being sent, SqlBufferOlt class is used. |
| // DO NOT ADD any fields to this class. It is designed to reduce the number |
| // of bytes shipped between eid and fs. |
| /////////////////////////////////////////////////////////////////////////////// |
| class SqlBufferOltSmall : public SqlBufferHeader |
| { |
| public: |
| |
| SqlBufferOltSmall() |
| : SqlBufferHeader(OLT_SMALL_) |
| { |
| str_pad(filler_, 2, '\0'); |
| }; |
| |
| |
| void init() |
| { |
| SqlBufferHeader::init(); |
| }; |
| |
| |
| moveStatus moveInSendData(ULng32 projRowLen, |
| ex_expr_base * expr, |
| atp_struct * atp1, |
| atp_struct * workAtp, |
| unsigned short tuppIndex); |
| |
| |
| NABoolean moveOutSendData(tupp &outTupp, ULng32 returnedRowLen); |
| |
| |
| NABoolean moveOutReplyData(void * currQState, |
| tupp &outTupp, |
| ULng32 returnedRowLen, |
| ComDiagsArea ** diagsArea, |
| ExStatisticsArea ** statsArea, |
| Int64 * numStatsBytes); |
| |
| |
| NABoolean sendData() { return (sendFlags() & SEND_DATA_) != 0; }; |
| |
| void setSendData(NABoolean v) |
| {(v ? sendFlags() |= SEND_DATA_ : sendFlags() &= ~SEND_DATA_);} |
| |
| |
| NABoolean replyData() { return (replyFlags() & REPLY_DATA_) != 0; }; |
| |
| void setReplyData(NABoolean v) |
| {(v ? replyFlags() |= REPLY_DATA_ : replyFlags() &= ~REPLY_DATA_);} |
| |
| |
| NABoolean replyRowAffected() { return (replyFlags() & REPLY_ROW_AFFECTED_) != 0; }; |
| |
| void setReplyRowAffected(NABoolean v) |
| {(v ? replyFlags() |= REPLY_ROW_AFFECTED_ : replyFlags() &= ~REPLY_ROW_AFFECTED_);} |
| |
| |
| NABoolean replyStats() { return (replyFlags() & REPLY_STATS_) != 0; }; |
| |
| void setReplyStats(NABoolean v) |
| {(v ? replyFlags() |= REPLY_STATS_ : replyFlags() &= ~REPLY_STATS_);} |
| |
| NABoolean replyStatsOnly() |
| { return (replyFlags() & REPLY_STATS_ONLY_) != 0; }; |
| |
| void setReplyStatsOnly(NABoolean v) |
| {(v ? replyFlags() |= REPLY_STATS_ONLY_ : replyFlags() &= ~REPLY_STATS_ONLY_);} |
| |
| |
| char * sendDataPtr() |
| { |
| return (sendData() ? (char *)((char *)this+sizeof(SqlBufferOltSmall)) : NULL); |
| }; |
| |
| private: |
| enum SendFlags |
| { |
| SEND_DATA_ = 0x01 |
| }; |
| |
| enum ReplyFlags |
| { |
| REPLY_DATA_ = 0x01, |
| REPLY_ROW_AFFECTED_ = 0x02, |
| REPLY_STATS_ = 0x04, |
| REPLY_STATS_ONLY_ = 0x08 |
| }; |
| |
| char filler_[2]; |
| }; |
| |
| ////////////////////////////////////////////////////////////// |
| // class SqlBufferOlt |
| ////////////////////////////////////////////////////////////// |
| class SqlBufferOlt : public SqlBufferBase |
| { |
| private: |
| enum OltBufFlags |
| { |
| STATS_ = 0x01, CONTAINS_OLT_SMALL_ = 0x02, DATA_PROCESSED_ = 0x04 |
| }; |
| |
| enum Contents |
| { |
| NOTHING_YET_ = 0, |
| ERROR_, DATA_, DATA_WARNING_, |
| NODATA_, NODATA_ROWAFFECTED_, NODATA_ROWCOUNT_, NODATA_WARNING_, |
| NODATA_ROWAFFECTED_WARNING_, NODATA_ROWCOUNT_WARNING_, STATSONLY_ |
| }; |
| |
| public: |
| SqlBufferOlt() |
| : SqlBufferBase(SqlBufferBase::OLT_), |
| oltBufFlags_(0) |
| {}; |
| |
| virtual Lng32 getClassSize(){return sizeof(SqlBufferOlt);}; |
| |
| // initialize data members after allocation, given the total length |
| // in bytes of the allocated sql_buffer |
| virtual void init(ULng32 in_size_in_bytes, |
| NABoolean clear = FALSE); |
| |
| // reinitialize data members; note that this version of init() |
| // can only be used after a buffer has been initialized via |
| // init(unsigned long). |
| virtual void init(); |
| |
| // converts all pointers in tuple descriptors to offset relative |
| // to the beginning of sql_buffer. NOTE: sql_buffer is not derived |
| // from the ExGod class but has similar pack and unpack methods. |
| virtual void pack(); |
| |
| virtual void unpack(); |
| |
| // add a new tuple descriptor to the end of the buffer |
| virtual tupp_descriptor *add_tuple_desc(Lng32 tup_data_size); |
| |
| // remove the tuple desc with the highest number from the buffer |
| virtual void remove_tuple_desc(); |
| |
| |
| virtual moveStatus |
| moveInSendOrReplyData(NABoolean isSend, // TRUE = send |
| NABoolean doMoveControl, // TRUE = move |
| // control always |
| NABoolean doMoveData, // TRUE = move data. |
| void * currQState, // up_state(reply) or |
| // down_state(send) |
| ULng32 controlInfoLen, |
| ControlInfo ** controlInfo, |
| ULng32 projRowLen, |
| tupp_descriptor ** outTdesc, |
| ComDiagsArea * diagsArea, |
| tupp_descriptor ** diagsDesc, |
| ex_expr_base * expr = NULL, |
| atp_struct * atp1 = NULL, |
| atp_struct * workAtp = NULL, |
| atp_struct * destAtp = NULL, |
| unsigned short tuppIndex = 0, |
| NABoolean doMoveStats = FALSE, // if TRUE & statsArea |
| // is passed in, |
| // move in stats |
| ExStatisticsArea * statsArea = NULL, |
| tupp_descriptor ** statsDesc = NULL, |
| NABoolean useExternalDA = FALSE, |
| NABoolean callerHasExternalDA = FALSE, |
| tupp_descriptor * defragTd = NULL |
| #if (defined(_DEBUG)) |
| ,ex_tcb * tcb = NULL // for debuggin |
| #endif |
| ,NABoolean noMoveWarnings = FALSE |
| ); |
| |
| |
| |
| virtual NABoolean moveOutSendOrReplyData(NABoolean isSend, |
| void * currQState, |
| tupp &outTupp, |
| ControlInfo ** controlInfo, |
| ComDiagsArea ** diagsArea, |
| ExStatisticsArea ** statsArea = NULL, |
| Int64 * numStatsBytes = NULL, |
| NABoolean noStateChange = FALSE, |
| NABoolean unpackDA = FALSE, |
| CollHeap * heap = NULL); |
| |
| |
| |
| moveStatus moveInSendData(ULng32 projRowLen, |
| ex_expr_base * expr, |
| atp_struct * atp1, |
| atp_struct * workAtp, |
| unsigned short tuppIndex); |
| |
| |
| NABoolean moveOutSendData(tupp &outTupp); |
| |
| |
| moveStatus |
| moveInReplyData(NABoolean doMoveControl, |
| NABoolean doMoveData, |
| void * currQState, |
| ULng32 projRowLen, |
| ComDiagsArea * diagsArea, |
| tupp_descriptor ** diagsDesc, |
| ex_expr_base * expr, |
| atp_struct * atp1, |
| atp_struct * workAtp, |
| atp_struct * destAtp, |
| unsigned short tuppIndex, |
| NABoolean doMoveStats, // if TRUE & statsArea |
| // is passed in, move in stats |
| ExStatisticsArea * statsArea, |
| tupp_descriptor ** statsDesc); |
| |
| |
| NABoolean moveOutReplyData(void * currQState, |
| tupp &outTupp, |
| ComDiagsArea ** diagsArea, |
| ExStatisticsArea ** statsArea, |
| Int64 * numStatsBytes); |
| |
| |
| virtual SqlBufferOlt * castToSqlBufferOlt() { return this; }; |
| |
| |
| NABoolean isStats() { return (oltBufFlags_ & STATS_) != 0; }; |
| |
| void setIsStats(NABoolean v) |
| {(v ? oltBufFlags_ |= STATS_ : oltBufFlags_ &= ~STATS_);} |
| |
| |
| NABoolean dataProcessed() { return (oltBufFlags_ & DATA_PROCESSED_) != 0; }; |
| |
| void setDataProcessed(NABoolean v) |
| {(v ? oltBufFlags_ |= DATA_PROCESSED_ : oltBufFlags_ &= ~DATA_PROCESSED_);} |
| |
| |
| NABoolean containsOltSmall() { return (oltBufFlags_ & CONTAINS_OLT_SMALL_) != 0; }; |
| |
| void setContainsOltSmall(NABoolean v) |
| {(v ? oltBufFlags_ |= CONTAINS_OLT_SMALL_ : oltBufFlags_ &= ~CONTAINS_OLT_SMALL_);} |
| |
| |
| virtual ULng32 get_used_size() |
| { return getSendBufferSize(); } |
| |
| |
| Contents getContents() { return (Contents)contents_; } |
| |
| void setContents(Contents c) { contents_ = (unsigned char)c; } |
| |
| |
| tupp_descriptor * getNextTuppDesc(tupp_descriptor * tdesc, |
| Lng32 rowlen = -1) |
| { |
| tupp_descriptor * nextTdesc = NULL; |
| |
| if (tdesc) |
| { |
| nextTdesc = |
| (tupp_descriptor*)(tdesc->getTupleAddress() + |
| ROUND8(tdesc->getAllocatedSize())); |
| } |
| else |
| { |
| nextTdesc = |
| (tupp_descriptor*)((char *)this+ROUND8(sizeof(SqlBufferOlt))); |
| |
| if (rowlen >= 0) |
| { |
| sizeInBytes_ = ROUND8(sizeof(SqlBufferOlt)); |
| } |
| } |
| |
| if (rowlen < 0) |
| nextTdesc->setRelocatedAddress(0); |
| else |
| { |
| nextTdesc->init(rowlen, 0, |
| (char *)nextTdesc+ |
| ROUND8(sizeof(tupp_descriptor))); |
| sizeInBytes_ += ROUND8(sizeof(tupp_descriptor)) + ROUND8(rowlen); |
| } |
| |
| return nextTdesc; |
| } |
| |
| char * getSendDataPtr() |
| { |
| return (char *)this+ROUND8(sizeof(SqlBufferOlt)); |
| } |
| |
| virtual ULng32 getSendBufferSize() |
| { |
| return sizeInBytes_; |
| } |
| |
| char * getReplyDataPtr() |
| { |
| if (containsOltSmall()) |
| { |
| if ((dataProcessed()) && (NOT isStats())) |
| return (char *)this+ROUND8(sizeof(SqlBufferOlt)) + |
| ROUND8(sizeof(SqlBufferOltSmall)) - |
| sizeof(SqlBufferHeader); |
| else |
| return (char *)this+ROUND8(sizeof(SqlBufferOlt)); |
| } |
| else |
| { |
| // on NT, skip the vtbl ptr. It is at the beginning of the class. |
| return (char *)this + sizeof(char*); |
| } |
| } |
| |
| virtual ULng32 getReplyBufferSize() |
| { |
| if (containsOltSmall()) |
| return sizeInBytes_; |
| |
| // on NT, skip the vtbl ptr. It is at the beginning of the class. |
| return (sizeInBytes_ - sizeof(char*)); |
| } |
| |
| // is space for a tuple with the given length available? |
| virtual short space_available(Lng32 tup_data_size) |
| { |
| return -1; |
| } |
| |
| |
| private: |
| unsigned char oltBufFlags_; |
| unsigned char contents_; |
| short filler_; |
| }; |
| |
| /* |
| definitions moved to sql_buffer_size.h |
| |
| static unsigned long SqlBufferGetTuppSize( |
| long recordLength = 0, |
| SqlBufferHeader::BufferType bufType = SqlBufferHeader::NORMAL_) |
| { |
| long sizeofTuppDescriptor = |
| ((bufType == SqlBufferHeader::DENSE_) ? ROUND8(sizeof(TupleDescInfo)) |
| : sizeof(tupp_descriptor)); |
| |
| return ROUND8(recordLength) + sizeofTuppDescriptor; |
| |
| } |
| |
| // a static method used to determine the needed buffer length if a |
| // given number of records with a given length are to be stored |
| |
| |
| static unsigned long SqlBufferNeededSize(long numTuples, |
| long recordLength, |
| SqlBufferHeader::BufferType bufType) |
| { |
| // Return the header size plus the size of any tuple descriptors |
| // beyond the first (which is included in the header) plus the |
| // size for the aligned data. |
| long headerSize = 0; |
| switch (bufType) |
| { |
| case SqlBufferHeader::DENSE_: |
| headerSize = sizeof(SqlBufferDense); |
| break; |
| |
| case SqlBufferHeader::OLT_: |
| headerSize = sizeof(SqlBufferOlt); |
| break; |
| |
| case SqlBufferHeader::NORMAL_: |
| headerSize = sizeof(SqlBufferNormal); |
| break; |
| |
| default: |
| headerSize = sizeof(SqlBufferNormal); |
| break; |
| } |
| |
| headerSize = ROUND8(headerSize); |
| |
| return (headerSize + |
| (numTuples * SqlBufferGetTuppSize(recordLength, bufType))); |
| } |
| */ |
| |
| #ifndef UDRSERV_BUILD |
| ///////////////////////////////////////////////////////////////////////////// |
| // class sql_buffer pool |
| ///////////////////////////////////////////////////////////////////////////// |
| class sql_buffer_pool : public ExGod |
| { |
| public: |
| |
| // allocate a buffer pool from a space object (everything gets |
| // deallocated when the space object gets deleted) and pre-allocate |
| // numberOfBuffers buffers of size defaultBufferSize |
| sql_buffer_pool(Lng32 numberOfBuffers, |
| Lng32 defaultBufferSize, |
| CollHeap * space, |
| SqlBufferBase::BufferType bufType |
| = SqlBufferBase::NORMAL_); |
| |
| ~sql_buffer_pool(); |
| |
| // add a new sql_buffer to the pool by specifying its total size or the |
| // number of tupp_descriptors and their length |
| SqlBufferBase * addBuffer(Lng32 totalBufferSize, bool failureIsFatal = true); |
| SqlBufferBase * addBuffer(Lng32 totalBufferSize, |
| SqlBufferBase::BufferType bufType, |
| bool failureIsFatal = true); |
| |
| // this method allocates one buffer but doesn't add it to pool. |
| static SqlBufferBase * addBuffer(Lng32 totalBufferSize, |
| SqlBufferBase::BufferType bufType, |
| CollHeap * space); |
| |
| // gets an empty buffer with at least freeSpace bytes of free space or |
| // returns NULL if no free buffer found |
| SqlBufferBase * get_free_buffer(Lng32 freeSpace); |
| |
| // initializes tp to point to a new tupp_descriptor in the pool |
| // that has a data length of tupDataSize |
| // RETURNS: -1, if tuple found. 0, otherwise. |
| short get_free_tuple(tupp &tp, Lng32 tupDataSize, SqlBuffer **buf=NULL); |
| |
| // returns a new tupp_descriptor in the pool |
| // that has a data length of tupDataSize. |
| // Sets the reference count to 1. |
| // RETURNS: tupp_descriptor, if tuple found. NULL, otherwise. |
| // If buf is non-Null, also sets buf to the buffer from which |
| // the tupp_descriptor was allocated. This is used to later |
| // resize the tuple if needed. |
| tupp_descriptor * get_free_tupp_descriptor(Lng32 tupDataSize, SqlBuffer **buf=NULL); |
| |
| // call free_buffer for all buffers in the pool |
| void free_buffers(); |
| |
| // call compactBuffer for all buffers in the pool |
| void compact_buffers(); |
| |
| inline Lng32 get_number_of_buffers() const |
| { return currNumberOfBuffers_; } |
| |
| inline Lng32 get_max_number_of_buffers() const |
| { return maxNumberOfBuffers_;} |
| |
| inline void set_max_number_of_buffers(Lng32 maxnumbuf) |
| {maxNumberOfBuffers_ = maxnumbuf;} |
| |
| // for debugging purposes |
| void printAllBufferInfo(); |
| |
| |
| Lng32 getTotalMemorySize() { return memoryUsed_;} |
| |
| void getUsedMemorySize(UInt32 &staticMemSize, |
| UInt32 &dynMemSize); |
| |
| |
| void resizeLastTuple(UInt32 tup_data_size, char *dataPointer); |
| |
| SqlBufferHeader::moveStatus moveIn(atp_struct *atp1, |
| atp_struct *atp2, |
| UInt16 tuppIndex, |
| Lng32 tupDataSize, |
| ex_expr_base *moveExpr, |
| NABoolean addBufferIfNeeded, |
| Lng32 bufferSize); |
| |
| SqlBufferHeader::moveStatus moveIn(atp_struct *atp, |
| UInt16 tuppIndex, |
| Lng32 tupDataSize, |
| char *srcData, |
| NABoolean addBufferIfNeeded, |
| Lng32 bufferSize); |
| |
| NABoolean staticMode() { return ((flags_ & STATIC_MODE) != 0); }; |
| |
| void setStaticMode(NABoolean v) |
| { ( v ? flags_ |= STATIC_MODE : flags_ &= ~STATIC_MODE ); } |
| |
| |
| Lng32 defaultBufferSize() { return defaultBufferSize_; }; |
| |
| // current buffer regardles of how much space |
| short currentBufferHasEnoughSpace( Lng32 tupDataSize); |
| |
| SqlBufferBase * getDefragBuffer() const |
| { |
| return defragBuffer_; |
| } |
| |
| tupp_descriptor * addDefragTuppDescriptor(Lng32 dataSize); |
| tupp_descriptor * getDefragTd() |
| { |
| return defragTd_; |
| } |
| |
| #if (defined(_DEBUG)) |
| static void logDefragInfo(char * txt, |
| Lng32 neededSpace, |
| Lng32 actNeededSpace, |
| Lng32 freeBuffSpace, |
| void *p, |
| Lng32 NumRowsInBuff, |
| ex_tcb * tcb = NULL); |
| #endif |
| |
| private: |
| enum Flags {STATIC_MODE = 0x0001}; |
| |
| // how many buffers are currently allocated |
| Lng32 currNumberOfBuffers_; |
| |
| // limit of the number of buffers in the pool |
| Lng32 maxNumberOfBuffers_; |
| |
| // total amount of memory occupied by all the buffers |
| Lng32 memoryUsed_; |
| |
| Lng32 defaultBufferSize_; |
| |
| // a linked list of sql_buffers who make up the pool |
| Queue * staticBufferList_; |
| |
| // a linked list of sql_buffers who make up the pool. This |
| // list is used to allocate tuples that are needed during work(). |
| Queue * dynBufferList_; |
| |
| // buffers are allocated from a space object |
| CollHeap * space_; |
| |
| ULng32 flags_; |
| |
| SqlBufferBase::BufferType bufType_; |
| |
| //buffer used for defragmentation.it only needs to hold one row. |
| SqlBufferBase *defragBuffer_; |
| // tuple descriptor to the row in the defrag buffer |
| tupp_descriptor * defragTd_; |
| |
| // private methods |
| // get the current buffer with enough free space |
| inline SqlBuffer * getCurrentBuffer(Lng32 freeSpace,Int32 mustBeEmpty = 0); |
| |
| |
| |
| // try to find a buffer that is not in use by an I/O operation and that |
| // has at least freeSpace free space without performing any cleanup |
| SqlBufferBase * findBuffer(Lng32 freeSpace, |
| Int32 mustBeEmpty = 0); |
| |
| // same as above, but try to free up some space if needed |
| SqlBufferBase * getBuffer(Lng32 freeSpace, |
| Int32 mustBeEmpty = 0); |
| |
| SqlBufferBase * addBuffer(Queue * bufferList, |
| Lng32 totalBufferSize, |
| SqlBufferBase::BufferType bufType, |
| bool failureIsFatal = true); |
| |
| SqlBufferBase * addBuffer(Lng32 numTupps, Lng32 recordLength); |
| |
| Queue * activeBufferList() |
| {return (staticMode() ? staticBufferList_ : dynBufferList_);}; |
| |
| public: |
| |
| SqlBuffer * getCurrentBuffer(); |
| |
| |
| }; |
| |
| |
| |
| #endif // UDRSERV_BUILD |
| |
| #endif |