1 /*
2 Copyright (c) 2003, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #define DBTUX_MAINT_CPP
26 #include "Dbtux.hpp"
27
28 #define JAM_FILE_ID 369
29
30
31 /*
32 * Maintain index.
33 */
34
35 void
execTUX_MAINT_REQ(Signal * signal)36 Dbtux::execTUX_MAINT_REQ(Signal* signal)
37 {
38 jamEntry();
39 TuxMaintReq* const sig = (TuxMaintReq*)signal->getDataPtrSend();
40 // ignore requests from redo log
41 IndexPtr indexPtr;
42 c_indexPool.getPtr(indexPtr, sig->indexId);
43
44 if (unlikely(! (indexPtr.p->m_state == Index::Online ||
45 indexPtr.p->m_state == Index::Building)))
46 {
47 jam();
48 #ifdef VM_TRACE
49 if (debugFlags & DebugMaint) {
50 TupLoc tupLoc(sig->pageId, sig->pageIndex);
51 debugOut << "opInfo=" << hex << sig->opInfo;
52 debugOut << " tableId=" << dec << sig->tableId;
53 debugOut << " indexId=" << dec << sig->indexId;
54 debugOut << " fragId=" << dec << sig->fragId;
55 debugOut << " tupLoc=" << tupLoc;
56 debugOut << " tupVersion=" << dec << sig->tupVersion;
57 debugOut << " -- ignored at ISP=" << dec << c_internalStartPhase;
58 debugOut << " TOS=" << dec << c_typeOfStart;
59 debugOut << endl;
60 }
61 #endif
62 sig->errorCode = 0;
63 return;
64 }
65
66 TuxMaintReq reqCopy = *sig;
67 TuxMaintReq* const req = &reqCopy;
68 const Uint32 opCode = req->opInfo & 0xFF;
69 // get the index
70 ndbrequire(indexPtr.p->m_tableId == req->tableId);
71 // get base fragment id and extra bits
72 const Uint32 fragId = req->fragId;
73 // get the fragment
74 FragPtr fragPtr;
75 findFrag(jamBuffer(), *indexPtr.p, fragId, fragPtr);
76 ndbrequire(fragPtr.i != RNIL);
77 Frag& frag = *fragPtr.p;
78 // set up search entry
79 TreeEnt ent;
80 ent.m_tupLoc = TupLoc(req->pageId, req->pageIndex);
81 ent.m_tupVersion = req->tupVersion;
82 // set up and read search key
83 KeyData searchKey(indexPtr.p->m_keySpec, false, 0);
84 searchKey.set_buf(c_ctx.c_searchKey, MaxAttrDataSize << 2);
85 readKeyAttrs(c_ctx, frag, ent, searchKey, indexPtr.p->m_numAttrs);
86 if (unlikely(! indexPtr.p->m_storeNullKey) &&
87 searchKey.get_null_cnt() == indexPtr.p->m_numAttrs) {
88 jam();
89 return;
90 }
91 #ifdef VM_TRACE
92 if (debugFlags & DebugMaint) {
93 const Uint32 opFlag = req->opInfo >> 8;
94 debugOut << "opCode=" << dec << opCode;
95 debugOut << " opFlag=" << dec << opFlag;
96 debugOut << " tableId=" << dec << req->tableId;
97 debugOut << " indexId=" << dec << req->indexId;
98 debugOut << " fragId=" << dec << req->fragId;
99 debugOut << " entry=" << ent;
100 debugOut << endl;
101 }
102 #endif
103 // do the operation
104 req->errorCode = 0;
105 TreePos treePos;
106 bool ok;
107 switch (opCode) {
108 case TuxMaintReq::OpAdd:
109 jam();
110 ok = searchToAdd(c_ctx, frag, searchKey, ent, treePos);
111 #ifdef VM_TRACE
112 if (debugFlags & DebugMaint) {
113 debugOut << treePos << (! ok ? " - error" : "") << endl;
114 }
115 #endif
116 if (! ok) {
117 jam();
118 // there is no "Building" state so this will have to do
119 if (indexPtr.p->m_state == Index::Online) {
120 jam();
121 req->errorCode = TuxMaintReq::SearchError;
122 }
123 break;
124 }
125 /*
126 * At most one new node is inserted in the operation. Pre-allocate
127 * it so that the operation cannot fail.
128 */
129 if (frag.m_freeLoc == NullTupLoc) {
130 jam();
131 NodeHandle node(frag);
132 req->errorCode = allocNode(c_ctx, node);
133 if (req->errorCode != 0) {
134 jam();
135 break;
136 }
137 frag.m_freeLoc = node.m_loc;
138 ndbrequire(frag.m_freeLoc != NullTupLoc);
139 }
140 treeAdd(c_ctx, frag, treePos, ent);
141 frag.m_entryCount++;
142 frag.m_entryBytes += searchKey.get_data_len();
143 frag.m_entryOps++;
144 break;
145 case TuxMaintReq::OpRemove:
146 jam();
147 ok = searchToRemove(c_ctx, frag, searchKey, ent, treePos);
148 #ifdef VM_TRACE
149 if (debugFlags & DebugMaint) {
150 debugOut << treePos << (! ok ? " - error" : "") << endl;
151 }
152 #endif
153 if (! ok) {
154 jam();
155 // there is no "Building" state so this will have to do
156 if (indexPtr.p->m_state == Index::Online) {
157 jam();
158 req->errorCode = TuxMaintReq::SearchError;
159 }
160 break;
161 }
162 treeRemove(frag, treePos);
163 ndbrequire(frag.m_entryCount != 0);
164 frag.m_entryCount--;
165 frag.m_entryBytes -= searchKey.get_data_len();
166 frag.m_entryOps++;
167 break;
168 default:
169 ndbrequire(false);
170 break;
171 }
172 #ifdef VM_TRACE
173 if (debugFlags & DebugTree) {
174 printTree(signal, frag, debugOut);
175 }
176 #endif
177 // copy back
178 *sig = *req;
179
180 //ndbrequire(c_keyAttrs[0] == c_keyAttrs[1]);
181 //ndbrequire(c_sqlCmp[0] == c_sqlCmp[1]);
182 //ndbrequire(c_searchKey[0] == c_searchKey[1]);
183 //ndbrequire(c_entryKey[0] == c_entryKey[1]);
184 //ndbrequire(c_dataBuffer[0] == c_dataBuffer[1]);
185 }
186