SCI_Transporter.hpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:12k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #ifndef SCI_Transporter_H 
  14. #define SCI_Transporter_H 
  15. #include "Transporter.hpp" 
  16. #include "SHM_Buffer.hpp" 
  17.  
  18.  
  19. #include <sisci_api.h> 
  20. #include <sisci_error.h> 
  21. #include <sisci_types.h> 
  22.  
  23. #include <ndb_types.h> 
  24.  
  25. /** 
  26.  *  The SCI Transporter 
  27.  * 
  28.  *  The design goal of the SCI transporter is to deliver high performance  
  29.  *  data transfers (low latency, high bandwidth) combined with very high  
  30.  *  availability (failover support).  
  31.  *  High performance is an inherit feature of SCI and the, whereas failover  
  32.  *  support is implemented at the application level.  
  33.  *  In SCI the programming model is similar to the shared memory paradigm.  
  34.  *  A process on one node (A) allocates a memory segment and import the 
  35.  *  segment to  its virtual address space. Another node (B) can connect to  
  36.  *  the segment and map this segment into its virtual address space.  
  37.  *  If A writes data to the segment, then B can read it and vice versa, through 
  38.  *  ordinary loads and stores. This is also called PIO (programmable IO), and  
  39.  *  is one thing that distinguish SCI from other interconnects such as, 
  40.  *  ethernet, Gig-e, Myrinet, and Infiniband. By using PIO, lower network  
  41.  *  latency is achieved, compared to the interconnects mentioned above. 
  42.  *  In order for NDB to utilize SCI,  the SCI transporter relies on the  
  43.  *  SISCI api. The SISCI api provides a high level abstraction to the low 
  44.  *  level SCI driver called PCISCI driver. 
  45.  *  The SISCI api provides functions to setup, export, and import 
  46.  *  memory segments in a process virtual address space, and also functions to 
  47.  *  guarantee the correctness of data transfers between nodes. Basically, the  
  48.  *  
  49.  *  In NDB Cluster, each SCI transporter creates a local segment  
  50.  *  that is mapped into the virtual address space. After the creation of the  
  51.  *  local segment, the SCI transporter connects to a segment created by another 
  52.  *  transporter at a remote node, and the maps the remote segment into its  
  53.  *  virtual address space. However, since NDB Cluster relies on redundancy 
  54.  *  at the network level, by using dual SCI adapters communica 
  55.  * 
  56.  * 
  57.  */ 
  58. /**  
  59.  * class SCITransporter 
  60.  * @brief - main class for the SCI transporter. 
  61.  */ 
  62. class SCI_Transporter : public Transporter { 
  63.   friend class TransporterRegistry; 
  64. public:   
  65.  
  66.   /** 
  67.    * Init the transporter. Allocate sendbuffers and open a SCI virtual device 
  68.    * for each adapter. 
  69.    * @return true if successful, otherwize false 
  70.    */ 
  71.   bool initTransporter();                 
  72.    
  73.    
  74.   /** 
  75.    * Creates a sequence for error checking. 
  76.    * @param adapterid the adapter on which to create a new sequence. 
  77.    * @return SCI_ERR_OK if ok, otherwize something else. 
  78.    */ 
  79.   sci_error_t createSequence(Uint32 adapterid);      
  80.    
  81.    
  82.   /** 
  83.    * starts a sequence for error checking. 
  84.    * The actual checking that a sequence is correct is done implicitly 
  85.    * in SCIMemCpy (in doSend).  
  86.    * @param adapterid the adapter on which to start the sequence. 
  87.    * @return SCI_ERR_OK if ok, otherwize something else. 
  88.    */ 
  89.   sci_error_t startSequence(Uint32 adapterid);          
  90.  
  91.  
  92.   /** Initiate Local Segment: create a memory segment, 
  93.    * prepare a memory segment, map the local segment  
  94.    * into  memory space and make segment available. 
  95.    * @return SCI_ERR_OK if ok, otherwize something else. 
  96.    */ 
  97.   sci_error_t initLocalSegment();        
  98.  
  99.   /** 
  100.    * Calculate the segment id for the remote segment 
  101.    * @param localNodeId - local id (e.g. 1 = mgm , 2 = ndb.2 etc.) 
  102.    * @param remoteNodeId - remote id (e.g. 1 = mgm , 2 = ndb.2 etc.) 
  103.    * @return a segment id 
  104.    */ 
  105.   Uint32  remoteSegmentId(Uint16 localNodeId, Uint16 remoteNodeId);     
  106.  
  107.   // Get local segment id (inline) 
  108.   Uint32  hostSegmentId(Uint16 localNodeId, Uint16 remoteNodeId); 
  109.    
  110.   /** 
  111.    * closeSCI closes the SCI virtual device 
  112.    */ 
  113.   void closeSCI();                       
  114.  
  115.  
  116.   /** 
  117.    * Check the status of the remote node, 
  118.    * if it is connected or has disconnected 
  119.    * @return true if connected, otherwize false. 
  120.    */ 
  121.   bool checkConnected(); 
  122.  
  123.   /** 
  124.    * Check if the segment are properly connected to each other (remotely 
  125.    * and locally).  
  126.    * @return True if the both the local segment is mapped and the  
  127.    * remote segment is mapped. Otherwize false. 
  128.    */ 
  129.   bool getConnectionStatus(); 
  130.   virtual Uint32 get_free_buffer() const;   
  131. private: 
  132.   SCI_Transporter(TransporterRegistry &t_reg,
  133.                   const char *local_host,
  134.                   const char *remote_host,
  135.                   int port,
  136.                   Uint32 packetSize,  
  137.   Uint32 bufferSize, 
  138.   Uint32 nAdapters, 
  139.   Uint16 remoteSciNodeId0,  
  140.   Uint16 remoteSciNodeId1,  
  141.   NodeId localNodeID,  
  142.   NodeId remoteNodeID,  
  143.   bool checksum,  
  144.   bool signalId, 
  145.   Uint32 reportFreq = 4096); 
  146.  
  147.    /** 
  148.    * Destructor. Disconnects the transporter. 
  149.    */ 
  150. ~SCI_Transporter();    
  151.   bool m_mapped; 
  152.   bool m_initLocal; 
  153.   bool m_sciinit; 
  154.   Uint32 m_swapCounter; 
  155.   Uint32 m_failCounter; 
  156.   /** 
  157.    * For statistics on transfered packets  
  158.    */   
  159. //#ifdef DEBUG_TRANSPORTER 
  160. #if 1
  161.   Uint32 i1024; 
  162.   Uint32 i2048; 
  163.   Uint32 i2049; 
  164.   Uint32 i10242048; 
  165.   Uint32 i20484096; 
  166.   Uint32 i4096; 
  167.   Uint32 i4097; 
  168. #endif
  169.  
  170.   volatile Uint32 * m_localStatusFlag; 
  171.   volatile Uint32 * m_remoteStatusFlag; 
  172.   volatile Uint32 * m_remoteStatusFlag2; 
  173.   struct {
  174.     Uint32 * m_buffer;       // The buffer
  175.     Uint32 m_dataSize;       // No of words in buffer
  176.     Uint32 m_sendBufferSize; // Buffer size
  177.     Uint32 m_forceSendLimit; // Send when buffer is this full
  178.   } m_sendBuffer;
  179.   SHM_Reader * reader; 
  180.   SHM_Writer * writer; 
  181.   SHM_Writer * writer2; 
  182.  
  183.   /** 
  184.    * Statistics 
  185.    */ 
  186.   Uint32 m_reportFreq; 
  187.  
  188.  
  189.   Uint32 m_adapters;   
  190.   Uint32 m_numberOfRemoteNodes; 
  191.  
  192.   Uint16 m_remoteNodes[2]; 
  193.  
  194.   typedef struct SciAdapter { 
  195.     sci_desc_t scidesc; 
  196.     Uint32 localSciNodeId; 
  197.     bool linkStatus; 
  198.   } SciAdapter; 
  199.  
  200.   SciAdapter* sciAdapters; 
  201.   Uint32 m_ActiveAdapterId; 
  202.   Uint32 m_StandbyAdapterId; 
  203.  
  204.   typedef struct sourceSegm { 
  205.     sci_local_segment_t localHandle; // Handle to local segment to be mapped
  206.     struct localHandleMap { 
  207.       sci_map_t map;                   // Handle to the new mapped segment.  
  208.                                        // 2 = max adapters in one node 
  209.     } lhm[2];  
  210.      
  211.     volatile void *mappedMemory; // Used when reading 
  212.   } sourceSegm; 
  213.  
  214.   typedef struct targetSegm { 
  215.     struct remoteHandleMap { 
  216.       sci_remote_segment_t remoteHandle; //Handle to local segment to be mapped
  217.       sci_map_t          map;            //Handle to the new mapped segment 
  218.     } rhm[2]; 
  219.  
  220.     sci_sequence_status_t m_SequenceStatus;    // Used for error checking 
  221.     sci_sequence_t sequence;  
  222.     volatile void * mappedMemory;              // Used when writing 
  223.     SHM_Writer * writer; 
  224.   } targetSegm; 
  225.    
  226.   sci_sequence_status_t m_SequenceStatus;    // Used for error checking 
  227.  
  228.  
  229.   // Shared between all SCI users  active=(either prim or second) 
  230.   sci_desc_t     activeSCIDescriptor;    
  231.   
  232.   sourceSegm*     m_SourceSegm;               // Local segment reference 
  233.   targetSegm*     m_TargetSegm;               // Remote segment reference 
  234.   
  235.   Uint32 m_LocalAdapterId;    // Adapter Id  
  236.   Uint16 m_LocalSciNodeId;    // The SCI-node Id of this machine (adapter 0) 
  237.   Uint16 m_LocalSciNodeId1;   // The SCI-node Id of this machine (adapter 1) 
  238.   Uint16 m_RemoteSciNodeId;   // The SCI-node Id of remote machine (adapter 0) 
  239.   Uint16 m_RemoteSciNodeId1;  // The SCI-node Id of remote machine (adapter 1) 
  240.  
  241.   Uint32 m_PacketSize;        // The size of each data packet 
  242.   Uint32 m_BufferSize;        // Mapped SCI buffer size  
  243.  
  244.   Uint32 * getWritePtr(Uint32 lenBytes, Uint32 prio);
  245.   void updateWritePtr(Uint32 lenBytes, Uint32 prio);
  246.   /** 
  247.    * doSend. Copies the data from the source (the send buffer) to the  
  248.    * shared mem. segment. 
  249.    * Sequences are used for error checking. 
  250.    * If an error occurs, the transfer is retried. 
  251.    * If the link that we need to swap to is broken, we will disconnect.
  252.    * @return Returns true if datatransfer ok. If not retriable 
  253.    * then false is returned. 
  254.    */ 
  255.   bool doSend();   
  256.  
  257.   /** 
  258.    * @param adapterNo  the adapter for which to retrieve the node id. 
  259.    * @return Returns the node id for an adapter. 
  260.    */ 
  261.   Uint32 getLocalNodeId(Uint32 adapterNo); 
  262.              
  263.   bool hasDataToRead() const { 
  264.     return reader->empty() == false;
  265.   } 
  266.  
  267.   bool hasDataToSend() const {
  268.     return m_sendBuffer.m_dataSize > 0;
  269.   }
  270.   /**  
  271.    * Make the local segment unavailable, no new connections will be accepted. 
  272.    * @return Returns true if the segment was successfully disconnected. 
  273.    */ 
  274.   bool disconnectLocal();                   
  275.  
  276.   /**  
  277.    * Make the local segment unavailable, no new connections will be accepted. 
  278.    * @return Returns true if the segment was successfully disconnected. 
  279.    */ 
  280.   bool disconnectRemote();       
  281.    
  282.   void resetToInitialState(); 
  283.              
  284.   /** 
  285.    *  It is always possible to send data with SCI! 
  286.    *  @return True (always) 
  287.    */ 
  288.   bool sendIsPossible(struct timeval * timeout); 
  289.    
  290.   void getReceivePtr(Uint32 ** ptr, Uint32 ** eod){
  291.     reader->getReadPtr(* ptr, * eod);
  292.   }
  293.   void updateReceivePtr(Uint32 *ptr){
  294.     reader->updateReadPtr(ptr);
  295.   }
  296.  
  297.   /** 
  298.    *   Corresponds to SHM_Transporter::setupBuffers() 
  299.    *   Initiates the start pointer of the buffer and read pointers. 
  300.    *   Initiate the localSegment for the SHM reader. 
  301.    */ 
  302.   void setupLocalSegment();   
  303.  
  304.   /** 
  305.    *  Initiate the remoteSegment for the SHM writer 
  306.    */ 
  307.   void setupRemoteSegment();   
  308.  
  309.   /** 
  310.    * Set the connect flag in the remote memory segment (write through) 
  311.    */ 
  312.   void setConnected();   
  313.    
  314.   /** 
  315.    * Set the disconnect flag in the remote memory segment (write through) 
  316.    */ 
  317.   void setDisconnect();   
  318.    
  319.   /** 
  320.    * Check if there is a link between the adapter and the switch 
  321.    * @param adapterNo  the adapter for which to retrieve the link status. 
  322.    * @return Returns true if there is a link between adapter and switch. 
  323.    * Otherwize false is returned and the cables must be checked. 
  324.    */ 
  325.   bool getLinkStatus(Uint32 adapterNo); 
  326.  
  327.   /** 
  328.    * failoverShmWriter takes the state of the active writer and inserts into 
  329.    * the standby writer. 
  330.    */ 
  331.   void failoverShmWriter(); 
  332.  
  333.   bool init_local();
  334.   bool init_remote();
  335. protected: 
  336.    
  337.   /** Perform a connection between segment 
  338.    * This is a client node, trying to connect to a remote segment. 
  339.    * @param timeout, the time the connect thread sleeps before  
  340.    * retrying. 
  341.    * @return Returns true on success, otherwize falser 
  342.    */ 
  343.   bool connect_server_impl(NDB_SOCKET_TYPE sockfd);
  344.   bool connect_client_impl(NDB_SOCKET_TYPE sockfd);
  345.  
  346.   /** 
  347.    *  We will disconnect if: 
  348.    *  -# the other node has disconnected from us 
  349.    *  -# unrecoverable error in transmission, on both adapters 
  350.    *  -# if we are shutdown properly 
  351.    */ 
  352.   void disconnectImpl(); 
  353.  
  354.   static bool initSCI(); 
  355. }; 
  356.  
  357.  
  358. /** The theLocalAdapterId combined with the theRemoteNodeId constructs 
  359.  *  (SCI ids)* a unique identifier for the local segment 
  360.  */ 
  361. inline  
  362. Uint32 
  363. SCI_Transporter::hostSegmentId(Uint16 SciLocalNodeId,  
  364.        Uint16 SciRemoteNodeId) { 
  365.  
  366.   return (SciLocalNodeId << 16) | SciRemoteNodeId;  
  367.  
  368. /** The theLocalAdapterId combined with the theRemoteNodeId constructs 
  369.  *  (SCI ids)* a unique identifier for the remote segment 
  370.  */ 
  371. inline  
  372. Uint32 
  373. SCI_Transporter::remoteSegmentId(Uint16 SciLocalNodeId, 
  374.  Uint16 SciRemoteNodeId) { 
  375.    
  376.   return (SciRemoteNodeId << 16) | SciLocalNodeId; 
  377.  
  378.  
  379. #endif