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