350 lines
11 KiB
C++
350 lines
11 KiB
C++
/*
|
|
Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL hereby grant you an additional
|
|
permission to link the program and your derivative works with the
|
|
separately licensed software that they have included with MySQL.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License, version 2.0, for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef NdbReceiver_H
|
|
#define NdbReceiver_H
|
|
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL // Not part of public interface
|
|
|
|
#include <ndb_types.h>
|
|
|
|
|
|
class Ndb;
|
|
class NdbImpl;
|
|
class NdbTransaction;
|
|
class NdbRecord;
|
|
class NdbRecAttr;
|
|
class NdbQueryOperationImpl;
|
|
class NdbReceiverBuffer;
|
|
|
|
class NdbReceiver
|
|
{
|
|
friend class Ndb;
|
|
friend class NdbImpl;
|
|
friend class NdbOperation;
|
|
friend class NdbQueryImpl;
|
|
friend class NdbQueryOperationImpl;
|
|
friend class NdbResultStream;
|
|
friend class NdbScanOperation;
|
|
friend class NdbIndexOperation;
|
|
friend class NdbIndexScanOperation;
|
|
friend class NdbTransaction;
|
|
friend class NdbWorker;
|
|
friend int compare_ndbrecord(const NdbReceiver *r1,
|
|
const NdbReceiver *r2,
|
|
const NdbRecord *key_record,
|
|
const NdbRecord *result_record,
|
|
bool descending,
|
|
bool read_range_no);
|
|
friend int spjTest(int argc, char** argv);
|
|
|
|
public:
|
|
enum ReceiverType { NDB_UNINITIALIZED,
|
|
NDB_OPERATION = 1,
|
|
NDB_SCANRECEIVER = 2,
|
|
NDB_INDEX_OPERATION = 3,
|
|
NDB_QUERY_OPERATION = 4
|
|
};
|
|
|
|
NdbReceiver(Ndb *aNdb);
|
|
int init(ReceiverType type, void* owner);
|
|
void release();
|
|
~NdbReceiver();
|
|
|
|
Uint32 getId() const{
|
|
return m_id;
|
|
}
|
|
|
|
ReceiverType getType() const {
|
|
return m_type;
|
|
}
|
|
|
|
inline NdbTransaction * getTransaction(ReceiverType type) const;
|
|
void* getOwner() const {
|
|
return m_owner;
|
|
}
|
|
|
|
bool checkMagicNumber() const;
|
|
static Uint32 getMagicNumber() { return (Uint32)0x11223344; }
|
|
Uint32 getMagicNumberFromObject() const;
|
|
|
|
inline void next(NdbReceiver* next_arg) { m_next = next_arg;}
|
|
inline NdbReceiver* next() { return m_next; }
|
|
|
|
void setErrorCode(int);
|
|
|
|
/**
|
|
* Construct a receive buffer for a batched result set.
|
|
* 'buffer' has to be allocated with size as calculated by
|
|
* result_bufsize, and pointer should be Uint32 aligned.
|
|
*/
|
|
static
|
|
NdbReceiverBuffer* initReceiveBuffer(
|
|
Uint32 *buffer,
|
|
Uint32 bufSize, // Size in Uint32 words
|
|
Uint32 batchRows);
|
|
|
|
/**
|
|
* Prepare for receiving of rows into specified buffer.
|
|
* This buffer is later navigated, and retrieved from,
|
|
* by either getNextRow() or setCurrentRow(). The row is
|
|
* then 'unpacked' into 'row_buffer' set by do_setup_ndbrecord().
|
|
*/
|
|
void prepareReceive(NdbReceiverBuffer *buf);
|
|
|
|
private:
|
|
Uint32 theMagicNumber;
|
|
Ndb* const m_ndb;
|
|
Uint32 m_id;
|
|
Uint32 m_tcPtrI;
|
|
ReceiverType m_type;
|
|
void* m_owner;
|
|
NdbReceiver* m_next;
|
|
|
|
/**
|
|
* At setup
|
|
*/
|
|
class NdbRecAttr * getValue(const class NdbColumnImpl*, char * user_dst_ptr);
|
|
void getValues(const NdbRecord*, char*);
|
|
void prepareSend();
|
|
|
|
static
|
|
void calculate_batch_size(const NdbImpl&,
|
|
Uint32 parallelism,
|
|
Uint32& batch_size,
|
|
Uint32& batch_byte_size);
|
|
|
|
void calculate_batch_size(Uint32 parallelism,
|
|
Uint32& batch_size,
|
|
Uint32& batch_byte_size) const;
|
|
|
|
/**
|
|
* Calculate size of result buffer which has to be
|
|
* allocated for a buffered result set, and later given to
|
|
* initReceiveBuffer() as 'buffer' argument.
|
|
*
|
|
* The 'batch_rows' and 'batch_bytes' argument may have been
|
|
* set by 'calculate_batch_size'. On return from this method
|
|
* the 'batch_bytes' size may be capped to the max possible
|
|
* batch size if 'batch_rows' are returned.
|
|
*/
|
|
static
|
|
void result_bufsize(const NdbRecord *result_record,
|
|
const Uint32* read_mask,
|
|
const NdbRecAttr *first_rec_attr,
|
|
Uint32 key_size,
|
|
bool read_range_no,
|
|
bool read_correlation,
|
|
Uint32 parallelism,
|
|
Uint32 batch_rows, //In: 'REQ' argument to TC
|
|
Uint32& batch_bytes, //In/Out: 'REQ' Argument to TC
|
|
Uint32& buffer_bytes); //Out: ReceiveBuffer size
|
|
|
|
/*
|
|
Set up buffers for receiving TRANSID_AI and KEYINFO20 signals
|
|
during a scan using NdbRecord.
|
|
*/
|
|
void do_setup_ndbrecord(const NdbRecord *ndb_record,
|
|
char *row_buffer,
|
|
bool read_range_no, bool read_key_info);
|
|
|
|
|
|
/**
|
|
* Calculate size required for an 'unpacked' result row
|
|
* where the current result row is stored. A buffer of this size is used
|
|
* as 'row_buffer' argument to do_setup_ndbrecord().
|
|
*/
|
|
static
|
|
Uint32 ndbrecord_rowsize(const NdbRecord *ndb_record,
|
|
bool read_range_no);
|
|
|
|
int execKEYINFO20(Uint32 info, const Uint32* ptr, Uint32 len);
|
|
int execTRANSID_AI(const Uint32* ptr, Uint32 len);
|
|
int execTCOPCONF(Uint32 len);
|
|
int execSCANOPCONF(Uint32 tcPtrI, Uint32 len, Uint32 rows);
|
|
|
|
/* Assist functions to execTRANSID_AI */
|
|
const Uint32 * handle_extra_get_values(Uint32 & save_pos,
|
|
Uint32 * aLength,
|
|
const Uint32 *aDataPtr,
|
|
Uint32 attrSize,
|
|
bool isScan,
|
|
Uint32 attrId,
|
|
Uint32 origLength,
|
|
bool & ndbrecord_part_done);
|
|
const Uint32 * handle_attached_rec_attrs(Uint32 attrId,
|
|
const Uint32 *aDataPtr,
|
|
Uint32 origLength,
|
|
Uint32 attrSize,
|
|
Uint32 * aLength);
|
|
|
|
/* Convert from packed transporter to NdbRecord / RecAttr format. */
|
|
int unpackRow(const Uint32* ptr, Uint32 len, char* row);
|
|
|
|
/* NdbRecord describing row layout expected by API */
|
|
const NdbRecord *m_ndb_record;
|
|
|
|
/* The (single) current row in 'unpacked' NdbRecord format */
|
|
char *m_row_buffer;
|
|
|
|
/* Block of memory used to buffer all rows in a batch during scan. */
|
|
NdbReceiverBuffer *m_recv_buffer;
|
|
|
|
/**
|
|
* m_read_range_no & m_read_key_info is true if we are reading
|
|
* range / keyinfo as part of scans.
|
|
*/
|
|
bool m_read_range_no;
|
|
bool m_read_key_info;
|
|
|
|
/**
|
|
* Holds the list of RecAttr defined by getValue()
|
|
* which to retrieve data into when a row is unpacked.
|
|
* These RecAttr's are owner by this NdbReceiver and
|
|
* terminated by ::release()
|
|
*/
|
|
class NdbRecAttr* m_firstRecAttr;
|
|
class NdbRecAttr* m_lastRecAttr; // A helper for getValue()
|
|
|
|
/* Savepoint for unprocessed RecAttr data from current row. */
|
|
const Uint32* m_rec_attr_data;
|
|
Uint32 m_rec_attr_len;
|
|
|
|
/*
|
|
When an NdbReceiver is sitting in the NdbScanOperation::m_sent_receivers
|
|
array, waiting to receive TRANSID_AI data from the kernel, its index into
|
|
m_sent_receivers is stored in m_list_index, so that we can remove it when
|
|
done without having to search for it.
|
|
*/
|
|
Uint32 m_list_index;
|
|
/*
|
|
m_current_row holds the next row / key to be delivered to
|
|
the application.
|
|
*/
|
|
Uint32 m_current_row;
|
|
|
|
/*
|
|
m_expected_result_length: Total number of 32-bit words of TRANSID_AI and
|
|
KEYINFO20 data to receive. This is set to zero until SCAN_TABCONF has
|
|
been received.
|
|
*/
|
|
Uint32 m_expected_result_length;
|
|
Uint32 m_received_result_length;
|
|
|
|
/**
|
|
* Unpack a packed stream of field values, whose presence and nullness
|
|
* is indicated by a leading bitmap into a list of NdbRecAttr objects
|
|
* Return the number of words read from the input stream.
|
|
*/
|
|
static
|
|
Uint32 unpackRecAttr(NdbRecAttr**, Uint32 bmlen,
|
|
const Uint32* aDataPtr, Uint32 aLength);
|
|
|
|
/**
|
|
* Unpack a stream of field values, whose presence and nullness
|
|
* is indicated by a leading bitmap, into an NdbRecord row.
|
|
* Return the number of words consumed.
|
|
*/
|
|
static
|
|
Uint32 unpackNdbRecord(const NdbRecord *record, Uint32 bmlen,
|
|
const Uint32* aDataPtr,
|
|
char* row);
|
|
|
|
/**
|
|
* Handle a stream of field values, both 'READ_PACKED' and plain
|
|
* unpacked fields, into a list of NdbRecAttr objects.
|
|
* Return 0 on success, or -1 on error
|
|
*/
|
|
static
|
|
int handle_rec_attrs(NdbRecAttr* rec_attr_list,
|
|
const Uint32* aDataPtr,
|
|
Uint32 aLength);
|
|
|
|
|
|
/**
|
|
* Unpack data for the specified 'row' previously stored into
|
|
* the 'buffer'. Handles both the row in NdbRecord format, and
|
|
* the key recieved as KEYINFO, if present.
|
|
*/
|
|
const char *unpackBuffer(const NdbReceiverBuffer *buffer, Uint32 row);
|
|
|
|
/**
|
|
* Result set is navigated either sequentialy or randomly to a
|
|
* specific row. The NdbRecord contents is then unpacked into
|
|
* 'm_row_buffer' and returned. KeyInfo, Range no and RecAttr
|
|
* values may be retrieved by specific calls below.
|
|
*/
|
|
const char *getRow(const NdbReceiverBuffer* buffer, Uint32 row);
|
|
const char *getNextRow();
|
|
|
|
/* Fetch the NdbRecord part of current row */
|
|
const char *getCurrentRow() const { return m_row_buffer; }
|
|
|
|
/* get_range_no() returns the range_no for current row. */
|
|
int get_range_no() const;
|
|
|
|
/* Fetch keyinfo from KEYINFO20 signal for current row. */
|
|
int get_keyinfo20(Uint32 & scaninfo, Uint32 & length,
|
|
const char * & data_ptr) const;
|
|
|
|
/** Fetch RecAttr values for current row. */
|
|
int get_AttrValues(NdbRecAttr* rec_attr_list) const;
|
|
};
|
|
|
|
#ifdef NDB_NO_DROPPED_SIGNAL
|
|
#include <stdlib.h>
|
|
#endif
|
|
|
|
inline
|
|
bool
|
|
NdbReceiver::checkMagicNumber() const {
|
|
bool retVal = (theMagicNumber == getMagicNumber());
|
|
#ifdef NDB_NO_DROPPED_SIGNAL
|
|
if(!retVal){
|
|
abort();
|
|
}
|
|
#endif
|
|
return retVal;
|
|
}
|
|
|
|
inline
|
|
Uint32
|
|
NdbReceiver::getMagicNumberFromObject() const
|
|
{
|
|
return theMagicNumber;
|
|
}
|
|
|
|
inline
|
|
int
|
|
NdbReceiver::execTCOPCONF(Uint32 len){
|
|
const Uint32 tmp = m_received_result_length;
|
|
m_expected_result_length = len;
|
|
#ifdef assert
|
|
assert(!(tmp && !len));
|
|
#endif
|
|
return ((bool)len ^ (bool)tmp ? 0 : 1);
|
|
}
|
|
|
|
#endif // DOXYGEN_SHOULD_SKIP_INTERNAL
|
|
#endif
|