diff options
Diffstat (limited to 'ndb/src/old_files/rep/storage')
-rw-r--r-- | ndb/src/old_files/rep/storage/GCIBuffer.cpp | 173 | ||||
-rw-r--r-- | ndb/src/old_files/rep/storage/GCIBuffer.hpp | 112 | ||||
-rw-r--r-- | ndb/src/old_files/rep/storage/GCIContainer.cpp | 272 | ||||
-rw-r--r-- | ndb/src/old_files/rep/storage/GCIContainer.hpp | 121 | ||||
-rw-r--r-- | ndb/src/old_files/rep/storage/GCIContainerPS.cpp | 128 | ||||
-rw-r--r-- | ndb/src/old_files/rep/storage/GCIContainerPS.hpp | 90 | ||||
-rw-r--r-- | ndb/src/old_files/rep/storage/GCIPage.cpp | 165 | ||||
-rw-r--r-- | ndb/src/old_files/rep/storage/GCIPage.hpp | 114 | ||||
-rw-r--r-- | ndb/src/old_files/rep/storage/LogRecord.hpp | 81 | ||||
-rw-r--r-- | ndb/src/old_files/rep/storage/Makefile | 14 | ||||
-rw-r--r-- | ndb/src/old_files/rep/storage/NodeConnectInfo.hpp | 29 | ||||
-rw-r--r-- | ndb/src/old_files/rep/storage/NodeGroup.cpp | 149 | ||||
-rw-r--r-- | ndb/src/old_files/rep/storage/NodeGroup.hpp | 109 | ||||
-rw-r--r-- | ndb/src/old_files/rep/storage/NodeGroupInfo.cpp | 218 | ||||
-rw-r--r-- | ndb/src/old_files/rep/storage/NodeGroupInfo.hpp | 145 |
15 files changed, 1920 insertions, 0 deletions
diff --git a/ndb/src/old_files/rep/storage/GCIBuffer.cpp b/ndb/src/old_files/rep/storage/GCIBuffer.cpp new file mode 100644 index 00000000000..013600b30a5 --- /dev/null +++ b/ndb/src/old_files/rep/storage/GCIBuffer.cpp @@ -0,0 +1,173 @@ +/* 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 */ + +#include <ndb_global.h> +#include "GCIBuffer.hpp" + +/***************************************************************************** + * Constructor / Destructor + *****************************************************************************/ + +GCIBuffer::GCIBuffer(Uint32 gci, Uint32 id) +{ + m_gci = gci; + m_id = id; + m_complete = false; + m_receivedBytes = 0; +} + +GCIBuffer::~GCIBuffer() +{ + /** + * Loop through all pages and delete them + */ + for(Uint32 i=0; i<m_pageList.size(); i++) { + delete m_pageList[i]; + m_pageList[i] = 0; + } + m_pageList.clear(); + // m_pageList = 0; +} + +/***************************************************************************** + * Inserts + *****************************************************************************/ + +void +GCIBuffer::insertLogRecord(Uint32 tableId, Uint32 operation, + class LinearSectionPtr ptr[3]) +{ + GCIPage * p; + if(m_pageList.size() == 0) { + p = new GCIPage(m_gci); + assert(p != NULL); + m_pageList.push_back(p); + } + + p = m_pageList.back(); + if (!p->insertLogRecord(tableId, operation, ptr)) { + /** + * GCIPage is full. + */ + GCIPage * newPage = new GCIPage(m_gci); + assert(newPage != NULL); + m_pageList.push_back(newPage); + bool res = newPage->insertLogRecord(tableId, operation, ptr); + + if(!res) { + ndbout << "GCIBuffer: gci : " << m_gci << endl; + assert(res); + } + } +} + +/** + * @todo: We must be able to distinguish between Scan meta + * data and log meta data. + * Currently only scan meta data is considered. + */ +void +GCIBuffer::insertMetaRecord(Uint32 tableId, class LinearSectionPtr ptr[3]) +{ + GCIPage * p; + if(m_pageList.size()==0) { + p = new GCIPage(m_gci); + assert(p != NULL); + m_pageList.push_back(p); + } + + p = m_pageList.back(); + + if (!p->insertMetaRecord(tableId, ptr)) { + /** + * Page is full. + */ + GCIPage * newPage = new GCIPage(m_gci); + assert(newPage != NULL); + m_pageList.push_back(newPage); + + bool res = newPage->insertMetaRecord(tableId, ptr); + assert(res); + } +} + +void +GCIBuffer::insertPage(Uint32 gci, char * dataPtr, Uint32 dataBLen) +{ + /** + * allocate a new GCIPage + */ + GCIPage * page = new GCIPage(gci); + assert(page != 0); + + /** + * copy data into page + */ + page->copyDataToPage(dataPtr, dataBLen); + + /** + * put page on pagelist. + */ + m_pageList.push_back(page); + + /** + * Update GCI Buffer received bytes + */ + m_receivedBytes += dataBLen; +} + + +/***************************************************************************** + * Iterator + *****************************************************************************/ + +GCIBuffer::iterator::iterator(const GCIBuffer* gciBuffer) +{ + m_gciBuffer = gciBuffer; + m_iterator=0; + +} + +GCIPage * +GCIBuffer::iterator::first() +{ + m_iterator = 0; + if(m_gciBuffer->m_pageList.size() == 0) return NULL; + return (m_gciBuffer->m_pageList)[m_iterator]; +} + + +GCIPage * +GCIBuffer::iterator::next() +{ + m_iterator++; + if(m_gciBuffer->m_pageList.size() == 0) return NULL; + + if((m_iterator<m_gciBuffer->m_pageList.size())) + return (m_gciBuffer->m_pageList)[m_iterator]; + else + return NULL; +} + + +bool +GCIBuffer::iterator::exists() +{ + return (m_iterator < m_gciBuffer->m_pageList.size()); +} + + + diff --git a/ndb/src/old_files/rep/storage/GCIBuffer.hpp b/ndb/src/old_files/rep/storage/GCIBuffer.hpp new file mode 100644 index 00000000000..8a8473d1d49 --- /dev/null +++ b/ndb/src/old_files/rep/storage/GCIBuffer.hpp @@ -0,0 +1,112 @@ +/* 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 */ + +#ifndef GCI_BUFFER_HPP +#define GCI_BUFFER_HPP + +#include "GCIPage.hpp" +#include <Vector.hpp> +#include <TransporterDefinitions.hpp> + +#include <signaldata/RepImpl.hpp> + +/** + * @class GCIBuffer + * @brief A GCIBuffer contains pages containing log records for ONE gci. + * + * @todo Load and save to disk + */ + +class GCIBuffer +{ +public: + GCIBuffer(Uint32 gci, Uint32 id); + ~GCIBuffer(); + + /** + * @fn insertLogRecord + * @param tableId Table this will be LogRecord applies to. + * @param operation Operation this LogRecord represents + * @param ptr Ptr of type LinearSectionPtr that contains the data. + * @return A full page or 0, if the insert didn't generate a full page. + */ + void insertLogRecord(Uint32 tableId, Uint32 operation, + class LinearSectionPtr ptr[3]); + + void insertMetaRecord(Uint32 tableId, class LinearSectionPtr ptr[3]); + + /** + * @fn inserts a page, containing Records into a GCI Buffer. + * @param gci - the gci of the page. + * @param dataPtr - Pointer originating from Page::m_page. + * @param dataBLen - length of dataptr in bytes + * @note Page must NOT be deallocated after being inserted! + */ + void insertPage(Uint32 gci, char * dataPtr, Uint32 dataBLen); + + /** + * @fn isComplete + * @return True if this GCI Buffer is done (gci is completed). + */ + bool isComplete() { return m_complete; }; + void setComplete() { m_complete = true; }; + + /** + * @fn getReceivedBytes + * @returns the total number of bytes that this buffer has received. + */ + Uint32 getReceivedBytes() const { return m_receivedBytes;} ; + + /** + * Iterator for pages + */ + class iterator { + public: + iterator(const GCIBuffer* gciBuffer); + GCIPage * first(); ///< @return First page (or NULL if no page exists) + GCIPage * next(); ///< @return Next page (or NULL if no more page exists) + bool exists(); ///< @return true if another page exists (for next()) + private: + Uint32 m_iterator; + const GCIBuffer * m_gciBuffer; + }; + friend class GCIBuffer::iterator; + + /*************************************************************************** + * GCI Buffer meta information + ***************************************************************************/ + void setGCI(Uint32 gci) { m_gci = gci; }; + Uint32 getGCI() { return m_gci; }; + + void setId(Uint32 id) { m_id = id; }; + Uint32 getId() { return m_id; }; + + bool m_force; // if true, ignore "execute" errors when + // restoring buffer (PUBLIC) during phase + // starting. +private: + /*************************************************************************** + * Private Variables + ***************************************************************************/ + Uint32 m_gci; ///< GCI of this buffer + Uint32 m_id; ///< <m_gci, id> names GCIBuffer + bool m_complete; ///< GCI complete; buffer contains + ///< everything + Vector <GCIPage *> m_pageList; ///< Storage for data/log record pages. + Uint32 m_receivedBytes; ///< Received bytes in this buffer +}; + +#endif diff --git a/ndb/src/old_files/rep/storage/GCIContainer.cpp b/ndb/src/old_files/rep/storage/GCIContainer.cpp new file mode 100644 index 00000000000..c161db0769b --- /dev/null +++ b/ndb/src/old_files/rep/storage/GCIContainer.cpp @@ -0,0 +1,272 @@ +/* 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 */ + +#include "GCIContainer.hpp" +#include <NdbOut.hpp> +#include <NdbMem.h> +#include <new> + +#include <rep/rep_version.hpp> + +//#define GCICONTAINER_DEBUG + +/***************************************************************************** + * Constructors / Destructors + *****************************************************************************/ + +GCIContainer::GCIContainer(Uint32 maxNoOfIds) +{ + m_maxNoOfIds = maxNoOfIds; + + gciRange = new GCIRange[maxNoOfIds * sizeof(GCIRange)]; + + for(Uint32 i = 0; i < maxNoOfIds; i++) { + gciRange[i].m_firstGCI = 1; // The empty interval = [1,0] + gciRange[i].m_lastGCI = 0; + } + theMutexPtr = NdbMutex_Create(); +} + +GCIContainer::~GCIContainer() +{ + for(Uint32 i=0; i < m_bufferList.size(); i++) { + delete m_bufferList[i]; + m_bufferList[i] = 0; + } + + m_bufferList=0; + delete [] gciRange; + NdbMutex_Destroy(theMutexPtr); +} + +/***************************************************************************** + * GCIBuffer Create / Destroy + *****************************************************************************/ + +GCIBuffer * +GCIContainer::createGCIBuffer(Uint32 gci, Uint32 id) +{ + GCIBuffer * buf = new GCIBuffer(gci, id); + if (buf == NULL) REPABORT("Could not allocate new buffer"); + + m_bufferList.push_back(buf, true); + +#ifdef GCICONTAINER_DEBUG + ndbout_c("GCIContainer: New buffer created (GCI: %d, Id: %d)", gci, id); +#endif + return buf; +} + +/** + * Delete all GCI buffers strictly less than "gci" + */ +void +GCIContainer::destroyGCIBuffersBeforeGCI(Uint32 gci, Uint32 id) +{ + for(Uint32 i = 0 ; i < m_bufferList.size(); i++) { + if(m_bufferList[i]->getGCI() < gci) { +#ifdef GCICONTAINER_DEBUG + ndbout_c("GCIContainer: Destroying buffer (GCI: %d, id: %d)", + m_bufferList[i]->getGCI(), id); +#endif + destroyGCIBuffer(i, id); + } + } +} + +/** + * Delete one GCI Buffer + */ +bool +GCIContainer::destroyGCIBuffer(Uint32 gci, Uint32 id) +{ + m_bufferList.lock(); + for(Uint32 i = 0 ; i < m_bufferList.size(); i++) { + if((m_bufferList[i]->getGCI() == gci) && + (m_bufferList[i]->getId() == id)) { + + /** + * Delete the GCI Buffer + */ + delete m_bufferList[i]; + m_bufferList[i] = 0; + + /** + * Remove from the list of buffers stored in GCIContainer + */ + m_bufferList.erase(i,false); + m_bufferList.unlock(); + + /** + * Set info + */ + NdbMutex_Lock(theMutexPtr); + if(gciRange[id].m_firstGCI != gci) + RLOG(("WARNING! Buffer %d deleted from [%d-%d]", + gci, gciRange[id].m_firstGCI, gciRange[id].m_lastGCI)); + + gciRange[id].m_firstGCI++; + + /** + * Normalize empty interval to [1,0] + */ + if (gciRange[id].m_firstGCI > gciRange[id].m_lastGCI){ + gciRange[id].m_firstGCI = 1; + gciRange[id].m_lastGCI = 0; + } + NdbMutex_Unlock(theMutexPtr); + return true; + } + } + m_bufferList.unlock(); + return false; +} + +/***************************************************************************** + * GCIBuffer interface + *****************************************************************************/ + +GCIBuffer * +GCIContainer::getGCIBuffer(Uint32 gci, Uint32 id) +{ + GCIBuffer * gciBuffer = 0; + + m_bufferList.lock(); + for(Uint32 i=0; i < m_bufferList.size(); i++) { + gciBuffer = m_bufferList[i]; + if((gciBuffer->getGCI() == gci) && (gciBuffer->getId() == id)) { + m_bufferList.unlock(); + return gciBuffer; + } + } + m_bufferList.unlock(); + return 0; +} + +void +GCIContainer::setCompleted(Uint32 gci, Uint32 id) +{ + GCIBuffer * gciBuffer = getGCIBuffer(gci, id); + if(gciBuffer == 0) gciBuffer = createGCIBuffer(gci, id); + + gciBuffer->setComplete(); + +#ifdef GCICONTAINER_DEBUG + ndbout_c("GCIContainer: Buffer completely stored in GCIContainer (GCI: %d)", + gci); +#endif + + NdbMutex_Lock(theMutexPtr); + + /** + * If this is the first GCI Buffer to be completed + * then both first and last must be updated. + * Subsequently, only the last value must be updated. + */ + if(gciRange[id].m_firstGCI == 1 && gciRange[id].m_lastGCI == 0) { + gciRange[id].m_firstGCI = gci; + gciRange[id].m_lastGCI = gci; + } else { + if (gci != gciRange[id].m_lastGCI + 1) { + RLOG(("WARNING! Non-consequtive buffer %u completed [%u-%u])", + gci, gciRange[id].m_firstGCI, gciRange[id].m_lastGCI)); + } + gciRange[id].m_lastGCI = gci; + } + NdbMutex_Unlock(theMutexPtr); +} + +void +GCIContainer::getAvailableGCIBuffers(Uint32 id, Uint32 * first, Uint32 * last) +{ + NdbMutex_Lock(theMutexPtr); + *first = gciRange[id].m_firstGCI; + *last = gciRange[id].m_lastGCI; + NdbMutex_Unlock(theMutexPtr); +} + +/***************************************************************************** + * Inserts + *****************************************************************************/ +void +GCIContainer::insertMetaRecord(Uint32 id, Uint32 tableId, + class LinearSectionPtr ptr[3], Uint32 gci) +{ + /********************************************************** + * 1. Find correct GCI Buffer (Doesn't exist? Create one) + **********************************************************/ + GCIBuffer * gciBuffer = getGCIBuffer(gci, id); + if(gciBuffer == 0) gciBuffer = createGCIBuffer(gci, id); + + /********************************** + * 2. Insert record into GCIBuffer + **********************************/ + gciBuffer->insertMetaRecord(tableId, ptr); +} + +void +GCIContainer::insertLogRecord(Uint32 id, Uint32 tableId, Uint32 operation, + class LinearSectionPtr ptr[3], Uint32 gci) +{ + /********************************************************* + * 1. Find correct GCI Buffer (doesn't exist? create one) + *********************************************************/ + GCIBuffer * gciBuffer = getGCIBuffer(gci, id); + if(gciBuffer == 0) gciBuffer = createGCIBuffer(gci, id); + /********************************** + * 2. Insert record into GCIBuffer + **********************************/ + gciBuffer->insertLogRecord(tableId, operation, ptr); +} + +void +GCIContainer::insertPage(Uint32 gci, Uint32 id, + char * dataPtr, Uint32 dataBLen) +{ + /********************************************************* + * 1. Find correct GCI Buffer (doesn't exist? create one) + *********************************************************/ + GCIBuffer * gciBuffer = getGCIBuffer(gci, id); + if(gciBuffer == 0) gciBuffer = createGCIBuffer(gci, id); + + /******************************** + * 2. Insert page into GCIBuffer + ********************************/ + gciBuffer->insertPage(gci, dataPtr, dataBLen); +} + +bool +GCIContainer::reset() +{ + /** + * Clear the intervals + */ + for(Uint32 i = 0; i < m_maxNoOfIds; i++) { + gciRange[i].m_firstGCI = 1; // The empty interval = [1,0] + gciRange[i].m_lastGCI = 0; + } + + /** + * Destroy ALL gci buffers for ALL ids + */ + for(Uint32 i=0; i < m_bufferList.size(); i++) { + delete m_bufferList[i]; + m_bufferList[i] = 0; + } + m_bufferList.clear(); + + return true; +} diff --git a/ndb/src/old_files/rep/storage/GCIContainer.hpp b/ndb/src/old_files/rep/storage/GCIContainer.hpp new file mode 100644 index 00000000000..48cbc66bfbd --- /dev/null +++ b/ndb/src/old_files/rep/storage/GCIContainer.hpp @@ -0,0 +1,121 @@ +/* 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 */ + +#ifndef GCI_CONTAINER_HPP +#define GCI_CONTAINER_HPP + +#include <Vector.hpp> + +#include "LogRecord.hpp" +#include "GCIBuffer.hpp" + +#undef swap +#include <list> +#include <iterator> + +/** + * @class GCIContainer + * @brief Responsible for storing LogRecord:s in GCIBuffer:s + * + * Each GCIBuffer stored in the GCIContainer is named by a pair <GCI, id>. + * (On PS REP the id is the nodeId, on SS REP the id is the node group). + */ +class GCIContainer { +public: + GCIContainer(Uint32 maxNoOfIds); + ~GCIContainer(); + + /*************************************************************************** + * GCIBuffer interface + ***************************************************************************/ + /** + * @return GCIBuffer if success, NULL otherwise + */ + GCIBuffer * createGCIBuffer(Uint32 gci, Uint32 id); + + /** + * Destroy all buffers with GCI strictly less than gci. + */ + void destroyGCIBuffersBeforeGCI(Uint32 gci, Uint32 id); + + /** + * Destroy all buffers with GCI gci. + * @return true if buffer was deleted, false if no buffer exists + */ + bool destroyGCIBuffer(Uint32 gci, Uint32 id); + + /** + * Fetch buffer + * @return GCIBuffer for gci, or NULL if no buffer found + */ + GCIBuffer * getGCIBuffer(Uint32 gci, Uint32 id); + + /** + * Set that buffer is completed, i.e. no more records are to be inserted + */ + void setCompleted(Uint32 gci, Uint32 id); + + + /** + * @fn insertPage + * @param gci GCI this page belongs to. + * @param id Id this page belongs to. + * @param dataPtr Pointer originating from Page::m_page + * @param dataBLen Length in bytes of data following dataptr. + */ + void insertPage(Uint32 gci, Uint32 id, char * dataPtr, Uint32 dataBLen); + + + /*************************************************************************** + * Record interface + ***************************************************************************/ + void insertLogRecord(Uint32 id, Uint32 tableId, Uint32 operation, + class LinearSectionPtr ptr[3], Uint32 gci); + + void insertMetaRecord(Uint32 id, Uint32 tableId, + class LinearSectionPtr ptr[3], Uint32 gci); + + /** + * Get available (complete) GCI Buffers that exists in the container. + * first == last means that there is one complete buffer + * @param id Id for which to as for available gci buffers. + * @param first First complete gci buffer + * @param last Last complete gci buffer + */ + void getAvailableGCIBuffers(Uint32 id, Uint32 * first, Uint32 * last); + + /** + * Resets the gcicontainer to its original state (initial state and empty) + * I.e., same state as when the object was first constructed. + * @return true if reset was ok + */ + bool reset(); + +private: + NdbMutex* theMutexPtr; + MutexVector <GCIBuffer *> m_bufferList; ///< All GCIBuffers stored + + typedef struct GCIRange { + Uint32 m_firstGCI; + Uint32 m_lastGCI; + }; + + Uint32 m_maxNoOfIds; + + GCIRange * gciRange; ///< Array of GCI ranges for each id +}; + +#endif diff --git a/ndb/src/old_files/rep/storage/GCIContainerPS.cpp b/ndb/src/old_files/rep/storage/GCIContainerPS.cpp new file mode 100644 index 00000000000..5adb53f965c --- /dev/null +++ b/ndb/src/old_files/rep/storage/GCIContainerPS.cpp @@ -0,0 +1,128 @@ +/* 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 */ + +#include "GCIContainerPS.hpp" +#include <NdbOut.hpp> +#include <NdbMem.h> +#include <new> + +GCIContainerPS::GCIContainerPS(Uint32 maxNoOfNodeGrps) +{ + m_container = new GCIContainer(maxNoOfNodeGrps); + if (!m_container) REPABORT("Could not allocate new GCIContainer"); +} + +GCIContainerPS::~GCIContainerPS() +{ + delete m_container; +} + +void +GCIContainerPS::setNodeGroupInfo(NodeGroupInfo * info) +{ + m_nodeGroupInfo=info; +}; + +void +GCIContainerPS::createGCIBuffer(Uint32 gci, Uint32 id) +{ + m_container->createGCIBuffer(gci, id); +} + +void +GCIContainerPS::getAvailableGCIBuffers(Uint32 id /*nodegrp */, + Uint32 * first, Uint32 * last) { + + Uint32 nodeId = m_nodeGroupInfo->getPrimaryNode(id); + if(!nodeId) { + *first = 1; + *last = 0; + return; + } + + /** + *@todo do smart stuff with this! + */ + m_container->getAvailableGCIBuffers(nodeId, first, last); + +} + +void +GCIContainerPS::destroyGCIBuffersBeforeGCI(Uint32 gci) +{ + //for each node in every nodeGrp do: + NodeGroupInfo::iterator * it; + for(Uint32 i=0; i<m_nodeGroupInfo->getNoOfNodeGroups(); i++) { + it = new NodeGroupInfo::iterator(i, m_nodeGroupInfo); + for(NodeConnectInfo * nci=it->first(); it->exists();nci=it->next()) { + m_container->destroyGCIBuffersBeforeGCI(gci, nci->nodeId); + } + delete it; + } +} + +void +GCIContainerPS::insertLogRecord(Uint32 id, Uint32 tableId, Uint32 operation, + class LinearSectionPtr ptr[3], Uint32 gci) +{ + m_container->insertLogRecord(id, tableId, operation, ptr, gci); +} + +void +GCIContainerPS::insertMetaRecord(Uint32 id, Uint32 tableId, + class LinearSectionPtr ptr[3], Uint32 gci) +{ + m_container->insertMetaRecord(id, tableId, ptr, gci); +} + +void +GCIContainerPS::setCompleted(Uint32 gci, Uint32 id) +{ + m_container->setCompleted(gci, id); +} + +GCIBuffer * +GCIContainerPS::getGCIBuffer(Uint32 gci, Uint32 id) +{ + return m_container->getGCIBuffer(gci, id); +} + +/** + * @todo: fix return value + */ +bool +GCIContainerPS::destroyGCIBuffer(Uint32 gci, Uint32 id) +{ + //for each node in nodeGrp id do: + NodeGroupInfo::iterator * it; + it = new NodeGroupInfo::iterator(id, m_nodeGroupInfo); + for(NodeConnectInfo * nci=it->first(); it->exists();nci=it->next()) + { + if(!m_container->destroyGCIBuffer(gci, nci->nodeId)) + { + delete it; + return false; + } + } + delete it; + return true; +} + +bool +GCIContainerPS::reset() +{ + return m_container->reset(); +} diff --git a/ndb/src/old_files/rep/storage/GCIContainerPS.hpp b/ndb/src/old_files/rep/storage/GCIContainerPS.hpp new file mode 100644 index 00000000000..7f5aaac4840 --- /dev/null +++ b/ndb/src/old_files/rep/storage/GCIContainerPS.hpp @@ -0,0 +1,90 @@ +/* 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 */ + +#ifndef GCI_CONTAINER_PS_HPP +#define GCI_CONTAINER_PS_HPP + +#include <Vector.hpp> +#include <TransporterDefinitions.hpp> + +#include "NodeGroupInfo.hpp" +#include <rep/storage/GCIContainer.hpp> + +#include <list> +#include <iterator> + +/** + * @class GCIContainerPS + * @brief Interface to GCIContainer that takes node groups into account + */ +class GCIContainerPS +{ +public: + GCIContainerPS(Uint32 maxNoOfNodeGrps); + ~GCIContainerPS(); + + void setNodeGroupInfo(NodeGroupInfo * info); + NodeGroupInfo * getNodeGroupInfo() {return m_nodeGroupInfo;}; + + void createGCIBuffer(Uint32 gci, Uint32 id); + void getAvailableGCIBuffers(Uint32 id /*nodegrp */, + Uint32 * first, Uint32 * last); + + /*************************************************************************** + * Record interface + ***************************************************************************/ + void insertLogRecord(Uint32 grpId, Uint32 tableId, Uint32 operation, + class LinearSectionPtr ptr[3], Uint32 gci); + + void insertMetaRecord(Uint32 grpId, Uint32 tableId, + class LinearSectionPtr ptr[3], Uint32 gci); + + /** + * Destroy all buffers with GCI strictly less than gci. + */ + void destroyGCIBuffersBeforeGCI(Uint32 gci); + + /** + * Set that buffer is completed, i.e. no more records are to be inserted + */ + void setCompleted(Uint32 gci, Uint32 id); + + /** + * Fetch buffer + * @return GCIBuffer for gci, or NULL if no buffer found + */ + GCIBuffer * getGCIBuffer(Uint32 gci, Uint32 id); + + /** + * Destroy all buffers with GCI gci. + * @return true if buffer was deleted, false if no buffer exists + */ + bool destroyGCIBuffer(Uint32 gci, Uint32 id); + + + /** + * Resets the gcicontainer to its original state (initial state and empty) + * @return true if reset was ok + */ + bool reset(); + +private: + GCIContainer * m_container; + NodeGroupInfo * m_nodeGroupInfo; +}; + + +#endif diff --git a/ndb/src/old_files/rep/storage/GCIPage.cpp b/ndb/src/old_files/rep/storage/GCIPage.cpp new file mode 100644 index 00000000000..05ecde2fee1 --- /dev/null +++ b/ndb/src/old_files/rep/storage/GCIPage.cpp @@ -0,0 +1,165 @@ +/* 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 */ + +#include "GCIPage.hpp" +#include "assert.h" +#include <new> + +GCIPage::GCIPage(Uint32 gci) +{ + m_first = NULL; + m_last = NULL; + m_gci = gci; + m_full = false; + m_currentPagePos=m_page; + m_usedBytes = 0; +} + +/***************************************************************************** + * Insert + *****************************************************************************/ + +/** + * Store a new log record on this page. + * @return True if success, false otherwise + */ +bool +GCIPage::insertLogRecord(Uint32 tableId, Uint32 operation, + class LinearSectionPtr ptr[3]) +{ + /** + * Calculate size of new logrecord in bytes + */ + assert(m_page!=NULL); + Uint32 size = 4*ptr[0].sz + 4*ptr[1].sz + sizeof(LogRecord); + + if(!((m_currentPagePos + size ) < (m_page + m_pageBSize))) { + m_full = true; + return false; // No free space. GCIBuffer must allocate a new page + } + LogRecord * lr = new(m_currentPagePos) LogRecord(); + if (lr==0) REPABORT("Could not allocate new log record"); + + lr->recordType = Record::LOG; + lr->recordLen = size; + lr->operation = operation; + lr->tableId = tableId; + lr->attributeHeaderWSize = ptr[0].sz; + lr->attributeDataWSize = ptr[1].sz; + + m_currentPagePos += sizeof(LogRecord); + + lr->attributeHeader = (Uint32*)m_currentPagePos; + memcpy(lr->attributeHeader, ptr[0].p, lr->attributeHeaderWSize * 4); + + m_currentPagePos += lr->attributeHeaderWSize * 4; + + lr->attributeData = (Uint32*)m_currentPagePos; + memcpy(lr->attributeData, ptr[1].p, lr->attributeDataWSize * 4); + + m_currentPagePos += lr->attributeDataWSize * 4; + + m_usedBytes+=size; + return true; +} + +/** + * Store a new log record on this page. + * @return True if sucessful, false otherwise. + */ +bool +GCIPage::insertMetaRecord(Uint32 tableId, class LinearSectionPtr ptr[3]) +{ + /** + * Calculate size of new logrecord in bytes + */ + Uint32 size = 4*ptr[0].sz + sizeof(MetaRecord); + + if(!((m_currentPagePos + size ) < (m_page + m_pageBSize))) { + m_full = true; + return false; // No free space. GCIBuffer must allocate a new page + } + MetaRecord * mr = new(m_currentPagePos) MetaRecord(); + if (mr==0) REPABORT("Could not allocate new meta record"); + + // mr->operation = operation; + mr->recordType = Record::META; + mr->recordLen = size; + + mr->tableId = tableId; + mr->dataLen = ptr[0].sz; + + + m_currentPagePos += sizeof(MetaRecord); + + mr->data = (Uint32*)m_currentPagePos; + memcpy(mr->data, ptr[0].p, mr->dataLen * 4); + + m_currentPagePos += mr->dataLen * 4; + + m_usedBytes+=size; + return true; +} + +/** + * copy function + */ +void +GCIPage::copyDataToPage(char * dataPtr, Uint32 dataBLen) +{ + assert (dataBLen < m_pageBSize); + memcpy(m_page, dataPtr, dataBLen); + m_currentPagePos=m_page + dataBLen; + m_usedBytes = dataBLen; + m_full = true; + m_first = (Record * )m_page; + dataPtr = 0; +} + +/***************************************************************************** + * Iterator + *****************************************************************************/ + +GCIPage::iterator::iterator(const GCIPage* page) +{ + m_gciPage = page; + m_data = m_gciPage->m_page; + m_currentRecord = (Record*)m_data; +} + +Record * +GCIPage::iterator::first() +{ + return m_currentRecord; +} + +Record * +GCIPage::iterator::next() +{ + m_currentRecord = (Record*) + ((char*)(m_currentRecord)+ m_currentRecord->recordLen); + if((char*)m_currentRecord < (char*)(m_data + m_gciPage->m_usedBytes)) + return m_currentRecord; + else { + return 0; + } +} + +bool +GCIPage::iterator::exists() +{ + return ((char*)m_currentRecord < (m_data + m_gciPage->m_usedBytes)); +} diff --git a/ndb/src/old_files/rep/storage/GCIPage.hpp b/ndb/src/old_files/rep/storage/GCIPage.hpp new file mode 100644 index 00000000000..50c5ab0cfba --- /dev/null +++ b/ndb/src/old_files/rep/storage/GCIPage.hpp @@ -0,0 +1,114 @@ +/* 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 */ + +#ifndef GCI_PAGE_HPP +#define GCI_PAGE_HPP + +#include "LogRecord.hpp" +#include <TransporterDefinitions.hpp> + +#include <rep/rep_version.hpp> + +/** + * @class GCIPage + * @brief A GCIPage contains a number of LogRecords for a certain GCI. + */ +class GCIPage +{ +public: + GCIPage(Uint32 gci); + GCIPage(Uint32 gci, char * dataPtr, Uint32 szBytes); + + /** + * @fn insertLogRecord + * @param tableId the table this will be LogRecord applies to. + * @param operation the operation this LogRecord represents + * @param ptr A LinearSectionPtr p'tr that contains the data. + * @return PAGE_FULL if the page is full, otherwise "true" + */ + bool insertLogRecord(Uint32 tableId, Uint32 operation, + class LinearSectionPtr ptr[3]); + + /** + * @fn insertMetaRecord + */ + bool insertMetaRecord(Uint32 tableId, class LinearSectionPtr ptr[3]); + + /** + * @fn getFirstRecord + * @return First record (or NULL if no record is stored on page) + */ + Record * getFirstRecord() { return m_first; }; + + /** + * @fn getStorage + */ + Uint32 * getStoragePtr() const {return (Uint32*)m_page;} ; + Uint32 getStorageByteSize() const {return m_usedBytes;} ; + Uint32 getStorageWordSize() const {return m_usedBytes >> 2;}; + + /** + * @fn copyDataToPage + * @info copy dataPtr to Page + * @param dataPtr - data to copy + * @param dataBLen - size in bytes to copy. + */ + void copyDataToPage(char * dataPtr, Uint32 szBytes); + + /** + * Iterator for records (Not yet used! Maybe should not be used.) + */ + class iterator { + public: + iterator(const GCIPage* page); + Record * first(); ///< @return First record (or NULL if no page exists) + Record * next(); ///< @return Next record (or NULL if no more records) + bool exists(); ///< @return true if another record exists-for next() + private: + Record * m_currentRecord; + const char * m_data; + const GCIPage * m_gciPage; + }; + friend class GCIPage::iterator; + + /** + * @fn getGCI + * Get the GCI of all log records stored on this page. + */ + Uint32 getGCI() { return m_gci; }; + + /** + * @fn isFull + * @return true if page is full, i.e. is one attempt to add a record + * has failed, false otherwise. + */ + bool isFull() { return m_full; }; + +private: + Uint32 m_gci; ///< GCI for this page + + Record * m_first; ///< Pointer to first log record + Record * m_last; ///< Pointer to last log record + + bool m_full; + + static const Uint32 m_pageBSize = 8192; ///< Page size in bytes + char m_page[m_pageBSize]; ///< Storage for pages + char * m_currentPagePos; + Uint32 m_usedBytes; +}; + +#endif diff --git a/ndb/src/old_files/rep/storage/LogRecord.hpp b/ndb/src/old_files/rep/storage/LogRecord.hpp new file mode 100644 index 00000000000..a0bf3d52372 --- /dev/null +++ b/ndb/src/old_files/rep/storage/LogRecord.hpp @@ -0,0 +1,81 @@ +/* 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 */ + +#ifndef LOG_RECORD_HPP +#define LOG_RECORD_HPP + +#include <ndb_global.h> +#include <portlib/NdbMem.h> + +/** + * @class Record + * @brief + */ +class Record { +public: + enum RecordType { META = 1, LOG = 2 }; + RecordType recordType; + Uint32 recordLen; ///< Size in bytes of entire log record, incl payload +}; + + +/** + * @class LogRecord + * @brief + */ +class LogRecord : public Record { +public: + ~LogRecord() { + NdbMem_Free(attributeHeader); + NdbMem_Free(attributeData); + } + +public: + Uint32 gci; //0 + Uint32 operation; //4 + Uint32 tableId; //8 + + Uint32 attributeHeaderWSize; //12 + Uint32 attributeDataWSize; //16 + Uint32 * attributeHeader; //20 + Uint32 * attributeData; //24 + + /** + * Next pointer + */ +}; + + +/** + * @class MetaRecord + * @brief + */ +class MetaRecord : public Record { +public: + ~MetaRecord() { + NdbMem_Free(data); + } + +public: + Uint32 gci; + Uint32 tableId; + Uint32 dataLen; //in words of the data (below) + Uint32 *data; +}; + + +#endif + diff --git a/ndb/src/old_files/rep/storage/Makefile b/ndb/src/old_files/rep/storage/Makefile new file mode 100644 index 00000000000..89b3af455e8 --- /dev/null +++ b/ndb/src/old_files/rep/storage/Makefile @@ -0,0 +1,14 @@ +include .defs.mk + +TYPE := repserver + +ARCHIVE_TARGET := repstorage + +SOURCES = GCIContainer.cpp \ + GCIContainerPS.cpp \ + GCIBuffer.cpp \ + GCIPage.cpp \ + NodeGroupInfo.cpp \ + NodeGroup.cpp + +include $(NDB_TOP)/Epilogue.mk diff --git a/ndb/src/old_files/rep/storage/NodeConnectInfo.hpp b/ndb/src/old_files/rep/storage/NodeConnectInfo.hpp new file mode 100644 index 00000000000..403f92a5999 --- /dev/null +++ b/ndb/src/old_files/rep/storage/NodeConnectInfo.hpp @@ -0,0 +1,29 @@ +/* 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 */ + +#ifndef NODE_CONNECTINFO_HPP +#define NODE_CONNECTINFO_HPP + +#include <ndb_types.h> + +struct NodeConnectInfo { + NodeConnectInfo(Uint16 n, bool c): nodeId(n), connected(c) {}; + Uint32 nodeId; + bool connected; +}; + + +#endif diff --git a/ndb/src/old_files/rep/storage/NodeGroup.cpp b/ndb/src/old_files/rep/storage/NodeGroup.cpp new file mode 100644 index 00000000000..33451efb104 --- /dev/null +++ b/ndb/src/old_files/rep/storage/NodeGroup.cpp @@ -0,0 +1,149 @@ +/* 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 */ + +#include "NodeGroup.hpp" +#include <NdbOut.hpp> + +//#define NODE_GROUP_DEBUG + +NodeGroup::NodeGroup(Uint32 nodeGrp) { + m_nodeGrp = nodeGrp; + m_primaryNode = 0; +} + +NodeGroup::~NodeGroup() { + for(Uint32 i=0; i<m_nodeConnectList.size(); i++) { + delete m_nodeConnectList[i]; + m_nodeConnectList.erase(i); + } +} + +void +NodeGroup::addNode(Uint32 nodeId, bool connected) { +#ifdef NODE_GROUP_DEBUG + ndbout_c("NodeGroup: addNode(nodeId=%d, connected=%d), nodegrp=%d", + nodeId, connected, m_nodeGrp); +#endif + + /** + * If node already in node group, then do nothing except + * setting the connect statusflag for the node (in case it + * has changed). + */ + for(Uint32 i=0; i < m_nodeConnectList.size(); i++) + if(m_nodeConnectList[i]->nodeId == nodeId) { + m_nodeConnectList[i]->connected = connected; + return; + } + + /** + * If node not already in node group, then add node + */ + m_nodeConnectList.push_back(new NodeConnectInfo(nodeId, connected)); + sort(); + +#ifdef NODE_GROUP_DEBUG + for(Uint32 i=0; i < m_nodeConnectList.size(); i++) + ndbout_c("NodeGroup: NodeId=%d", m_nodeConnectList[i]->nodeId); +#endif +} + +/** + * crappy sort + */ +void NodeGroup::sort() { + NodeConnectInfo * tmp; + if(m_nodeConnectList.size()<2) + return; + for(Uint32 i=0; i < m_nodeConnectList.size()-1; i++) { + for(Uint32 j=m_nodeConnectList.size()-1;j>i+1; j--) { + if(m_nodeConnectList[j]->nodeId < m_nodeConnectList[j-1]->nodeId) { + tmp=m_nodeConnectList[j]; + m_nodeConnectList[j]=m_nodeConnectList[j-1]; + m_nodeConnectList[j-1]=tmp; + } + } + } +} + +Uint32 +NodeGroup::getFirstConnectedNode() { + for(Uint32 i=0; i<m_nodeConnectList.size(); i++){ + if(m_nodeConnectList[i]->connected) + return m_nodeConnectList[i]->nodeId; + } + return 0; +} + +Uint32 +NodeGroup::getNodeGrp() { + return m_nodeGrp; +} + +Vector <NodeConnectInfo *> * +NodeGroup::getNodeConnectList(){ + return &m_nodeConnectList; +} + +void +NodeGroup::setNodeConnectStatus(Uint32 nodeId, bool connected) { + for(Uint32 i=0; i<m_nodeConnectList.size(); i++){ + if(m_nodeConnectList[i]->nodeId==nodeId) { + m_nodeConnectList[i]->connected=connected; + break; + } + } +} + +bool +NodeGroup::isConnected(Uint32 nodeId) { + for(Uint32 i=0; i<m_nodeConnectList.size(); i++){ + if(m_nodeConnectList[i]->nodeId == nodeId) { + return m_nodeConnectList[i]->connected; + } + } + REPABORT1("Check for non-existing node to be connected", nodeId); +} + + +bool +NodeGroup::fullyConnected() { + for(Uint32 i=0; i<m_nodeConnectList.size(); i++){ + if(!(m_nodeConnectList[i]->connected)) + return false; + } + return true; +} + +bool +NodeGroup::connectedNodeGrp() { + for(Uint32 i=0; i<m_nodeConnectList.size(); i++){ + if(m_nodeConnectList[i]->connected) { + return true; + } + } + return false; +} + + +bool +NodeGroup::exists(Uint32 nodeId) { + for(Uint32 i=0;i<m_nodeConnectList.size();i++) { + if(m_nodeConnectList[i]->nodeId==nodeId) + return true; + } + return false; +} diff --git a/ndb/src/old_files/rep/storage/NodeGroup.hpp b/ndb/src/old_files/rep/storage/NodeGroup.hpp new file mode 100644 index 00000000000..1f515e02a23 --- /dev/null +++ b/ndb/src/old_files/rep/storage/NodeGroup.hpp @@ -0,0 +1,109 @@ +/* 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 */ + +#ifndef NODE_GROUP_HPP +#define NODE_GROUP_HPP + +#include "NodeConnectInfo.hpp" +#include <Vector.hpp> +#include <ndb_types.h> + +#include <rep/rep_version.hpp> + +/** + * @class NodeGroup + * @brief Contains info about all nodes belonging to one node group + */ +class NodeGroup { +public: + NodeGroup(Uint32 nodeGrp); + ~NodeGroup(); + /** + * Add node to node group + * @param nodeId Node id of node to add + * @param connected Status of this node (true==connected) + */ + void addNode(Uint32 nodeId, bool connected); + + /** + * get first connected node in this node group + * @returns nodeId, 0 if there is no connected node... + */ + Uint32 getFirstConnectedNode(); + + /** + * get the primary node id + * @returns nodeId, the primary node id + */ + Uint32 getPrimaryNode() {return m_primaryNode;}; + + + /** + * sets a node in this nodegroup as the primary node + */ + void setPrimaryNode(Uint32 nodeId) {m_primaryNode=nodeId;}; + + + /** + * get the node group + * @returns the nodegroup number (m_nodeGrp) + */ + Uint32 getNodeGrp(); + + /** + * set the connection status for a particular node + * @param nodeId - the nodeId to set the connect status on + * @param connected - the status of this node (true==connected) + */ + void setNodeConnectStatus(Uint32 nodeId, bool connected); + + /** + * Get the connection status for a particular node + * @param nodeId - the nodeId to check the connect status on + * @returns true if node is connected, otherwise false + */ + bool isConnected(Uint32 nodeId); + + /** + * gives the status of this nodegroup. + * @returns true if atleast one node in the node group is connected + */ + bool connectedNodeGrp(); + + /** + * @returns true if ALL nodes are connected + */ + bool fullyConnected(); + + /** + * + * @returns true if node exists in nodegroup + */ + bool exists(Uint32 nodeId); + + Vector <NodeConnectInfo *> * getNodeConnectList(); + +private: + /** + * Sort list (bubble sort) + */ + void sort(); + Uint32 m_primaryNode; + Uint32 m_nodeGrp; + Vector<NodeConnectInfo *> m_nodeConnectList; +}; + +#endif diff --git a/ndb/src/old_files/rep/storage/NodeGroupInfo.cpp b/ndb/src/old_files/rep/storage/NodeGroupInfo.cpp new file mode 100644 index 00000000000..8c250268997 --- /dev/null +++ b/ndb/src/old_files/rep/storage/NodeGroupInfo.cpp @@ -0,0 +1,218 @@ +/* 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 */ + +#include "NodeGroupInfo.hpp" + +NodeGroupInfo::NodeGroupInfo() +{ +} + +NodeGroupInfo::~NodeGroupInfo() +{ + for(Uint32 i=0; i<m_nodeGroupList.size(); i++) { + delete m_nodeGroupList[i]; + } + m_nodeGroupList.clear(); +} + + +void +NodeGroupInfo::setPrimaryNode(Uint32 nodeGrp, Uint32 nodeId) { + Uint32 pos; + /** + * Validation check to find out that the nodegroup really exists. + * The list is not sorted, so the index of the nodegroup is returned + * in pos. + */ + if(existsNodeGroup(nodeGrp, &pos)) { + m_nodeGroupList[pos]->setPrimaryNode(nodeId); + } else { + /** + * could not find node group + */ + RLOG(("Node group not found")); + REPABORT("Node group not found"); + } +} + +Uint32 +NodeGroupInfo::getPrimaryNode(Uint32 nodeGrp) { + Uint32 pos; + /** + * Validation check to find out that the nodegroup really exists. + * The list is not sorted, so the index of the nodegroup is returned + * in pos. + */ + if(existsNodeGroup(nodeGrp, &pos)) { + return m_nodeGroupList[pos]->getPrimaryNode(); + } else { + /** + * could not find node group + */ + RLOG(("Node group not found")); + REPABORT("Node group not found"); + } +} + +void +NodeGroupInfo::addNodeToNodeGrp(Uint32 nodeId, bool connected, Uint32 nodeGrp) +{ + Uint32 pos; + if(existsNodeGroup(nodeGrp, &pos)) { + /** + * NG exists -> just add the node + */ + m_nodeGroupList[pos]->addNode(nodeId, connected); + + } else { + /** + * NG do not exist -> create a new nodeGrp and add the node + */ + m_nodeGroupList.push_back(new NodeGroup(nodeGrp)); + + /** + * paranoia + */ + if(existsNodeGroup(nodeGrp, &pos)) { + m_nodeGroupList[pos]->addNode(nodeId, connected); + } else { + REPABORT(""); + } + } +} + +Uint32 +NodeGroupInfo::findNodeGroup(Uint32 nodeId) +{ + /** + * Check for existance in each nodegroup + */ + for(Uint32 i=0; i<m_nodeGroupList.size(); i++) { + if(m_nodeGroupList[i]->exists(nodeId)) return i; + } + + REPABORT1("No node group known for node", nodeId); +} + +Uint32 +NodeGroupInfo::getFirstConnectedNode(Uint32 nodeGrp) +{ + Uint32 pos; + /** + * Validation check to find out that the nodegroup really exists. + * The list is not sorted, so the index of the nodegroup is returned + * in pos. + */ + if(existsNodeGroup(nodeGrp, &pos)) { + return m_nodeGroupList[pos]->getFirstConnectedNode(); + } else { + /** + * could not find node group + */ + REPABORT(""); + } +} + +bool +NodeGroupInfo::connectedNodeGrp(Uint32 nodeGrp) +{ + return m_nodeGroupList[nodeGrp]->connectedNodeGrp(); +} + +bool +NodeGroupInfo::isConnected(Uint32 nodeId) +{ + Uint32 nodeGrp = findNodeGroup(nodeId); + return m_nodeGroupList[nodeGrp]->isConnected(nodeId); + +} + +bool +NodeGroupInfo::fullyConnected() +{ + for(Uint32 i=0; i<m_nodeGroupList.size(); i++) { + if(!(m_nodeGroupList[i]->fullyConnected())) + return false; + } + return true; +} + + +void +NodeGroupInfo::setConnectStatus(Uint32 nodeId, bool connected) +{ + Uint32 nodeGrp = findNodeGroup(nodeId); + m_nodeGroupList[nodeGrp]->setNodeConnectStatus(nodeId,connected); +} + + +bool +NodeGroupInfo::existsNodeGroup(Uint32 nodeGrp, Uint32 * pos) +{ + for(Uint32 i=0; i<m_nodeGroupList.size(); i++) { + if(m_nodeGroupList[i]->getNodeGrp()==nodeGrp) { + *pos=i; + return true; + } + } + return false; +} + + +/***************************************************************************** + * Iterator + *****************************************************************************/ + +NodeGroupInfo::iterator::iterator(Uint32 nodeGrp, NodeGroupInfo * ngi) +{ + m_iterator = 0; + for(Uint32 i=0; i < ngi->m_nodeGroupList.size(); i++) { + if(ngi->m_nodeGroupList[i]->getNodeGrp()==nodeGrp) { + m_nodeList = ngi->m_nodeGroupList[i]->getNodeConnectList(); + return; + } + } + m_nodeList=0; +} + +bool +NodeGroupInfo::iterator::exists() +{ + if(m_nodeList==0) return 0; + return (m_iterator < m_nodeList->size()); +} + +NodeConnectInfo * +NodeGroupInfo::iterator::first() +{ + m_iterator=0; + if(m_nodeList==0) return 0; + if(m_nodeList->size() == 0) return 0; + return (*m_nodeList)[m_iterator]; +} + +NodeConnectInfo * +NodeGroupInfo::iterator::next() +{ + m_iterator++; + if(m_nodeList==0) return 0; + if(m_nodeList->size() == 0) return 0; + if(m_iterator<m_nodeList->size()) + return (*m_nodeList)[m_iterator]; + else + return 0; +} + diff --git a/ndb/src/old_files/rep/storage/NodeGroupInfo.hpp b/ndb/src/old_files/rep/storage/NodeGroupInfo.hpp new file mode 100644 index 00000000000..3d0499d4425 --- /dev/null +++ b/ndb/src/old_files/rep/storage/NodeGroupInfo.hpp @@ -0,0 +1,145 @@ +/* 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 */ + +#ifndef NODE_GROUPINFO_HPP +#define NODE_GROUPINFO_HPP + +#include <Vector.hpp> +#include <NdbTick.h> +#include <NdbMain.h> +#include <NdbOut.hpp> +//#include <NdbSleep.h> + +#include "NodeGroup.hpp" +#include <rep/rep_version.hpp> + +/** + * @class NodeGroupInfo + * @brief Contains info about all node groups and their connectivity status + */ +class NodeGroupInfo { +public: + NodeGroupInfo(); + ~NodeGroupInfo(); + + /** + * Add a node to a nodegroup together with the status of the node + * @param nodeId - the nodeId to add + * @param connected - true/false + * @param nodeGrp - the nodegroup to add this node to + */ + void addNodeToNodeGrp(Uint32 nodeId, bool connected, Uint32 nodeGrp); + + /** + * Get the nodegroup that a node belongs to. + * @param nodeId - the nodeId to check wich nodegroup it belongs to + * @return the nodegroup + */ + Uint32 findNodeGroup(Uint32 nodeId); + + /** + * Get the first connected node in a node group + * @param nodegroup - the node group to get the node in. + * @return nodeId, 0 if there is no connected node in the nodegroup + */ + Uint32 getFirstConnectedNode(Uint32 nodeGrp); + + + /** + * sets a nodeId in a nodeGroup as the primary node. If the + * primary node fails, then a new node in the node group is chosen + * @param nodegroup - the node group to get the node in. + * @param nodeId, 0 if there is no connected node in the nodegroup + */ + void setPrimaryNode(Uint32 nodeGrp, Uint32 nodeId); + + /** + * gets the nodeId in the nodegroup of the primary node. + * @param nodegroup - the node group to get the node in. + * @return nodeId, 0 if there is no connected node in the nodegroup + */ + Uint32 getPrimaryNode(Uint32 nodeGrp); + + + /** + * Checks if at least one node in the nodegroup is connected. + * @param nodeGrp - the nodegrp to check + * @return true if >0 nodes are connected in the nodegroup + */ + bool connectedNodeGrp(Uint32 nodeGrp); + + /** + * Checks if a node is connected or not + * @param nodeId - the nodeId to check connectivity + * @return true if node is connected + */ + bool isConnected(Uint32 nodeId); + + /** + * Set if a node is connected or not + * @param nodeId - the nodeId to set the connect flag fory + * @param connected - true if connect false if disconnect + */ + void setConnectStatus(Uint32 nodeId, bool connected); + + /** + * Check if all nodes are connected in all nodegroups + * @return return true if ALL nodes are connected in ALL nodeGroups + */ + bool fullyConnected(); + + /** + * Get the number of nodegroups + * @return the number of nodegroups. + */ + Uint32 getNoOfNodeGroups() { return m_nodeGroupList.size();}; + + /** + * @class iterator + * The iterator class iterates over a nodegroup, returning nodeIds + * in that node group. + * + * @code + * NodeGroupInfo::iterator * it; + * for(Uint32 i=0;i < m_nodeGroupInfo->getNoOfNodeGroups();i++) { + * it = new NodeGroupInfo::iterator(i,m_nodeGroupInfo); + * for(NodeConnectInfo * nci=it->first(); it->exists();nci=it->next()) + * ndbout_c("Iterating: %d", nci->nodeId); + * + * } + * @end code + */ + class iterator { + public: + iterator(Uint32 nodeGrp, NodeGroupInfo * ngi); + NodeConnectInfo * first(); ///< @return nodeConnectInfo* if exists. + ///< (NULL if no more nodes exists) + NodeConnectInfo * next(); ///< @return nodeConnectInfo* if exists. + ///< (NULL if no more nodes exists) + bool exists(); ///< @return true if another nodeId exists (for next()) + private: + Uint32 m_iterator; + const Vector<NodeConnectInfo *> * m_nodeList; + }; + friend class NodeGroupInfo::iterator; + +private: + bool existsNodeGroup(Uint32 nodeGrp, Uint32 * pos); + + Vector<NodeGroup *> m_nodeGroupList; +}; + +#endif |