1 /* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
22
23 #ifndef NDB_INDEX_STAT_IMPL_HPP
24 #define NDB_INDEX_STAT_IMPL_HPP
25
26 #include <ndb_global.h>
27 #include <ndb_limits.h>
28 #include <NdbDictionary.hpp>
29 #include <NdbIndexStat.hpp>
30 #include <util/NdbPack.hpp>
31 #include <NdbError.hpp>
32 #include <NdbMutex.h>
33 #include <NdbTick.h>
34 class Ndb;
35 class NdbTransaction;
36 class NdbIndexScanOperation;
37 class NdbRecAttr;
38 class NdbOperation;
39 class NdbEventOperation;
40
41 extern const uint g_ndb_index_stat_head_frm_len;
42 extern const uint8 g_ndb_index_stat_head_frm_data[];
43 extern const uint g_ndb_index_stat_sample_frm_len;
44 extern const uint8 g_ndb_index_stat_sample_frm_data[];
45
46 class NdbIndexStatImpl : public NdbIndexStat {
47 public:
48 friend class NdbIndexStat;
49 struct Con;
50 struct Cache;
51
52 enum { MaxKeyCount = MAX_INDEX_STAT_KEY_COUNT };
53 enum { MaxKeyBytes = MAX_INDEX_STAT_KEY_SIZE * 4 };
54 enum { MaxValueBytes = MAX_INDEX_STAT_VALUE_SIZE * 4 };
55 enum { MaxValueCBytes = MAX_INDEX_STAT_VALUE_CSIZE * 4 };
56
57 NdbIndexStatImpl(NdbIndexStat& facade);
58 ~NdbIndexStatImpl();
59 void init();
60
61 NdbIndexStat* const m_facade;
62 Head m_facadeHead; // owned by facade
63 bool m_indexSet;
64 Uint32 m_indexId;
65 Uint32 m_indexVersion;
66 Uint32 m_tableId;
67 uint m_keyAttrs;
68 uint m_valueAttrs;
69 NdbPack::Spec m_keySpec;
70 NdbPack::Spec m_valueSpec;
71 NdbPack::Type* m_keySpecBuf;
72 NdbPack::Type* m_valueSpecBuf;
73 NdbPack::Data m_keyData;
74 NdbPack::Data m_valueData;
75 Uint8* m_keyDataBuf;
76 Uint8* m_valueDataBuf;
77 Cache* m_cacheBuild;
78 Cache* m_cacheQuery;
79 Cache* m_cacheClean;
80 // mutex for query cache switch, memory barrier would do
81 NdbMutex* m_query_mutex;
82 NdbEventOperation* m_eventOp;
83 Mem* m_mem_handler;
84 NdbIndexStat::Error m_error;
85
86 // sys tables meta
87 struct Sys {
88 NdbIndexStatImpl* const m_impl;
89 Ndb* const m_ndb;
90 NdbDictionary::Dictionary* m_dic;
91 const NdbDictionary::Table* m_headtable;
92 const NdbDictionary::Table* m_sampletable;
93 const NdbDictionary::Index* m_sampleindex1;
94 int m_obj_cnt;
95 enum { ObjCnt = 3 };
96 Sys(NdbIndexStatImpl* impl, Ndb* ndb);
97 ~Sys();
98 };
99 void sys_release(Sys& sys);
100 int make_headtable(NdbDictionary::Table& tab);
101 int make_sampletable(NdbDictionary::Table& tab);
102 int make_sampleindex1(NdbDictionary::Index& ind);
103 int check_table(const NdbDictionary::Table& tab1,
104 const NdbDictionary::Table& tab2);
105 int check_index(const NdbDictionary::Index& ind1,
106 const NdbDictionary::Index& ind2);
107 int get_systables(Sys& sys);
108 int create_systables(Ndb* ndb);
109 int drop_systables(Ndb* ndb);
110 int check_systables(Sys& sys);
111 int check_systables(Ndb* ndb);
112
113 // operation context
114 struct Con {
115 NdbIndexStatImpl* const m_impl;
116 Head& m_head;
117 Ndb* const m_ndb;
118 NdbDictionary::Dictionary* m_dic;
119 const NdbDictionary::Table* m_headtable;
120 const NdbDictionary::Table* m_sampletable;
121 const NdbDictionary::Index* m_sampleindex1;
122 NdbTransaction* m_tx;
123 NdbOperation* m_op;
124 NdbIndexScanOperation* m_scanop;
125 Cache* m_cacheBuild;
126 uint m_cachePos;
127 uint m_cacheKeyOffset; // in bytes
128 uint m_cacheValueOffset; // in bytes
129 MicroSecondTimer m_start;
130 Con(NdbIndexStatImpl* impl, Head& head, Ndb* ndb);
131 ~Con();
132 int startTransaction();
133 int execute(bool commit);
134 int getNdbOperation();
135 int getNdbIndexScanOperation();
136 void set_time();
137 NDB_TICKS get_time();
138 };
139
140 // index
141 int set_index(const NdbDictionary::Index& index,
142 const NdbDictionary::Table& table);
143 void reset_index();
144
145 // init m_facadeHead here (keep API struct a POD)
146 void init_head(Head& head);
147
148 // sys tables data
149 int sys_init(Con& con);
150 void sys_release(Con& con);
151 int sys_read_head(Con& con, bool commit);
152 int sys_head_setkey(Con& con);
153 int sys_head_getvalue(Con& con);
154 int sys_sample_setkey(Con& con);
155 int sys_sample_getvalue(Con& con);
156 int sys_sample_setbound(Con& con, int sv_bound);
157
158 // update, delete (head may record elapsed time)
159 int update_stat(Ndb* ndb, Head& head);
160 int delete_stat(Ndb* ndb, Head& head);
161
162 // read
163 int read_head(Ndb* ndb, Head& head);
164 int read_stat(Ndb* ndb, Head& head);
165 int read_start(Con& con);
166 int read_next(Con& con);
167 int read_commit(Con& con);
168 int save_start(Con& con);
169 int save_next(Con& con);
170 int save_commit(Con& con);
171 int cache_init(Con& con);
172 int cache_insert(Con& con);
173 int cache_commit(Con& con);
174
175 // cache
176 struct Cache {
177 bool m_valid;
178 uint m_keyAttrs; // number of attrs in index key
179 uint m_valueAttrs; // number of values
180 uint m_fragCount; // index fragments
181 uint m_sampleVersion;
182 uint m_sampleCount; // sample count from head record
183 uint m_keyBytes; // total key bytes from head record
184 uint m_valueLen; // value bytes per entry i.e. valueAttrs * ValueSize
185 uint m_valueBytes; // total value bytes i.e. sampleCount * valuelen
186 uint m_addrLen; // 1-4 based on keyBytes
187 uint m_addrBytes; // total address bytes
188 Uint8* m_addrArray;
189 Uint8* m_keyArray;
190 Uint8* m_valueArray;
191 Cache* m_nextClean;
192 // performance
193 mutable Uint64 m_save_time;
194 mutable Uint64 m_sort_time;
195 Cache();
196 // pos is index < sampleCount, addr is offset in keyArray
197 uint get_keyaddr(uint pos) const;
198 void set_keyaddr(uint pos, uint addr);
199 // get pointers to key and value arrays at pos
200 const Uint8* get_keyptr(uint addr) const;
201 Uint8* get_keyptr(uint addr);
202 const Uint8* get_valueptr(uint pos) const;
203 Uint8* get_valueptr(uint pos);
204 // for sort
205 void swap_entry(uint pos1, uint pos2);
206 // get stats values primitives
207 double get_rir(uint pos) const;
208 double get_rir(uint pos1, uint pos2) const;
209 double get_unq(uint pos, uint k) const;
210 double get_unq(uint pos1, uint pos2, uint k) const;
211 double get_rpk(uint pos, uint k) const;
212 double get_rpk(uint pos1, uint pos2, uint k) const;
213 };
214 int cache_cmpaddr(const Cache& c, uint addr1, uint addr2) const;
215 int cache_cmppos(const Cache& c, uint pos1, uint pos2) const;
216 int cache_sort(Cache& c);
217 void cache_isort(Cache& c);
218 void cache_hsort(Cache& c);
219 void cache_hsort_sift(Cache& c, int i, int count);
220 void cache_hsort_verify(Cache& c, int count);
221 int cache_verify(const Cache& c);
222 void move_cache();
223 void clean_cache();
224 void free_cache(Cache* c);
225 void free_cache();
226
227 // query cache dump (not available via facade)
228 struct CacheIter {
229 Uint32 m_keyCount;
230 Uint32 m_sampleCount;
231 Uint32 m_sampleIndex;
232 NdbPack::DataC m_keyData;
233 NdbPack::DataC m_valueData;
234 CacheIter(const NdbIndexStatImpl& impl);
235 };
236 int dump_cache_start(CacheIter& iter);
237 bool dump_cache_next(CacheIter& iter);
238
239 // bound
240 struct Bound {
241 NdbPack::Data m_data;
242 NdbPack::Bound m_bound;
243 int m_type; // 0-lower 1-upper
244 int m_strict;
245 Bound(const NdbPack::Spec& spec);
246 };
247 int finalize_bound(Bound&);
248
249 // range
250 struct Range {
251 Range(Bound& bound1, Bound& bound2);
252 Bound& m_bound1;
253 Bound& m_bound2;
254 };
255 int finalize_range(Range& range);
256 int convert_range(Range& range,
257 const NdbRecord* key_record,
258 const NdbIndexScanOperation::IndexBound* ib);
259
260 // computed stats values
261 struct StatValue {
262 bool m_empty;
263 double m_rir;
264 double m_unq[MaxKeyCount];
265 StatValue();
266 };
267
268 // query
269 struct StatBound {
270 uint m_pos; // non-empty bound is between pos-1,pos
271 uint m_numEqL; // components matching key at pos-1
272 uint m_numEqH; // components matching key at pos
273 StatValue m_value;
274 const char* m_rule;
275 StatBound();
276 };
277 struct Stat {
278 StatBound m_stat1;
279 StatBound m_stat2;
280 StatValue m_value;
281 const char* m_rule[3];
282 Stat();
283 };
284 void query_normalize(const Cache&, StatValue&);
285 void query_unq2rpk(const Cache&, StatValue&);
286 int query_stat(const Range&, Stat&);
287 void query_interpolate(const Cache&, const Range&, Stat&);
288 void query_interpolate(const Cache&, const Bound&, StatBound&);
289 void query_search(const Cache&, const Bound&, StatBound&);
290 int query_keycmp(const Cache&, const Bound&, uint pos, Uint32& numEq);
291
292 // events and polling
293 int create_sysevents(Ndb* ndb);
294 int drop_sysevents(Ndb* ndb);
295 int check_sysevents(Ndb* ndb);
296 //
297 int create_listener(Ndb* ndb);
298 int execute_listener(Ndb* ndb);
299 int poll_listener(Ndb* ndb, int max_wait_ms);
300 int next_listener(Ndb* ndb);
301 int drop_listener(Ndb* ndb);
302
303 // default memory allocator
304 struct MemDefault : public Mem {
305 virtual void* mem_alloc(UintPtr bytes);
306 virtual void mem_free(void* ptr);
307 MemDefault();
308 virtual ~MemDefault();
309 };
310 MemDefault c_mem_default_handler;
311
312 // error
313 const NdbIndexStat::Error& getNdbError() const;
314 void setError(int code, int line, int extra = 0);
315 void setError(const Con& con, int line);
316 void mapError(const int* map, int code);
317
318 // moved from NdbIndexStat.hpp by jonas
319
320 /* Need 2 words per column in a bound plus space for the
321 * bound data.
322 * Worst case is 32 cols in key and max key size used.
323 */
324 STATIC_CONST( BoundBufWords = (2 * NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY)
325 + NDB_MAX_KEYSIZE_IN_WORDS );
326 };
327
328 inline
Bound(const NdbPack::Spec & spec)329 NdbIndexStatImpl::Bound::Bound(const NdbPack::Spec& spec) :
330 m_data(spec, true, 0),
331 m_bound(m_data)
332 {
333 m_type = -1;
334 m_strict = -1;
335 }
336
337 inline
Range(Bound & bound1,Bound & bound2)338 NdbIndexStatImpl::Range::Range(Bound& bound1, Bound& bound2) :
339 m_bound1(bound1),
340 m_bound2(bound2)
341 {
342 bound1.m_type = 0;
343 bound2.m_type = 1;
344 }
345
346 inline int
finalize_range(Range & range)347 NdbIndexStatImpl::finalize_range(Range& range)
348 {
349 if (finalize_bound(range.m_bound1) == -1)
350 return -1;
351 if (finalize_bound(range.m_bound2) == -1)
352 return -1;
353 return 0;
354 }
355
356 inline
StatValue()357 NdbIndexStatImpl::StatValue::StatValue()
358 {
359 m_empty = false;
360 }
361
362 inline
StatBound()363 NdbIndexStatImpl::StatBound::StatBound()
364 {
365 m_pos = 0;
366 m_numEqL = 0;
367 m_numEqH = 0;
368 }
369
370 inline
Stat()371 NdbIndexStatImpl::Stat::Stat()
372 {
373 m_rule[0] = 0;
374 m_rule[1] = 0;
375 m_rule[2] = 0;
376 }
377
378 #endif
379