1 /*
2    Copyright (c) 2009, 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 #include "Dbtux.hpp"
26 
27 #define JAM_FILE_ID 373
28 
29 
30 struct mt_BuildIndxCtx
31 {
32   Uint32 indexId;
33   Uint32 tableId;
34   Uint32 fragId;
35   Dbtup* tup_ptr;
36   Dbtux::TuxCtx * tux_ctx_ptr;
37   NdbMutex * alloc_mutex_ptr;
38 };
39 
40 Uint32
Dbtux_mt_buildIndexFragment_wrapper_C(void * obj)41 Dbtux_mt_buildIndexFragment_wrapper_C(void * obj)
42 {
43   return Dbtux::mt_buildIndexFragment_wrapper(obj);
44 }
45 
46 Uint32
mt_buildIndexFragment_wrapper(void * obj)47 Dbtux::mt_buildIndexFragment_wrapper(void * obj)
48 {
49   mt_BuildIndxReq* req = reinterpret_cast<mt_BuildIndxReq*>(obj);
50   TuxCtx * tux_ctx = reinterpret_cast<TuxCtx*>(req->mem_buffer);
51   {
52     /**
53      * Setup ctx object...
54      */
55     Uint32 * ptr = reinterpret_cast<Uint32*>(req->mem_buffer);
56     ptr += (sizeof(* tux_ctx) + 3) / 4;
57 
58     tux_ctx->jamBuffer = getThrJamBuf();
59     tux_ctx->c_searchKey = ptr;
60     ptr += MaxAttrDataSize;
61     tux_ctx->c_entryKey = ptr;
62     ptr += MaxAttrDataSize;
63     tux_ctx->c_dataBuffer = ptr;
64     ptr += MaxAttrDataSize;
65 #ifdef VM_TRACE
66     tux_ctx->c_debugBuffer = (char*)ptr;
67     ptr += (DebugBufferBytes + 3) / 4;
68 #endif
69     if (!(UintPtr(ptr) - UintPtr(req->mem_buffer) <= req->buffer_size))
70       abort();
71   }
72 
73   mt_BuildIndxCtx ctx;
74   ctx.indexId = req->indexId;
75   ctx.tableId = req->tableId;
76   ctx.fragId = req->fragId;
77   ctx.tux_ctx_ptr = tux_ctx;
78   ctx.tup_ptr = reinterpret_cast<Dbtup*>(req->tup_ptr);
79 
80   Dbtux* tux = reinterpret_cast<Dbtux*>(req->tux_ptr);
81   return tux->mt_buildIndexFragment(&ctx);
82 }
83 
84 Uint32 // error code
mt_buildIndexFragment(mt_BuildIndxCtx * req)85 Dbtux::mt_buildIndexFragment(mt_BuildIndxCtx* req)
86 {
87   IndexPtr indexPtr;
88   c_indexPool.getPtr(indexPtr, req->indexId);
89   ndbrequire(indexPtr.p->m_tableId == req->tableId);
90   // get base fragment id and extra bits
91   const Uint32 fragId = req->fragId;
92   // get the fragment
93   FragPtr fragPtr;
94   TuxCtx & ctx = * (TuxCtx*)req->tux_ctx_ptr;
95   findFrag(ctx.jamBuffer, *indexPtr.p, fragId, fragPtr);
96   ndbrequire(fragPtr.i != RNIL);
97   Frag& frag = *fragPtr.p;
98   Local_key pos;
99   Uint32 fragPtrI;
100   int err = req->tup_ptr->mt_scan_init(req->tableId, req->fragId,
101                                        &pos, &fragPtrI);
102   bool moveNext = false;
103   while (globalData.theRestartFlag != perform_stop &&
104          err == 0 &&
105          (err = req->tup_ptr->mt_scan_next(req->tableId,
106                                            fragPtrI, &pos, moveNext)) == 0)
107   {
108     moveNext = true;
109 
110     // set up search entry
111     TreeEnt ent;
112     ent.m_tupLoc = TupLoc(pos.m_page_no, pos.m_page_idx);
113     ent.m_tupVersion = pos.m_file_no; // used for version
114 
115     // set up and read search key
116     KeyData searchKey(indexPtr.p->m_keySpec, false, 0);
117     searchKey.set_buf(ctx.c_searchKey, MaxAttrDataSize << 2);
118     readKeyAttrs(ctx, frag, ent, searchKey, indexPtr.p->m_numAttrs);
119 
120     if (unlikely(! indexPtr.p->m_storeNullKey) &&
121         searchKey.get_null_cnt() == indexPtr.p->m_numAttrs) {
122       thrjam(ctx.jamBuffer);
123       continue;
124     }
125 
126     TreePos treePos;
127     bool ok = searchToAdd(ctx, frag, searchKey, ent, treePos);
128     ndbrequire(ok);
129 
130     /*
131      * At most one new node is inserted in the operation.  Pre-allocate
132      * it so that the operation cannot fail.
133      */
134     if (frag.m_freeLoc == NullTupLoc)
135     {
136       thrjam(ctx.jamBuffer);
137       NodeHandle node(frag);
138       err = -(int)allocNode(ctx, node);
139 
140       if (err != 0)
141       {
142         break;
143       }
144       frag.m_freeLoc = node.m_loc;
145       ndbrequire(frag.m_freeLoc != NullTupLoc);
146     }
147     treeAdd(ctx, frag, treePos, ent);
148     frag.m_entryCount++;
149     frag.m_entryBytes += searchKey.get_data_len();
150     frag.m_entryOps++;
151   }
152 
153   if (err < 0)
154   {
155     return -err;
156   }
157 
158   return 0;
159 };
160