1 /*
2 Copyright (C) 2003-2008 MySQL AB, 2008 Sun Microsystems, Inc.
3 All rights reserved. Use is subject to license terms.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation. The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License, version 2.0, for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #include <ndb_global.h>
27
28 #include "SCI_Transporter.hpp"
29 #include <NdbOut.hpp>
30 #include <NdbSleep.h>
31 #include <NdbTick.h>
32 #include <NdbTick.h>
33
34 #include "TransporterInternalDefinitions.hpp"
35 #include <TransporterCallback.hpp>
36
37 #include <InputStream.hpp>
38 #include <OutputStream.hpp>
39
40 #define FLAGS 0
41 #define DEBUG_TRANSPORTER
SCI_Transporter(TransporterRegistry & t_reg,const char * lHostName,const char * rHostName,int r_port,bool isMgmConnection,Uint32 packetSize,Uint32 bufferSize,Uint32 nAdapters,Uint16 remoteSciNodeId0,Uint16 remoteSciNodeId1,NodeId _localNodeId,NodeId _remoteNodeId,NodeId serverNodeId,bool chksm,bool signalId,Uint32 reportFreq)42 SCI_Transporter::SCI_Transporter(TransporterRegistry &t_reg,
43 const char *lHostName,
44 const char *rHostName,
45 int r_port,
46 bool isMgmConnection,
47 Uint32 packetSize,
48 Uint32 bufferSize,
49 Uint32 nAdapters,
50 Uint16 remoteSciNodeId0,
51 Uint16 remoteSciNodeId1,
52 NodeId _localNodeId,
53 NodeId _remoteNodeId,
54 NodeId serverNodeId,
55 bool chksm,
56 bool signalId,
57 Uint32 reportFreq) :
58 Transporter(t_reg, tt_SCI_TRANSPORTER,
59 lHostName, rHostName, r_port, isMgmConnection, _localNodeId,
60 _remoteNodeId, serverNodeId, 0, false, chksm, signalId,
61 4 * ((packetSize + 3)/4) + MAX_MESSAGE_SIZE)
62 {
63 DBUG_ENTER("SCI_Transporter::SCI_Transporter");
64 m_PacketSize = (packetSize + 3)/4 ;
65 m_BufferSize = bufferSize;
66
67 m_RemoteSciNodeId = remoteSciNodeId0;
68
69 if(remoteSciNodeId0 == 0 || remoteSciNodeId1 == 0)
70 m_numberOfRemoteNodes=1;
71 else
72 m_numberOfRemoteNodes=2;
73
74 m_RemoteSciNodeId1 = remoteSciNodeId1;
75
76
77 m_initLocal=false;
78 m_failCounter=0;
79 m_remoteNodes[0]=remoteSciNodeId0;
80 m_remoteNodes[1]=remoteSciNodeId1;
81 m_adapters = nAdapters;
82 m_ActiveAdapterId=0;
83 m_StandbyAdapterId=1;
84
85 m_mapped = false;
86 m_sciinit=false;
87
88 sciAdapters= new SciAdapter[nAdapters* (sizeof (SciAdapter))];
89 if(sciAdapters==NULL) {
90 }
91 m_SourceSegm= new sourceSegm[nAdapters* (sizeof (sourceSegm))];
92 if(m_SourceSegm==NULL) {
93 }
94 m_TargetSegm= new targetSegm[nAdapters* (sizeof (targetSegm))];
95 if(m_TargetSegm==NULL) {
96 }
97 m_reportFreq= reportFreq;
98
99 //reset all statistic counters.
100 #ifdef DEBUG_TRANSPORTER
101 i1024=0;
102 i2048=0;
103 i2049=0;
104 i10242048=0;
105 i20484096=0;
106 i4096=0;
107 i4097=0;
108 #endif
109 DBUG_VOID_RETURN;
110 }
111
112
113 bool
configure_derived(const TransporterConfiguration * conf)114 SCI_Transporter::configure_derived(const TransporterConfiguration* conf)
115 {
116 if (conf->sci.sendLimit == (m_PacketSize + 3)/4 &&
117 conf->sci.bufferSize == m_buffersize &&
118 conf->sci.nLocalAdapters == m_adapters &&
119 conf->sci.remoteSciNodeId0 == m_remoteNodes[0] &&
120 conf->sci.remoteSciNodeId1 == m_remoteNodes[1])
121 return true; // No change
122 return false; // Can't reconfigure
123 }
124
125
disconnectImpl()126 void SCI_Transporter::disconnectImpl()
127 {
128 DBUG_ENTER("SCI_Transporter::disconnectImpl");
129 sci_error_t err;
130 if(m_mapped){
131 setDisconnect();
132 DBUG_PRINT("info", ("connect status = %d, remote node = %d",
133 (int)getConnectionStatus(), remoteNodeId));
134 disconnectRemote();
135 disconnectLocal();
136 }
137
138 m_initLocal=false;
139 m_mapped = false;
140
141 if(m_sciinit) {
142 for(Uint32 i=0; i<m_adapters ; i++) {
143 SCIClose(sciAdapters[i].scidesc, FLAGS, &err);
144
145 if(err != SCI_ERR_OK) {
146 report_error(TE_SCI_UNABLE_TO_CLOSE_CHANNEL);
147 DBUG_PRINT("error",
148 ("Cannot close channel to the driver. Error code 0x%x",
149 err));
150 }
151 }
152 }
153 m_sciinit=false;
154
155 #ifdef DEBUG_TRANSPORTER
156 ndbout << "total: " << i1024+ i10242048 + i2048+i2049 << endl;
157 ndbout << "<1024: " << i1024 << endl;
158 ndbout << "1024-2047: " << i10242048 << endl;
159 ndbout << "==2048: " << i2048 << endl;
160 ndbout << "2049-4096: " << i20484096 << endl;
161 ndbout << "==4096: " << i4096 << endl;
162 ndbout << ">4096: " << i4097 << endl;
163 #endif
164 DBUG_VOID_RETURN;
165 }
166
167
initTransporter()168 bool SCI_Transporter::initTransporter() {
169 DBUG_ENTER("SCI_Transporter::initTransporter");
170 if(m_BufferSize < (2*MAX_MESSAGE_SIZE + 4096)){
171 m_BufferSize = 2 * MAX_MESSAGE_SIZE + 4096;
172 }
173
174 DBUG_PRINT("info", ("SCI packet size %d", m_PacketSize * 4));
175 if(!getLinkStatus(m_ActiveAdapterId) ||
176 (m_adapters > 1 &&
177 !getLinkStatus(m_StandbyAdapterId))) {
178 DBUG_PRINT("error",
179 ("The link is not fully operational. Check the cables and the switches"));
180 //NDB should terminate
181 report_error(TE_SCI_LINK_ERROR);
182 DBUG_RETURN(false);
183 }
184 DBUG_RETURN(true);
185 } // initTransporter()
186
187
188
getLocalNodeId(Uint32 adapterNo)189 Uint32 SCI_Transporter::getLocalNodeId(Uint32 adapterNo)
190 {
191 sci_query_adapter_t queryAdapter;
192 sci_error_t error;
193 Uint32 _localNodeId;
194
195 queryAdapter.subcommand = SCI_Q_ADAPTER_NODEID;
196 queryAdapter.localAdapterNo = adapterNo;
197 queryAdapter.data = &_localNodeId;
198
199 SCIQuery(SCI_Q_ADAPTER,(void*)(&queryAdapter),(Uint32)NULL,&error);
200
201 if(error != SCI_ERR_OK)
202 return 0;
203 return _localNodeId;
204 }
205
206
getLinkStatus(Uint32 adapterNo)207 bool SCI_Transporter::getLinkStatus(Uint32 adapterNo)
208 {
209 sci_query_adapter_t queryAdapter;
210 sci_error_t error;
211 int linkstatus;
212 queryAdapter.subcommand = SCI_Q_ADAPTER_LINK_OPERATIONAL;
213
214 queryAdapter.localAdapterNo = adapterNo;
215 queryAdapter.data = &linkstatus;
216
217 SCIQuery(SCI_Q_ADAPTER,(void*)(&queryAdapter),(Uint32)NULL,&error);
218
219 if(error != SCI_ERR_OK) {
220 DBUG_PRINT("error", ("error %d querying adapter", error));
221 return false;
222 }
223 if(linkstatus<=0)
224 return false;
225 return true;
226 }
227
228
229
initLocalSegment()230 sci_error_t SCI_Transporter::initLocalSegment() {
231 DBUG_ENTER("SCI_Transporter::initLocalSegment");
232 Uint32 segmentSize = m_BufferSize;
233 Uint32 offset = 0;
234 sci_error_t err;
235 if(!m_sciinit) {
236 for(Uint32 i=0; i<m_adapters ; i++) {
237 SCIOpen(&(sciAdapters[i].scidesc), FLAGS, &err);
238 sciAdapters[i].localSciNodeId=getLocalNodeId(i);
239 DBUG_PRINT("info", ("SCInode iD %d adapter %d\n",
240 sciAdapters[i].localSciNodeId, i));
241 if(err != SCI_ERR_OK) {
242 DBUG_PRINT("error",
243 ("Cannot open an SCI virtual device. Error code 0x%x",
244 err));
245 DBUG_RETURN(err);
246 }
247 }
248 }
249
250 m_sciinit=true;
251
252 SCICreateSegment(sciAdapters[0].scidesc,
253 &(m_SourceSegm[0].localHandle),
254 hostSegmentId(localNodeId, remoteNodeId),
255 segmentSize,
256 0,
257 0,
258 0,
259 &err);
260
261 if(err != SCI_ERR_OK) {
262 DBUG_PRINT("error", ("Error creating segment, err = 0x%x", err));
263 DBUG_RETURN(err);
264 } else {
265 DBUG_PRINT("info", ("created segment id : %d",
266 hostSegmentId(localNodeId, remoteNodeId)));
267 }
268
269 /** Prepare the segment*/
270 for(Uint32 i=0; i < m_adapters; i++) {
271 SCIPrepareSegment((m_SourceSegm[0].localHandle),
272 i,
273 FLAGS,
274 &err);
275
276 if(err != SCI_ERR_OK) {
277 DBUG_PRINT("error",
278 ("Local Segment is not accessible by an SCI adapter. Error code 0x%x\n",
279 err));
280 DBUG_RETURN(err);
281 }
282 }
283
284
285 m_SourceSegm[0].mappedMemory =
286 SCIMapLocalSegment((m_SourceSegm[0].localHandle),
287 &(m_SourceSegm[0].lhm[0].map),
288 offset,
289 segmentSize,
290 NULL,
291 FLAGS,
292 &err);
293
294
295
296 if(err != SCI_ERR_OK) {
297 DBUG_PRINT("error", ("Cannot map area of size %d. Error code 0x%x",
298 segmentSize,err));
299 doDisconnect();
300 DBUG_RETURN(err);
301 }
302
303
304 /** Make the local segment available*/
305 for(Uint32 i=0; i < m_adapters; i++) {
306 SCISetSegmentAvailable((m_SourceSegm[0].localHandle),
307 i,
308 FLAGS,
309 &err);
310
311 if(err != SCI_ERR_OK) {
312 DBUG_PRINT("error",
313 ("Local Segment is not available for remote connections. Error code 0x%x\n",
314 err));
315 DBUG_RETURN(err);
316 }
317 }
318 setupLocalSegment();
319 DBUG_RETURN(err);
320
321 } // initLocalSegment()
322
323
doSend()324 bool SCI_Transporter::doSend() {
325 #ifdef DEBUG_TRANSPORTER
326 NDB_TICKS startSec=0, stopSec=0;
327 Uint32 startMicro=0, stopMicro=0, totalMicro=0;
328 #endif
329 sci_error_t err;
330 Uint32 retry=0;
331
332 if (!fetch_send_iovec_data())
333 return false;
334
335 Uint32 used = m_send_iovec_used;
336 if (used == 0)
337 return true; // Nothing to send
338
339 #ifdef DEBUG_TRANSPORTER
340 Uint32 sizeToSend = 0;
341 for (Uint32 i = 0; i < used; i++)
342 sizeToSend += m_send_iovec[i].iov_len;
343
344 if(sizeToSend < 1024 )
345 i1024++;
346 if(sizeToSend > 1024 && sizeToSend < 2048 )
347 i10242048++;
348 if(sizeToSend==2048)
349 i2048++;
350 if(sizeToSend>2048 && sizeToSend < 4096)
351 i20484096++;
352 if(sizeToSend==4096)
353 i4096++;
354 if(sizeToSend==4097)
355 i4097++;
356 #endif
357
358 bool status = true;
359 Uint32 curr = 0;
360 Uint32 total = 0;
361 while (curr < used)
362 {
363 tryagain:
364 if (retry > 3) {
365 DBUG_PRINT("error", ("SCI Transfer failed"));
366 report_error(TE_SCI_UNRECOVERABLE_DATA_TFX_ERROR);
367 status = false;
368 break;
369 }
370 Uint32 segSize = m_send_iovec[curr].iov_len;
371 Uint32 * insertPtr = (Uint32 *)
372 (m_TargetSegm[m_ActiveAdapterId].writer)->getWritePtr(segSize);
373
374 if(insertPtr != 0) {
375
376 const Uint32 remoteOffset=(Uint32)
377 ((char*)insertPtr -
378 (char*)(m_TargetSegm[m_ActiveAdapterId].mappedMemory));
379
380 SCIMemCpy(m_TargetSegm[m_ActiveAdapterId].sequence,
381 (void*)m_send_iovec[curr].iov_base,
382 m_TargetSegm[m_ActiveAdapterId].rhm[m_ActiveAdapterId].map,
383 remoteOffset,
384 segSize,
385 SCI_FLAG_ERROR_CHECK,
386 &err);
387
388 if (err != SCI_ERR_OK) {
389 if (err == SCI_ERR_OUT_OF_RANGE ||
390 err == SCI_ERR_SIZE_ALIGNMENT ||
391 err == SCI_ERR_OFFSET_ALIGNMENT) {
392 DBUG_PRINT("error", ("Data transfer error = %d", err));
393 report_error(TE_SCI_UNRECOVERABLE_DATA_TFX_ERROR);
394 status = false;
395 break;
396 }
397 if(err == SCI_ERR_TRANSFER_FAILED) {
398 if(getLinkStatus(m_ActiveAdapterId))
399 {
400 retry++;
401 goto tryagain;
402 }
403 if (m_adapters == 1) {
404 DBUG_PRINT("error", ("SCI Transfer failed"));
405 report_error(TE_SCI_UNRECOVERABLE_DATA_TFX_ERROR);
406 status = false;
407 break;
408 }
409 m_failCounter++;
410 Uint32 temp=m_ActiveAdapterId;
411 if (getLinkStatus(m_StandbyAdapterId)) {
412 failoverShmWriter();
413 SCIStoreBarrier(m_TargetSegm[m_StandbyAdapterId].sequence,0);
414 m_ActiveAdapterId=m_StandbyAdapterId;
415 m_StandbyAdapterId=temp;
416 DBUG_PRINT("error", ("Swapping from adapter %u to %u",
417 m_StandbyAdapterId, m_ActiveAdapterId));
418 } else {
419 report_error(TE_SCI_UNRECOVERABLE_DATA_TFX_ERROR);
420 DBUG_PRINT("error", ("SCI Transfer failed"));
421 }
422 }
423 break;
424 } else {
425 SHM_Writer * writer = (m_TargetSegm[m_ActiveAdapterId].writer);
426 writer->updateWritePtr(segSize);
427
428 curr++;
429 total += segSize;
430 }
431 } else {
432 /**
433 * If we end up here, the SCI segment is full. As long as we manage to
434 * send _something_, that is ok.
435 */
436 if (curr == 0)
437 {
438 DBUG_PRINT("error", ("the segment is full for some reason"));
439 status = false;
440 }
441 break;
442 } //if
443 }
444
445 if (total > 0)
446 iovec_data_sent(total);
447
448 return status;
449 } // doSend()
450
451
452
failoverShmWriter()453 void SCI_Transporter::failoverShmWriter() {
454 #if 0
455 (m_TargetSegm[m_StandbyAdapterId].writer)
456 ->copyIndexes((m_TargetSegm[m_StandbyAdapterId].writer));
457 #endif
458 } //failoverShm
459
460
setupLocalSegment()461 void SCI_Transporter::setupLocalSegment()
462 {
463 DBUG_ENTER("SCI_Transporter::setupLocalSegment");
464 Uint32 sharedSize = 0;
465 sharedSize =4096; //start of the buffer is page aligend
466
467 Uint32 sizeOfBuffer = m_BufferSize;
468
469 sizeOfBuffer -= sharedSize;
470
471 Uint32 * localReadIndex =
472 (Uint32*)m_SourceSegm[m_ActiveAdapterId].mappedMemory;
473 Uint32 * localWriteIndex = (Uint32*)(localReadIndex+ 1);
474 m_localStatusFlag = (Uint32*)(localReadIndex + 3);
475
476 char * localStartOfBuf = (char*)
477 ((char*)m_SourceSegm[m_ActiveAdapterId].mappedMemory+sharedSize);
478
479 * localReadIndex = 0;
480 * localWriteIndex = 0;
481
482 const Uint32 slack = MAX_MESSAGE_SIZE;
483
484 reader = new SHM_Reader(localStartOfBuf,
485 sizeOfBuffer,
486 slack,
487 localReadIndex,
488 localWriteIndex);
489
490 reader->clear();
491 DBUG_VOID_RETURN;
492 } //setupLocalSegment
493
setupRemoteSegment()494 void SCI_Transporter::setupRemoteSegment()
495 {
496 DBUG_ENTER("SCI_Transporter::setupRemoteSegment");
497 Uint32 sharedSize = 0;
498 sharedSize =4096; //start of the buffer is page aligned
499
500 Uint32 sizeOfBuffer = m_BufferSize;
501 const Uint32 slack = MAX_MESSAGE_SIZE;
502 sizeOfBuffer -= sharedSize;
503
504 Uint32 *segPtr = (Uint32*) m_TargetSegm[m_ActiveAdapterId].mappedMemory ;
505
506 Uint32 * remoteReadIndex = (Uint32*)segPtr;
507 Uint32 * remoteWriteIndex = (Uint32*)(segPtr + 1);
508 m_remoteStatusFlag = (Uint32*)(segPtr + 3);
509
510 char * remoteStartOfBuf = ( char*)((char*)segPtr+(sharedSize));
511
512 writer = new SHM_Writer(remoteStartOfBuf,
513 sizeOfBuffer,
514 slack,
515 remoteReadIndex,
516 remoteWriteIndex);
517
518 writer->clear();
519
520 m_TargetSegm[0].writer=writer;
521
522 if(createSequence(m_ActiveAdapterId)!=SCI_ERR_OK) {
523 report_error(TE_SCI_UNABLE_TO_CREATE_SEQUENCE);
524 DBUG_PRINT("error", ("Unable to create sequence on active"));
525 doDisconnect();
526 }
527 if (m_adapters > 1) {
528 segPtr = (Uint32*) m_TargetSegm[m_StandbyAdapterId].mappedMemory ;
529
530 Uint32 * remoteReadIndex2 = (Uint32*)segPtr;
531 Uint32 * remoteWriteIndex2 = (Uint32*) (segPtr + 1);
532 m_remoteStatusFlag2 = (Uint32*)(segPtr + 3);
533
534 char * remoteStartOfBuf2 = ( char*)((char *)segPtr+sharedSize);
535
536 /**
537 * setup a writer. writer2 is used to mirror the changes of
538 * writer on the standby
539 * segment, so that in the case of a failover, we can switch
540 * to the stdby seg. quickly.*
541 */
542 writer2 = new SHM_Writer(remoteStartOfBuf2,
543 sizeOfBuffer,
544 slack,
545 remoteReadIndex2,
546 remoteWriteIndex2);
547
548 * remoteReadIndex = 0;
549 * remoteWriteIndex = 0;
550 writer2->clear();
551 m_TargetSegm[1].writer=writer2;
552 if(createSequence(m_StandbyAdapterId)!=SCI_ERR_OK) {
553 report_error(TE_SCI_UNABLE_TO_CREATE_SEQUENCE);
554 DBUG_PRINT("error", ("Unable to create sequence on standby"));
555 doDisconnect();
556 }
557 }
558 DBUG_VOID_RETURN;
559 } //setupRemoteSegment
560
561 bool
init_local()562 SCI_Transporter::init_local()
563 {
564 DBUG_ENTER("SCI_Transporter::init_local");
565 if(!m_initLocal) {
566 if(initLocalSegment()!=SCI_ERR_OK){
567 NdbSleep_MilliSleep(10);
568 //NDB SHOULD TERMINATE AND COMPUTER REBOOTED!
569 report_error(TE_SCI_CANNOT_INIT_LOCALSEGMENT);
570 DBUG_RETURN(false);
571 }
572 m_initLocal=true;
573 }
574 DBUG_RETURN(true);
575 }
576
577 bool
init_remote()578 SCI_Transporter::init_remote()
579 {
580 DBUG_ENTER("SCI_Transporter::init_remote");
581 sci_error_t err;
582 Uint32 offset = 0;
583 if(!m_mapped ) {
584 DBUG_PRINT("info", ("Map remote segments"));
585 for(Uint32 i=0; i < m_adapters ; i++) {
586 m_TargetSegm[i].rhm[i].remoteHandle=0;
587 SCIConnectSegment(sciAdapters[i].scidesc,
588 &(m_TargetSegm[i].rhm[i].remoteHandle),
589 m_remoteNodes[i],
590 remoteSegmentId(localNodeId, remoteNodeId),
591 i,
592 0,
593 0,
594 0,
595 0,
596 &err);
597
598 if(err != SCI_ERR_OK) {
599 NdbSleep_MilliSleep(10);
600 DBUG_PRINT("error", ("Error connecting segment, err 0x%x", err));
601 DBUG_RETURN(false);
602 }
603 }
604 // Map the remote memory segment into program space
605 for(Uint32 i=0; i < m_adapters ; i++) {
606 m_TargetSegm[i].mappedMemory =
607 SCIMapRemoteSegment((m_TargetSegm[i].rhm[i].remoteHandle),
608 &(m_TargetSegm[i].rhm[i].map),
609 offset,
610 m_BufferSize,
611 NULL,
612 FLAGS,
613 &err);
614
615 if(err!= SCI_ERR_OK) {
616 DBUG_PRINT("error",
617 ("Cannot map a segment to the remote node %d. Error code 0x%x",
618 m_RemoteSciNodeId, err));
619 //NDB SHOULD TERMINATE AND COMPUTER REBOOTED!
620 report_error(TE_SCI_CANNOT_MAP_REMOTESEGMENT);
621 DBUG_RETURN(false);
622 }
623 }
624 m_mapped=true;
625 setupRemoteSegment();
626 setConnected();
627 DBUG_PRINT("info", ("connected and mapped to segment, remoteNode: %d",
628 remoteNodeId));
629 DBUG_PRINT("info", ("remoteSegId: %d",
630 remoteSegmentId(localNodeId, remoteNodeId)));
631 DBUG_RETURN(true);
632 } else {
633 DBUG_RETURN(getConnectionStatus());
634 }
635 }
636
637 bool
connect_client_impl(NDB_SOCKET_TYPE sockfd)638 SCI_Transporter::connect_client_impl(NDB_SOCKET_TYPE sockfd)
639 {
640 SocketInputStream s_input(sockfd);
641 SocketOutputStream s_output(sockfd);
642 char buf[256];
643 DBUG_ENTER("SCI_Transporter::connect_client_impl");
644 // Wait for server to create and attach
645 if (s_input.gets(buf, 256) == 0) {
646 DBUG_PRINT("error", ("No initial response from server in SCI"));
647 NDB_CLOSE_SOCKET(sockfd);
648 DBUG_RETURN(false);
649 }
650 if (!init_local()) {
651 NDB_CLOSE_SOCKET(sockfd);
652 DBUG_RETURN(false);
653 }
654
655 // Send ok to server
656 s_output.println("sci client 1 ok");
657
658 if (!init_remote()) {
659 NDB_CLOSE_SOCKET(sockfd);
660 DBUG_RETURN(false);
661 }
662 // Wait for ok from server
663 if (s_input.gets(buf, 256) == 0) {
664 DBUG_PRINT("error", ("No second response from server in SCI"));
665 NDB_CLOSE_SOCKET(sockfd);
666 DBUG_RETURN(false);
667 }
668 // Send ok to server
669 s_output.println("sci client 2 ok");
670
671 NDB_CLOSE_SOCKET(sockfd);
672 DBUG_PRINT("info", ("Successfully connected client to node %d",
673 remoteNodeId));
674 DBUG_RETURN(true);
675 }
676
677 bool
connect_server_impl(NDB_SOCKET_TYPE sockfd)678 SCI_Transporter::connect_server_impl(NDB_SOCKET_TYPE sockfd)
679 {
680 SocketOutputStream s_output(sockfd);
681 SocketInputStream s_input(sockfd);
682 char buf[256];
683 DBUG_ENTER("SCI_Transporter::connect_server_impl");
684
685 if (!init_local()) {
686 NDB_CLOSE_SOCKET(sockfd);
687 DBUG_RETURN(false);
688 }
689 // Send ok to client
690 s_output.println("sci server 1 ok");
691
692 // Wait for ok from client
693 if (s_input.gets(buf, 256) == 0) {
694 DBUG_PRINT("error", ("No response from client in SCI"));
695 NDB_CLOSE_SOCKET(sockfd);
696 DBUG_RETURN(false);
697 }
698
699 if (!init_remote()) {
700 NDB_CLOSE_SOCKET(sockfd);
701 DBUG_RETURN(false);
702 }
703 // Send ok to client
704 s_output.println("sci server 2 ok");
705 // Wait for ok from client
706 if (s_input.gets(buf, 256) == 0) {
707 DBUG_PRINT("error", ("No second response from client in SCI"));
708 NDB_CLOSE_SOCKET(sockfd);
709 DBUG_RETURN(false);
710 }
711
712 NDB_CLOSE_SOCKET(sockfd);
713 DBUG_PRINT("info", ("Successfully connected server to node %d",
714 remoteNodeId));
715 DBUG_RETURN(true);
716 }
717
createSequence(Uint32 adapterid)718 sci_error_t SCI_Transporter::createSequence(Uint32 adapterid) {
719 sci_error_t err;
720 SCICreateMapSequence((m_TargetSegm[adapterid].rhm[adapterid].map),
721 &(m_TargetSegm[adapterid].sequence),
722 SCI_FLAG_FAST_BARRIER,
723 &err);
724 return err;
725 } // createSequence()
726
disconnectLocal()727 bool SCI_Transporter::disconnectLocal()
728 {
729 DBUG_ENTER("SCI_Transporter::disconnectLocal");
730 sci_error_t err;
731 m_ActiveAdapterId=0;
732
733 /** Free resources used by a local segment
734 */
735
736 SCIUnmapSegment(m_SourceSegm[0].lhm[0].map,0,&err);
737 if(err!=SCI_ERR_OK) {
738 report_error(TE_SCI_UNABLE_TO_UNMAP_SEGMENT);
739 DBUG_PRINT("error", ("Unable to unmap segment"));
740 DBUG_RETURN(false);
741 }
742
743 SCIRemoveSegment((m_SourceSegm[m_ActiveAdapterId].localHandle),
744 FLAGS,
745 &err);
746
747 if(err!=SCI_ERR_OK) {
748 report_error(TE_SCI_UNABLE_TO_REMOVE_SEGMENT);
749 DBUG_PRINT("error", ("Unable to remove segment"));
750 DBUG_RETURN(false);
751 }
752 DBUG_PRINT("info", ("Local memory segment is unmapped and removed"));
753 DBUG_RETURN(true);
754 } // disconnectLocal()
755
756
disconnectRemote()757 bool SCI_Transporter::disconnectRemote() {
758 DBUG_ENTER("SCI_Transporter::disconnectRemote");
759 sci_error_t err;
760 for(Uint32 i=0; i<m_adapters; i++) {
761 /**
762 * Segment unmapped, disconnect from the remotely connected segment
763 */
764 SCIUnmapSegment(m_TargetSegm[i].rhm[i].map,0,&err);
765 if(err!=SCI_ERR_OK) {
766 report_error(TE_SCI_UNABLE_TO_UNMAP_SEGMENT);
767 DBUG_PRINT("error", ("Unable to unmap segment"));
768 DBUG_RETURN(false);
769 }
770
771 SCIDisconnectSegment(m_TargetSegm[i].rhm[i].remoteHandle,
772 FLAGS,
773 &err);
774 if(err!=SCI_ERR_OK) {
775 report_error(TE_SCI_UNABLE_TO_DISCONNECT_SEGMENT);
776 DBUG_PRINT("error", ("Unable to disconnect segment"));
777 DBUG_RETURN(false);
778 }
779 DBUG_PRINT("info", ("Remote memory segment is unmapped and disconnected"));
780 }
781 DBUG_RETURN(true);
782 } // disconnectRemote()
783
784
~SCI_Transporter()785 SCI_Transporter::~SCI_Transporter() {
786 DBUG_ENTER("SCI_Transporter::~SCI_Transporter");
787 // Close channel to the driver
788 doDisconnect();
789 DBUG_VOID_RETURN;
790 } // ~SCI_Transporter()
791
closeSCI()792 void SCI_Transporter::closeSCI() {
793 // Termination of SCI
794 sci_error_t err;
795 DBUG_ENTER("SCI_Transporter::closeSCI");
796
797 // Disconnect and remove remote segment
798 disconnectRemote();
799
800 // Unmap and remove local segment
801
802 disconnectLocal();
803
804 // Closes an SCI virtual device
805 SCIClose(activeSCIDescriptor, FLAGS, &err);
806
807 if(err != SCI_ERR_OK) {
808 DBUG_PRINT("error",
809 ("Cannot close SCI channel to the driver. Error code 0x%x",
810 err));
811 }
812 SCITerminate();
813 DBUG_VOID_RETURN;
814 } // closeSCI()
815
816 enum SciStatus {
817 SCIDISCONNECT = 1,
818 SCICONNECTED = 2
819 };
820
821 bool
getConnectionStatus()822 SCI_Transporter::getConnectionStatus() {
823 if(*m_localStatusFlag == SCICONNECTED &&
824 (*m_remoteStatusFlag == SCICONNECTED ||
825 ((m_adapters > 1) &&
826 *m_remoteStatusFlag2 == SCICONNECTED)))
827 return true;
828 else
829 return false;
830 }
831
832 void
setConnected()833 SCI_Transporter::setConnected() {
834 *m_remoteStatusFlag = SCICONNECTED;
835 if (m_adapters > 1) {
836 *m_remoteStatusFlag2 = SCICONNECTED;
837 }
838 *m_localStatusFlag = SCICONNECTED;
839 }
840
841 void
setDisconnect()842 SCI_Transporter::setDisconnect() {
843 if(getLinkStatus(m_ActiveAdapterId))
844 *m_remoteStatusFlag = SCIDISCONNECT;
845 if (m_adapters > 1) {
846 if(getLinkStatus(m_StandbyAdapterId))
847 *m_remoteStatusFlag2 = SCIDISCONNECT;
848 }
849 }
850
851 bool
checkConnected()852 SCI_Transporter::checkConnected() {
853 if (*m_localStatusFlag == SCIDISCONNECT) {
854 return false;
855 }
856 else
857 return true;
858 }
859
860 static bool init = false;
861
862 bool
initSCI()863 SCI_Transporter::initSCI() {
864 DBUG_ENTER("SCI_Transporter::initSCI");
865 if(!init){
866 sci_error_t error;
867 // Initialize SISCI library
868 SCIInitialize(0, &error);
869 if(error != SCI_ERR_OK) {
870 DBUG_PRINT("error", ("Cannot initialize SISCI library."));
871 DBUG_PRINT("error",
872 ("Inconsistency between SISCI library and SISCI driver. Error code 0x%x",
873 error));
874 DBUG_RETURN(false);
875 }
876 init = true;
877 }
878 DBUG_RETURN(true);
879 }
880