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