2884 Jonas Oreland 2009-05-06
ndb - spj
Start using DataBuffer2
M storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp
M storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp
M storage/ndb/src/kernel/blocks/record_types.hpp
M storage/ndb/src/kernel/vm/ArenaPool.cpp
2883 Jonas Oreland 2009-05-06
ndb - Add DataBuffer2 which is DataBuffer but with Pool as template argument
A storage/ndb/src/kernel/vm/DataBuffer2.hpp
2882 Jonas Oreland 2009-05-05
ndb - spj - fix bug in ArenaPool
M storage/ndb/src/kernel/vm/ArenaPool.cpp
M storage/ndb/src/kernel/vm/ArenaPool.hpp
=== modified file 'storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp'
--- a/storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp 2009-05-04 13:01:07 +0000
+++ b/storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp 2009-05-06 12:18:38 +0000
@@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite
#include <AttributeHeader.hpp>
#include <DLFifoList.hpp>
#include <ArenaPool.hpp>
+#include <DataBuffer2.hpp>
class SectionReader;
struct QueryNode;
@@ -65,10 +66,10 @@ protected:
public:
struct Request;
struct TreeNode;
- typedef DataBuffer<15> Dependency_map;
- typedef LocalDataBuffer<15> Local_dependency_map;
- typedef DataBuffer<15> PatternStore;
- typedef LocalDataBuffer<15> Local_pattern_store;
+ typedef DataBuffer2<14, LocalArenaPoolImpl> Dependency_map;
+ typedef LocalDataBuffer2<14, LocalArenaPoolImpl> Local_dependency_map;
+ typedef DataBuffer2<14, LocalArenaPoolImpl> PatternStore;
+ typedef LocalDataBuffer2<14, LocalArenaPoolImpl> Local_pattern_store;
/**
* This struct represent a row being passed to a child
@@ -409,13 +410,9 @@ private:
Request_pool m_request_pool;
Request_hash m_scan_request_hash;
Request_hash m_lookup_request_hash;
+ ArenaPool m_dependency_map_pool;
TreeNode_pool m_treenode_pool;
- /**
- * TODO, make arena-variant of DataBuffer
- */
- Dependency_map::DataBufferPool m_dependency_map_pool;
-
void do_init(Request*, const struct LqhKeyReq*, Uint32 senderRef);
void store_lookup(Ptr<Request>);
void handle_early_lqhkey_ref(Signal*, const LqhKeyReq *, Uint32 err);
@@ -442,7 +439,7 @@ private:
void start(Signal*, Ptr<Request>, SegmentedSectionPtr);
void nodeFinished(Signal* signal, Ptr<Request>, Ptr<TreeNode>);
void cleanup(Ptr<Request>);
- void cleanup_common(Ptr<TreeNode>);
+ void cleanup_common(Ptr<Request>, Ptr<TreeNode>);
/**
* Misc
=== modified file 'storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp 2009-05-04 13:01:07 +0000
+++ b/storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp 2009-05-06 12:18:38 +0000
@@ -63,7 +63,10 @@ void Dbspj::execREAD_CONFIG_REQ(Signal*
m_treenode_pool.arena_pool_init(&m_arenaAllocator, RT_SPJ_TREENODE, pc);
m_lookup_request_hash.setSize(16);
m_scan_request_hash.setSize(16);
- m_dependency_map_pool.setSize(16);
+
+ Record_info ri;
+ Dependency_map::createRecordInfo(ri, RT_SPJ_DATABUFFER);
+ m_dependency_map_pool.init(&m_arenaAllocator, ri, pc);
ReadConfigConf* const conf =
reinterpret_cast<ReadConfigConf*>(signal->getDataPtrSend());
@@ -77,22 +80,93 @@ void Dbspj::execREAD_CONFIG_REQ(Signal*
void Dbspj::execSTTOR(Signal* signal)
{
+//#define UNIT_TEST_DATABUFFER2
+
jamEntry();
/* START CASE */
- // const Uint16 tphase = signal->theData[1];
+ const Uint16 tphase = signal->theData[1];
+
ndbout << "Dbspj::execSTTOR() inst:" << instance()
- << " phase=" << signal->theData[1] << endl;
+ << " phase=" << tphase << endl;
const Uint16 csignalKey = signal->theData[6];
signal->theData[0] = csignalKey;
signal->theData[1] = 3; /* BLOCK CATEGORY */
signal->theData[2] = 2; /* SIGNAL VERSION NUMBER */
- signal->theData[3] = 255; /* Start phase end*/
- //signal->theData[4] = 255;
+#ifdef UNIT_TEST_DATABUFFER2
+ signal->theData[3] = 120; /* Start phase end*/
+#else
+ signal->theData[3] = 255;
+#endif
+ signal->theData[4] = 255;
if(isNdbMtLqh()){
sendSignal(DBSPJ_REF, GSN_STTORRY, signal, 5, JBB);
}else{
sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 5, JBB);
}
+
+#ifdef UNIT_TEST_DATABUFFER2
+ if (tphase == 120)
+ {
+ ndbout_c("basic test of ArenaPool / DataBuffer2");
+
+ for (Uint32 i = 0; i<100; i++)
+ {
+ ArenaHead ah;
+ if (!m_arenaAllocator.seize(ah))
+ {
+ ndbout_c("Failed to allocate arena");
+ break;
+ }
+
+ ndbout_c("*** LOOP %u", i);
+ Uint32 sum = 0;
+ Dependency_map::Head head;
+ LocalArenaPoolImpl pool(ah, m_dependency_map_pool);
+ for (Uint32 j = 0; j<100; j++)
+ {
+ Uint32 sz = rand() % 1000;
+ if (0)
+ ndbout_c("adding %u", sz);
+ Local_dependency_map list(pool, head);
+ for (Uint32 i = 0; i<sz; i++)
+ signal->theData[i] = sum + i;
+ list.append(signal->theData, sz);
+ sum += sz;
+ }
+
+ {
+ ndbrequire(head.getSize() == sum);
+ Local_dependency_map list(pool, head);
+ Dependency_map::ConstDataBufferIterator it;
+ Uint32 cnt = 0;
+ for (list.first(it); !it.isNull(); list.next(it))
+ {
+ ndbrequire(* it.data == cnt);
+ cnt++;
+ }
+
+ ndbrequire(cnt == sum);
+ }
+
+ Resource_limit rl;
+ if (m_ctx.m_mm.get_resource_limit(7, rl))
+ {
+ ndbout_c("Resource %d min: %d max: %d curr: %d",
+ 7, rl.m_min, rl.m_max, rl.m_curr);
+ }
+
+ {
+ ndbout_c("release map");
+ Local_dependency_map list(pool, head);
+ list.release();
+ }
+
+ ndbout_c("release all");
+ m_arenaAllocator.release(ah);
+ ndbout_c("*** LOOP %u sum: %u", i, sum);
+ }
+ }
+#endif
}//Dbspj::execSTTOR()
/**
@@ -703,25 +777,23 @@ Dbspj::cleanup(Ptr<Request> requestPtr)
}
void
-Dbspj::cleanup_common(Ptr<TreeNode> treeNodePtr)
+Dbspj::cleanup_common(Ptr<Request> requestPtr, Ptr<TreeNode> treeNodePtr)
{
jam();
+ LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
{
- Local_dependency_map list(m_dependency_map_pool,
- treeNodePtr.p->m_dependent_nodes);
+ Local_dependency_map list(pool, treeNodePtr.p->m_dependent_nodes);
list.release();
}
{
- Local_pattern_store pattern(m_dependency_map_pool,
- treeNodePtr.p->m_keyPattern);
+ Local_pattern_store pattern(pool, treeNodePtr.p->m_keyPattern);
pattern.release();
}
{
- Local_pattern_store pattern(m_dependency_map_pool,
- treeNodePtr.p->m_attrParamPattern);
+ Local_pattern_store pattern(pool, treeNodePtr.p->m_attrParamPattern);
pattern.release();
}
@@ -1226,8 +1298,8 @@ Dbspj::lookup_execTRANSID_AI(Signal* sig
jam();
{
- Local_dependency_map list(m_dependency_map_pool,
- treeNodePtr.p->m_dependent_nodes);
+ LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
+ Local_dependency_map list(pool, treeNodePtr.p->m_dependent_nodes);
Dependency_map::ConstDataBufferIterator it;
for (list.first(it); !it.isNull(); list.next(it))
{
@@ -1339,8 +1411,8 @@ Dbspj::lookup_start_child(Signal* signal
/**
* Get key-pattern
*/
- Local_pattern_store pattern(m_dependency_map_pool,
- treeNodePtr.p->m_keyPattern);
+ LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
+ Local_pattern_store pattern(pool, treeNodePtr.p->m_keyPattern);
err = expand(ptrI, pattern, rowRef.m_row_data.m_section);
if (unlikely(err != 0))
@@ -1389,7 +1461,7 @@ void
Dbspj::lookup_cleanup(Ptr<Request> requestPtr,
Ptr<TreeNode> treeNodePtr)
{
- cleanup_common(treeNodePtr);
+ cleanup_common(requestPtr, treeNodePtr);
}
@@ -1742,8 +1814,8 @@ Dbspj::scanFrag_execTRANSID_AI(Signal* s
treeNodePtr.p->m_scanfrag_data.m_rows_received;
{
- Local_dependency_map list(m_dependency_map_pool,
- treeNodePtr.p->m_dependent_nodes);
+ LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
+ Local_dependency_map list(pool, treeNodePtr.p->m_dependent_nodes);
Dependency_map::ConstDataBufferIterator it;
for (list.first(it); !it.isNull(); list.next(it))
{
@@ -1854,7 +1926,7 @@ void
Dbspj::scanFrag_cleanup(Ptr<Request> requestPtr,
Ptr<TreeNode> treeNodePtr)
{
- cleanup_common(treeNodePtr);
+ cleanup_common(requestPtr, treeNodePtr);
}
/**
* END - MODULE SCAN FRAG
@@ -2313,8 +2385,8 @@ Dbspj::parseDA(Build_context& ctx,
{
DEBUG("adding " << dst[i] << " as parent");
Ptr<TreeNode> parentPtr = ctx.m_node_list[dst[i]];
- Local_dependency_map map(m_dependency_map_pool,
- parentPtr.p->m_dependent_nodes);
+ LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
+ Local_dependency_map map(pool, parentPtr.p->m_dependent_nodes);
if (unlikely(!map.append(&treeNodePtr.i, 1)))
{
err = DbspjErr::OutOfQueryMemory;
@@ -2343,8 +2415,8 @@ Dbspj::parseDA(Build_context& ctx,
Uint32 len = len_cnt & 0xFFFF; // length of pattern in words
Uint32 cnt = len_cnt >> 16; // no of parameters
- Local_pattern_store pattern(m_dependency_map_pool,
- treeNodePtr.p->m_keyPattern);
+ LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
+ Local_pattern_store pattern(pool, treeNodePtr.p->m_keyPattern);
if (cnt)
{
=== modified file 'storage/ndb/src/kernel/blocks/record_types.hpp'
--- a/storage/ndb/src/kernel/blocks/record_types.hpp 2009-05-04 07:12:52 +0000
+++ b/storage/ndb/src/kernel/blocks/record_types.hpp 2009-05-06 12:18:38 +0000
@@ -90,5 +90,6 @@
#define RT_SPJ_REQUEST MAKE_TID( 1, RG_QUERY_MEMORY)
#define RT_SPJ_TREENODE MAKE_TID( 2, RG_QUERY_MEMORY)
#define RT_SPJ_ARENA_BLOCK MAKE_TID( 3, RG_QUERY_MEMORY)
+#define RT_SPJ_DATABUFFER MAKE_TID( 4, RG_QUERY_MEMORY)
#endif
=== modified file 'storage/ndb/src/kernel/vm/ArenaPool.cpp'
--- a/storage/ndb/src/kernel/vm/ArenaPool.cpp 2009-05-05 13:15:52 +0000
+++ b/storage/ndb/src/kernel/vm/ArenaPool.cpp 2009-05-06 12:18:38 +0000
@@ -119,6 +119,10 @@ ArenaPool::seize(ArenaHead & ah, Ptr<voi
Uint32 sz = m_record_info.m_size;
Uint32 off = m_record_info.m_offset_magic;
+ if (0)
+ ndbout_c("pos: %u sz: %u (sum: %u) bs: %u",
+ pos, sz, (pos + sz), bs);
+
if (pos + sz <= bs)
{
/**
=== added file 'storage/ndb/src/kernel/vm/DataBuffer2.hpp'
--- a/storage/ndb/src/kernel/vm/DataBuffer2.hpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/kernel/vm/DataBuffer2.hpp 2009-05-06 12:15:41 +0000
@@ -0,0 +1,563 @@
+/* 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; version 2 of the License.
+
+ 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 DATA_BUFFER2_HPP
+#define DATA_BUFFER2_HPP
+
+/**
+ * @class DataBuffer
+ * @brief Buffer of data words
+ *
+ * @note The buffer is divided into segments (of size sz)
+ */
+template <Uint32 sz, typename Pool>
+class DataBuffer2 {
+public:
+ struct Segment {
+ Uint32 magic;
+ Uint32 nextPool;
+ Uint32 data[sz];
+ NdbOut& print(NdbOut& out){
+ out << "[DataBuffer<" << sz << ">::Segment this="
+ << this << dec << " nextPool= "
+ << nextPool << " ]";
+ return out;
+ }
+ };
+public:
+ typedef Pool DataBufferPool;
+
+ /**
+ * Head/anchor for data buffer
+ */
+ struct Head {
+ Head() ;
+
+ Uint32 used; // Words used
+ Uint32 firstItem; // First segment (or RNIL)
+ Uint32 lastItem; // Last segment (or RNIL)
+
+ /**
+ * Get size of databuffer, in words
+ */
+ Uint32 getSize() const { return used;}
+
+ /**
+ * Get segment size in words (template argument)
+ */
+ static Uint32 getSegmentSize() { return sz;}
+ };
+
+ /** Constructor */
+ DataBuffer2(DataBufferPool &);
+
+ /** Seize <b>n</b> words, Release */
+ bool seize(Uint32 n);
+ void release();
+
+ /**
+ * Get size of databuffer, in words
+ */
+ Uint32 getSize() const;
+
+ /**
+ * Check if buffer is empty
+ */
+ bool isEmpty() const;
+
+ /**
+ * Get segment size in words (template argument)
+ */
+ static Uint32 getSegmentSize();
+
+ void print(FILE*) const;
+
+ /* ----------------------------------------------------------------------- */
+
+ struct DataBufferIterator {
+ Ptr<Segment> curr; // Ptr to current segment
+ Uint32* data; // Pointer to current data (word)
+ Uint32 ind; // Word index within a segment
+ Uint32 pos; // Absolute word position within DataBuffer
+
+ void print(FILE* out) {
+ fprintf(out, "[DataBufferIterator curr.i=%d, data=%p, ind=%d, pos=%d]\n",
+ curr.i, (void*) data, ind, pos);
+ };
+
+ inline bool isNull() const { return curr.isNull();}
+ inline void setNull() { curr.setNull(); data = 0; ind = pos = RNIL;}
+ };
+ typedef DataBufferIterator Iterator;
+
+ struct ConstDataBufferIterator {
+ ConstPtr<Segment> curr;
+ const Uint32 * data;
+ Uint32 ind;
+ Uint32 pos;
+
+ inline bool isNull() const { return curr.isNull();}
+ inline void setNull() { curr.setNull(); data = 0; ind = pos = RNIL;}
+ };
+
+ /**
+ * Iterator
+ * @parameter hops Number of words to jump forward
+ * @note DataBuffer::next returns false if applied to last word.
+ */
+ bool first(DataBufferIterator &);
+ bool next(DataBufferIterator &);
+ bool next(DataBufferIterator &, Uint32 hops);
+ bool nextPool(DataBufferIterator &);
+
+ /**
+ * Set iterator to position
+ */
+ bool position(DataBufferIterator& it, Uint32 pos);
+
+ /** Iterator */
+ bool first(ConstDataBufferIterator &) const;
+ bool next(ConstDataBufferIterator &) const;
+ bool next(ConstDataBufferIterator &, Uint32 hops) const;
+ bool nextPool(ConstDataBufferIterator &) const;
+
+ /**
+ * Returns true if it is possible to store <em>len</em>
+ * no of words at position given in iterator.
+ */
+ bool importable(const DataBufferIterator, Uint32 len);
+
+ /**
+ * Stores <em>len</em> no of words starting at location <em>src</em> in
+ * databuffer at position given in iterator.
+ *
+ * @return true if success, false otherwise.
+ * @note Iterator is not advanced.
+ */
+ bool import(const DataBufferIterator &, const Uint32* src, Uint32 len);
+
+ /**
+ * Increases size with appends <em>len</em> words
+ * @return true if success, false otherwise.
+ */
+ bool append(const Uint32* src, Uint32 len);
+
+ static void createRecordInfo(Record_info & ri, Uint32 type_id);
+protected:
+ Head head;
+ DataBufferPool & thePool;
+
+private:
+ /**
+ * This is NOT a public method, since the intension is that the import
+ * method using iterators will be more effective in the future
+ */
+ bool import(Uint32 pos, const Uint32* src, Uint32 len);
+};
+
+template<Uint32 sz, typename Pool>
+class LocalDataBuffer2 : public DataBuffer2<sz, Pool> {
+public:
+ LocalDataBuffer2(typename DataBuffer2<sz, Pool>::DataBufferPool & thePool,
+ typename DataBuffer2<sz, Pool>::Head & _src)
+ : DataBuffer2<sz, Pool>(thePool), src(_src)
+ {
+ this->head = src;
+ }
+
+ ~LocalDataBuffer2(){
+ src = this->head;
+ }
+private:
+ typename DataBuffer2<sz, Pool>::Head & src;
+};
+
+template<Uint32 sz, typename Pool>
+inline
+DataBuffer2<sz, Pool>::Head::Head(){
+ used = 0;
+ firstItem = RNIL;
+ lastItem = RNIL;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool DataBuffer2<sz, Pool>::importable(const DataBufferIterator it, Uint32 len){
+ return (it.pos + len < head.used);
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool DataBuffer2<sz, Pool>::position(DataBufferIterator& it, Uint32 p){
+
+ // TODO: The current implementation is not the most effective one.
+ // A more effective implementation would start at the current
+ // position of the iterator.
+
+ if(!first(it)){
+ return false;
+ }
+ return next(it, p);
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::import(const DataBufferIterator & it,
+ const Uint32* src, Uint32 len)
+{
+ Uint32 ind = (it.pos % sz);
+ Uint32 left = sz - ind;
+ Segment * p = it.curr.p;
+
+ if (left)
+ {
+ memcpy(p->data+ind, src, 4 * left);
+ if (len <= left)
+ return true;
+
+ src += left;
+ len -= left;
+ }
+
+ while (len > sz)
+ {
+ p = static_cast<Segment*>(thePool.getPtr(p->nextPool));
+ memcpy(p->data, src, 4 * sz);
+ src += sz;
+ len -= sz;
+ }
+
+ if (len)
+ {
+ p = static_cast<Segment*>(thePool.getPtr(p->nextPool));
+ memcpy(p->data, src, 4 * len);
+ }
+
+ return true;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::append(const Uint32* src, Uint32 len){
+ if(len == 0)
+ return true;
+
+ Uint32 pos = head.used;
+ if(!seize(len)){
+ return false;
+ }
+ DataBufferIterator it;
+
+ if(position(it, pos) && import(it, src, len)){
+ return true;
+ }
+ abort();
+ return false;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+void DataBuffer2<sz, Pool>::print(FILE* out) const {
+ fprintf(out, "[DataBuffer used=%d words, segmentsize=%d words",
+ head.used, sz);
+
+ if (head.firstItem == RNIL) {
+ fprintf(out, ": No segments seized.]\n");
+ return;
+ } else {
+ fprintf(out, "\n");
+ }
+
+ Ptr<Segment> ptr;
+ ptr.i = head.firstItem;
+
+ Uint32 acc = 0;
+ for(; ptr.i != RNIL; ){
+ thePool.getPtr(ptr);
+ const Uint32 * rest = ptr.p->data;
+ for(Uint32 i = 0; i<sz; i++){
+ fprintf(out, " H'%.8x", rest[i]);
+ if(acc++ == 6){
+ acc = 0;
+ fprintf(out, "\n");
+ }
+ }
+ ptr.i = ptr.p->nextPool;
+ }
+ fprintf(out, " ]\n");
+}
+
+template<Uint32 sz, typename Pool>
+inline
+DataBuffer2<sz, Pool>::DataBuffer2(DataBufferPool & p) : thePool(p){
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::seize(Uint32 n){
+ Uint32 rest; // Free space in last segment (currently)
+
+ if(head.firstItem == RNIL)
+ {
+ rest = 0;
+ }
+ else
+ {
+ rest = (sz - (head.used % sz)) % sz;
+ }
+
+ if (0)
+ ndbout_c("seize(%u) used: %u rest: %u firstItem: 0x%x",
+ n, head.used, rest, head.firstItem);
+
+ if (rest >= n)
+ {
+ head.used += n;
+ return true;
+ }
+
+ Uint32 used = head.used + n;
+ Segment first;
+ Ptr<Segment> currPtr;
+ currPtr.p = &first;
+ first.nextPool = RNIL;
+
+ while (n >= sz)
+ {
+ Ptr<void> tmp;
+ if (thePool.seize(tmp))
+ {
+ currPtr.p->nextPool = tmp.i;
+ currPtr.i = tmp.i;
+ currPtr.p = static_cast<Segment*>(tmp.p);
+ }
+ else
+ {
+ goto error;
+ }
+ n -= sz;
+ }
+
+ if(n > rest)
+ {
+ Ptr<void> tmp;
+ if (thePool.seize(tmp))
+ {
+ currPtr.p->nextPool = tmp.i;
+ currPtr.i = tmp.i;
+ currPtr.p = static_cast<Segment*>(tmp.p);
+ }
+ else
+ {
+ goto error;
+ }
+ }
+
+ if (head.firstItem == RNIL)
+ {
+ head.firstItem = first.nextPool;
+ }
+ else
+ {
+ Segment* lastPtr = static_cast<Segment*>(thePool.getPtr(head.lastItem));
+ lastPtr->nextPool = first.nextPool;
+ }
+
+ head.used = used;
+ head.lastItem = currPtr.i;
+ currPtr.p->nextPool = RNIL;
+ return true;
+
+error:
+ currPtr.i = first.nextPool;
+ while (currPtr.i != RNIL)
+ {
+ currPtr.p = static_cast<Segment*>(thePool.getPtr(currPtr.i));
+ Ptr<void> tmp;
+ tmp.i = currPtr.i;
+ tmp.p = currPtr.p;
+ currPtr.i = currPtr.p->nextPool;
+ thePool.release(tmp);
+ }
+ return false;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+void
+DataBuffer2<sz, Pool>::release(){
+ Ptr<void> tmp;
+ tmp.i = head.firstItem;
+ while (tmp.i != RNIL)
+ {
+ tmp.p = thePool.getPtr(tmp.i);
+ Uint32 next = static_cast<Segment*>(tmp.p)->nextPool;
+ thePool.release(tmp);
+ tmp.i = next;
+ }
+}
+
+template<Uint32 sz, typename Pool>
+inline
+Uint32
+DataBuffer2<sz, Pool>::getSegmentSize(){
+ return sz;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::first(DataBufferIterator & it){
+ return first((ConstDataBufferIterator&)it);
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::next(DataBufferIterator & it){
+ return next((ConstDataBufferIterator&)it);
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::next(DataBufferIterator & it, Uint32 hops){
+ return next((ConstDataBufferIterator&)it, hops);
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::first(ConstDataBufferIterator & it) const {
+ it.curr.i = head.firstItem;
+ if(it.curr.i == RNIL){
+ it.setNull();
+ return false;
+ }
+ it.curr.p = static_cast<Segment*>(thePool.getPtr(it.curr.i));
+ it.data = &it.curr.p->data[0];
+ it.ind = 0;
+ it.pos = 0;
+ return true;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::next(ConstDataBufferIterator & it) const {
+ it.ind ++;
+ it.data ++;
+ it.pos ++;
+ if(it.ind < sz && it.pos < head.used){
+ return true;
+ }
+
+ if(it.pos < head.used){
+ it.curr.i = it.curr.p->nextPool;
+#ifdef ARRAY_GUARD
+ if(it.curr.i == RNIL){
+ /**
+ * This is actually "internal error"
+ * pos can't be less than head.used and at the same time we can't
+ * find next segment
+ *
+ * Note this must not "really" be checked since thePool.getPtr will
+ * abort when trying to get RNIL. That's why the check is within
+ * ARRAY_GUARD
+ */
+ ErrorReporter::handleAssert("DataBuffer2<sz, Pool>::next", __FILE__, __LINE__);
+ }
+#endif
+ it.curr.p = static_cast<Segment*>(thePool.getPtr(it.curr.i));
+ it.data = &it.curr.p->data[0];
+ it.ind = 0;
+ return true;
+ }
+ it.setNull();
+ return false;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::next(ConstDataBufferIterator & it, Uint32 hops) const {
+#if 0
+ for (Uint32 i=0; i<hops; i++) {
+ if (!this->next(it))
+ return false;
+ }
+ return true;
+#else
+ if(it.pos + hops < head.used){
+ while(hops >= sz){
+ it.curr.i = it.curr.p->nextPool;
+ it.curr.p = static_cast<Segment*>(thePool.getPtr(it.curr.i));
+ hops -= sz;
+ it.pos += sz;
+ }
+
+ it.ind += hops;
+ it.pos += hops;
+ if(it.ind < sz){
+ it.data = &it.curr.p->data[it.ind];
+ return true;
+ }
+
+ it.curr.i = it.curr.p->nextPool;
+ it.curr.p = static_cast<Segment*>(thePool.getPtr(it.curr.i));
+ it.ind -= sz;
+ it.data = &it.curr.p->data[it.ind];
+ return true;
+ }
+ it.setNull();
+ return false;
+#endif
+}
+
+template<Uint32 sz, typename Pool>
+inline
+Uint32
+DataBuffer2<sz, Pool>::getSize() const {
+ return head.used;
+}
+
+template<Uint32 sz, typename Pool>
+inline
+bool
+DataBuffer2<sz, Pool>::isEmpty() const {
+ return (head.used == 0);
+}
+
+template<Uint32 sz, typename Pool>
+inline
+void
+DataBuffer2<sz, Pool>::createRecordInfo(Record_info & ri, Uint32 type_id)
+{
+ Segment tmp;
+ const char * off_base = (char*)&tmp;
+ const char * off_next = (char*)&tmp.nextPool;
+ const char * off_magic = (char*)&tmp.magic;
+
+ ri.m_size = sizeof(tmp);
+ ri.m_offset_next_pool = Uint32(off_next - off_base);
+ ri.m_offset_magic = Uint32(off_magic - off_base);
+ ri.m_type_id = type_id;
+}
+
+#endif
+
Attachment: [text/bzr-bundle] bzr/jonas@mysql.com-20090506121838-4vlwcwguuke3u3qa.bundle
| Thread |
|---|
| • bzr push into mysql-5.1-telco-7.0-spj branch (jonas:2882 to 2884) | Jonas Oreland | 6 May |