summaryrefslogtreecommitdiff
path: root/ndb/src/old_files/rep/storage
diff options
context:
space:
mode:
Diffstat (limited to 'ndb/src/old_files/rep/storage')
-rw-r--r--ndb/src/old_files/rep/storage/GCIBuffer.cpp173
-rw-r--r--ndb/src/old_files/rep/storage/GCIBuffer.hpp112
-rw-r--r--ndb/src/old_files/rep/storage/GCIContainer.cpp272
-rw-r--r--ndb/src/old_files/rep/storage/GCIContainer.hpp121
-rw-r--r--ndb/src/old_files/rep/storage/GCIContainerPS.cpp128
-rw-r--r--ndb/src/old_files/rep/storage/GCIContainerPS.hpp90
-rw-r--r--ndb/src/old_files/rep/storage/GCIPage.cpp165
-rw-r--r--ndb/src/old_files/rep/storage/GCIPage.hpp114
-rw-r--r--ndb/src/old_files/rep/storage/LogRecord.hpp81
-rw-r--r--ndb/src/old_files/rep/storage/Makefile14
-rw-r--r--ndb/src/old_files/rep/storage/NodeConnectInfo.hpp29
-rw-r--r--ndb/src/old_files/rep/storage/NodeGroup.cpp149
-rw-r--r--ndb/src/old_files/rep/storage/NodeGroup.hpp109
-rw-r--r--ndb/src/old_files/rep/storage/NodeGroupInfo.cpp218
-rw-r--r--ndb/src/old_files/rep/storage/NodeGroupInfo.hpp145
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