Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
cb048699
Commit
cb048699
authored
Jun 16, 2004
by
unknown
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tux optim 6 - remove node cache
parent
becde519
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
385 additions
and
508 deletions
+385
-508
ndb/src/kernel/blocks/dbtux/Dbtux.hpp
ndb/src/kernel/blocks/dbtux/Dbtux.hpp
+69
-85
ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
+20
-22
ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
+0
-1
ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
+6
-7
ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
+0
-6
ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
+54
-140
ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
+33
-45
ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
+201
-201
ndb/src/kernel/blocks/dbtux/Times.txt
ndb/src/kernel/blocks/dbtux/Times.txt
+2
-1
No files found.
ndb/src/kernel/blocks/dbtux/Dbtux.hpp
View file @
cb048699
...
@@ -102,11 +102,6 @@ private:
...
@@ -102,11 +102,6 @@ private:
// sizes are in words (Uint32)
// sizes are in words (Uint32)
static
const
unsigned
MaxIndexFragments
=
2
*
NO_OF_FRAG_PER_NODE
;
static
const
unsigned
MaxIndexFragments
=
2
*
NO_OF_FRAG_PER_NODE
;
static
const
unsigned
MaxIndexAttributes
=
MAX_ATTRIBUTES_IN_INDEX
;
static
const
unsigned
MaxIndexAttributes
=
MAX_ATTRIBUTES_IN_INDEX
;
#ifdef VM_TRACE
static
const
unsigned
MaxNodeHandles
=
10000
;
// More space for printTree
#else
static
const
unsigned
MaxNodeHandles
=
128
;
// enough for 1 operation
#endif
static
const
unsigned
MaxAttrDataSize
=
2048
;
static
const
unsigned
MaxAttrDataSize
=
2048
;
public:
public:
static
const
unsigned
DescPageSize
=
256
;
static
const
unsigned
DescPageSize
=
256
;
...
@@ -179,7 +174,7 @@ private:
...
@@ -179,7 +174,7 @@ private:
};
};
/*
/*
* There is no const
variable
NullTupLoc since the compiler may not be
* There is no const
member
NullTupLoc since the compiler may not be
* able to optimize it to TupLoc() constants. Instead null values are
* able to optimize it to TupLoc() constants. Instead null values are
* constructed on the stack with TupLoc().
* constructed on the stack with TupLoc().
*/
*/
...
@@ -462,8 +457,7 @@ private:
...
@@ -462,8 +457,7 @@ private:
Uint16
m_descOff
;
Uint16
m_descOff
;
Uint16
m_numAttrs
;
Uint16
m_numAttrs
;
TreeHead
m_tree
;
TreeHead
m_tree
;
Uint32
m_nodeList
;
// node cache of current operation
TupLoc
m_freeLoc
;
// one node pre-allocated for insert
Uint32
m_nodeFree
;
// one node pre-allocated for insert
DLList
<
ScanOp
>
m_scanList
;
// current scans on this fragment
DLList
<
ScanOp
>
m_scanList
;
// current scans on this fragment
Uint32
m_tupIndexFragPtrI
;
Uint32
m_tupIndexFragPtrI
;
Uint32
m_tupTableFragPtrI
[
2
];
Uint32
m_tupTableFragPtrI
[
2
];
...
@@ -498,9 +492,8 @@ private:
...
@@ -498,9 +492,8 @@ private:
// node handles
// node handles
/*
/*
* A tree operation builds a cache of accessed nodes. This allows
* A node handle is a reference to a tree node in TUP. It is used to
* different implementations of index memory access. The cache is
* operate on the node. Node handles are allocated on the stack.
* committed and released at the end of the operation.
*/
*/
struct
NodeHandle
;
struct
NodeHandle
;
friend
struct
NodeHandle
;
friend
struct
NodeHandle
;
...
@@ -509,11 +502,9 @@ private:
...
@@ -509,11 +502,9 @@ private:
TupLoc
m_loc
;
// physical node address
TupLoc
m_loc
;
// physical node address
TreeNode
*
m_node
;
// pointer to node storage
TreeNode
*
m_node
;
// pointer to node storage
AccSize
m_acc
;
// accessed size
AccSize
m_acc
;
// accessed size
union
{
Uint32
m_next
;
// next active node under fragment
Uint32
nextPool
;
};
NodeHandle
(
Frag
&
frag
);
NodeHandle
(
Frag
&
frag
);
NodeHandle
(
const
NodeHandle
&
node
);
NodeHandle
&
operator
=
(
const
NodeHandle
&
node
);
// getters
// getters
TupLoc
getLink
(
unsigned
i
);
TupLoc
getLink
(
unsigned
i
);
unsigned
getChilds
();
// cannot spell
unsigned
getChilds
();
// cannot spell
...
@@ -521,20 +512,19 @@ private:
...
@@ -521,20 +512,19 @@ private:
unsigned
getOccup
();
unsigned
getOccup
();
int
getBalance
();
int
getBalance
();
Uint32
getNodeScan
();
Uint32
getNodeScan
();
Data
getPref
(
unsigned
i
);
TreeEnt
getEnt
(
unsigned
pos
);
TreeEnt
getMinMax
(
unsigned
i
);
// setters
// setters
void
setLink
(
unsigned
i
,
TupLoc
loc
);
void
setLink
(
unsigned
i
,
TupLoc
loc
);
void
setSide
(
unsigned
i
);
void
setSide
(
unsigned
i
);
void
setOccup
(
unsigned
n
);
void
setOccup
(
unsigned
n
);
void
setBalance
(
int
b
);
void
setBalance
(
int
b
);
void
setNodeScan
(
Uint32
scanPtrI
);
void
setNodeScan
(
Uint32
scanPtrI
);
// access other parts of the node
Data
getPref
(
unsigned
i
);
TreeEnt
getEnt
(
unsigned
pos
);
TreeEnt
getMinMax
(
unsigned
i
);
// for ndbrequire and ndbassert
// for ndbrequire and ndbassert
void
progError
(
int
line
,
int
cause
,
const
char
*
file
);
void
progError
(
int
line
,
int
cause
,
const
char
*
file
);
};
};
typedef
Ptr
<
NodeHandle
>
NodeHandlePtr
;
ArrayPool
<
NodeHandle
>
c_nodeHandlePool
;
// parameters for methods
// parameters for methods
...
@@ -565,17 +555,6 @@ private:
...
@@ -565,17 +555,6 @@ private:
ReadPar
();
ReadPar
();
};
};
/*
* Node storage operation.
*/
struct
StorePar
{
TupStoreTh
::
OpCode
m_opCode
;
// operation code
unsigned
m_offset
;
// data offset in words
unsigned
m_size
;
// number of words
Uint32
m_errorCode
;
// terrorCode from TUP
StorePar
();
};
/*
/*
* Tree search for entry.
* Tree search for entry.
*/
*/
...
@@ -649,15 +628,12 @@ private:
...
@@ -649,15 +628,12 @@ private:
/*
/*
* DbtuxNode.cpp
* DbtuxNode.cpp
*/
*/
void
seizeNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
);
int
allocNode
(
Signal
*
signal
,
NodeHandle
&
node
);
void
preallocNode
(
Signal
*
signal
,
Frag
&
frag
,
Uint32
&
errorCode
);
void
accessNode
(
Signal
*
signal
,
NodeHandle
&
node
,
AccSize
acc
);
void
findNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
,
TupLoc
loc
);
void
selectNode
(
Signal
*
signal
,
NodeHandle
&
node
,
TupLoc
loc
,
AccSize
acc
);
void
selectNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
,
TupLoc
loc
,
AccSize
acc
);
void
insertNode
(
Signal
*
signal
,
NodeHandle
&
node
,
AccSize
acc
);
void
insertNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
,
AccSize
acc
);
void
deleteNode
(
Signal
*
signal
,
NodeHandle
&
node
);
void
deleteNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
);
void
accessNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
,
AccSize
acc
);
void
setNodePref
(
Signal
*
signal
,
NodeHandle
&
node
,
unsigned
i
);
void
setNodePref
(
Signal
*
signal
,
NodeHandle
&
node
,
unsigned
i
);
void
commitNodes
(
Signal
*
signal
,
Frag
&
frag
,
bool
updateOk
);
// node operations
// node operations
void
nodePushUp
(
Signal
*
signal
,
NodeHandle
&
node
,
unsigned
pos
,
const
TreeEnt
&
ent
);
void
nodePushUp
(
Signal
*
signal
,
NodeHandle
&
node
,
unsigned
pos
,
const
TreeEnt
&
ent
);
void
nodePopDown
(
Signal
*
signal
,
NodeHandle
&
node
,
unsigned
pos
,
TreeEnt
&
ent
);
void
nodePopDown
(
Signal
*
signal
,
NodeHandle
&
node
,
unsigned
pos
,
TreeEnt
&
ent
);
...
@@ -675,8 +651,8 @@ private:
...
@@ -675,8 +651,8 @@ private:
void
treeSearch
(
Signal
*
signal
,
Frag
&
frag
,
SearchPar
searchPar
,
TreePos
&
treePos
);
void
treeSearch
(
Signal
*
signal
,
Frag
&
frag
,
SearchPar
searchPar
,
TreePos
&
treePos
);
void
treeAdd
(
Signal
*
signal
,
Frag
&
frag
,
TreePos
treePos
,
TreeEnt
ent
);
void
treeAdd
(
Signal
*
signal
,
Frag
&
frag
,
TreePos
treePos
,
TreeEnt
ent
);
void
treeRemove
(
Signal
*
signal
,
Frag
&
frag
,
TreePos
treePos
);
void
treeRemove
(
Signal
*
signal
,
Frag
&
frag
,
TreePos
treePos
);
void
treeRotateSingle
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandle
Ptr
&
nodePtr
,
unsigned
i
);
void
treeRotateSingle
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandle
&
node
,
unsigned
i
);
void
treeRotateDouble
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandle
Ptr
&
nodePtr
,
unsigned
i
);
void
treeRotateDouble
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandle
&
node
,
unsigned
i
);
/*
/*
* DbtuxScan.cpp
* DbtuxScan.cpp
...
@@ -1054,8 +1030,7 @@ Dbtux::Frag::Frag(ArrayPool<ScanOp>& scanOpPool) :
...
@@ -1054,8 +1030,7 @@ Dbtux::Frag::Frag(ArrayPool<ScanOp>& scanOpPool) :
m_descOff
(
0
),
m_descOff
(
0
),
m_numAttrs
(
ZNIL
),
m_numAttrs
(
ZNIL
),
m_tree
(),
m_tree
(),
m_nodeList
(
RNIL
),
m_freeLoc
(),
m_nodeFree
(
RNIL
),
m_scanList
(
scanOpPool
),
m_scanList
(
scanOpPool
),
m_tupIndexFragPtrI
(
RNIL
)
m_tupIndexFragPtrI
(
RNIL
)
{
{
...
@@ -1086,11 +1061,29 @@ Dbtux::NodeHandle::NodeHandle(Frag& frag) :
...
@@ -1086,11 +1061,29 @@ Dbtux::NodeHandle::NodeHandle(Frag& frag) :
m_frag
(
frag
),
m_frag
(
frag
),
m_loc
(),
m_loc
(),
m_node
(
0
),
m_node
(
0
),
m_acc
(
AccNone
),
m_acc
(
AccNone
)
m_next
(
RNIL
)
{
{
}
}
inline
Dbtux
::
NodeHandle
::
NodeHandle
(
const
NodeHandle
&
node
)
:
m_frag
(
node
.
m_frag
),
m_loc
(
node
.
m_loc
),
m_node
(
node
.
m_node
),
m_acc
(
node
.
m_acc
)
{
}
inline
Dbtux
::
NodeHandle
&
Dbtux
::
NodeHandle
::
operator
=
(
const
NodeHandle
&
node
)
{
ndbassert
(
&
m_frag
==
&
node
.
m_frag
);
m_loc
=
node
.
m_loc
;
m_node
=
node
.
m_node
;
m_acc
=
node
.
m_acc
;
return
*
this
;
}
inline
Dbtux
::
TupLoc
inline
Dbtux
::
TupLoc
Dbtux
::
NodeHandle
::
getLink
(
unsigned
i
)
Dbtux
::
NodeHandle
::
getLink
(
unsigned
i
)
{
{
...
@@ -1128,37 +1121,6 @@ Dbtux::NodeHandle::getNodeScan()
...
@@ -1128,37 +1121,6 @@ Dbtux::NodeHandle::getNodeScan()
return
m_node
->
m_nodeScan
;
return
m_node
->
m_nodeScan
;
}
}
inline
Dbtux
::
Data
Dbtux
::
NodeHandle
::
getPref
(
unsigned
i
)
{
TreeHead
&
tree
=
m_frag
.
m_tree
;
ndbrequire
(
m_acc
>=
AccPref
&&
i
<=
1
);
return
tree
.
getPref
(
m_node
,
i
);
}
inline
Dbtux
::
TreeEnt
Dbtux
::
NodeHandle
::
getEnt
(
unsigned
pos
)
{
TreeHead
&
tree
=
m_frag
.
m_tree
;
TreeEnt
*
entList
=
tree
.
getEntList
(
m_node
);
const
unsigned
occup
=
m_node
->
m_occup
;
ndbrequire
(
pos
<
occup
);
if
(
pos
==
0
||
pos
==
occup
-
1
)
{
ndbrequire
(
m_acc
>=
AccPref
)
}
else
{
ndbrequire
(
m_acc
==
AccFull
)
}
return
entList
[(
1
+
pos
)
%
occup
];
}
inline
Dbtux
::
TreeEnt
Dbtux
::
NodeHandle
::
getMinMax
(
unsigned
i
)
{
const
unsigned
occup
=
m_node
->
m_occup
;
ndbrequire
(
i
<=
1
&&
occup
!=
0
);
return
getEnt
(
i
==
0
?
0
:
occup
-
1
);
}
inline
void
inline
void
Dbtux
::
NodeHandle
::
setLink
(
unsigned
i
,
TupLoc
loc
)
Dbtux
::
NodeHandle
::
setLink
(
unsigned
i
,
TupLoc
loc
)
{
{
...
@@ -1195,6 +1157,37 @@ Dbtux::NodeHandle::setNodeScan(Uint32 scanPtrI)
...
@@ -1195,6 +1157,37 @@ Dbtux::NodeHandle::setNodeScan(Uint32 scanPtrI)
m_node
->
m_nodeScan
=
scanPtrI
;
m_node
->
m_nodeScan
=
scanPtrI
;
}
}
inline
Dbtux
::
Data
Dbtux
::
NodeHandle
::
getPref
(
unsigned
i
)
{
TreeHead
&
tree
=
m_frag
.
m_tree
;
ndbrequire
(
m_acc
>=
AccPref
&&
i
<=
1
);
return
tree
.
getPref
(
m_node
,
i
);
}
inline
Dbtux
::
TreeEnt
Dbtux
::
NodeHandle
::
getEnt
(
unsigned
pos
)
{
TreeHead
&
tree
=
m_frag
.
m_tree
;
TreeEnt
*
entList
=
tree
.
getEntList
(
m_node
);
const
unsigned
occup
=
m_node
->
m_occup
;
ndbrequire
(
pos
<
occup
);
if
(
pos
==
0
||
pos
==
occup
-
1
)
{
ndbrequire
(
m_acc
>=
AccPref
)
}
else
{
ndbrequire
(
m_acc
==
AccFull
)
}
return
entList
[(
1
+
pos
)
%
occup
];
}
inline
Dbtux
::
TreeEnt
Dbtux
::
NodeHandle
::
getMinMax
(
unsigned
i
)
{
const
unsigned
occup
=
m_node
->
m_occup
;
ndbrequire
(
i
<=
1
&&
occup
!=
0
);
return
getEnt
(
i
==
0
?
0
:
occup
-
1
);
}
// parameters for methods
// parameters for methods
inline
inline
...
@@ -1217,15 +1210,6 @@ Dbtux::ReadPar::ReadPar() :
...
@@ -1217,15 +1210,6 @@ Dbtux::ReadPar::ReadPar() :
{
{
}
}
inline
Dbtux
::
StorePar
::
StorePar
()
:
m_opCode
(
TupStoreTh
::
OpUndefined
),
m_offset
(
0
),
m_size
(
0
),
m_errorCode
(
0
)
{
}
inline
inline
Dbtux
::
SearchPar
::
SearchPar
()
:
Dbtux
::
SearchPar
::
SearchPar
()
:
m_data
(
0
),
m_data
(
0
),
...
...
ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
View file @
cb048699
...
@@ -106,13 +106,11 @@ Dbtux::printTree(Signal* signal, Frag& frag, NdbOut& out)
...
@@ -106,13 +106,11 @@ Dbtux::printTree(Signal* signal, Frag& frag, NdbOut& out)
signal
->
theData
[
1
]
=
1
;
signal
->
theData
[
1
]
=
1
;
execDUMP_STATE_ORD
(
signal
);
execDUMP_STATE_ORD
(
signal
);
if
(
debugFile
!=
0
)
{
if
(
debugFile
!=
0
)
{
commitNodes
(
signal
,
frag
,
false
);
printTree
(
signal
,
frag
,
debugOut
);
printTree
(
signal
,
frag
,
debugOut
);
}
}
}
}
ndbrequire
(
false
);
ndbrequire
(
false
);
}
}
commitNodes
(
signal
,
frag
,
false
);
}
}
void
void
...
@@ -123,9 +121,9 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar&
...
@@ -123,9 +121,9 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar&
return
;
return
;
}
}
TreeHead
&
tree
=
frag
.
m_tree
;
TreeHead
&
tree
=
frag
.
m_tree
;
NodeHandle
Ptr
nodePtr
;
NodeHandle
node
(
frag
)
;
selectNode
(
signal
,
frag
,
nodePtr
,
loc
,
AccFull
);
selectNode
(
signal
,
node
,
loc
,
AccFull
);
out
<<
par
.
m_path
<<
" "
<<
*
nodePtr
.
p
<<
endl
;
out
<<
par
.
m_path
<<
" "
<<
node
<<
endl
;
// check children
// check children
PrintPar
cpar
[
2
];
PrintPar
cpar
[
2
];
ndbrequire
(
strlen
(
par
.
m_path
)
+
1
<
sizeof
(
par
.
m_path
));
ndbrequire
(
strlen
(
par
.
m_path
)
+
1
<
sizeof
(
par
.
m_path
));
...
@@ -134,56 +132,56 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar&
...
@@ -134,56 +132,56 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar&
cpar
[
i
].
m_side
=
i
;
cpar
[
i
].
m_side
=
i
;
cpar
[
i
].
m_depth
=
0
;
cpar
[
i
].
m_depth
=
0
;
cpar
[
i
].
m_parent
=
loc
;
cpar
[
i
].
m_parent
=
loc
;
printNode
(
signal
,
frag
,
out
,
node
Ptr
.
p
->
getLink
(
i
),
cpar
[
i
]);
printNode
(
signal
,
frag
,
out
,
node
.
getLink
(
i
),
cpar
[
i
]);
if
(
!
cpar
[
i
].
m_ok
)
{
if
(
!
cpar
[
i
].
m_ok
)
{
par
.
m_ok
=
false
;
par
.
m_ok
=
false
;
}
}
}
}
// check child-parent links
// check child-parent links
if
(
node
Ptr
.
p
->
getLink
(
2
)
!=
par
.
m_parent
)
{
if
(
node
.
getLink
(
2
)
!=
par
.
m_parent
)
{
par
.
m_ok
=
false
;
par
.
m_ok
=
false
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
"parent loc "
<<
hex
<<
node
Ptr
.
p
->
getLink
(
2
);
out
<<
"parent loc "
<<
hex
<<
node
.
getLink
(
2
);
out
<<
" should be "
<<
hex
<<
par
.
m_parent
<<
endl
;
out
<<
" should be "
<<
hex
<<
par
.
m_parent
<<
endl
;
}
}
if
(
node
Ptr
.
p
->
getSide
()
!=
par
.
m_side
)
{
if
(
node
.
getSide
()
!=
par
.
m_side
)
{
par
.
m_ok
=
false
;
par
.
m_ok
=
false
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
"side "
<<
dec
<<
node
Ptr
.
p
->
getSide
();
out
<<
"side "
<<
dec
<<
node
.
getSide
();
out
<<
" should be "
<<
dec
<<
par
.
m_side
<<
endl
;
out
<<
" should be "
<<
dec
<<
par
.
m_side
<<
endl
;
}
}
// check balance
// check balance
const
int
balance
=
-
cpar
[
0
].
m_depth
+
cpar
[
1
].
m_depth
;
const
int
balance
=
-
cpar
[
0
].
m_depth
+
cpar
[
1
].
m_depth
;
if
(
node
Ptr
.
p
->
getBalance
()
!=
balance
)
{
if
(
node
.
getBalance
()
!=
balance
)
{
par
.
m_ok
=
false
;
par
.
m_ok
=
false
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
"balance "
<<
node
Ptr
.
p
->
getBalance
();
out
<<
"balance "
<<
node
.
getBalance
();
out
<<
" should be "
<<
balance
<<
endl
;
out
<<
" should be "
<<
balance
<<
endl
;
}
}
if
(
abs
(
node
Ptr
.
p
->
getBalance
())
>
1
)
{
if
(
abs
(
node
.
getBalance
())
>
1
)
{
par
.
m_ok
=
false
;
par
.
m_ok
=
false
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
"balance "
<<
node
Ptr
.
p
->
getBalance
()
<<
" is invalid"
<<
endl
;
out
<<
"balance "
<<
node
.
getBalance
()
<<
" is invalid"
<<
endl
;
}
}
// check occupancy
// check occupancy
if
(
node
Ptr
.
p
->
getOccup
()
>
tree
.
m_maxOccup
)
{
if
(
node
.
getOccup
()
>
tree
.
m_maxOccup
)
{
par
.
m_ok
=
false
;
par
.
m_ok
=
false
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
"occupancy "
<<
node
Ptr
.
p
->
getOccup
();
out
<<
"occupancy "
<<
node
.
getOccup
();
out
<<
" greater than max "
<<
tree
.
m_maxOccup
<<
endl
;
out
<<
" greater than max "
<<
tree
.
m_maxOccup
<<
endl
;
}
}
// check for occupancy of interior node
// check for occupancy of interior node
if
(
node
Ptr
.
p
->
getChilds
()
==
2
&&
nodePtr
.
p
->
getOccup
()
<
tree
.
m_minOccup
)
{
if
(
node
.
getChilds
()
==
2
&&
node
.
getOccup
()
<
tree
.
m_minOccup
)
{
par
.
m_ok
=
false
;
par
.
m_ok
=
false
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
"occupancy "
<<
node
Ptr
.
p
->
getOccup
()
<<
" of interior node"
;
out
<<
"occupancy "
<<
node
.
getOccup
()
<<
" of interior node"
;
out
<<
" less than min "
<<
tree
.
m_minOccup
<<
endl
;
out
<<
" less than min "
<<
tree
.
m_minOccup
<<
endl
;
}
}
// check missed half-leaf/leaf merge
// check missed half-leaf/leaf merge
for
(
unsigned
i
=
0
;
i
<=
1
;
i
++
)
{
for
(
unsigned
i
=
0
;
i
<=
1
;
i
++
)
{
if
(
node
Ptr
.
p
->
getLink
(
i
)
!=
NullTupLoc
&&
if
(
node
.
getLink
(
i
)
!=
NullTupLoc
&&
node
Ptr
.
p
->
getLink
(
1
-
i
)
==
NullTupLoc
&&
node
.
getLink
(
1
-
i
)
==
NullTupLoc
&&
node
Ptr
.
p
->
getOccup
()
+
cpar
[
i
].
m_occup
<=
tree
.
m_maxOccup
)
{
node
.
getOccup
()
+
cpar
[
i
].
m_occup
<=
tree
.
m_maxOccup
)
{
par
.
m_ok
=
false
;
par
.
m_ok
=
false
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
"missed merge with child "
<<
i
<<
endl
;
out
<<
"missed merge with child "
<<
i
<<
endl
;
...
@@ -191,7 +189,7 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar&
...
@@ -191,7 +189,7 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar&
}
}
// return values
// return values
par
.
m_depth
=
1
+
max
(
cpar
[
0
].
m_depth
,
cpar
[
1
].
m_depth
);
par
.
m_depth
=
1
+
max
(
cpar
[
0
].
m_depth
,
cpar
[
1
].
m_depth
);
par
.
m_occup
=
node
Ptr
.
p
->
getOccup
();
par
.
m_occup
=
node
.
getOccup
();
}
}
NdbOut
&
NdbOut
&
...
...
ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
View file @
cb048699
...
@@ -178,7 +178,6 @@ Dbtux::execREAD_CONFIG_REQ(Signal* signal)
...
@@ -178,7 +178,6 @@ Dbtux::execREAD_CONFIG_REQ(Signal* signal)
c_fragPool
.
setSize
(
nFragment
);
c_fragPool
.
setSize
(
nFragment
);
c_descPagePool
.
setSize
(
nDescPage
);
c_descPagePool
.
setSize
(
nDescPage
);
c_fragOpPool
.
setSize
(
MaxIndexFragments
);
c_fragOpPool
.
setSize
(
MaxIndexFragments
);
c_nodeHandlePool
.
setSize
(
MaxNodeHandles
);
c_scanOpPool
.
setSize
(
nScanOp
);
c_scanOpPool
.
setSize
(
nScanOp
);
c_scanBoundPool
.
setSize
(
nScanBoundWords
);
c_scanBoundPool
.
setSize
(
nScanBoundWords
);
/*
/*
...
...
ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
View file @
cb048699
...
@@ -72,7 +72,6 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
...
@@ -72,7 +72,6 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
}
}
ndbrequire
(
fragPtr
.
i
!=
RNIL
);
ndbrequire
(
fragPtr
.
i
!=
RNIL
);
Frag
&
frag
=
*
fragPtr
.
p
;
Frag
&
frag
=
*
fragPtr
.
p
;
ndbrequire
(
frag
.
m_nodeList
==
RNIL
);
// set up index entry
// set up index entry
TreeEnt
ent
;
TreeEnt
ent
;
ent
.
m_tupAddr
=
req
->
tupAddr
;
ent
.
m_tupAddr
=
req
->
tupAddr
;
...
@@ -143,17 +142,18 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
...
@@ -143,17 +142,18 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
}
}
/*
/*
* At most one new node is inserted in the operation. We keep one
* At most one new node is inserted in the operation. We keep one
* free node pre-allocated so the operation cannot fail. This also
* free node pre-allocated so the operation cannot fail.
* gives a real TupAddr for links to the new node.
*/
*/
if
(
frag
.
m_
nodeFree
==
RNIL
)
{
if
(
frag
.
m_
freeLoc
==
NullTupLoc
)
{
jam
();
jam
();
preallocNode
(
signal
,
frag
,
req
->
errorCode
);
NodeHandle
node
(
frag
);
req
->
errorCode
=
allocNode
(
signal
,
node
);
if
(
req
->
errorCode
!=
0
)
{
if
(
req
->
errorCode
!=
0
)
{
jam
();
jam
();
break
;
break
;
}
}
ndbrequire
(
frag
.
m_nodeFree
!=
RNIL
);
frag
.
m_freeLoc
=
node
.
m_loc
;
ndbrequire
(
frag
.
m_freeLoc
!=
NullTupLoc
);
}
}
treeAdd
(
signal
,
frag
,
treePos
,
ent
);
treeAdd
(
signal
,
frag
,
treePos
,
ent
);
break
;
break
;
...
@@ -175,7 +175,6 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
...
@@ -175,7 +175,6 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
break
;
break
;
}
}
// commit and release nodes
// commit and release nodes
commitNodes
(
signal
,
frag
,
req
->
errorCode
==
0
);
#ifdef VM_TRACE
#ifdef VM_TRACE
if
(
debugFlags
&
DebugTree
)
{
if
(
debugFlags
&
DebugTree
)
{
printTree
(
signal
,
frag
,
debugOut
);
printTree
(
signal
,
frag
,
debugOut
);
...
...
ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
View file @
cb048699
...
@@ -316,12 +316,6 @@ Dbtux::dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 sen
...
@@ -316,12 +316,6 @@ Dbtux::dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 sen
unsigned
i
=
--
indexPtr
.
p
->
m_numFrags
;
unsigned
i
=
--
indexPtr
.
p
->
m_numFrags
;
FragPtr
fragPtr
;
FragPtr
fragPtr
;
c_fragPool
.
getPtr
(
fragPtr
,
indexPtr
.
p
->
m_fragPtrI
[
i
]);
c_fragPool
.
getPtr
(
fragPtr
,
indexPtr
.
p
->
m_fragPtrI
[
i
]);
Frag
&
frag
=
*
fragPtr
.
p
;
ndbrequire
(
frag
.
m_nodeList
==
RNIL
);
if
(
frag
.
m_nodeFree
!=
RNIL
)
{
c_nodeHandlePool
.
release
(
frag
.
m_nodeFree
);
frag
.
m_nodeFree
=
RNIL
;
}
c_fragPool
.
release
(
fragPtr
);
c_fragPool
.
release
(
fragPtr
);
// the real time break is not used for anything currently
// the real time break is not used for anything currently
signal
->
theData
[
0
]
=
TuxContinueB
::
DropIndex
;
signal
->
theData
[
0
]
=
TuxContinueB
::
DropIndex
;
...
...
ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
View file @
cb048699
...
@@ -18,161 +18,94 @@
...
@@ -18,161 +18,94 @@
#include "Dbtux.hpp"
#include "Dbtux.hpp"
/*
/*
* Node handles.
* Allocate index node in TUP.
*
* Temporary version between "cache" and "pointer" implementations.
*/
*/
int
// Dbtux
Dbtux
::
allocNode
(
Signal
*
signal
,
NodeHandle
&
node
)
void
Dbtux
::
seizeNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
)
{
if
(
!
c_nodeHandlePool
.
seize
(
nodePtr
))
{
jam
();
return
;
}
new
(
nodePtr
.
p
)
NodeHandle
(
frag
);
nodePtr
.
p
->
m_next
=
frag
.
m_nodeList
;
frag
.
m_nodeList
=
nodePtr
.
i
;
}
void
Dbtux
::
preallocNode
(
Signal
*
signal
,
Frag
&
frag
,
Uint32
&
errorCode
)
{
{
ndbrequire
(
frag
.
m_nodeFree
==
RNIL
);
Frag
&
frag
=
node
.
m_frag
;
NodeHandlePtr
nodePtr
;
seizeNode
(
signal
,
frag
,
nodePtr
);
ndbrequire
(
nodePtr
.
i
!=
RNIL
);
// remove from cache XXX ugly
frag
.
m_nodeFree
=
frag
.
m_nodeList
;
frag
.
m_nodeList
=
nodePtr
.
p
->
m_next
;
// alloc index node in TUP
Uint32
pageId
=
NullTupLoc
.
m_pageId
;
Uint32
pageId
=
NullTupLoc
.
m_pageId
;
Uint32
pageOffset
=
NullTupLoc
.
m_pageOffset
;
Uint32
pageOffset
=
NullTupLoc
.
m_pageOffset
;
Uint32
*
node32
=
0
;
Uint32
*
node32
=
0
;
errorCode
=
c_tup
->
tuxAllocNode
(
signal
,
frag
.
m_tupIndexFragPtrI
,
pageId
,
pageOffset
,
node32
);
int
errorCode
=
c_tup
->
tuxAllocNode
(
signal
,
frag
.
m_tupIndexFragPtrI
,
pageId
,
pageOffset
,
node32
);
if
(
errorCode
!
=
0
)
{
if
(
errorCode
=
=
0
)
{
jam
();
jam
();
c_nodeHandlePool
.
release
(
nodePtr
);
node
.
m_loc
=
TupLoc
(
pageId
,
pageOffset
);
frag
.
m_nodeFree
=
RNIL
;
node
.
m_node
=
reinterpret_cast
<
TreeNode
*>
(
node32
);
return
;
node
.
m_acc
=
AccNone
;
ndbrequire
(
node
.
m_loc
!=
NullTupLoc
&&
node
.
m_node
!=
0
);
}
}
nodePtr
.
p
->
m_loc
=
TupLoc
(
pageId
,
pageOffset
);
return
errorCode
;
nodePtr
.
p
->
m_node
=
reinterpret_cast
<
TreeNode
*>
(
node32
);
ndbrequire
(
nodePtr
.
p
->
m_loc
!=
NullTupLoc
&&
nodePtr
.
p
->
m_node
!=
0
);
new
(
nodePtr
.
p
->
m_node
)
TreeNode
();
#ifdef VM_TRACE
TreeHead
&
tree
=
frag
.
m_tree
;
TreeNode
*
node
=
nodePtr
.
p
->
m_node
;
memset
(
tree
.
getPref
(
node
,
0
),
0xa2
,
tree
.
m_prefSize
<<
2
);
memset
(
tree
.
getPref
(
node
,
1
),
0xa2
,
tree
.
m_prefSize
<<
2
);
TreeEnt
*
entList
=
tree
.
getEntList
(
node
);
memset
(
entList
,
0xa4
,
(
tree
.
m_maxOccup
+
1
)
*
(
TreeEntSize
<<
2
));
#endif
}
}
/*
/*
*
Find node in the cache. XXX too slow, use direct links instead
*
Access more of the node.
*/
*/
void
void
Dbtux
::
findNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
,
TupLoc
lo
c
)
Dbtux
::
accessNode
(
Signal
*
signal
,
NodeHandle
&
node
,
AccSize
ac
c
)
{
{
NodeHandlePtr
tmpPtr
;
ndbrequire
(
node
.
m_loc
!=
NullTupLoc
&&
node
.
m_node
!=
0
);
tmpPtr
.
i
=
frag
.
m_nodeList
;
if
(
node
.
m_acc
>=
acc
)
while
(
tmpPtr
.
i
!=
RNIL
)
{
return
;
jam
();
// XXX could do prefetch
c_nodeHandlePool
.
getPtr
(
tmpPtr
);
node
.
m_acc
=
acc
;
if
(
tmpPtr
.
p
->
m_loc
==
loc
)
{
jam
();
nodePtr
=
tmpPtr
;
return
;
}
tmpPtr
.
i
=
tmpPtr
.
p
->
m_next
;
}
nodePtr
.
i
=
RNIL
;
nodePtr
.
p
=
0
;
}
}
/*
/*
*
Get handle for
existing node.
*
Set handle to point to
existing node.
*/
*/
void
void
Dbtux
::
selectNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
,
TupLoc
loc
,
AccSize
acc
)
Dbtux
::
selectNode
(
Signal
*
signal
,
NodeHandle
&
node
,
TupLoc
loc
,
AccSize
acc
)
{
{
ndbrequire
(
loc
!=
NullTupLoc
&&
acc
>
AccNone
);
Frag
&
frag
=
node
.
m_frag
;
NodeHandlePtr
tmpPtr
;
ndbrequire
(
loc
!=
NullTupLoc
);
// search in cache
Uint32
pageId
=
loc
.
m_pageId
;
findNode
(
signal
,
frag
,
tmpPtr
,
loc
);
Uint32
pageOffset
=
loc
.
m_pageOffset
;
if
(
tmpPtr
.
i
==
RNIL
)
{
Uint32
*
node32
=
0
;
jam
();
c_tup
->
tuxGetNode
(
frag
.
m_tupIndexFragPtrI
,
pageId
,
pageOffset
,
node32
);
// add new node
node
.
m_loc
=
loc
;
seizeNode
(
signal
,
frag
,
tmpPtr
);
node
.
m_node
=
reinterpret_cast
<
TreeNode
*>
(
node32
);
ndbrequire
(
tmpPtr
.
i
!=
RNIL
);
node
.
m_acc
=
AccNone
;
tmpPtr
.
p
->
m_loc
=
loc
;
ndbrequire
(
node
.
m_loc
!=
NullTupLoc
&&
node
.
m_node
!=
0
);
Uint32
pageId
=
loc
.
m_pageId
;
accessNode
(
signal
,
node
,
acc
);
Uint32
pageOffset
=
loc
.
m_pageOffset
;
Uint32
*
node32
=
0
;
c_tup
->
tuxGetNode
(
frag
.
m_tupIndexFragPtrI
,
pageId
,
pageOffset
,
node32
);
tmpPtr
.
p
->
m_node
=
reinterpret_cast
<
TreeNode
*>
(
node32
);
ndbrequire
(
tmpPtr
.
p
->
m_loc
!=
NullTupLoc
&&
tmpPtr
.
p
->
m_node
!=
0
);
}
if
(
tmpPtr
.
p
->
m_acc
<
acc
)
{
jam
();
accessNode
(
signal
,
frag
,
tmpPtr
,
acc
);
}
nodePtr
=
tmpPtr
;
}
}
/*
/*
*
Create new node in the cache using
the pre-allocated node.
*
Set handle to point to new node. Uses
the pre-allocated node.
*/
*/
void
void
Dbtux
::
insertNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
,
AccSize
acc
)
Dbtux
::
insertNode
(
Signal
*
signal
,
NodeHandle
&
node
,
AccSize
acc
)
{
{
ndbrequire
(
acc
>
AccNone
);
Frag
&
frag
=
node
.
m_frag
;
NodeHandlePtr
tmpPtr
;
TupLoc
loc
=
frag
.
m_freeLoc
;
// use the pre-allocated node
frag
.
m_freeLoc
=
NullTupLoc
;
tmpPtr
.
i
=
frag
.
m_nodeFree
;
selectNode
(
signal
,
node
,
loc
,
acc
);
frag
.
m_nodeFree
=
RNIL
;
new
(
node
.
m_node
)
TreeNode
();
c_nodeHandlePool
.
getPtr
(
tmpPtr
);
#ifdef VM_TRACE
// move it to the cache
TreeHead
&
tree
=
frag
.
m_tree
;
tmpPtr
.
p
->
m_next
=
frag
.
m_nodeList
;
memset
(
tree
.
getPref
(
node
.
m_node
,
0
),
0xa2
,
tree
.
m_prefSize
<<
2
);
frag
.
m_nodeList
=
tmpPtr
.
i
;
memset
(
tree
.
getPref
(
node
.
m_node
,
1
),
0xa2
,
tree
.
m_prefSize
<<
2
);
tmpPtr
.
p
->
m_acc
=
acc
;
TreeEnt
*
entList
=
tree
.
getEntList
(
node
.
m_node
);
nodePtr
=
tmpPtr
;
memset
(
entList
,
0xa4
,
(
tree
.
m_maxOccup
+
1
)
*
(
TreeEntSize
<<
2
));
#endif
}
}
/*
/*
* Delete existing node.
* Delete existing node.
*/
*/
void
void
Dbtux
::
deleteNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
)
Dbtux
::
deleteNode
(
Signal
*
signal
,
NodeHandle
&
node
)
{
{
NodeHandlePtr
tmpPtr
=
nodePtr
;
Frag
&
frag
=
node
.
m_frag
;
ndbrequire
(
tmpPtr
.
p
->
getOccup
()
==
0
);
ndbrequire
(
node
.
getOccup
()
==
0
);
Uint32
pageId
=
tmpPtr
.
p
->
m_loc
.
m_pageId
;
TupLoc
loc
=
node
.
m_loc
;
Uint32
pageOffset
=
tmpPtr
.
p
->
m_loc
.
m_pageOffset
;
Uint32
pageId
=
loc
.
m_pageId
;
Uint32
*
node32
=
reinterpret_cast
<
Uint32
*>
(
tmpPtr
.
p
->
m_node
);
Uint32
pageOffset
=
loc
.
m_pageOffset
;
Uint32
*
node32
=
reinterpret_cast
<
Uint32
*>
(
node
.
m_node
);
c_tup
->
tuxFreeNode
(
signal
,
frag
.
m_tupIndexFragPtrI
,
pageId
,
pageOffset
,
node32
);
c_tup
->
tuxFreeNode
(
signal
,
frag
.
m_tupIndexFragPtrI
,
pageId
,
pageOffset
,
node32
);
// invalidate handle and storage
// invalidate handle and storage
tmpPtr
.
p
->
m_loc
=
NullTupLoc
;
node
.
m_loc
=
NullTupLoc
;
tmpPtr
.
p
->
m_node
=
0
;
node
.
m_node
=
0
;
// scans have already been moved by nodePopDown or nodePopUp
}
/*
* Access more of the node.
*/
void
Dbtux
::
accessNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
,
AccSize
acc
)
{
NodeHandlePtr
tmpPtr
=
nodePtr
;
ndbrequire
(
tmpPtr
.
p
->
m_loc
!=
NullTupLoc
&&
tmpPtr
.
p
->
m_node
!=
0
);
if
(
tmpPtr
.
p
->
m_acc
>=
acc
)
return
;
// XXX could do prefetch
tmpPtr
.
p
->
m_acc
=
acc
;
}
}
/*
/*
...
@@ -201,25 +134,6 @@ Dbtux::setNodePref(Signal* signal, NodeHandle& node, unsigned i)
...
@@ -201,25 +134,6 @@ Dbtux::setNodePref(Signal* signal, NodeHandle& node, unsigned i)
copyAttrs
(
pref
,
readPar
.
m_data
,
copyPar
);
copyAttrs
(
pref
,
readPar
.
m_data
,
copyPar
);
}
}
/*
* Commit and release nodes at the end of an operation. Used also on
* error since no changes have been made (updateOk false).
*/
void
Dbtux
::
commitNodes
(
Signal
*
signal
,
Frag
&
frag
,
bool
updateOk
)
{
NodeHandlePtr
nodePtr
;
nodePtr
.
i
=
frag
.
m_nodeList
;
frag
.
m_nodeList
=
RNIL
;
while
(
nodePtr
.
i
!=
RNIL
)
{
c_nodeHandlePool
.
getPtr
(
nodePtr
);
// release
NodeHandlePtr
tmpPtr
=
nodePtr
;
nodePtr
.
i
=
nodePtr
.
p
->
m_next
;
c_nodeHandlePool
.
release
(
tmpPtr
);
}
}
// node operations
// node operations
/*
/*
...
...
ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
View file @
cb048699
...
@@ -42,7 +42,6 @@ Dbtux::execACC_SCANREQ(Signal* signal)
...
@@ -42,7 +42,6 @@ Dbtux::execACC_SCANREQ(Signal* signal)
}
}
ndbrequire
(
fragPtr
.
i
!=
RNIL
);
ndbrequire
(
fragPtr
.
i
!=
RNIL
);
Frag
&
frag
=
*
fragPtr
.
p
;
Frag
&
frag
=
*
fragPtr
.
p
;
ndbrequire
(
frag
.
m_nodeList
==
RNIL
);
// must be normal DIH/TC fragment
// must be normal DIH/TC fragment
ndbrequire
(
frag
.
m_fragId
<
(
1
<<
frag
.
m_fragOff
));
ndbrequire
(
frag
.
m_fragId
<
(
1
<<
frag
.
m_fragOff
));
TreeHead
&
tree
=
frag
.
m_tree
;
TreeHead
&
tree
=
frag
.
m_tree
;
...
@@ -241,7 +240,6 @@ Dbtux::execNEXT_SCANREQ(Signal* signal)
...
@@ -241,7 +240,6 @@ Dbtux::execNEXT_SCANREQ(Signal* signal)
debugOut
<<
"NEXT_SCANREQ scan "
<<
scanPtr
.
i
<<
" "
<<
scan
<<
endl
;
debugOut
<<
"NEXT_SCANREQ scan "
<<
scanPtr
.
i
<<
" "
<<
scan
<<
endl
;
}
}
#endif
#endif
ndbrequire
(
frag
.
m_nodeList
==
RNIL
);
// handle unlock previous and close scan
// handle unlock previous and close scan
switch
(
req
->
scanFlag
)
{
switch
(
req
->
scanFlag
)
{
case
NextScanReq
:
:
ZSCAN_NEXT
:
case
NextScanReq
:
:
ZSCAN_NEXT
:
...
@@ -278,9 +276,9 @@ Dbtux::execNEXT_SCANREQ(Signal* signal)
...
@@ -278,9 +276,9 @@ Dbtux::execNEXT_SCANREQ(Signal* signal)
if
(
scan
.
m_scanPos
.
m_loc
!=
NullTupLoc
)
{
if
(
scan
.
m_scanPos
.
m_loc
!=
NullTupLoc
)
{
jam
();
jam
();
const
TupLoc
loc
=
scan
.
m_scanPos
.
m_loc
;
const
TupLoc
loc
=
scan
.
m_scanPos
.
m_loc
;
NodeHandle
Ptr
nodePtr
;
NodeHandle
node
(
frag
)
;
selectNode
(
signal
,
frag
,
nodePtr
,
loc
,
AccHead
);
selectNode
(
signal
,
node
,
loc
,
AccHead
);
unlinkScan
(
*
nodePtr
.
p
,
scanPtr
);
unlinkScan
(
node
,
scanPtr
);
scan
.
m_scanPos
.
m_loc
=
NullTupLoc
;
scan
.
m_scanPos
.
m_loc
=
NullTupLoc
;
}
}
if
(
scan
.
m_lockwait
)
{
if
(
scan
.
m_lockwait
)
{
...
@@ -295,7 +293,6 @@ Dbtux::execNEXT_SCANREQ(Signal* signal)
...
@@ -295,7 +293,6 @@ Dbtux::execNEXT_SCANREQ(Signal* signal)
jamEntry
();
jamEntry
();
ndbrequire
(
lockReq
->
returnCode
==
AccLockReq
::
Success
);
ndbrequire
(
lockReq
->
returnCode
==
AccLockReq
::
Success
);
scan
.
m_state
=
ScanOp
::
Aborting
;
scan
.
m_state
=
ScanOp
::
Aborting
;
commitNodes
(
signal
,
frag
,
true
);
return
;
return
;
}
}
if
(
scan
.
m_state
==
ScanOp
::
Locked
)
{
if
(
scan
.
m_state
==
ScanOp
::
Locked
)
{
...
@@ -350,7 +347,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
...
@@ -350,7 +347,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
signal
->
theData
[
1
]
=
true
;
signal
->
theData
[
1
]
=
true
;
EXECUTE_DIRECT
(
DBLQH
,
GSN_CHECK_LCP_STOP
,
signal
,
2
);
EXECUTE_DIRECT
(
DBLQH
,
GSN_CHECK_LCP_STOP
,
signal
,
2
);
jamEntry
();
jamEntry
();
commitNodes
(
signal
,
frag
,
true
);
return
;
// stop
return
;
// stop
}
}
if
(
scan
.
m_lockwait
)
{
if
(
scan
.
m_lockwait
)
{
...
@@ -365,7 +361,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
...
@@ -365,7 +361,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
// if TC has ordered scan close, it will be detected here
// if TC has ordered scan close, it will be detected here
sendSignal
(
scan
.
m_userRef
,
GSN_NEXT_SCANCONF
,
sendSignal
(
scan
.
m_userRef
,
GSN_NEXT_SCANCONF
,
signal
,
signalLength
,
JBB
);
signal
,
signalLength
,
JBB
);
commitNodes
(
signal
,
frag
,
true
);
return
;
// stop
return
;
// stop
}
}
if
(
scan
.
m_state
==
ScanOp
::
First
)
{
if
(
scan
.
m_state
==
ScanOp
::
First
)
{
...
@@ -444,7 +439,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
...
@@ -444,7 +439,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
signal
->
theData
[
1
]
=
true
;
signal
->
theData
[
1
]
=
true
;
EXECUTE_DIRECT
(
DBLQH
,
GSN_CHECK_LCP_STOP
,
signal
,
2
);
EXECUTE_DIRECT
(
DBLQH
,
GSN_CHECK_LCP_STOP
,
signal
,
2
);
jamEntry
();
jamEntry
();
commitNodes
(
signal
,
frag
,
true
);
return
;
// stop
return
;
// stop
break
;
break
;
case
AccLockReq
:
:
Refused
:
case
AccLockReq
:
:
Refused
:
...
@@ -457,7 +451,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
...
@@ -457,7 +451,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
signal
->
theData
[
1
]
=
true
;
signal
->
theData
[
1
]
=
true
;
EXECUTE_DIRECT
(
DBLQH
,
GSN_CHECK_LCP_STOP
,
signal
,
2
);
EXECUTE_DIRECT
(
DBLQH
,
GSN_CHECK_LCP_STOP
,
signal
,
2
);
jamEntry
();
jamEntry
();
commitNodes
(
signal
,
frag
,
true
);
return
;
// stop
return
;
// stop
break
;
break
;
case
AccLockReq
:
:
NoFreeOp
:
case
AccLockReq
:
:
NoFreeOp
:
...
@@ -470,7 +463,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
...
@@ -470,7 +463,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
signal
->
theData
[
1
]
=
true
;
signal
->
theData
[
1
]
=
true
;
EXECUTE_DIRECT
(
DBLQH
,
GSN_CHECK_LCP_STOP
,
signal
,
2
);
EXECUTE_DIRECT
(
DBLQH
,
GSN_CHECK_LCP_STOP
,
signal
,
2
);
jamEntry
();
jamEntry
();
commitNodes
(
signal
,
frag
,
true
);
return
;
// stop
return
;
// stop
break
;
break
;
default:
default:
...
@@ -554,7 +546,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
...
@@ -554,7 +546,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
scan
.
m_lastEnt
=
ent
;
scan
.
m_lastEnt
=
ent
;
// next time look for next entry
// next time look for next entry
scan
.
m_state
=
ScanOp
::
Next
;
scan
.
m_state
=
ScanOp
::
Next
;
commitNodes
(
signal
,
frag
,
true
);
return
;
return
;
}
}
// XXX in ACC this is checked before req->checkLcpStop
// XXX in ACC this is checked before req->checkLcpStop
...
@@ -568,7 +559,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
...
@@ -568,7 +559,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
unsigned
signalLength
=
3
;
unsigned
signalLength
=
3
;
sendSignal
(
scanPtr
.
p
->
m_userRef
,
GSN_NEXT_SCANCONF
,
sendSignal
(
scanPtr
.
p
->
m_userRef
,
GSN_NEXT_SCANCONF
,
signal
,
signalLength
,
JBB
);
signal
,
signalLength
,
JBB
);
commitNodes
(
signal
,
frag
,
true
);
return
;
return
;
}
}
ndbrequire
(
false
);
ndbrequire
(
false
);
...
@@ -707,7 +697,7 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
...
@@ -707,7 +697,7 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
}
}
TreePos
pos
;
TreePos
pos
;
pos
.
m_loc
=
tree
.
m_root
;
pos
.
m_loc
=
tree
.
m_root
;
NodeHandle
Ptr
nodePtr
;
NodeHandle
node
(
frag
)
;
// unpack lower bound
// unpack lower bound
const
ScanBound
&
bound
=
*
scan
.
m_bound
[
0
];
const
ScanBound
&
bound
=
*
scan
.
m_bound
[
0
];
ScanBoundIterator
iter
;
ScanBoundIterator
iter
;
...
@@ -724,20 +714,20 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
...
@@ -724,20 +714,20 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
boundPar
.
m_dir
=
0
;
boundPar
.
m_dir
=
0
;
loop:
{
loop:
{
jam
();
jam
();
selectNode
(
signal
,
frag
,
nodePtr
,
pos
.
m_loc
,
AccPref
);
selectNode
(
signal
,
node
,
pos
.
m_loc
,
AccPref
);
const
unsigned
occup
=
node
Ptr
.
p
->
getOccup
();
const
unsigned
occup
=
node
.
getOccup
();
ndbrequire
(
occup
!=
0
);
ndbrequire
(
occup
!=
0
);
for
(
unsigned
i
=
0
;
i
<=
1
;
i
++
)
{
for
(
unsigned
i
=
0
;
i
<=
1
;
i
++
)
{
jam
();
jam
();
// compare prefix
// compare prefix
boundPar
.
m_data2
=
node
Ptr
.
p
->
getPref
(
i
);
boundPar
.
m_data2
=
node
.
getPref
(
i
);
boundPar
.
m_len2
=
tree
.
m_prefSize
;
boundPar
.
m_len2
=
tree
.
m_prefSize
;
int
ret
=
cmpScanBound
(
frag
,
boundPar
);
int
ret
=
cmpScanBound
(
frag
,
boundPar
);
if
(
ret
==
NdbSqlUtil
::
CmpUnknown
)
{
if
(
ret
==
NdbSqlUtil
::
CmpUnknown
)
{
jam
();
jam
();
// read full value
// read full value
ReadPar
readPar
;
ReadPar
readPar
;
readPar
.
m_ent
=
node
Ptr
.
p
->
getMinMax
(
i
);
readPar
.
m_ent
=
node
.
getMinMax
(
i
);
readPar
.
m_first
=
0
;
readPar
.
m_first
=
0
;
readPar
.
m_count
=
frag
.
m_numAttrs
;
readPar
.
m_count
=
frag
.
m_numAttrs
;
readPar
.
m_data
=
0
;
// leave in signal data
readPar
.
m_data
=
0
;
// leave in signal data
...
@@ -750,7 +740,7 @@ loop: {
...
@@ -750,7 +740,7 @@ loop: {
}
}
if
(
i
==
0
&&
ret
<
0
)
{
if
(
i
==
0
&&
ret
<
0
)
{
jam
();
jam
();
const
TupLoc
loc
=
node
Ptr
.
p
->
getLink
(
i
);
const
TupLoc
loc
=
node
.
getLink
(
i
);
if
(
loc
!=
NullTupLoc
)
{
if
(
loc
!=
NullTupLoc
)
{
jam
();
jam
();
// continue to left subtree
// continue to left subtree
...
@@ -763,12 +753,12 @@ loop: {
...
@@ -763,12 +753,12 @@ loop: {
pos
.
m_dir
=
3
;
pos
.
m_dir
=
3
;
scan
.
m_scanPos
=
pos
;
scan
.
m_scanPos
=
pos
;
scan
.
m_state
=
ScanOp
::
Next
;
scan
.
m_state
=
ScanOp
::
Next
;
linkScan
(
*
nodePtr
.
p
,
scanPtr
);
linkScan
(
node
,
scanPtr
);
return
;
return
;
}
}
if
(
i
==
1
&&
ret
>
0
)
{
if
(
i
==
1
&&
ret
>
0
)
{
jam
();
jam
();
const
TupLoc
loc
=
node
Ptr
.
p
->
getLink
(
i
);
const
TupLoc
loc
=
node
.
getLink
(
i
);
if
(
loc
!=
NullTupLoc
)
{
if
(
loc
!=
NullTupLoc
)
{
jam
();
jam
();
// continue to right subtree
// continue to right subtree
...
@@ -779,18 +769,18 @@ loop: {
...
@@ -779,18 +769,18 @@ loop: {
pos
.
m_dir
=
1
;
pos
.
m_dir
=
1
;
scan
.
m_scanPos
=
pos
;
scan
.
m_scanPos
=
pos
;
scan
.
m_state
=
ScanOp
::
Next
;
scan
.
m_state
=
ScanOp
::
Next
;
linkScan
(
*
nodePtr
.
p
,
scanPtr
);
linkScan
(
node
,
scanPtr
);
return
;
return
;
}
}
}
}
// read rest of current node
// read rest of current node
accessNode
(
signal
,
frag
,
nodePtr
,
AccFull
);
accessNode
(
signal
,
node
,
AccFull
);
// look for first entry
// look for first entry
ndbrequire
(
occup
>=
2
);
ndbrequire
(
occup
>=
2
);
for
(
unsigned
j
=
1
;
j
<
occup
;
j
++
)
{
for
(
unsigned
j
=
1
;
j
<
occup
;
j
++
)
{
jam
();
jam
();
ReadPar
readPar
;
ReadPar
readPar
;
readPar
.
m_ent
=
node
Ptr
.
p
->
getEnt
(
j
);
readPar
.
m_ent
=
node
.
getEnt
(
j
);
readPar
.
m_first
=
0
;
readPar
.
m_first
=
0
;
readPar
.
m_count
=
frag
.
m_numAttrs
;
readPar
.
m_count
=
frag
.
m_numAttrs
;
readPar
.
m_data
=
0
;
// leave in signal data
readPar
.
m_data
=
0
;
// leave in signal data
...
@@ -808,7 +798,7 @@ loop: {
...
@@ -808,7 +798,7 @@ loop: {
pos
.
m_dir
=
3
;
pos
.
m_dir
=
3
;
scan
.
m_scanPos
=
pos
;
scan
.
m_scanPos
=
pos
;
scan
.
m_state
=
ScanOp
::
Next
;
scan
.
m_state
=
ScanOp
::
Next
;
linkScan
(
*
nodePtr
.
p
,
scanPtr
);
linkScan
(
node
,
scanPtr
);
return
;
return
;
}
}
}
}
...
@@ -868,11 +858,11 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
...
@@ -868,11 +858,11 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
// use copy of position
// use copy of position
TreePos
pos
=
scan
.
m_scanPos
;
TreePos
pos
=
scan
.
m_scanPos
;
// get and remember original node
// get and remember original node
NodeHandle
Ptr
origNodePtr
;
NodeHandle
origNode
(
frag
)
;
selectNode
(
signal
,
frag
,
origNodePtr
,
pos
.
m_loc
,
AccHead
);
selectNode
(
signal
,
origNode
,
pos
.
m_loc
,
AccHead
);
ndbrequire
(
islinkScan
(
*
origNodePtr
.
p
,
scanPtr
));
ndbrequire
(
islinkScan
(
origNode
,
scanPtr
));
// current node in loop
// current node in loop
NodeHandle
Ptr
nodePtr
=
origNodePtr
;
NodeHandle
node
=
origNode
;
while
(
true
)
{
while
(
true
)
{
jam
();
jam
();
if
(
pos
.
m_dir
==
2
)
{
if
(
pos
.
m_dir
==
2
)
{
...
@@ -882,14 +872,14 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
...
@@ -882,14 +872,14 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
scan
.
m_state
=
ScanOp
::
Last
;
scan
.
m_state
=
ScanOp
::
Last
;
break
;
break
;
}
}
if
(
node
Ptr
.
p
->
m_loc
!=
pos
.
m_loc
)
{
if
(
node
.
m_loc
!=
pos
.
m_loc
)
{
jam
();
jam
();
selectNode
(
signal
,
frag
,
nodePtr
,
pos
.
m_loc
,
AccHead
);
selectNode
(
signal
,
node
,
pos
.
m_loc
,
AccHead
);
}
}
if
(
pos
.
m_dir
==
4
)
{
if
(
pos
.
m_dir
==
4
)
{
// coming down from parent proceed to left child
// coming down from parent proceed to left child
jam
();
jam
();
TupLoc
loc
=
node
Ptr
.
p
->
getLink
(
0
);
TupLoc
loc
=
node
.
getLink
(
0
);
if
(
loc
!=
NullTupLoc
)
{
if
(
loc
!=
NullTupLoc
)
{
jam
();
jam
();
pos
.
m_loc
=
loc
;
pos
.
m_loc
=
loc
;
...
@@ -909,10 +899,10 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
...
@@ -909,10 +899,10 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
if
(
pos
.
m_dir
==
3
)
{
if
(
pos
.
m_dir
==
3
)
{
// within node
// within node
jam
();
jam
();
unsigned
occup
=
node
Ptr
.
p
->
getOccup
();
unsigned
occup
=
node
.
getOccup
();
ndbrequire
(
occup
>=
1
);
ndbrequire
(
occup
>=
1
);
// access full node
// access full node
accessNode
(
signal
,
frag
,
nodePtr
,
AccFull
);
accessNode
(
signal
,
node
,
AccFull
);
// advance position
// advance position
if
(
!
pos
.
m_match
)
if
(
!
pos
.
m_match
)
pos
.
m_match
=
true
;
pos
.
m_match
=
true
;
...
@@ -920,7 +910,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
...
@@ -920,7 +910,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
pos
.
m_pos
++
;
pos
.
m_pos
++
;
if
(
pos
.
m_pos
<
occup
)
{
if
(
pos
.
m_pos
<
occup
)
{
jam
();
jam
();
pos
.
m_ent
=
node
Ptr
.
p
->
getEnt
(
pos
.
m_pos
);
pos
.
m_ent
=
node
.
getEnt
(
pos
.
m_pos
);
pos
.
m_dir
=
3
;
// unchanged
pos
.
m_dir
=
3
;
// unchanged
// XXX implement prefix optimization
// XXX implement prefix optimization
ReadPar
readPar
;
ReadPar
readPar
;
...
@@ -951,7 +941,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
...
@@ -951,7 +941,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
break
;
break
;
}
}
// after node proceed to right child
// after node proceed to right child
TupLoc
loc
=
node
Ptr
.
p
->
getLink
(
1
);
TupLoc
loc
=
node
.
getLink
(
1
);
if
(
loc
!=
NullTupLoc
)
{
if
(
loc
!=
NullTupLoc
)
{
jam
();
jam
();
pos
.
m_loc
=
loc
;
pos
.
m_loc
=
loc
;
...
@@ -964,8 +954,8 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
...
@@ -964,8 +954,8 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
if
(
pos
.
m_dir
==
1
)
{
if
(
pos
.
m_dir
==
1
)
{
// coming from right child proceed to parent
// coming from right child proceed to parent
jam
();
jam
();
pos
.
m_loc
=
node
Ptr
.
p
->
getLink
(
2
);
pos
.
m_loc
=
node
.
getLink
(
2
);
pos
.
m_dir
=
node
Ptr
.
p
->
getSide
();
pos
.
m_dir
=
node
.
getSide
();
continue
;
continue
;
}
}
ndbrequire
(
false
);
ndbrequire
(
false
);
...
@@ -974,16 +964,16 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
...
@@ -974,16 +964,16 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
scan
.
m_scanPos
=
pos
;
scan
.
m_scanPos
=
pos
;
// relink
// relink
if
(
scan
.
m_state
==
ScanOp
::
Current
)
{
if
(
scan
.
m_state
==
ScanOp
::
Current
)
{
ndbrequire
(
pos
.
m_loc
==
node
Ptr
.
p
->
m_loc
);
ndbrequire
(
pos
.
m_loc
==
node
.
m_loc
);
if
(
origNode
Ptr
.
i
!=
nodePtr
.
i
)
{
if
(
origNode
.
m_loc
!=
node
.
m_loc
)
{
jam
();
jam
();
unlinkScan
(
*
origNodePtr
.
p
,
scanPtr
);
unlinkScan
(
origNode
,
scanPtr
);
linkScan
(
*
nodePtr
.
p
,
scanPtr
);
linkScan
(
node
,
scanPtr
);
}
}
}
else
if
(
scan
.
m_state
==
ScanOp
::
Last
)
{
}
else
if
(
scan
.
m_state
==
ScanOp
::
Last
)
{
jam
();
jam
();
ndbrequire
(
pos
.
m_loc
==
NullTupLoc
);
ndbrequire
(
pos
.
m_loc
==
NullTupLoc
);
unlinkScan
(
*
origNodePtr
.
p
,
scanPtr
);
unlinkScan
(
origNode
,
scanPtr
);
}
else
{
}
else
{
ndbrequire
(
false
);
ndbrequire
(
false
);
}
}
...
@@ -1043,7 +1033,6 @@ void
...
@@ -1043,7 +1033,6 @@ void
Dbtux
::
scanClose
(
Signal
*
signal
,
ScanOpPtr
scanPtr
)
Dbtux
::
scanClose
(
Signal
*
signal
,
ScanOpPtr
scanPtr
)
{
{
ScanOp
&
scan
=
*
scanPtr
.
p
;
ScanOp
&
scan
=
*
scanPtr
.
p
;
Frag
&
frag
=
*
c_fragPool
.
getPtr
(
scanPtr
.
p
->
m_fragPtrI
);
ndbrequire
(
!
scan
.
m_lockwait
&&
scan
.
m_accLockOp
==
RNIL
);
ndbrequire
(
!
scan
.
m_lockwait
&&
scan
.
m_accLockOp
==
RNIL
);
// unlock all not unlocked by LQH
// unlock all not unlocked by LQH
for
(
unsigned
i
=
0
;
i
<
MaxAccLockOps
;
i
++
)
{
for
(
unsigned
i
=
0
;
i
<
MaxAccLockOps
;
i
++
)
{
...
@@ -1068,7 +1057,6 @@ Dbtux::scanClose(Signal* signal, ScanOpPtr scanPtr)
...
@@ -1068,7 +1057,6 @@ Dbtux::scanClose(Signal* signal, ScanOpPtr scanPtr)
sendSignal
(
scanPtr
.
p
->
m_userRef
,
GSN_NEXT_SCANCONF
,
sendSignal
(
scanPtr
.
p
->
m_userRef
,
GSN_NEXT_SCANCONF
,
signal
,
signalLength
,
JBB
);
signal
,
signalLength
,
JBB
);
releaseScanOp
(
scanPtr
);
releaseScanOp
(
scanPtr
);
commitNodes
(
signal
,
frag
,
true
);
}
}
void
void
...
...
ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
View file @
cb048699
This diff is collapsed.
Click to expand it.
ndb/src/kernel/blocks/dbtux/Times.txt
View file @
cb048699
...
@@ -31,6 +31,7 @@ optim 4 mc02/a 42 ms 80 ms 87 pct
...
@@ -31,6 +31,7 @@ optim 4 mc02/a 42 ms 80 ms 87 pct
optim 5 mc02/a 43 ms 77 ms 77 pct
optim 5 mc02/a 43 ms 77 ms 77 pct
mc02/b 54 ms 118 ms 117 pct
mc02/b 54 ms 118 ms 117 pct
optim 6 mc02/a 42 ms 70 ms 66 pct
mc02/b 53 ms 109 ms 105 pct
vim: set et:
vim: set et:
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment