diff options
Diffstat (limited to 'storage/ndb/src/common/transporter/SendBuffer.hpp')
-rw-r--r-- | storage/ndb/src/common/transporter/SendBuffer.hpp | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/storage/ndb/src/common/transporter/SendBuffer.hpp b/storage/ndb/src/common/transporter/SendBuffer.hpp new file mode 100644 index 00000000000..63a01f3de24 --- /dev/null +++ b/storage/ndb/src/common/transporter/SendBuffer.hpp @@ -0,0 +1,190 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +//**************************************************************************** +// +// NAME +// SendBuffer +// +// DESCRIPTION +// The SendBuffer is a circular buffer storing signals waiting to be sent. +// The signals can be of variable size and are copied into the buffer +// in Protocol 6 format. There will be two SendBuffer instances +// (priority level A and B) for each transporter using a buffer for +// sending. The buffering will in most cases be done to send as big +// packages as possible over TCP/IP. +// +//***************************************************************************/ +#ifndef SendBuffer_H +#define SendBuffer_H + +#include "TransporterDefinitions.hpp" +#include <TransporterCallback.hpp> + +#ifdef DEBUG_TRANSPORTER +#include <ndb_global.h> +#endif + +class SendBuffer { + friend class TCP_Transporter; +public: + // Set member variables + SendBuffer(Uint32 bufSize); + + // Deallocate the buffer memory + ~SendBuffer(); + + // Allocate memory for the buffer and initialize the buffer pointers + bool initBuffer(Uint32 aRemoteNodeId); + + // Number of bytes remaining in the buffer + Uint32 bufferSizeRemaining(); + + // Number of bytes of data in the buffer + int bufferSize(); + + // Empty the buffer + void emptyBuffer(); + + /** + * The transporter calls updateBuffer after a retrieve followed by + * a successful send, to update the cirkular buffer pointers. + * updateBuffer is called with the number of bytes really sent, + * it may be that it is less than what was retrived from the buffer. + * If that is the case there will be an incomplete message (slack) + * in the SendBuffer. + * + * Returns 0 if buffer empty + * else ~0 + */ + Uint32 bytesSent(Uint32 len); + +#ifdef DEBUG_TRANSPORTER + // Prints the buffer status on the screen. Can be used for testing purposes. + void print(); +#endif + + Uint32* getInsertPtr(Uint32 bytes); + void updateInsertPtr(Uint32 bytes); + +private: + + Uint32 sizeOfBuffer; // Length, in number of bytes, of the buffer memory + Uint32 dataSize; // Number of bytes in buffer + + Uint32 * startOfBuffer; // Pointer to the start of the buffer memory + Uint32 * endOfBuffer; // Pointer to end of buffer + + Uint32 * insertPtr; // Where to insert next + + char * sendPtr; // Where data to send starts + Uint32 sendDataSize; // Num bytes to send + + Uint32 theRemoteNodeId; +}; + +inline +Uint32 +SendBuffer::bytesSent(Uint32 bytes) { + + if(bytes > dataSize){ +#ifdef DEBUG_TRANSPORTER + printf("bytes(%d) > dataSize(%d)\n", bytes, dataSize); +#endif + abort(); + // reportError(0 ,theRemoteNodeId, TE_INVALID_MESSAGE_LENGTH); + return 0; + }//if + + if(bytes > sendDataSize){ +#ifdef DEBUG_TRANSPORTER + printf("bytes(%d) > sendDataSize(%d)\n", bytes, sendDataSize); +#endif + abort(); + //reportError(0,theRemoteNodeId, TE_INVALID_MESSAGE_LENGTH); + return 0; + }//if + + dataSize -= bytes; + sendPtr += bytes; + sendDataSize -= bytes; + + if(sendDataSize == 0){ + if(sendPtr > (char*)insertPtr){ + sendPtr = (char *)startOfBuffer; + sendDataSize = dataSize; + } else { + sendPtr = ((char*)insertPtr) - dataSize; + sendDataSize = dataSize; + } + } + + if(dataSize == 0) + return 0; + return ~0; +} + +inline +Uint32* +SendBuffer::getInsertPtr(Uint32 len){ + if (bufferSizeRemaining() < len){ + return 0; + } + + const char * const tmpInsertPtr = (char *) insertPtr; + + if(tmpInsertPtr >= sendPtr){ + // Is there enough space at the end of the buffer? + if ((tmpInsertPtr + len) < (char*)endOfBuffer){ + sendDataSize += len; + return insertPtr; + } else { + // We have passed the end of the cirkular buffer, + // must start from the beginning + // Is there enough space in the beginning of the buffer? + if ((Uint32)(sendPtr - (char *)startOfBuffer) <= len){ + // Not enough space available, insert failed + return 0; + } else { + // There is space available at the beginning of the buffer + // We start from the beginning, set endOfData and insertPtr + insertPtr = startOfBuffer; + if(sendDataSize != 0){ + return insertPtr; + } + sendPtr = (char *)startOfBuffer; + sendDataSize = len; + return insertPtr; + } + } + } else { + // sendPtr > insertPtr + // Is there enought room + if((tmpInsertPtr + len) < sendPtr){ + return insertPtr; + } + return 0; + } +} + +inline +void +SendBuffer::updateInsertPtr(Uint32 lenBytes){ + dataSize += lenBytes; + insertPtr += (lenBytes / 4); +} + +#endif // Define of SendBuffer_H |