~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2003 MySQL AB
 
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 as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
#include "Cmvmi.hpp"
 
17
 
 
18
#include <Configuration.hpp>
 
19
#include <kernel_types.h>
 
20
#include <TransporterRegistry.hpp>
 
21
#include <NdbOut.hpp>
 
22
#include <NdbMem.h>
 
23
 
 
24
#include <SignalLoggerManager.hpp>
 
25
#include <FastScheduler.hpp>
 
26
 
 
27
#define DEBUG(x) { ndbout << "CMVMI::" << x << endl; }
 
28
 
 
29
#include <signaldata/TestOrd.hpp>
 
30
#include <signaldata/EventReport.hpp>
 
31
#include <signaldata/TamperOrd.hpp>
 
32
#include <signaldata/StartOrd.hpp>
 
33
#include <signaldata/CloseComReqConf.hpp>
 
34
#include <signaldata/SetLogLevelOrd.hpp>
 
35
#include <signaldata/EventSubscribeReq.hpp>
 
36
#include <signaldata/DumpStateOrd.hpp>
 
37
#include <signaldata/DisconnectRep.hpp>
 
38
 
 
39
#include <EventLogger.hpp>
 
40
#include <TimeQueue.hpp>
 
41
 
 
42
#include <NdbSleep.h>
 
43
#include <SafeCounter.hpp>
 
44
 
 
45
// Used here only to print event reports on stdout/console.
 
46
EventLogger g_eventLogger;
 
47
extern int simulate_error_during_shutdown;
 
48
 
 
49
Cmvmi::Cmvmi(Block_context& ctx) :
 
50
  SimulatedBlock(CMVMI, ctx)
 
51
  ,subscribers(subscriberPool)
 
52
{
 
53
  BLOCK_CONSTRUCTOR(Cmvmi);
 
54
 
 
55
  Uint32 long_sig_buffer_size;
 
56
  const ndb_mgm_configuration_iterator * p = 
 
57
    m_ctx.m_config.getOwnConfigIterator();
 
58
  ndbrequire(p != 0);
 
59
 
 
60
  ndb_mgm_get_int_parameter(p, CFG_DB_LONG_SIGNAL_BUFFER,  
 
61
                            &long_sig_buffer_size);
 
62
 
 
63
  long_sig_buffer_size= long_sig_buffer_size / 256;
 
64
  g_sectionSegmentPool.setSize(long_sig_buffer_size,
 
65
                               false,true,true,CFG_DB_LONG_SIGNAL_BUFFER);
 
66
 
 
67
  // Add received signals
 
68
  addRecSignal(GSN_CONNECT_REP, &Cmvmi::execCONNECT_REP);
 
69
  addRecSignal(GSN_DISCONNECT_REP, &Cmvmi::execDISCONNECT_REP);
 
70
 
 
71
  addRecSignal(GSN_NDB_TAMPER,  &Cmvmi::execNDB_TAMPER, true);
 
72
  addRecSignal(GSN_SET_LOGLEVELORD,  &Cmvmi::execSET_LOGLEVELORD);
 
73
  addRecSignal(GSN_EVENT_REP,  &Cmvmi::execEVENT_REP);
 
74
  addRecSignal(GSN_STTOR,  &Cmvmi::execSTTOR);
 
75
  addRecSignal(GSN_READ_CONFIG_REQ,  &Cmvmi::execREAD_CONFIG_REQ);
 
76
  addRecSignal(GSN_CLOSE_COMREQ,  &Cmvmi::execCLOSE_COMREQ);
 
77
  addRecSignal(GSN_ENABLE_COMORD,  &Cmvmi::execENABLE_COMORD);
 
78
  addRecSignal(GSN_OPEN_COMREQ,  &Cmvmi::execOPEN_COMREQ);
 
79
  addRecSignal(GSN_TEST_ORD,  &Cmvmi::execTEST_ORD);
 
80
 
 
81
  addRecSignal(GSN_TAMPER_ORD,  &Cmvmi::execTAMPER_ORD);
 
82
  addRecSignal(GSN_STOP_ORD,  &Cmvmi::execSTOP_ORD);
 
83
  addRecSignal(GSN_START_ORD,  &Cmvmi::execSTART_ORD);
 
84
  addRecSignal(GSN_EVENT_SUBSCRIBE_REQ, 
 
85
               &Cmvmi::execEVENT_SUBSCRIBE_REQ);
 
86
 
 
87
  addRecSignal(GSN_DUMP_STATE_ORD, &Cmvmi::execDUMP_STATE_ORD);
 
88
 
 
89
  addRecSignal(GSN_TESTSIG, &Cmvmi::execTESTSIG);
 
90
  addRecSignal(GSN_NODE_START_REP, &Cmvmi::execNODE_START_REP, true);
 
91
  
 
92
  subscriberPool.setSize(5);
 
93
  
 
94
  const ndb_mgm_configuration_iterator * db = m_ctx.m_config.getOwnConfigIterator();
 
95
  for(unsigned j = 0; j<LogLevel::LOGLEVEL_CATEGORIES; j++){
 
96
    Uint32 logLevel;
 
97
    if(!ndb_mgm_get_int_parameter(db, CFG_MIN_LOGLEVEL+j, &logLevel)){
 
98
      clogLevel.setLogLevel((LogLevel::EventCategory)j, 
 
99
                            logLevel);
 
100
    }
 
101
  }
 
102
  
 
103
  ndb_mgm_configuration_iterator * iter = m_ctx.m_config.getClusterConfigIterator();
 
104
  for(ndb_mgm_first(iter); ndb_mgm_valid(iter); ndb_mgm_next(iter)){
 
105
    jam();
 
106
    Uint32 nodeId;
 
107
    Uint32 nodeType;
 
108
 
 
109
    ndbrequire(!ndb_mgm_get_int_parameter(iter,CFG_NODE_ID, &nodeId));
 
110
    ndbrequire(!ndb_mgm_get_int_parameter(iter,CFG_TYPE_OF_SECTION,&nodeType));
 
111
 
 
112
    switch(nodeType){
 
113
    case NodeInfo::DB:
 
114
      c_dbNodes.set(nodeId);
 
115
      break;
 
116
    case NodeInfo::API:
 
117
    case NodeInfo::MGM:
 
118
      break;
 
119
    default:
 
120
      ndbrequire(false);
 
121
    }
 
122
    setNodeInfo(nodeId).m_type = nodeType;
 
123
  }
 
124
 
 
125
  setNodeInfo(getOwnNodeId()).m_connected = true;
 
126
  setNodeInfo(getOwnNodeId()).m_version = ndbGetOwnVersion();
 
127
}
 
128
 
 
129
Cmvmi::~Cmvmi()
 
130
{
 
131
  m_shared_page_pool.clear();
 
132
}
 
133
 
 
134
#ifdef ERROR_INSERT
 
135
NodeBitmask c_error_9000_nodes_mask;
 
136
extern Uint32 MAX_RECEIVED_SIGNALS;
 
137
#endif
 
138
 
 
139
void Cmvmi::execNDB_TAMPER(Signal* signal) 
 
140
{
 
141
  jamEntry();
 
142
  SET_ERROR_INSERT_VALUE(signal->theData[0]);
 
143
  if(ERROR_INSERTED(9999)){
 
144
    CRASH_INSERTION(9999);
 
145
  }
 
146
 
 
147
  if(ERROR_INSERTED(9998)){
 
148
    while(true) NdbSleep_SecSleep(1);
 
149
  }
 
150
 
 
151
  if(ERROR_INSERTED(9997)){
 
152
    ndbrequire(false);
 
153
  }
 
154
 
 
155
#ifndef NDB_WIN32
 
156
  if(ERROR_INSERTED(9996)){
 
157
    simulate_error_during_shutdown= SIGSEGV;
 
158
    ndbrequire(false);
 
159
  }
 
160
 
 
161
  if(ERROR_INSERTED(9995)){
 
162
    simulate_error_during_shutdown= SIGSEGV;
 
163
    kill(getpid(), SIGABRT);
 
164
  }
 
165
#endif
 
166
 
 
167
#ifdef ERROR_INSERT
 
168
  if (signal->theData[0] == 9003)
 
169
  {
 
170
    if (MAX_RECEIVED_SIGNALS < 1024)
 
171
    {
 
172
      MAX_RECEIVED_SIGNALS = 1024;
 
173
    }
 
174
    else
 
175
    {
 
176
      MAX_RECEIVED_SIGNALS = 1 + (rand() % 128);
 
177
    }
 
178
    ndbout_c("MAX_RECEIVED_SIGNALS: %d", MAX_RECEIVED_SIGNALS);
 
179
    CLEAR_ERROR_INSERT_VALUE;
 
180
  }
 
181
#endif
 
182
}//execNDB_TAMPER()
 
183
 
 
184
void Cmvmi::execSET_LOGLEVELORD(Signal* signal) 
 
185
{
 
186
  SetLogLevelOrd * const llOrd = (SetLogLevelOrd *)&signal->theData[0];
 
187
  LogLevel::EventCategory category;
 
188
  Uint32 level;
 
189
  jamEntry();
 
190
 
 
191
  for(unsigned int i = 0; i<llOrd->noOfEntries; i++){
 
192
    category = (LogLevel::EventCategory)(llOrd->theData[i] >> 16);
 
193
    level = llOrd->theData[i] & 0xFFFF;
 
194
    
 
195
    clogLevel.setLogLevel(category, level);
 
196
  }
 
197
}//execSET_LOGLEVELORD()
 
198
 
 
199
void Cmvmi::execEVENT_REP(Signal* signal) 
 
200
{
 
201
  //-----------------------------------------------------------------------
 
202
  // This message is sent to report any types of events in NDB.
 
203
  // Based on the log level they will be either ignored or
 
204
  // reported. Currently they are printed, but they will be
 
205
  // transferred to the management server for further distribution
 
206
  // to the graphical management interface.
 
207
  //-----------------------------------------------------------------------
 
208
  EventReport * const eventReport = (EventReport *)&signal->theData[0]; 
 
209
  Ndb_logevent_type eventType = eventReport->getEventType();
 
210
  Uint32 nodeId= eventReport->getNodeId();
 
211
  if (nodeId == 0)
 
212
  {
 
213
    nodeId= refToNode(signal->getSendersBlockRef());
 
214
    eventReport->setNodeId(nodeId);
 
215
  }
 
216
 
 
217
  jamEntry();
 
218
  
 
219
  /**
 
220
   * If entry is not found
 
221
   */
 
222
  Uint32 threshold;
 
223
  LogLevel::EventCategory eventCategory;
 
224
  Logger::LoggerLevel severity;  
 
225
  EventLoggerBase::EventTextFunction textF;
 
226
  if (EventLoggerBase::event_lookup(eventType,eventCategory,threshold,severity,textF))
 
227
    return;
 
228
  
 
229
  SubscriberPtr ptr;
 
230
  for(subscribers.first(ptr); ptr.i != RNIL; subscribers.next(ptr)){
 
231
    if(ptr.p->logLevel.getLogLevel(eventCategory) < threshold){
 
232
      continue;
 
233
    }
 
234
    
 
235
    sendSignal(ptr.p->blockRef, GSN_EVENT_REP, signal, signal->length(), JBB);
 
236
  }
 
237
  
 
238
  if(clogLevel.getLogLevel(eventCategory) < threshold){
 
239
    return;
 
240
  }
 
241
 
 
242
  // Print the event info
 
243
  g_eventLogger.log(eventReport->getEventType(), signal->theData);
 
244
 
 
245
  return;
 
246
}//execEVENT_REP()
 
247
 
 
248
void
 
249
Cmvmi::execEVENT_SUBSCRIBE_REQ(Signal * signal){
 
250
  EventSubscribeReq * subReq = (EventSubscribeReq *)&signal->theData[0];
 
251
  Uint32 senderRef = signal->getSendersBlockRef();
 
252
  SubscriberPtr ptr;
 
253
  jamEntry();
 
254
  DBUG_ENTER("Cmvmi::execEVENT_SUBSCRIBE_REQ");
 
255
 
 
256
  /**
 
257
   * Search for subcription
 
258
   */
 
259
  for(subscribers.first(ptr); ptr.i != RNIL; subscribers.next(ptr)){
 
260
    if(ptr.p->blockRef == subReq->blockRef)
 
261
      break;
 
262
  }
 
263
  
 
264
  if(ptr.i == RNIL){
 
265
    /**
 
266
     * Create a new one
 
267
     */
 
268
    if(subscribers.seize(ptr) == false){
 
269
      sendSignal(senderRef, GSN_EVENT_SUBSCRIBE_REF, signal, 1, JBB);
 
270
      return;
 
271
    }
 
272
    ptr.p->logLevel.clear();
 
273
    ptr.p->blockRef = subReq->blockRef;    
 
274
  }
 
275
  
 
276
  if(subReq->noOfEntries == 0){
 
277
    /**
 
278
     * Cancel subscription
 
279
     */
 
280
    subscribers.release(ptr.i);
 
281
  } else {
 
282
    /**
 
283
     * Update subscription
 
284
     */
 
285
    LogLevel::EventCategory category;
 
286
    Uint32 level = 0;
 
287
    for(Uint32 i = 0; i<subReq->noOfEntries; i++){
 
288
      category = (LogLevel::EventCategory)(subReq->theData[i] >> 16);
 
289
      level = subReq->theData[i] & 0xFFFF;
 
290
      ptr.p->logLevel.setLogLevel(category, level);
 
291
      DBUG_PRINT("info",("entry %d: level=%d, category= %d", i, level, category));
 
292
    }
 
293
  }
 
294
  
 
295
  signal->theData[0] = ptr.i;
 
296
  sendSignal(senderRef, GSN_EVENT_SUBSCRIBE_CONF, signal, 1, JBB);
 
297
  DBUG_VOID_RETURN;
 
298
}
 
299
 
 
300
void
 
301
Cmvmi::cancelSubscription(NodeId nodeId){
 
302
  
 
303
  SubscriberPtr ptr;
 
304
  subscribers.first(ptr);
 
305
  
 
306
  while(ptr.i != RNIL){
 
307
    Uint32 i = ptr.i;
 
308
    BlockReference blockRef = ptr.p->blockRef;
 
309
    
 
310
    subscribers.next(ptr);
 
311
    
 
312
    if(refToNode(blockRef) == nodeId){
 
313
      subscribers.release(i);
 
314
    }
 
315
  }
 
316
}
 
317
 
 
318
void Cmvmi::sendSTTORRY(Signal* signal)
 
319
{
 
320
  jam();
 
321
  signal->theData[3] = 1;
 
322
  signal->theData[4] = 3;
 
323
  signal->theData[5] = 8;
 
324
  signal->theData[6] = 255;
 
325
  sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 7, JBB);
 
326
}//Cmvmi::sendSTTORRY
 
327
 
 
328
 
 
329
void 
 
330
Cmvmi::execREAD_CONFIG_REQ(Signal* signal)
 
331
{
 
332
  jamEntry();
 
333
 
 
334
  const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
 
335
 
 
336
  Uint32 ref = req->senderRef;
 
337
  Uint32 senderData = req->senderData;
 
338
 
 
339
  const ndb_mgm_configuration_iterator * p = 
 
340
    m_ctx.m_config.getOwnConfigIterator();
 
341
  ndbrequire(p != 0);
 
342
 
 
343
  Uint64 page_buffer = 64*1024*1024;
 
344
  ndb_mgm_get_int64_parameter(p, CFG_DB_DISK_PAGE_BUFFER_MEMORY, &page_buffer);
 
345
  
 
346
  Uint32 pages = 0;
 
347
  pages += page_buffer / GLOBAL_PAGE_SIZE; // in pages
 
348
  pages += LCP_RESTORE_BUFFER;
 
349
  m_global_page_pool.setSize(pages + 64, true);
 
350
  
 
351
  Uint64 shared_mem = 8*1024*1024;
 
352
  ndb_mgm_get_int64_parameter(p, CFG_DB_SGA, &shared_mem);
 
353
  shared_mem /= GLOBAL_PAGE_SIZE;
 
354
  if (shared_mem)
 
355
  {
 
356
    Resource_limit rl;
 
357
    rl.m_min = 0;
 
358
    rl.m_max = shared_mem;
 
359
    rl.m_resource_id = 0;
 
360
    m_ctx.m_mm.set_resource_limit(rl);
 
361
  }
 
362
  
 
363
  ndbrequire(m_ctx.m_mm.init());
 
364
  {
 
365
    void* ptr = m_ctx.m_mm.get_memroot();
 
366
    m_shared_page_pool.set((GlobalPage*)ptr, ~0);
 
367
  }
 
368
  
 
369
  ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
 
370
  conf->senderRef = reference();
 
371
  conf->senderData = senderData;
 
372
  sendSignal(ref, GSN_READ_CONFIG_CONF, signal, 
 
373
             ReadConfigConf::SignalLength, JBB);
 
374
}
 
375
 
 
376
void Cmvmi::execSTTOR(Signal* signal)
 
377
{
 
378
  Uint32 theStartPhase  = signal->theData[1];
 
379
 
 
380
  jamEntry();
 
381
  if (theStartPhase == 1){
 
382
    jam();
 
383
 
 
384
    if(m_ctx.m_config.lockPagesInMainMemory() == 1)
 
385
    {
 
386
      int res = NdbMem_MemLockAll(0);
 
387
      if(res != 0){
 
388
        g_eventLogger.warning("Failed to memlock pages");
 
389
        warningEvent("Failed to memlock pages");
 
390
      }
 
391
    }
 
392
    
 
393
    sendSTTORRY(signal);
 
394
    return;
 
395
  } else if (theStartPhase == 3) {
 
396
    jam();
 
397
    globalData.activateSendPacked = 1;
 
398
    sendSTTORRY(signal);
 
399
  } else if (theStartPhase == 8){
 
400
    /*---------------------------------------------------*/
 
401
    /* Open com to API + REP nodes                       */
 
402
    /*---------------------------------------------------*/
 
403
    signal->theData[0] = 0; // no answer
 
404
    signal->theData[1] = 0; // no id
 
405
    signal->theData[2] = NodeInfo::API;
 
406
    execOPEN_COMREQ(signal);
 
407
    globalData.theStartLevel = NodeState::SL_STARTED;
 
408
    sendSTTORRY(signal);
 
409
  }
 
410
}
 
411
 
 
412
void Cmvmi::execCLOSE_COMREQ(Signal* signal)
 
413
{
 
414
  // Close communication with the node and halt input/output from 
 
415
  // other blocks than QMGR
 
416
  
 
417
  CloseComReqConf * const closeCom = (CloseComReqConf *)&signal->theData[0];
 
418
 
 
419
  const BlockReference userRef = closeCom->xxxBlockRef;
 
420
  Uint32 failNo = closeCom->failNo;
 
421
//  Uint32 noOfNodes = closeCom->noOfNodes;
 
422
  
 
423
  jamEntry();
 
424
  for (unsigned i = 0; i < MAX_NODES; i++)
 
425
  {
 
426
    if(NodeBitmask::get(closeCom->theNodes, i))
 
427
    {
 
428
      jam();
 
429
 
 
430
      //-----------------------------------------------------
 
431
      // Report that the connection to the node is closed
 
432
      //-----------------------------------------------------
 
433
      signal->theData[0] = NDB_LE_CommunicationClosed;
 
434
      signal->theData[1] = i;
 
435
      sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
 
436
      
 
437
      globalTransporterRegistry.setIOState(i, HaltIO);
 
438
      globalTransporterRegistry.do_disconnect(i);
 
439
    }
 
440
  }
 
441
 
 
442
  if (failNo != 0) 
 
443
  {
 
444
    jam();
 
445
    signal->theData[0] = userRef;
 
446
    signal->theData[1] = failNo;
 
447
    sendSignal(QMGR_REF, GSN_CLOSE_COMCONF, signal, 19, JBA);
 
448
  }
 
449
}
 
450
 
 
451
void Cmvmi::execOPEN_COMREQ(Signal* signal)
 
452
{
 
453
  // Connect to the specifed NDB node, only QMGR allowed communication 
 
454
  // so far with the node
 
455
 
 
456
  const BlockReference userRef = signal->theData[0];
 
457
  Uint32 tStartingNode = signal->theData[1];
 
458
  Uint32 tData2 = signal->theData[2];
 
459
  jamEntry();
 
460
 
 
461
  const Uint32 len = signal->getLength();
 
462
  if(len == 2)
 
463
  {
 
464
#ifdef ERROR_INSERT
 
465
    if (! ((ERROR_INSERTED(9000) || ERROR_INSERTED(9002)) 
 
466
           && c_error_9000_nodes_mask.get(tStartingNode)))
 
467
#endif
 
468
    {
 
469
      if (globalData.theStartLevel != NodeState::SL_STARTED &&
 
470
          (getNodeInfo(tStartingNode).m_type != NodeInfo::DB &&
 
471
           getNodeInfo(tStartingNode).m_type != NodeInfo::MGM))
 
472
      {
 
473
        jam();
 
474
        goto done;
 
475
      }
 
476
 
 
477
      globalTransporterRegistry.do_connect(tStartingNode);
 
478
      globalTransporterRegistry.setIOState(tStartingNode, HaltIO);
 
479
      
 
480
      //-----------------------------------------------------
 
481
      // Report that the connection to the node is opened
 
482
      //-----------------------------------------------------
 
483
      signal->theData[0] = NDB_LE_CommunicationOpened;
 
484
      signal->theData[1] = tStartingNode;
 
485
      sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
 
486
      //-----------------------------------------------------
 
487
    }
 
488
  } else {
 
489
    for(unsigned int i = 1; i < MAX_NODES; i++ ) 
 
490
    {
 
491
      jam();
 
492
      if (i != getOwnNodeId() && getNodeInfo(i).m_type == tData2)
 
493
      {
 
494
        jam();
 
495
 
 
496
#ifdef ERROR_INSERT
 
497
        if ((ERROR_INSERTED(9000) || ERROR_INSERTED(9002))
 
498
            && c_error_9000_nodes_mask.get(i))
 
499
          continue;
 
500
#endif
 
501
        
 
502
        globalTransporterRegistry.do_connect(i);
 
503
        globalTransporterRegistry.setIOState(i, HaltIO);
 
504
        
 
505
        signal->theData[0] = NDB_LE_CommunicationOpened;
 
506
        signal->theData[1] = i;
 
507
        sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
 
508
      }
 
509
    }
 
510
  }
 
511
  
 
512
done:  
 
513
  if (userRef != 0) {
 
514
    jam(); 
 
515
    signal->theData[0] = tStartingNode;
 
516
    signal->theData[1] = tData2;
 
517
    sendSignal(userRef, GSN_OPEN_COMCONF, signal, len - 1,JBA);
 
518
  }
 
519
}
 
520
 
 
521
void Cmvmi::execENABLE_COMORD(Signal* signal)
 
522
{
 
523
  // Enable communication with all our NDB blocks to this node
 
524
  
 
525
  Uint32 tStartingNode = signal->theData[0];
 
526
  globalTransporterRegistry.setIOState(tStartingNode, NoHalt);
 
527
  setNodeInfo(tStartingNode).m_connected = true;
 
528
    //-----------------------------------------------------
 
529
  // Report that the version of the node
 
530
  //-----------------------------------------------------
 
531
  signal->theData[0] = NDB_LE_ConnectedApiVersion;
 
532
  signal->theData[1] = tStartingNode;
 
533
  signal->theData[2] = getNodeInfo(tStartingNode).m_version;
 
534
 
 
535
  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
 
536
  //-----------------------------------------------------
 
537
  
 
538
  jamEntry();
 
539
}
 
540
 
 
541
void Cmvmi::execDISCONNECT_REP(Signal *signal)
 
542
{
 
543
  const DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
 
544
  const Uint32 hostId = rep->nodeId;
 
545
  const Uint32 errNo  = rep->err;
 
546
  
 
547
  jamEntry();
 
548
 
 
549
  setNodeInfo(hostId).m_connected = false;
 
550
  setNodeInfo(hostId).m_connectCount++;
 
551
  const NodeInfo::NodeType type = getNodeInfo(hostId).getType();
 
552
  ndbrequire(type != NodeInfo::INVALID);
 
553
 
 
554
  sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal, 
 
555
             DisconnectRep::SignalLength, JBA);
 
556
  
 
557
  cancelSubscription(hostId);
 
558
 
 
559
  signal->theData[0] = NDB_LE_Disconnected;
 
560
  signal->theData[1] = hostId;
 
561
  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
 
562
}
 
563
 
 
564
void Cmvmi::execCONNECT_REP(Signal *signal){
 
565
  const Uint32 hostId = signal->theData[0];
 
566
  jamEntry();
 
567
  
 
568
  const NodeInfo::NodeType type = (NodeInfo::NodeType)getNodeInfo(hostId).m_type;
 
569
  ndbrequire(type != NodeInfo::INVALID);
 
570
  globalData.m_nodeInfo[hostId].m_version = 0;
 
571
  globalData.m_nodeInfo[hostId].m_signalVersion = 0;
 
572
  
 
573
  if(type == NodeInfo::DB || globalData.theStartLevel >= NodeState::SL_STARTED){
 
574
    jam();
 
575
    
 
576
    /**
 
577
     * Inform QMGR that client has connected
 
578
     */
 
579
 
 
580
    signal->theData[0] = hostId;
 
581
    sendSignal(QMGR_REF, GSN_CONNECT_REP, signal, 1, JBA);
 
582
  } else if(globalData.theStartLevel == NodeState::SL_CMVMI ||
 
583
            globalData.theStartLevel == NodeState::SL_STARTING) {
 
584
    jam();
 
585
    /**
 
586
     * Someone connected before start was finished
 
587
     */
 
588
    if(type == NodeInfo::MGM){
 
589
      jam();
 
590
      signal->theData[0] = hostId;
 
591
      sendSignal(QMGR_REF, GSN_CONNECT_REP, signal, 1, JBA);
 
592
    } else {
 
593
      /**
 
594
       * Dont allow api nodes to connect
 
595
       */
 
596
      ndbout_c("%d %d %d", hostId, type, globalData.theStartLevel);
 
597
      abort();
 
598
      globalTransporterRegistry.do_disconnect(hostId);
 
599
    }
 
600
  }
 
601
  
 
602
  /* Automatically subscribe events for MGM nodes.
 
603
   */
 
604
  if(type == NodeInfo::MGM){
 
605
    jam();
 
606
    globalTransporterRegistry.setIOState(hostId, NoHalt);
 
607
  }
 
608
 
 
609
  //------------------------------------------
 
610
  // Also report this event to the Event handler
 
611
  //------------------------------------------
 
612
  signal->theData[0] = NDB_LE_Connected;
 
613
  signal->theData[1] = hostId;
 
614
  signal->header.theLength = 2;
 
615
  
 
616
  execEVENT_REP(signal);
 
617
}
 
618
 
 
619
#ifdef VM_TRACE
 
620
void
 
621
modifySignalLogger(bool allBlocks, BlockNumber bno, 
 
622
                   TestOrd::Command cmd, 
 
623
                   TestOrd::SignalLoggerSpecification spec){
 
624
  SignalLoggerManager::LogMode logMode;
 
625
 
 
626
  /**
 
627
   * Mapping between SignalLoggerManager::LogMode and 
 
628
   *                 TestOrd::SignalLoggerSpecification
 
629
   */
 
630
  switch(spec){
 
631
  case TestOrd::InputSignals:
 
632
    logMode = SignalLoggerManager::LogIn;
 
633
    break;
 
634
  case TestOrd::OutputSignals:
 
635
    logMode = SignalLoggerManager::LogOut;
 
636
    break;
 
637
  case TestOrd::InputOutputSignals:
 
638
    logMode = SignalLoggerManager::LogInOut;
 
639
    break;
 
640
  default:
 
641
    return;
 
642
    break;
 
643
  }
 
644
  
 
645
  switch(cmd){
 
646
  case TestOrd::On:
 
647
    globalSignalLoggers.logOn(allBlocks, bno, logMode);
 
648
    break;
 
649
  case TestOrd::Off:
 
650
    globalSignalLoggers.logOff(allBlocks, bno, logMode);
 
651
    break;
 
652
  case TestOrd::Toggle:
 
653
    globalSignalLoggers.logToggle(allBlocks, bno, logMode);
 
654
    break;
 
655
  case TestOrd::KeepUnchanged:
 
656
    // Do nothing
 
657
    break;
 
658
  }
 
659
  globalSignalLoggers.flushSignalLog();
 
660
}
 
661
#endif
 
662
 
 
663
void
 
664
Cmvmi::execTEST_ORD(Signal * signal){
 
665
  jamEntry();
 
666
  
 
667
#ifdef VM_TRACE
 
668
  TestOrd * const testOrd = (TestOrd *)&signal->theData[0];
 
669
 
 
670
  TestOrd::Command cmd;
 
671
 
 
672
  {
 
673
    /**
 
674
     * Process Trace command
 
675
     */
 
676
    TestOrd::TraceSpecification traceSpec;
 
677
 
 
678
    testOrd->getTraceCommand(cmd, traceSpec);
 
679
    unsigned long traceVal = traceSpec;
 
680
    unsigned long currentTraceVal = globalSignalLoggers.getTrace();
 
681
    switch(cmd){
 
682
    case TestOrd::On:
 
683
      currentTraceVal |= traceVal;
 
684
      break;
 
685
    case TestOrd::Off:
 
686
      currentTraceVal &= (~traceVal);
 
687
      break;
 
688
    case TestOrd::Toggle:
 
689
      currentTraceVal ^= traceVal;
 
690
      break;
 
691
    case TestOrd::KeepUnchanged:
 
692
      // Do nothing
 
693
      break;
 
694
    }
 
695
    globalSignalLoggers.setTrace(currentTraceVal);
 
696
  }
 
697
  
 
698
  {
 
699
    /**
 
700
     * Process Log command
 
701
     */
 
702
    TestOrd::SignalLoggerSpecification logSpec;
 
703
    BlockNumber bno;
 
704
    unsigned int loggers = testOrd->getNoOfSignalLoggerCommands();
 
705
    
 
706
    if(loggers == (unsigned)~0){ // Apply command to all blocks
 
707
      testOrd->getSignalLoggerCommand(0, bno, cmd, logSpec);
 
708
      modifySignalLogger(true, bno, cmd, logSpec);
 
709
    } else {
 
710
      for(unsigned int i = 0; i<loggers; i++){
 
711
        testOrd->getSignalLoggerCommand(i, bno, cmd, logSpec);
 
712
        modifySignalLogger(false, bno, cmd, logSpec);
 
713
      }
 
714
    }
 
715
  }
 
716
 
 
717
  {
 
718
    /**
 
719
     * Process test command
 
720
     */
 
721
    testOrd->getTestCommand(cmd);
 
722
    switch(cmd){
 
723
    case TestOrd::On:{
 
724
      SET_GLOBAL_TEST_ON;
 
725
    }
 
726
    break;
 
727
    case TestOrd::Off:{
 
728
      SET_GLOBAL_TEST_OFF;
 
729
    }
 
730
    break;
 
731
    case TestOrd::Toggle:{
 
732
      TOGGLE_GLOBAL_TEST_FLAG;
 
733
    }
 
734
    break;
 
735
    case TestOrd::KeepUnchanged:
 
736
      // Do nothing
 
737
      break;
 
738
    }
 
739
    globalSignalLoggers.flushSignalLog();
 
740
  }
 
741
 
 
742
#endif
 
743
}
 
744
 
 
745
void Cmvmi::execSTOP_ORD(Signal* signal) 
 
746
{
 
747
  jamEntry();
 
748
  globalData.theRestartFlag = perform_stop;
 
749
}//execSTOP_ORD()
 
750
 
 
751
void
 
752
Cmvmi::execSTART_ORD(Signal* signal) {
 
753
 
 
754
  StartOrd * const startOrd = (StartOrd *)&signal->theData[0];
 
755
  jamEntry();
 
756
  
 
757
  Uint32 tmp = startOrd->restartInfo;
 
758
  if(StopReq::getPerformRestart(tmp)){
 
759
    jam();
 
760
    /**
 
761
     *
 
762
     */
 
763
    NdbRestartType type = NRT_Default;
 
764
    if(StopReq::getNoStart(tmp) && StopReq::getInitialStart(tmp))
 
765
      type = NRT_NoStart_InitialStart;
 
766
    if(StopReq::getNoStart(tmp) && !StopReq::getInitialStart(tmp))
 
767
      type = NRT_NoStart_Restart;
 
768
    if(!StopReq::getNoStart(tmp) && StopReq::getInitialStart(tmp))
 
769
      type = NRT_DoStart_InitialStart;
 
770
    if(!StopReq::getNoStart(tmp)&&!StopReq::getInitialStart(tmp))
 
771
      type = NRT_DoStart_Restart;
 
772
    NdbShutdown(NST_Restart, type);
 
773
  }
 
774
 
 
775
  if(globalData.theRestartFlag == system_started){
 
776
    jam()
 
777
    /**
 
778
     * START_ORD received when already started(ignored)
 
779
     */
 
780
    //ndbout << "START_ORD received when already started(ignored)" << endl;
 
781
    return;
 
782
  }
 
783
  
 
784
  if(globalData.theRestartFlag == perform_stop){
 
785
    jam()
 
786
    /**
 
787
     * START_ORD received when stopping(ignored)
 
788
     */
 
789
    //ndbout << "START_ORD received when stopping(ignored)" << endl;
 
790
    return;
 
791
  }
 
792
  
 
793
  if(globalData.theStartLevel == NodeState::SL_NOTHING){
 
794
    jam();
 
795
    globalData.theStartLevel = NodeState::SL_CMVMI;
 
796
    /**
 
797
     * Open connections to management servers
 
798
     */
 
799
    for(unsigned int i = 1; i < MAX_NODES; i++ ){
 
800
      if (getNodeInfo(i).m_type == NodeInfo::MGM){ 
 
801
        if(!globalTransporterRegistry.is_connected(i)){
 
802
          globalTransporterRegistry.do_connect(i);
 
803
          globalTransporterRegistry.setIOState(i, NoHalt);
 
804
        }
 
805
      }
 
806
    }
 
807
 
 
808
    EXECUTE_DIRECT(QMGR, GSN_START_ORD, signal, 1);
 
809
    return ;
 
810
  }
 
811
  
 
812
  if(globalData.theStartLevel == NodeState::SL_CMVMI){
 
813
    jam();
 
814
 
 
815
    if(m_ctx.m_config.lockPagesInMainMemory() == 2)
 
816
    {
 
817
      int res = NdbMem_MemLockAll(1);
 
818
      if(res != 0)
 
819
      {
 
820
        g_eventLogger.warning("Failed to memlock pages");
 
821
        warningEvent("Failed to memlock pages");
 
822
      }
 
823
      else
 
824
      {
 
825
        g_eventLogger.info("Locked future allocations");
 
826
      }
 
827
    }
 
828
    
 
829
    globalData.theStartLevel  = NodeState::SL_STARTING;
 
830
    globalData.theRestartFlag = system_started;
 
831
    /**
 
832
     * StartLevel 1
 
833
     *
 
834
     * Do Restart
 
835
     */
 
836
    
 
837
    // Disconnect all nodes as part of the system restart. 
 
838
    // We need to ensure that we are starting up
 
839
    // without any connected nodes.   
 
840
    for(unsigned int i = 1; i < MAX_NODES; i++ ){
 
841
      if (i != getOwnNodeId() && getNodeInfo(i).m_type != NodeInfo::MGM){
 
842
        globalTransporterRegistry.do_disconnect(i);
 
843
        globalTransporterRegistry.setIOState(i, HaltIO);
 
844
      }
 
845
    }
 
846
    
 
847
    /**
 
848
     * Start running startphases
 
849
     */
 
850
    sendSignal(NDBCNTR_REF, GSN_START_ORD, signal, 1, JBA);  
 
851
    return;
 
852
  }
 
853
}//execSTART_ORD()
 
854
 
 
855
void Cmvmi::execTAMPER_ORD(Signal* signal) 
 
856
{
 
857
  jamEntry();
 
858
  // TODO We should maybe introduce a CONF and REF signal
 
859
  // to be able to indicate if we really introduced an error.
 
860
#ifdef ERROR_INSERT
 
861
  TamperOrd* const tamperOrd = (TamperOrd*)&signal->theData[0];
 
862
  signal->theData[2] = 0;
 
863
  signal->theData[1] = tamperOrd->errorNo;
 
864
  signal->theData[0] = 5;
 
865
  sendSignal(DBDIH_REF, GSN_DIHNDBTAMPER, signal, 3,JBB);
 
866
#endif
 
867
 
 
868
}//execTAMPER_ORD()
 
869
 
 
870
#ifdef VM_TRACE
 
871
class RefSignalTest {
 
872
public:
 
873
  enum ErrorCode {
 
874
    OK = 0,
 
875
    NF_FakeErrorREF = 7
 
876
  };
 
877
  Uint32 senderRef;
 
878
  Uint32 senderData;
 
879
  Uint32 errorCode;
 
880
};
 
881
#endif
 
882
 
 
883
 
 
884
static int iii;
 
885
 
 
886
static
 
887
int
 
888
recurse(char * buf, int loops, int arg){
 
889
  char * tmp = (char*)alloca(arg);
 
890
  printf("tmp = %p\n", tmp);
 
891
  for(iii = 0; iii<arg; iii += 1024){
 
892
    tmp[iii] = (iii % 23 + (arg & iii));
 
893
  }
 
894
  
 
895
  if(loops == 0)
 
896
    return tmp[345];
 
897
  else
 
898
    return tmp[arg/loops] + recurse(tmp, loops - 1, arg);
 
899
}
 
900
 
 
901
void
 
902
Cmvmi::execDUMP_STATE_ORD(Signal* signal)
 
903
{
 
904
 
 
905
  sendSignal(QMGR_REF, GSN_DUMP_STATE_ORD,    signal, signal->length(), JBB);
 
906
  sendSignal(NDBCNTR_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
 
907
  sendSignal(DBTC_REF, GSN_DUMP_STATE_ORD,    signal, signal->length(), JBB);
 
908
  sendSignal(DBDIH_REF, GSN_DUMP_STATE_ORD,   signal, signal->length(), JBB);
 
909
  sendSignal(DBDICT_REF, GSN_DUMP_STATE_ORD,  signal, signal->length(), JBB);
 
910
  sendSignal(DBLQH_REF, GSN_DUMP_STATE_ORD,   signal, signal->length(), JBB);
 
911
  sendSignal(DBTUP_REF, GSN_DUMP_STATE_ORD,   signal, signal->length(), JBB);
 
912
  sendSignal(DBACC_REF, GSN_DUMP_STATE_ORD,   signal, signal->length(), JBB);
 
913
  sendSignal(NDBFS_REF, GSN_DUMP_STATE_ORD,   signal, signal->length(), JBB);
 
914
  sendSignal(BACKUP_REF, GSN_DUMP_STATE_ORD,  signal, signal->length(), JBB);
 
915
  sendSignal(DBUTIL_REF, GSN_DUMP_STATE_ORD,  signal, signal->length(), JBB);
 
916
  sendSignal(SUMA_REF, GSN_DUMP_STATE_ORD,    signal, signal->length(), JBB);
 
917
  sendSignal(TRIX_REF, GSN_DUMP_STATE_ORD,    signal, signal->length(), JBB);
 
918
  sendSignal(DBTUX_REF, GSN_DUMP_STATE_ORD,   signal, signal->length(), JBB);
 
919
  sendSignal(LGMAN_REF, GSN_DUMP_STATE_ORD,   signal, signal->length(), JBB);
 
920
  sendSignal(TSMAN_REF, GSN_DUMP_STATE_ORD,   signal, signal->length(), JBB);
 
921
  sendSignal(PGMAN_REF, GSN_DUMP_STATE_ORD,   signal, signal->length(), JBB);
 
922
  
 
923
  /**
 
924
   *
 
925
   * Here I can dump CMVMI state if needed
 
926
   */
 
927
  if(signal->theData[0] == 13){
 
928
#if 0
 
929
    int loop = 100;
 
930
    int len = (10*1024*1024);
 
931
    if(signal->getLength() > 1)
 
932
      loop = signal->theData[1];
 
933
    if(signal->getLength() > 2)
 
934
      len = signal->theData[2];
 
935
    
 
936
    ndbout_c("recurse(%d loop, %dkb per recurse)", loop, len/1024);
 
937
    int a = recurse(0, loop, len);
 
938
    ndbout_c("after...%d", a);
 
939
#endif
 
940
  }
 
941
 
 
942
  DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0];
 
943
  Uint32 arg = dumpState->args[0];
 
944
  if (arg == DumpStateOrd::CmvmiDumpConnections){
 
945
    for(unsigned int i = 1; i < MAX_NODES; i++ ){
 
946
      const char* nodeTypeStr = "";
 
947
      switch(getNodeInfo(i).m_type){
 
948
      case NodeInfo::DB:
 
949
        nodeTypeStr = "DB";
 
950
        break;
 
951
      case NodeInfo::API:
 
952
        nodeTypeStr = "API";
 
953
        break;
 
954
      case NodeInfo::MGM:
 
955
        nodeTypeStr = "MGM";
 
956
        break;
 
957
      case NodeInfo::INVALID:
 
958
        nodeTypeStr = 0;
 
959
        break;
 
960
      default:
 
961
        nodeTypeStr = "<UNKNOWN>";
 
962
      }
 
963
 
 
964
      if(nodeTypeStr == 0)
 
965
        continue;
 
966
 
 
967
      infoEvent("Connection to %d (%s) %s", 
 
968
                i, 
 
969
                nodeTypeStr,
 
970
                globalTransporterRegistry.getPerformStateString(i));
 
971
    }
 
972
  }
 
973
  
 
974
  if (arg == DumpStateOrd::CmvmiDumpSubscriptions)
 
975
  {
 
976
    SubscriberPtr ptr;
 
977
    subscribers.first(ptr);  
 
978
    g_eventLogger.info("List subscriptions:");
 
979
    while(ptr.i != RNIL)
 
980
    {
 
981
      g_eventLogger.info("Subscription: %u, nodeId: %u, ref: 0x%x",
 
982
                         ptr.i,  refToNode(ptr.p->blockRef), ptr.p->blockRef);
 
983
      for(Uint32 i = 0; i < LogLevel::LOGLEVEL_CATEGORIES; i++)
 
984
      {
 
985
        Uint32 level = ptr.p->logLevel.getLogLevel((LogLevel::EventCategory)i);
 
986
        g_eventLogger.info("Category %u Level %u", i, level);
 
987
      }
 
988
      subscribers.next(ptr);
 
989
    }
 
990
  }
 
991
 
 
992
  if (arg == DumpStateOrd::CmvmiDumpLongSignalMemory){
 
993
    infoEvent("Cmvmi: g_sectionSegmentPool size: %d free: %d",
 
994
              g_sectionSegmentPool.getSize(),
 
995
              g_sectionSegmentPool.getNoOfFree());
 
996
  }
 
997
 
 
998
  if (dumpState->args[0] == 1000)
 
999
  {
 
1000
    Uint32 len = signal->getLength();
 
1001
    if (signal->getLength() == 1)
 
1002
    {
 
1003
      signal->theData[1] = 0;
 
1004
      signal->theData[2] = ~0;
 
1005
      sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 3, JBB);
 
1006
      return;
 
1007
    }
 
1008
    Uint32 id = signal->theData[1];
 
1009
    Resource_limit rl;
 
1010
    if (!m_ctx.m_mm.get_resource_limit(id, rl))
 
1011
      len = 2;
 
1012
    else
 
1013
    {
 
1014
      if (rl.m_min || rl.m_curr || rl.m_max)
 
1015
        infoEvent("Resource %d min: %d max: %d curr: %d",
 
1016
                  id, rl.m_min, rl.m_max, rl.m_curr);
 
1017
    }
 
1018
 
 
1019
    if (len == 3)
 
1020
    {
 
1021
      signal->theData[0] = 1000;
 
1022
      signal->theData[1] = id+1;
 
1023
      signal->theData[2] = ~0;
 
1024
      sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 3, JBB);
 
1025
    }
 
1026
    return;
 
1027
  }
 
1028
  
 
1029
  if (arg == DumpStateOrd::CmvmiSetRestartOnErrorInsert)
 
1030
  {
 
1031
    if(signal->getLength() == 1)
 
1032
    {
 
1033
      Uint32 val = (Uint32)NRT_NoStart_Restart;
 
1034
      const ndb_mgm_configuration_iterator * p = 
 
1035
        m_ctx.m_config.getOwnConfigIterator();
 
1036
      ndbrequire(p != 0);
 
1037
      
 
1038
      if(!ndb_mgm_get_int_parameter(p, CFG_DB_STOP_ON_ERROR_INSERT, &val))
 
1039
      {
 
1040
        m_ctx.m_config.setRestartOnErrorInsert(val);
 
1041
      }
 
1042
    }
 
1043
    else
 
1044
    {
 
1045
      m_ctx.m_config.setRestartOnErrorInsert(signal->theData[1]);
 
1046
    }
 
1047
  }
 
1048
 
 
1049
  if (arg == DumpStateOrd::CmvmiTestLongSigWithDelay) {
 
1050
    unsigned i;
 
1051
    Uint32 loopCount = dumpState->args[1];
 
1052
    const unsigned len0 = 11;
 
1053
    const unsigned len1 = 123;
 
1054
    Uint32 sec0[len0];
 
1055
    Uint32 sec1[len1];
 
1056
    for (i = 0; i < len0; i++)
 
1057
      sec0[i] = i;
 
1058
    for (i = 0; i < len1; i++)
 
1059
      sec1[i] = 16 * i;
 
1060
    Uint32* sig = signal->getDataPtrSend();
 
1061
    sig[0] = reference();
 
1062
    sig[1] = 20; // test type
 
1063
    sig[2] = 0;
 
1064
    sig[3] = 0;
 
1065
    sig[4] = loopCount;
 
1066
    sig[5] = len0;
 
1067
    sig[6] = len1;
 
1068
    sig[7] = 0;
 
1069
    LinearSectionPtr ptr[3];
 
1070
    ptr[0].p = sec0;
 
1071
    ptr[0].sz = len0;
 
1072
    ptr[1].p = sec1;
 
1073
    ptr[1].sz = len1;
 
1074
    sendSignal(reference(), GSN_TESTSIG, signal, 8, JBB, ptr, 2);
 
1075
  }
 
1076
 
 
1077
#ifdef ERROR_INSERT
 
1078
  if (arg == 9000 || arg == 9002)
 
1079
  {
 
1080
    SET_ERROR_INSERT_VALUE(arg);
 
1081
    for (Uint32 i = 1; i<signal->getLength(); i++)
 
1082
      c_error_9000_nodes_mask.set(signal->theData[i]);
 
1083
  }
 
1084
  
 
1085
  if (arg == 9001)
 
1086
  {
 
1087
    CLEAR_ERROR_INSERT_VALUE;
 
1088
    if (signal->getLength() == 1 || signal->theData[1])
 
1089
    {
 
1090
      for (Uint32 i = 0; i<MAX_NODES; i++)
 
1091
      {
 
1092
        if (c_error_9000_nodes_mask.get(i))
 
1093
        {
 
1094
          signal->theData[0] = 0;
 
1095
          signal->theData[1] = i;
 
1096
          EXECUTE_DIRECT(CMVMI, GSN_OPEN_COMREQ, signal, 2);
 
1097
        }
 
1098
      }
 
1099
    }
 
1100
    c_error_9000_nodes_mask.clear();
 
1101
  }
 
1102
#endif
 
1103
 
 
1104
#ifdef VM_TRACE
 
1105
#if 0
 
1106
  {
 
1107
    SafeCounterManager mgr(* this); mgr.setSize(1);
 
1108
    SafeCounterHandle handle;
 
1109
 
 
1110
    {
 
1111
      SafeCounter tmp(mgr, handle);
 
1112
      tmp.init<RefSignalTest>(CMVMI, GSN_TESTSIG, /* senderData */ 13);
 
1113
      tmp.setWaitingFor(3);
 
1114
      ndbrequire(!tmp.done());
 
1115
      ndbout_c("Allocted");
 
1116
    }
 
1117
    ndbrequire(!handle.done());
 
1118
    {
 
1119
      SafeCounter tmp(mgr, handle);
 
1120
      tmp.clearWaitingFor(3);
 
1121
      ndbrequire(tmp.done());
 
1122
      ndbout_c("Deallocted");
 
1123
    }
 
1124
    ndbrequire(handle.done());
 
1125
  }
 
1126
#endif
 
1127
#endif
 
1128
 
 
1129
  if (arg == 9999)
 
1130
  {
 
1131
    Uint32 delay = 1000;
 
1132
    switch(signal->getLength()){
 
1133
    case 1:
 
1134
      break;
 
1135
    case 2:
 
1136
      delay = signal->theData[1];
 
1137
      break;
 
1138
    default:{
 
1139
      Uint32 dmin = signal->theData[1];
 
1140
      Uint32 dmax = signal->theData[2];
 
1141
      delay = dmin + (rand() % (dmax - dmin));
 
1142
      break;
 
1143
    }
 
1144
    }
 
1145
    
 
1146
    signal->theData[0] = 9999;
 
1147
    if (delay == 0)
 
1148
    {
 
1149
      execNDB_TAMPER(signal);
 
1150
    }
 
1151
    else if (delay < 10)
 
1152
    {
 
1153
      sendSignal(reference(), GSN_NDB_TAMPER, signal, 1, JBB);
 
1154
    }
 
1155
    else
 
1156
    {
 
1157
      sendSignalWithDelay(reference(), GSN_NDB_TAMPER, signal, delay, 1);
 
1158
    }
 
1159
  }
 
1160
}//Cmvmi::execDUMP_STATE_ORD()
 
1161
 
 
1162
void
 
1163
Cmvmi::execNODE_START_REP(Signal* signal)
 
1164
{
 
1165
#ifdef ERROR_INSERT
 
1166
  if (ERROR_INSERTED(9002) && signal->theData[0] == getOwnNodeId())
 
1167
  {
 
1168
    signal->theData[0] = 9001;
 
1169
    execDUMP_STATE_ORD(signal);
 
1170
  }
 
1171
#endif
 
1172
}
 
1173
 
 
1174
BLOCK_FUNCTIONS(Cmvmi)
 
1175
 
 
1176
static Uint32 g_print;
 
1177
static LinearSectionPtr g_test[3];
 
1178
 
 
1179
void
 
1180
Cmvmi::execTESTSIG(Signal* signal){
 
1181
  Uint32 i;
 
1182
  /**
 
1183
   * Test of SafeCounter
 
1184
   */
 
1185
  jamEntry();
 
1186
 
 
1187
  if(!assembleFragments(signal)){
 
1188
    jam();
 
1189
    return;
 
1190
  }
 
1191
 
 
1192
  Uint32 ref = signal->theData[0];
 
1193
  Uint32 testType = signal->theData[1];
 
1194
  Uint32 fragmentLength = signal->theData[2];
 
1195
  g_print = signal->theData[3];
 
1196
//  Uint32 returnCount = signal->theData[4];
 
1197
  Uint32 * secSizes = &signal->theData[5];
 
1198
  
 
1199
  if(g_print){
 
1200
    SignalLoggerManager::printSignalHeader(stdout, 
 
1201
                                           signal->header,
 
1202
                                           0,
 
1203
                                           getOwnNodeId(),
 
1204
                                           true);
 
1205
    ndbout_c("-- Fixed section --");    
 
1206
    for(i = 0; i<signal->length(); i++){
 
1207
      fprintf(stdout, "H'0x%.8x ", signal->theData[i]);
 
1208
      if(((i + 1) % 6) == 0)
 
1209
        fprintf(stdout, "\n");
 
1210
    }
 
1211
    fprintf(stdout, "\n");
 
1212
    
 
1213
    for(i = 0; i<signal->header.m_noOfSections; i++){
 
1214
      SegmentedSectionPtr ptr(0,0,0);
 
1215
      ndbout_c("-- Section %d --", i);
 
1216
      signal->getSection(ptr, i);
 
1217
      ndbrequire(ptr.p != 0);
 
1218
      print(ptr, stdout);
 
1219
      ndbrequire(ptr.sz == secSizes[i]);
 
1220
    }
 
1221
  }
 
1222
 
 
1223
  /**
 
1224
   * Validate length:s
 
1225
   */
 
1226
  for(i = 0; i<signal->header.m_noOfSections; i++){
 
1227
    SegmentedSectionPtr ptr;
 
1228
    signal->getSection(ptr, i);
 
1229
    ndbrequire(ptr.p != 0);
 
1230
    ndbrequire(ptr.sz == secSizes[i]);
 
1231
  }
 
1232
 
 
1233
  /**
 
1234
   * Testing send with delay.
 
1235
   */
 
1236
  if (testType == 20) {
 
1237
    if (signal->theData[4] == 0) {
 
1238
      releaseSections(signal);
 
1239
      return;
 
1240
    }
 
1241
    signal->theData[4]--;
 
1242
    sendSignalWithDelay(reference(), GSN_TESTSIG, signal, 100, 8);
 
1243
    return;
 
1244
  }
 
1245
  
 
1246
  NodeReceiverGroup rg(CMVMI, c_dbNodes);
 
1247
 
 
1248
  if(signal->getSendersBlockRef() == ref){
 
1249
    /**
 
1250
     * Signal from API (not via NodeReceiverGroup)
 
1251
     */
 
1252
    if((testType % 2) == 1){
 
1253
      signal->theData[4] = 1;
 
1254
    } else {
 
1255
      signal->theData[1] --;
 
1256
      signal->theData[4] = rg.m_nodes.count();
 
1257
    }
 
1258
  } 
 
1259
  
 
1260
  switch(testType){
 
1261
  case 1:
 
1262
    sendSignal(ref, GSN_TESTSIG,  signal, signal->length(), JBB);      
 
1263
    break;
 
1264
  case 2:
 
1265
    sendSignal(rg, GSN_TESTSIG,  signal, signal->length(), JBB);
 
1266
    break;
 
1267
  case 3:
 
1268
  case 4:{
 
1269
    LinearSectionPtr ptr[3];
 
1270
    const Uint32 secs = signal->getNoOfSections();
 
1271
    for(i = 0; i<secs; i++){
 
1272
      SegmentedSectionPtr sptr(0,0,0);
 
1273
      signal->getSection(sptr, i);
 
1274
      ptr[i].sz = sptr.sz;
 
1275
      ptr[i].p = new Uint32[sptr.sz];
 
1276
      copy(ptr[i].p, sptr);
 
1277
    }
 
1278
    
 
1279
    if(testType == 3){
 
1280
      sendSignal(ref, GSN_TESTSIG,  signal, signal->length(), JBB, ptr, secs); 
 
1281
    } else {
 
1282
      sendSignal(rg, GSN_TESTSIG,  signal, signal->length(), JBB, ptr, secs); 
 
1283
    }
 
1284
    for(Uint32 i = 0; i<secs; i++){
 
1285
      delete[] ptr[i].p;
 
1286
    }
 
1287
    break;
 
1288
  }
 
1289
  case 5:
 
1290
  case 6:{
 
1291
    
 
1292
    NodeReceiverGroup tmp;
 
1293
    if(testType == 5){
 
1294
      tmp  = ref;
 
1295
    } else {
 
1296
      tmp = rg;
 
1297
    }
 
1298
    
 
1299
    FragmentSendInfo fragSend;
 
1300
    sendFirstFragment(fragSend,
 
1301
                      tmp,
 
1302
                      GSN_TESTSIG,
 
1303
                      signal,
 
1304
                      signal->length(),
 
1305
                      JBB,
 
1306
                      fragmentLength);
 
1307
    int count = 1;
 
1308
    while(fragSend.m_status != FragmentSendInfo::SendComplete){
 
1309
      count++;
 
1310
      if(g_print)
 
1311
        ndbout_c("Sending fragment %d", count);
 
1312
      sendNextSegmentedFragment(signal, fragSend);
 
1313
    }
 
1314
    break;
 
1315
  }
 
1316
  case 7:
 
1317
  case 8:{
 
1318
    LinearSectionPtr ptr[3];
 
1319
    const Uint32 secs = signal->getNoOfSections();
 
1320
    for(i = 0; i<secs; i++){
 
1321
      SegmentedSectionPtr sptr(0,0,0);
 
1322
      signal->getSection(sptr, i);
 
1323
      ptr[i].sz = sptr.sz;
 
1324
      ptr[i].p = new Uint32[sptr.sz];
 
1325
      copy(ptr[i].p, sptr);
 
1326
    }
 
1327
 
 
1328
    NodeReceiverGroup tmp;
 
1329
    if(testType == 7){
 
1330
      tmp  = ref;
 
1331
    } else {
 
1332
      tmp = rg;
 
1333
    }
 
1334
 
 
1335
    FragmentSendInfo fragSend;
 
1336
    sendFirstFragment(fragSend,
 
1337
                      tmp,
 
1338
                      GSN_TESTSIG,
 
1339
                      signal,
 
1340
                      signal->length(),
 
1341
                      JBB,
 
1342
                      ptr,
 
1343
                      secs,
 
1344
                      fragmentLength);
 
1345
    
 
1346
    int count = 1;
 
1347
    while(fragSend.m_status != FragmentSendInfo::SendComplete){
 
1348
      count++;
 
1349
      if(g_print)
 
1350
        ndbout_c("Sending fragment %d", count);
 
1351
      sendNextLinearFragment(signal, fragSend);
 
1352
    }
 
1353
    
 
1354
    for(i = 0; i<secs; i++){
 
1355
      delete[] ptr[i].p;
 
1356
    }
 
1357
    break;
 
1358
  }
 
1359
  case 9:
 
1360
  case 10:{
 
1361
 
 
1362
    Callback m_callBack;
 
1363
    m_callBack.m_callbackFunction = 
 
1364
      safe_cast(&Cmvmi::sendFragmentedComplete);
 
1365
    
 
1366
    if(testType == 9){
 
1367
      m_callBack.m_callbackData = 9;
 
1368
      sendFragmentedSignal(ref,
 
1369
                           GSN_TESTSIG, signal, signal->length(), JBB, 
 
1370
                           m_callBack,
 
1371
                           fragmentLength);
 
1372
    } else {
 
1373
      m_callBack.m_callbackData = 10;
 
1374
      sendFragmentedSignal(rg,
 
1375
                           GSN_TESTSIG, signal, signal->length(), JBB, 
 
1376
                           m_callBack,
 
1377
                           fragmentLength);
 
1378
    }
 
1379
    break;
 
1380
  }
 
1381
  case 11:
 
1382
  case 12:{
 
1383
 
 
1384
    const Uint32 secs = signal->getNoOfSections();
 
1385
    memset(g_test, 0, sizeof(g_test));
 
1386
    for(i = 0; i<secs; i++){
 
1387
      SegmentedSectionPtr sptr(0,0,0);
 
1388
      signal->getSection(sptr, i);
 
1389
      g_test[i].sz = sptr.sz;
 
1390
      g_test[i].p = new Uint32[sptr.sz];
 
1391
      copy(g_test[i].p, sptr);
 
1392
    }
 
1393
    
 
1394
    
 
1395
    Callback m_callBack;
 
1396
    m_callBack.m_callbackFunction = 
 
1397
      safe_cast(&Cmvmi::sendFragmentedComplete);
 
1398
    
 
1399
    if(testType == 11){
 
1400
      m_callBack.m_callbackData = 11;
 
1401
      sendFragmentedSignal(ref,
 
1402
                           GSN_TESTSIG, signal, signal->length(), JBB, 
 
1403
                           g_test, secs,
 
1404
                           m_callBack,
 
1405
                           fragmentLength);
 
1406
    } else {
 
1407
      m_callBack.m_callbackData = 12;
 
1408
      sendFragmentedSignal(rg,
 
1409
                           GSN_TESTSIG, signal, signal->length(), JBB, 
 
1410
                           g_test, secs,
 
1411
                           m_callBack,
 
1412
                           fragmentLength);
 
1413
    }
 
1414
    break;
 
1415
  }
 
1416
  case 13:{
 
1417
    ndbrequire(signal->getNoOfSections() == 0);
 
1418
    Uint32 loop = signal->theData[9];
 
1419
    if(loop > 0){
 
1420
      signal->theData[9] --;
 
1421
      sendSignal(CMVMI_REF, GSN_TESTSIG, signal, signal->length(), JBB);
 
1422
      return;
 
1423
    }
 
1424
    sendSignal(ref, GSN_TESTSIG, signal, signal->length(), JBB);
 
1425
    return;
 
1426
  }
 
1427
  case 14:{
 
1428
    Uint32 count = signal->theData[8];
 
1429
    signal->theData[10] = count * rg.m_nodes.count();
 
1430
    for(i = 0; i<count; i++){
 
1431
      sendSignal(rg, GSN_TESTSIG, signal, signal->length(), JBB); 
 
1432
    }
 
1433
    return;
 
1434
  }
 
1435
 
 
1436
  default:
 
1437
    ndbrequire(false);
 
1438
  }
 
1439
  return;
 
1440
}
 
1441
 
 
1442
void
 
1443
Cmvmi::sendFragmentedComplete(Signal* signal, Uint32 data, Uint32 returnCode){
 
1444
  if(g_print)
 
1445
    ndbout_c("sendFragmentedComplete: %d", data);
 
1446
  if(data == 11 || data == 12){
 
1447
    for(Uint32 i = 0; i<3; i++){
 
1448
      if(g_test[i].p != 0)
 
1449
        delete[] g_test[i].p;
 
1450
    }
 
1451
  }
 
1452
}