MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NdbImpl.hpp
1 /*
2  Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
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 as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #ifndef NDB_IMPL_HPP
19 #define NDB_IMPL_HPP
20 
21 #include <ndb_global.h>
22 #include "API.hpp"
23 #include <NdbOut.hpp>
24 #include <kernel/ndb_limits.h>
25 #include <NdbTick.h>
26 
27 #include "NdbQueryOperationImpl.hpp"
28 #include "ndb_cluster_connection_impl.hpp"
29 #include "NdbDictionaryImpl.hpp"
30 #include "ObjectMap.hpp"
31 #include "trp_client.hpp"
32 #include "trp_node.hpp"
33 #include "NdbWaiter.hpp"
34 
35 template <class T>
37 {
39  ~Ndb_free_list_t();
40 
41  int fill(Ndb*, Uint32 cnt);
42  T* seize(Ndb*);
43  void release(T*);
44  void release(Uint32 cnt, T* head, T* tail);
45  void clear();
46  Uint32 get_sizeof() const { return sizeof(T); }
47  T * m_free_list;
48  Uint32 m_alloc_cnt, m_free_cnt;
49 };
50 
54 class NdbImpl : public trp_client
55 {
56 public:
58  ~NdbImpl();
59 
60  int send_event_report(bool has_lock, Uint32 *data, Uint32 length);
61 
62  Ndb &m_ndb;
63  Ndb * m_next_ndb_object, * m_prev_ndb_object;
64 
65  Ndb_cluster_connection_impl &m_ndb_cluster_connection;
66  TransporterFacade * const m_transporter_facade;
67 
68  NdbDictionaryImpl m_dictionary;
69 
70  // Ensure good distribution of connects
71  Uint32 theCurrentConnectIndex;
73 
74  NdbObjectIdMap theNdbObjectIdMap;
75 
76  Uint32 theNoOfDBnodes; // The number of DB nodes
77  Uint8 theDBnodes[MAX_NDB_NODES]; // The node number of the DB nodes
78 
79  // 1 indicates to release all connections to node
80  Uint32 the_release_ind[MAX_NDB_NODES];
81 
82  NdbWaiter theWaiter;
83 
84  NdbEventOperationImpl *m_ev_op;
85 
86  int m_optimized_node_selection;
87 
88  BaseString m_dbname; // Database name
89  BaseString m_schemaname; // Schema name
90 
91  BaseString m_prefix; // Buffer for preformatted internal name <db>/<schema>/
92 
93  int update_prefix()
94  {
95  if (!m_prefix.assfmt("%s%c%s%c", m_dbname.c_str(), table_name_separator,
96  m_schemaname.c_str(), table_name_separator))
97  {
98  return -1;
99  }
100  return 0;
101  }
102 
103 /*
104  We need this friend accessor function to work around a HP compiler problem,
105  where template class friends are not working.
106 */
107  static inline void setNdbError(Ndb &ndb,int code){
108  ndb.theError.code = code;
109  return;
110  }
111 
112  bool forceShortRequests;
113 
114  static inline void setForceShortRequests(Ndb* ndb, bool val)
115  {
116  ndb->theImpl->forceShortRequests = val;
117  }
118 
119  Uint32 get_waitfor_timeout() const {
120  return m_ndb_cluster_connection.m_config.m_waitfor_timeout;
121  }
122  const NdbApiConfig& get_ndbapi_config_parameters() const {
123  return m_ndb_cluster_connection.m_config;
124  }
125 
126  BaseString m_systemPrefix; // Buffer for preformatted for <sys>/<def>/
127 
128  void* customDataPtr;
129 
130  Uint64 clientStats[ Ndb::NumClientStatistics ];
131 
132  inline void incClientStat(const Ndb::ClientStatistics stat, const Uint64 inc) {
133  assert(stat < Ndb::NumClientStatistics);
134  if (likely(stat < Ndb::NumClientStatistics))
135  clientStats[ stat ] += inc;
136  };
137 
138  inline void decClientStat(const Ndb::ClientStatistics stat, const Uint64 dec) {
139  assert(stat < Ndb::NumClientStatistics);
140  if (likely(stat < Ndb::NumClientStatistics))
141  clientStats[ stat ] -= dec;
142  };
143 
144  inline void setClientStat(const Ndb::ClientStatistics stat, const Uint64 val) {
145  assert(stat < Ndb::NumClientStatistics);
146  if (likely(stat < Ndb::NumClientStatistics))
147  clientStats[ stat ] = val;
148  };
149 
150  /* We don't record the sent/received bytes of some GSNs as they are
151  * generated constantly and are not targetted to specific
152  * Ndb instances.
153  * See also TransporterFacade::TRACE_GSN
154  */
155  static bool recordGSN(Uint32 gsn)
156  {
157  switch(gsn)
158  {
159  case GSN_API_REGREQ:
160  case GSN_API_REGCONF:
161  case GSN_SUB_GCP_COMPLETE_REP:
162  case GSN_SUB_GCP_COMPLETE_ACK:
163  return false;
164  default:
165  return true;
166  }
167  }
168 
176  Ndb_free_list_t<NdbApiSignal> theSignalIdleList;
177  Ndb_free_list_t<NdbLabel> theLabelList;
178  Ndb_free_list_t<NdbBranch> theBranchList;
179  Ndb_free_list_t<NdbSubroutine> theSubroutineList;
180  Ndb_free_list_t<NdbCall> theCallList;
181  Ndb_free_list_t<NdbBlob> theNdbBlobIdleList;
182  Ndb_free_list_t<NdbReceiver> theScanList;
183  Ndb_free_list_t<NdbLockHandle> theLockHandleList;
184  Ndb_free_list_t<NdbIndexScanOperation> theScanOpIdleList;
185  Ndb_free_list_t<NdbOperation> theOpIdleList;
186  Ndb_free_list_t<NdbIndexOperation> theIndexOpIdleList;
187  Ndb_free_list_t<NdbTransaction> theConIdleList;
188 
192  virtual void trp_deliver_signal(const NdbApiSignal*,
193  const LinearSectionPtr p[3]);
194  virtual void recordWaitTimeNanos(Uint64 nanos);
195  // Is node available for running transactions
196  bool get_node_alive(NodeId nodeId) const;
197  bool get_node_stopping(NodeId nodeId) const;
198  bool getIsDbNode(NodeId nodeId) const;
199  bool getIsNodeSendable(NodeId nodeId) const;
200  Uint32 getNodeGrp(NodeId nodeId) const;
201  Uint32 getNodeSequence(NodeId nodeId) const;
202  Uint32 getNodeNdbVersion(NodeId nodeId) const;
203  Uint32 getMinDbNodeVersion() const;
204  bool check_send_size(Uint32 node_id, Uint32 send_size) const { return true;}
205 
206  int sendSignal(NdbApiSignal*, Uint32 nodeId);
207  int sendSignal(NdbApiSignal*, Uint32 nodeId,
208  const LinearSectionPtr ptr[3], Uint32 secs);
209  int sendSignal(NdbApiSignal*, Uint32 nodeId,
210  const GenericSectionPtr ptr[3], Uint32 secs);
211  int sendFragmentedSignal(NdbApiSignal*, Uint32 nodeId,
212  const LinearSectionPtr ptr[3], Uint32 secs);
213  int sendFragmentedSignal(NdbApiSignal*, Uint32 nodeId,
214  const GenericSectionPtr ptr[3], Uint32 secs);
215 };
216 
217 #ifdef VM_TRACE
218 #define TRACE_DEBUG(x) ndbout << x << endl;
219 #else
220 #define TRACE_DEBUG(x)
221 #endif
222 
223 #define CHECK_STATUS_MACRO \
224  {if (checkInitState() == -1) { theError.code = 4100; DBUG_RETURN(-1);}}
225 #define CHECK_STATUS_MACRO_VOID \
226  {if (checkInitState() == -1) { theError.code = 4100; DBUG_VOID_RETURN;}}
227 #define CHECK_STATUS_MACRO_ZERO \
228  {if (checkInitState() == -1) { theError.code = 4100; DBUG_RETURN(0);}}
229 #define CHECK_STATUS_MACRO_NULL \
230  {if (checkInitState() == -1) { theError.code = 4100; DBUG_RETURN(NULL);}}
231 
232 inline
233 void *
234 Ndb::int2void(Uint32 val){
235  return theImpl->theNdbObjectIdMap.getObject(val);
236 }
237 
238 inline
239 NdbReceiver *
240 Ndb::void2rec(void* val){
241  return (NdbReceiver*)val;
242 }
243 
244 inline
246 Ndb::void2con(void* val){
247  return (NdbTransaction*)val;
248 }
249 
250 inline
252 Ndb::void2rec_op(void* val){
253  return (NdbOperation*)(void2rec(val)->getOwner());
254 }
255 
256 inline
258 Ndb::void2rec_iop(void* val){
259  return (NdbIndexOperation*)(void2rec(val)->getOwner());
260 }
261 
262 inline
264 NdbReceiver::getTransaction() const {
265  switch(getType()){
266  case NDB_UNINITIALIZED:
267  assert(false);
268  return NULL;
269  case NDB_QUERY_OPERATION:
270  return &((NdbQueryOperationImpl*)m_owner)->getQuery().getNdbTransaction();
271  default:
272  return ((NdbOperation*)m_owner)->theNdbCon;
273  }
274 }
275 
276 
277 inline
278 int
279 Ndb::checkInitState()
280 {
281  theError.code = 0;
282 
283  if (theInitState != Initialised)
284  return -1;
285  return 0;
286 }
287 
288 Uint32 convertEndian(Uint32 Data);
289 
290 enum LockMode {
291  Read,
292  Update,
293  Insert,
294  Delete
295 };
296 
297 template<class T>
298 inline
300 {
301  m_free_list= 0;
302  m_alloc_cnt= m_free_cnt= 0;
303 }
304 
305 template<class T>
306 inline
308 {
309  clear();
310 }
311 
312 template<class T>
313 inline
314 int
315 Ndb_free_list_t<T>::fill(Ndb* ndb, Uint32 cnt)
316 {
317 #ifndef HAVE_purify
318  if (m_free_list == 0)
319  {
320  m_free_cnt++;
321  m_alloc_cnt++;
322  m_free_list = new T(ndb);
323  if (m_free_list == 0)
324  {
325  NdbImpl::setNdbError(*ndb, 4000);
326  assert(false);
327  return -1;
328  }
329  }
330  while(m_alloc_cnt < cnt)
331  {
332  T* obj= new T(ndb);
333  if(obj == 0)
334  {
335  NdbImpl::setNdbError(*ndb, 4000);
336  assert(false);
337  return -1;
338  }
339  obj->next(m_free_list);
340  m_free_cnt++;
341  m_alloc_cnt++;
342  m_free_list = obj;
343  }
344  return 0;
345 #else
346  return 0;
347 #endif
348 }
349 
350 template<class T>
351 inline
352 T*
354 {
355 #ifndef HAVE_purify
356  T* tmp = m_free_list;
357  if (tmp)
358  {
359  m_free_list = (T*)tmp->next();
360  tmp->next(NULL);
361  m_free_cnt--;
362  return tmp;
363  }
364 
365  if((tmp = new T(ndb)))
366  {
367  m_alloc_cnt++;
368  }
369  else
370  {
371  NdbImpl::setNdbError(*ndb, 4000);
372  assert(false);
373  }
374  return tmp;
375 #else
376  return new T(ndb);
377 #endif
378 }
379 
380 template<class T>
381 inline
382 void
384 {
385 #ifndef HAVE_purify
386  obj->next(m_free_list);
387  m_free_list = obj;
388  m_free_cnt++;
389 #else
390  delete obj;
391 #endif
392 }
393 
394 
395 template<class T>
396 inline
397 void
399 {
400  T* obj = m_free_list;
401  while(obj)
402  {
403  T* curr = obj;
404  obj = (T*)obj->next();
405  delete curr;
406  m_alloc_cnt--;
407  }
408 }
409 
410 template<class T>
411 inline
412 void
413 Ndb_free_list_t<T>::release(Uint32 cnt, T* head, T* tail)
414 {
415 #ifndef HAVE_purify
416  if (cnt)
417  {
418 #ifdef VM_TRACE
419  {
420  T* tmp = head;
421  while (tmp != 0 && tmp != tail) tmp = (T*)tmp->next();
422  assert(tmp == tail);
423  }
424 #endif
425  tail->next(m_free_list);
426  m_free_list = head;
427  m_free_cnt += cnt;
428  }
429 #else
430  if (cnt)
431  {
432  T* tmp = head;
433  while (tmp != 0 && tmp != tail)
434  {
435  T * next = (T*)tmp->next();
436  delete tmp;
437  tmp = next;
438  }
439  delete tail;
440  }
441 #endif
442 }
443 
444 inline
445 bool
446 NdbImpl::getIsDbNode(NodeId n) const {
447  return
448  getNodeInfo(n).defined &&
449  getNodeInfo(n).m_info.m_type == NodeInfo::DB;
450 }
451 
452 inline
453 Uint32
454 NdbImpl::getNodeGrp(NodeId n) const {
455  return getNodeInfo(n).m_state.nodeGroup;
456 }
457 
458 
459 inline
460 bool
461 NdbImpl::get_node_alive(NodeId n) const {
462  return getNodeInfo(n).m_alive;
463 }
464 
465 inline
466 bool
467 NdbImpl::get_node_stopping(NodeId n) const {
468  const trp_node & node = getNodeInfo(n);
469  assert(node.m_info.getType() == NodeInfo::DB);
470  return (!node.m_state.getSingleUserMode() &&
471  node.m_state.startLevel >= NodeState::SL_STOPPING_1);
472 }
473 
474 inline
475 bool
476 NdbImpl::getIsNodeSendable(NodeId n) const {
477  const trp_node & node = getNodeInfo(n);
478  const Uint32 startLevel = node.m_state.startLevel;
479  const NodeInfo::NodeType node_type = node.m_info.getType();
480  assert(node_type == NodeInfo::DB ||
481  node_type == NodeInfo::MGM);
482 
483  return node.compatible && (startLevel == NodeState::SL_STARTED ||
484  startLevel == NodeState::SL_STOPPING_1 ||
485  node.m_state.getSingleUserMode() ||
486  node_type == NodeInfo::MGM);
487 }
488 
489 inline
490 Uint32
491 NdbImpl::getNodeSequence(NodeId n) const {
492  return getNodeInfo(n).m_info.m_connectCount;
493 }
494 
495 inline
496 Uint32
497 NdbImpl::getNodeNdbVersion(NodeId n) const
498 {
499  return getNodeInfo(n).m_info.m_version;
500 }
501 
502 inline
503 void
504 NdbImpl::recordWaitTimeNanos(Uint64 nanos)
505 {
506  incClientStat( Ndb::WaitNanosCount, nanos );
507 }
508 
509 inline
510 int
511 NdbImpl::sendSignal(NdbApiSignal * signal, Uint32 nodeId)
512 {
513  if (getIsNodeSendable(nodeId))
514  {
515  if (likely(recordGSN(signal->theVerId_signalNumber)))
516  {
517  incClientStat(Ndb::BytesSentCount, signal->getLength() << 2);
518  }
519  return raw_sendSignal(signal, nodeId);
520  }
521  return -1;
522 }
523 
524 inline
525 int
526 NdbImpl::sendSignal(NdbApiSignal * signal, Uint32 nodeId,
527  const LinearSectionPtr ptr[3], Uint32 secs)
528 {
529  if (getIsNodeSendable(nodeId))
530  {
531  if (likely(recordGSN(signal->theVerId_signalNumber)))
532  {
533  incClientStat(Ndb::BytesSentCount,
534  ((signal->getLength() << 2) +
535  ((secs > 2)? ptr[2].sz << 2: 0) +
536  ((secs > 1)? ptr[1].sz << 2: 0) +
537  ((secs > 0)? ptr[0].sz << 2: 0)));
538  }
539  return raw_sendSignal(signal, nodeId, ptr, secs);
540  }
541  return -1;
542 }
543 
544 inline
545 int
546 NdbImpl::sendSignal(NdbApiSignal * signal, Uint32 nodeId,
547  const GenericSectionPtr ptr[3], Uint32 secs)
548 {
549  if (getIsNodeSendable(nodeId))
550  {
551  if (likely(recordGSN(signal->theVerId_signalNumber)))
552  {
553  incClientStat(Ndb::BytesSentCount,
554  ((signal->getLength() << 2) +
555  ((secs > 2)? ptr[2].sz << 2 : 0) +
556  ((secs > 1)? ptr[1].sz << 2: 0) +
557  ((secs > 0)? ptr[0].sz << 2: 0)));
558  }
559  return raw_sendSignal(signal, nodeId, ptr, secs);
560  }
561  return -1;
562 }
563 
564 inline
565 int
566 NdbImpl::sendFragmentedSignal(NdbApiSignal * signal, Uint32 nodeId,
567  const LinearSectionPtr ptr[3], Uint32 secs)
568 {
569  if (getIsNodeSendable(nodeId))
570  {
571  if (likely(recordGSN(signal->theVerId_signalNumber)))
572  {
573  incClientStat(Ndb::BytesSentCount,
574  ((signal->getLength() << 2) +
575  ((secs > 2)? ptr[2].sz << 2 : 0) +
576  ((secs > 1)? ptr[1].sz << 2: 0) +
577  ((secs > 0)? ptr[0].sz << 2: 0)));
578  }
579  return raw_sendFragmentedSignal(signal, nodeId, ptr, secs);
580  }
581  return -1;
582 }
583 
584 inline
585 int
586 NdbImpl::sendFragmentedSignal(NdbApiSignal * signal, Uint32 nodeId,
587  const GenericSectionPtr ptr[3], Uint32 secs)
588 {
589  if (getIsNodeSendable(nodeId))
590  {
591  if (likely(recordGSN(signal->theVerId_signalNumber)))
592  {
593  incClientStat(Ndb::BytesSentCount,
594  ((signal->getLength() << 2) +
595  ((secs > 2)? ptr[2].sz << 2 : 0) +
596  ((secs > 1)? ptr[1].sz << 2 : 0) +
597  ((secs > 0)? ptr[0].sz << 2 : 0)));
598  }
599  return raw_sendFragmentedSignal(signal, nodeId, ptr, secs);
600  }
601  return -1;
602 }
603 
604 #endif