Example #1
0
/**
   north_lbg_createIndex

  create a AF UNIX context given by index 
   That function tries to allocate a free PDP
   context. In case of success, it returns the
   index of the Transaction context.

@param     : north_lbg_ctx_id is the reference of the context
@retval   : MS controller reference (if OK)
retval     -1 if out of context.
 */
uint32_t north_lbg_createIndex(uint32_t north_lbg_ctx_id) {
    north_lbg_ctx_t *p;

    /*
     **  Get the first free context
     */
    p = north_lbg_getObjCtx_p(north_lbg_ctx_id);
    if (p == NULL) {
        severe( "MS ref out of range: %u", north_lbg_ctx_id );
        return RUC_NOK;
    }
    /*
     ** return an error if the context is not free
     */
    if (p->free == FALSE) {
        severe( "the context is not free : %u", north_lbg_ctx_id );
        return RUC_NOK;
    }
    /*
     **  reinitilisation of the context
     */
    north_lbg_ctxInit(p, FALSE);
    /*
     ** remove it for the linked list
     */
    north_lbg_context_allocated++;


    p->free = FALSE;
    ruc_objRemove((ruc_obj_desc_t*) p);

    return RUC_OK;
}
Example #2
0
 /**
*  API to re-configure the destination ports of a load balancing group.
   The load balancing group must have been configured previously with north_lbg_configure_af_inet() 
  
 @param lbg_idx index of the load balancing group
 @param remote_ip_p table of new destination ports
 @param nb_instances number of instances in remote_ip_p table
 
  @retval -1 when LBG reference does not exist
  @retval 0 else
*/
int north_lbg_re_configure_af_inet_destination_port(int lbg_idx,north_remote_ip_list_t *remote_ip_p, int  nb_instances)
{
  north_lbg_ctx_t  *lbg_p;
  int    i;
  north_lbg_entry_ctx_t *entry_p;
    
  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    severe("north_lbg_re_configure_af_inet_destination_port bad lbg idx %d", lbg_idx);
    return -1;
  }
  /* Do not change the number of instance */  
  if (nb_instances != lbg_p->nb_entries_conf)
  {
    /*
    ** no instances!!
    */
    severe("north_lbg_re_configure_af_inet_destination_port %d instances while waiting for %d",
                    nb_instances, lbg_p->nb_entries_conf);
    return -1;   
  }

  /* Modify the destination ports of each entrie */
  entry_p = lbg_p->entry_tb;
  for (i = 0; i < nb_instances ; i++,entry_p++) {
    af_inet_sock_client_modify_destination_port(entry_p->sock_ctx_ref, remote_ip_p[i].remote_port_host); 
  }
  return 0;
}
Example #3
0
/**
*  Set the lbg entry to use when sending

  @param lbg_idx : reference of the load balancing group


  @retval none
*/
void north_lbg_set_active_entry(int  lbg_idx, int sock_idx_in_lbg)
{
  north_lbg_ctx_t  *lbg_p;
  
  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    severe("north_lbg_set_active_entry: no such instance %d ",lbg_idx);
    return;
  }
  //info("JPM lbg %d %s Set active %d",lbg_idx,lbg_p->name,sock_idx_in_lbg);
  
  lbg_p->active_lbg_entry = sock_idx_in_lbg;
  
  /*
  ** When the socket becomes active, stop the polling
  */ 
  if (lbg_p->active_lbg_entry != -1) {
    af_unix_ctx_generic_t *sock_p = af_unix_getObjCtx_p(lbg_p->entry_tb[sock_idx_in_lbg].sock_ctx_ref);
    if (sock_p == NULL)
    {
      severe("north_lbg_set_active_entry: no such socket %d in lbg %d entry %d",
              lbg_p->entry_tb[sock_idx_in_lbg].sock_ctx_ref,
	      lbg_idx,sock_idx_in_lbg);
      return;
    }    
    sock_p->cnx_supevision.s.check_cnx_rq = 0;
  }
  return;  
}
Example #4
0
/*
 ** Procedures to set rechain_when_lbg_gets_down indicator
 * @param  idx  index of the load balancing group
 */
void north_lbg_rechain_when_lbg_gets_down(int idx) {
    north_lbg_ctx_t * lbg;

    lbg = north_lbg_getObjCtx_p(idx);
    if (lbg == NULL) return;

    lbg->rechain_when_lbg_gets_down = 1;
}
Example #5
0
/**
*  create a north load balancing object with AF_INET

  @param lbg_idx : reference of the load balancing group
  @param buf_p: pointer to the buffer to send
  @param rsp_size : expected response size in byte
  @param disk_time: estimated disk_time in us
  
  retval 0 : success
  retval -1 : error
*/
int north_lbg_send_with_shaping(int  lbg_idx,void *buf_p,uint32_t rsp_size,uint32_t disk_time)
{                             
  north_lbg_ctx_t  *lbg_p;
  int ret = 0;


  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    severe("north_lbg_send: no such instance %d ",lbg_idx);
    return -1;
  }
  if ((lbg_p->state == NORTH_LBG_SHUTTING_DOWN) || (lbg_p->free == TRUE))
  {
     return -1;
  }
  /*
  ** we have the context, search for a valid entry
  */
  if (lbg_p->state == NORTH_LBG_DOWN)
  {
    /*
    ** Insert the buffer in the global pending list of the load balancing froup
    */
    ruc_objInsertTail((ruc_obj_desc_t*)&lbg_p->xmitList[0],(ruc_obj_desc_t*)buf_p);  
    /*
    ** update statistics
    */
    lbg_p->stats.xmitQueuelen++;     
    return 0;  
  }
  /*
  ** check if the main queue is empty if the queue is not empty just queue our message
  ** at the tail of the load balancer main queue
  */
  if (!ruc_objIsEmptyList((ruc_obj_desc_t*)&lbg_p->xmitList[0]))
  {
     /*
     ** queue the message at the tail
     */
     ruc_objInsertTail((ruc_obj_desc_t*)&lbg_p->xmitList[0],(ruc_obj_desc_t*)buf_p);  
    /*
    ** update statistics
    */
    lbg_p->stats.xmitQueuelen++;     
    return 0;  
  }
  /*
  ** call the traffic shaper
  */
  ret = trshape_queue_buf(0,buf_p,rsp_size,disk_time,north_lbg_send_from_shaper,lbg_idx);
  return ret;
}
Example #6
0
/**
*  Tells whether the lbg target is local to this server or not

  @param entry_idx : index of the entry that must be set
  @param *p  : pointer to the bitmap array

  @retval none
*/
int north_lbg_is_local(int  lbg_idx)
{
  north_lbg_ctx_t  *lbg_p;
  
  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    warning("north_lbg_is_local: no such instance %d ",lbg_idx);
    return 0;
  }
  return lbg_p->local;
}
Example #7
0
/**
*  Set the lbg mode in active/standby

  @param lbg_idx : reference of the load balancing group


  @retval none
*/
int north_lbg_get_active_standby_mode(int  lbg_idx)
{
  north_lbg_ctx_t  *lbg_p;
  
  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    return 0;
  }

  return lbg_p->active_standby_mode;
}
Example #8
0
/**
*  Set the lbg mode in active/standby

  @param lbg_idx : reference of the load balancing group


  @retval none
*/
void north_lbg_set_active_standby_mode(int  lbg_idx)
{
  north_lbg_ctx_t  *lbg_p;
  
  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    warning("north_lbg_set_active_standby_mode: no such instance %d ",lbg_idx);
    return;
  }

  lbg_p->active_standby_mode = 1;
}
Example #9
0
/**
*  API that provide the current state of a load balancing Group

 @param lbg_idx : index of the load balancing group
 
 @retval   1 : available
 @retval   0 : unavailable
*/
int north_lbg_is_available(int lbg_idx)
{

  north_lbg_ctx_t  *lbg_p;

  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    warning("north_lbg_is_available: no such instance %d ",lbg_idx);
    return 0;
  }
  if (lbg_p->state != NORTH_LBG_UP) return 0;
  return lbg_p->available_state;
}
Example #10
0
/**
*  Get the lbg entry to use when sending

  @param lbg_idx : reference of the load balancing group


  @retval none
*/
int north_lbg_get_active_entry(int  lbg_idx)
{
  north_lbg_ctx_t  *lbg_p;
  
  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    warning("north_lbg_get_active_entry: no such instance %d ",lbg_idx);
    return -1;
  }
  //info("JPM lbg %d %s Get active %d",lbg_idx,lbg_p->name,lbg_p->active_lbg_entry);

  return lbg_p->active_lbg_entry;
}
Example #11
0
/**
*  API that provide the current state of a load balancing Group

 @param lbg_idx : index of the load balancing group
 
 @retval    NORTH_LBG_DEPENDENCY : lbg is idle or the reference is out of range
 @retval    NORTH_LBG_UP : at least one connection is UP
 @retval    NORTH_LBG_DOWN : all the connection are down
*/
int north_lbg_get_state(int lbg_idx)
{

  north_lbg_ctx_t  *lbg_p;


  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    warning("north_lbg_get_state: no such instance %d ",lbg_idx);
    return NORTH_LBG_DEPENDENCY;
  }
  return lbg_p->state;

}
Example #12
0
/**
*  Configure the TMO of the application for connexion supervision
   
   @param lbg_idx: reference of the load balancing group
   @param tmo_sec : timeout value

  retval 0 : success
  retval -1 : error
*/
int  north_lbg_set_application_tmo4supervision(int lbg_idx,int tmo_sec)
{
  north_lbg_ctx_t  *lbg_p;
    
  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    severe("north_lbg_set_application_tmo4supervision bad lbg idx %d", lbg_idx);
    return -1;
  }
  /*
  ** save the reference of the callback in the lbg context
  */
  lbg_p->tmo_supervision_in_sec = tmo_sec;
  return 0;

}
Example #13
0
 /**
*  API to configure a load balancing group.
   The load balancing group must have been created previously with north_lbg_create_no_conf() 
  
 @param lbg_idx             Index of the load balancing group
 @param next_global_entry_idx_p Pointer to the next lbg entry to select
 
  @retval >= reference of the load balancer object
  @retval < 0 error (out of context ??)
*/
int north_lbg_set_next_global_entry_idx_p(int lbg_idx, int * next_global_entry_idx_p)
{
  north_lbg_ctx_t  *lbg_p;
  
  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    warning("north_lbg_set_next_global_entry_idx_p: no such instance %d ",lbg_idx);
    return -1;
  }

  lbg_p->next_global_entry_idx_p = next_global_entry_idx_p;
  * next_global_entry_idx_p = 0;

  return 0;

} 
Example #14
0
/**
*  API that provide the current state of a load balancing Group

 @param lbg_idx : index of the load balancing group
 
 @retval   none
*/
void north_lbg_update_available_state(uint32_t lbg_idx)
{

  north_lbg_ctx_t  *lbg_p;
  
  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    warning("north_lbg_update_available_state: no such instance %d ",lbg_idx);
    return;
  }
  if (lbg_p->userPollingCallBack == NULL) return;
  
  int    i;
  north_lbg_entry_ctx_t *entry_p;
  af_unix_ctx_generic_t *sock_p ;
 
  /* configure each stream connection */
  entry_p = lbg_p->entry_tb;
  for (i = 0; i < lbg_p->nb_entries_conf ; i++,entry_p++) {
     /*
     ** get the reference from idx
     */
     sock_p = af_unix_getObjCtx_p(entry_p->sock_ctx_ref);
     if (sock_p == NULL)
     {
        continue;
     }
     if (sock_p->cnx_availability_state == AF_UNIX_CNX_AVAILABLE)
     {
       lbg_p->available_state = 1;
       /*
       ** for the future when we will move the supervision contexts in the load balancer
       ** we change the state of the global availability of the LBG to STORCLI_LBG_RUNNING
       ** Up to now all that code is in storcli.
       */
       
       return;
     }
   }
   lbg_p->available_state = 0;
}  
Example #15
0
/**
*  Attach a supervision Application callback with the load balancing group
   That callback is configured on each entry of the LBG
   
   @param lbg_idx: reference of the load balancing group
   @param supervision_callback supervision_callback

  retval 0 : success
  retval -1 : error
*/
int  north_lbg_attach_application_supervision_callback(int lbg_idx,af_stream_poll_CBK_t supervision_callback)
{
  north_lbg_ctx_t  *lbg_p;
  int ret;
    
  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    severe("north_lbg_attach_application_supervision_callback bad lbg idx %d", lbg_idx);
    return -1;
  }
  /*
  ** save the reference of the callback in the lbg context
  */
  lbg_p->userPollingCallBack = supervision_callback;
  if (lbg_p->nb_entries_conf== 0) return 0;
  ret = north_lbg_attach_app_sup_cbk_on_entries(lbg_p);
  return ret;

}
Example #16
0
/**
   delete a load balancer
   
   That function is intended to be called when
   a Transaction context is deleted. It returns the
   Transaction context to the free list. The delete
   procedure of the MS automaton and
   controller are called by that service.

   If the Transaction context is out of limit, and 
   error is returned.

@param     : load balancer object index
@retval   : RUC_OK : context has been deleted
@retval     RUC_NOK : out of limit index.
 */
uint32_t north_lbg_free_from_idx(uint32_t north_lbg_ctx_id) {
    north_lbg_ctx_t *p;

    if (north_lbg_ctx_id >= north_lbg_context_count) {
        /*
         ** index is out of limits
         */
        return RUC_NOK;
    }
    /*
     ** get the reference from idx
     */
    p = north_lbg_getObjCtx_p(north_lbg_ctx_id);
    /*
     **  remove the xmit block
     */
    //   ruc_objRemove((ruc_obj_desc_t *)&p->xmitCtx);

    /*
     ** remove it from the active list
     */
    ruc_objRemove((ruc_obj_desc_t*) p);
    p->state = NORTH_LBG_DEPENDENCY;

    /*
     **  insert it in the free list
     */
    north_lbg_context_allocated--;


    p->free = TRUE;
    ruc_objInsertTail((ruc_obj_desc_t*) north_lbg_context_freeListHead,
            (ruc_obj_desc_t*) p);

    return RUC_OK;

}
Example #17
0
/**
*  Get the IP@ of active entry of the lbg

  @param lbg_idx : reference of the load balancing group


  @retval != 0 IP@ of the active export
  @retval == 0 no IP@
*/
uint32_t north_lbg_get_remote_ip_address(int  lbg_idx)
{
  north_lbg_ctx_t  *lbg_p;
  
  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    return 0;
  }

  if (lbg_p->active_standby_mode < 0) return 0;  
  /*
  ** When the socket becomes active, stop the polling
  */ 
  if (lbg_p->active_lbg_entry != -1) {
    af_unix_ctx_generic_t *sock_p = af_unix_getObjCtx_p(lbg_p->entry_tb[lbg_p->active_lbg_entry].sock_ctx_ref);
    if (sock_p == NULL)
    {
      return 0;
    }    
    return (sock_p->remote_ipaddr_host);
  }
  return 0;
}
Example #18
0
/**
*  create a north load balancing object with AF_INET

  @param lbg_idx : reference of the load balancing group
  @param buf_p: pointer to the buffer to send
  
  retval 0 : success
  retval -1 : error
*/
int north_lbg_send(int  lbg_idx,void *buf_p)
{                             
  north_lbg_ctx_t  *lbg_p;
  int entry_idx;
  int ret = 0;

  /*
  ** remove the buffer from any pending list
  */
  ruc_objRemove((ruc_obj_desc_t*)buf_p);
  
  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    severe("north_lbg_send: no such instance %d ",lbg_idx);
    return -1;
  }
  if ((lbg_p->state == NORTH_LBG_SHUTTING_DOWN) || (lbg_p->free == TRUE))
  {
     return -1;
  }
reloop:
  /*
  ** we have the context, search for a valid entry
  */
  if (lbg_p->state == NORTH_LBG_DOWN)
  {
    /*
    ** Insert the buffer in the global pending list of the load balancing froup
    */
    ruc_objInsertTail((ruc_obj_desc_t*)&lbg_p->xmitList[0],(ruc_obj_desc_t*)buf_p);  
    /*
    ** update statistics
    */
    lbg_p->stats.xmitQueuelen++;     
    return 0;  
  }
  /*
  ** check if the main queue is empty if the queue is not empty just queue our message
  ** at the tail of the load balancer main queue
  */
  if (!ruc_objIsEmptyList((ruc_obj_desc_t*)&lbg_p->xmitList[0]))
  {
     /*
     ** queue the message at the tail
     */
     ruc_objInsertTail((ruc_obj_desc_t*)&lbg_p->xmitList[0],(ruc_obj_desc_t*)buf_p);  
    /*
    ** update statistics
    */
    lbg_p->stats.xmitQueuelen++;     
    return 0;  
  }
  
  
  /*
  ** Check whether this LBG is in active/standby mode
  ** in this case send the message on the active connection
  */
  if (lbg_p->active_standby_mode == 1) {
  
    /*
    ** No actibve entry elected. The LBG should nbe down !!!
    */
    if (lbg_p->active_lbg_entry < 0) {
      /*
      ** queue the message at the tail
      */
      ruc_objInsertTail((ruc_obj_desc_t*)&lbg_p->xmitList[0],(ruc_obj_desc_t*)buf_p);  
      /*
      ** update statistics
      */
      lbg_p->stats.xmitQueuelen++;     
      return 0;  
    }
    
    /*
    ** Get the active socket to send on
    */
    entry_idx = lbg_p->active_lbg_entry;
  }
  
  else {

     /*
     ** OK there is at least one entry that is free, so get the next valid entry
     */
     entry_idx = north_lbg_get_next_valid_entry(lbg_p);
     if (entry_idx < 0)
     {
       /*
       ** that situation must not occur since there is at leat one entry that is UP!!!!
       */
   //    RUC_WARNING(-1);
       return -1;    
     }
     
  }   
  /*
  ** That's fine, get the pointer to the entry in order to get its socket context reference
  */
  north_lbg_entry_ctx_t  *entry_p = &lbg_p->entry_tb[entry_idx];
  NORTH_LBG_START_PROF((&entry_p->stats));
  ret = af_unix_generic_send_stream_with_idx(entry_p->sock_ctx_ref,buf_p); 
  NORTH_LBG_STOP_PROF((&entry_p->stats));
  if (ret == 0)
  {
    /*
    ** set the timer to supervise the connection (it only affects client connections)
    */
    if (lbg_p->userPollingCallBack != NULL)
    {
      af_unix_ctx_generic_t *this = af_unix_getObjCtx_p(entry_p->sock_ctx_ref);
      af_inet_enable_cnx_supervision(this);
      af_inet_set_cnx_tmo(this,lbg_p->tmo_supervision_in_sec*10*5);
    }
    lbg_p->stats.totalXmit++; 
    entry_p->stats.totalXmit++;     
    return 0; 
  } 
  /*
  ** retry on a next entry
  ** we might need to update the retry counter of the buffer ??
  */
  lbg_p->stats.totalXmitError++; 
  goto reloop;
  
  return 0;
}
Example #19
0
/**
* Load Balncing group deletion API

  - delete all the TCP of AF_UNIX conections
  - stop the timer  assoicated with each connection
  - release all the xmit pending buffers associated with the load balancing group 

 @param lbg_id : user ereference of the load balancing group
 
 @retval 0 : success
 @retval < 0  errno (see errno for details)
*/
int  north_lbg_delete(int lbg_id)
{
    int ret;
   north_lbg_entry_ctx_t *entry_p ;
   ruc_obj_desc_t        *pnext = (ruc_obj_desc_t*)NULL;
   north_lbg_ctx_t       *lbg_p;
   int i;
   void *bufRef;
   
   lbg_p = north_lbg_getObjCtx_p(lbg_id);
   if (lbg_p == NULL) 
   {
     errno = EINVAL;
     return -1;
   }

    lbg_p->state = NORTH_LBG_SHUTTING_DOWN;
    /*
    **get the pointer to the destination stored in the buffer
    */

    /*
    ** OK, now go the buffer that might be queued on that entry and do the same
    */
    for (i = 0;  i < lbg_p->nb_entries_conf; i++)
    {
      entry_p = &lbg_p->entry_tb[i];

      /*
      ** stop the timer
      */
      north_lbg_entry_stop_timer(entry_p);      
      /*
      ** delete the TCP or AF_UNIX connection
      */
      ret = af_unix_delete_socket(entry_p->sock_ctx_ref);
      if (ret < 0) severe("failure on af_unix_delete_socket()entry  %d",i);
      entry_p->sock_ctx_ref = -1;
      /*
      ** Purge the buffer that are queued in the xmitlist done of the entry
      */
      while ((bufRef = (void*) ruc_objGetNext((ruc_obj_desc_t*)&entry_p->xmitList,
                                           &pnext))
                  !=NULL) 
      { 
        /*
        ** remove it from the list because it might be queued afterwards on a new queue
        */        
        ruc_objRemove((ruc_obj_desc_t*)bufRef);
        while (1) 
        {	 	 
             if (lbg_p->userDiscCallBack!= NULL)
             {
              (lbg_p->userDiscCallBack)(NULL,lbg_p->index,bufRef, EPIPE); 
              break;        
             }
             /*
             ** release the buffer
             */
             ruc_buf_freeBuffer(bufRef); 
             break;               
        }   
      }
    }
    /*
    ** Purge the pending xmit list of the load balancer
    */
    for (i = 0; i < NORTH_LBG_MAX_PRIO; i++)
    {
      pnext = (ruc_obj_desc_t*)NULL;
      while ((bufRef = (void*) ruc_objGetNext((ruc_obj_desc_t*)&lbg_p->xmitList[i],
                                           &pnext))
                  !=NULL) 
      { 
        /*
        ** remove it from the list because it might be queued afterwards on a new queue
        */        
        ruc_objRemove((ruc_obj_desc_t*)bufRef);
        while (1) 
        {	 	 
             if (lbg_p->userDiscCallBack!= NULL)
             {
              (lbg_p->userDiscCallBack)(NULL,lbg_p->index,bufRef, EPIPE); 
              break;        
             }
             /*
             ** release the buffer
             */
             ruc_buf_freeBuffer(bufRef); 
             break;               
        }   
      }
    }
    /*
    ** release the lbg context
    */
    north_lbg_free_from_ptr(lbg_p);
    return 0;

}
Example #20
0
int north_lbg_send_from_shaper(int  lbg_idx,void *buf_p)
{

  north_lbg_ctx_t  *lbg_p;
  int entry_idx;
  int ret = 0;
  /*
  ** remove the buffer from any pending list
  */
  ruc_objRemove((ruc_obj_desc_t*)buf_p);
  
  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    severe("north_lbg_send: no such instance %d ",lbg_idx);
    return -1;
  }
  /*
  ** OK there is at least one entry that is free, so get the next valid entry
  */
reloop:
  entry_idx = north_lbg_get_next_valid_entry(lbg_p);
  if (entry_idx < 0)
  {
    /*
    ** that situation must not occur since there is at leat one entry that is UP!!!!
    */
//    RUC_WARNING(-1);
    return -1;    
  }
  /*
  ** That's fine, get the pointer to the entry in order to get its socket context reference
  */
  north_lbg_entry_ctx_t  *entry_p = &lbg_p->entry_tb[entry_idx];
  NORTH_LBG_START_PROF((&entry_p->stats));
  ret = af_unix_generic_send_stream_with_idx(entry_p->sock_ctx_ref,buf_p); 
  NORTH_LBG_STOP_PROF((&entry_p->stats));
  if (ret == 0)
  {
    /*
    ** set the timer to supervise the connection (it only affects client connections)
    */
    if (lbg_p->userPollingCallBack != NULL)
    {
      af_unix_ctx_generic_t *this = af_unix_getObjCtx_p(entry_p->sock_ctx_ref);
      af_inet_enable_cnx_supervision(this);
      af_inet_set_cnx_tmo(this,lbg_p->tmo_supervision_in_sec*10*5);
    }
    lbg_p->stats.totalXmit++; 
    entry_p->stats.totalXmit++;     
    return 0; 
  } 
  /*
  ** retry on a next entry
  ** we might need to update the retry counter of the buffer ??
  */
  lbg_p->stats.totalXmitError++; 
  goto reloop;
  
  return 0;
}
int rozofs_export_poll_tx(af_unix_ctx_generic_t  *sock_p,
                          uint32_t prog,uint32_t vers,
                          int opcode,xdrproc_t encode_fct,void *msg2encode_p,
                          void *xmit_buf,
                          int      extra_len,  
                          int applicative_tmo_sec,                          
                          sys_recv_pf_t recv_cbk,void *user_ctx_p) 
{
    DEBUG_FUNCTION;
   
    uint8_t           *arg_p;
    uint32_t          *header_size_p;
    rozofs_tx_ctx_t   *rozofs_tx_ctx_p = NULL;
    int               bufsize;
    int               ret;
    int               position;
    XDR               xdrs;    
	struct rpc_msg   call_msg;
    uint32_t         null_val = 0;
    uint32_t sock_idx_in_lbg = -1;

   /*
   ** get the entry within the load balancing group
   */
   {
      north_lbg_ctx_t *lbg_p;
      int lbg_id = sock_p->availability_param;
      int start_idx;
      /*
      ** Get the pointer to the lbg
      */
      lbg_p = north_lbg_getObjCtx_p(lbg_id);
      if (lbg_p == NULL) 
      {
	severe("rozofs_export_poll_tx: no such instance %d ",lbg_id);
	return -1;
      }      
      for (start_idx = 0; start_idx < lbg_p->nb_entries_conf; start_idx++)
      {
        if (lbg_p->entry_tb[start_idx].sock_ctx_ref  == sock_p->index) break;
      }
      if (lbg_p->nb_entries_conf == start_idx)
      {
	severe("rozofs_export_poll_tx: no such instance %d ",sock_p->index);      
        return -1;
      }
      /**
      ** start_idx is the index within the load balancing
      */
      sock_idx_in_lbg = start_idx;
      //info("JPM poll lbg %d %s entry %d",lbg_id,lbg_p->name,sock_idx_in_lbg);
      
    }
    
    /*
    ** allocate a transaction context
    */
    rozofs_tx_ctx_p = rozofs_tx_alloc();  
    if (rozofs_tx_ctx_p == NULL) 
    {
       /*
       ** out of context
       ** --> put a pending list for the future to avoid repluing ENOMEM
       */
       TX_STATS(ROZOFS_TX_NO_CTX_ERROR);
       errno = ENOMEM;
       goto error;
    }    
    /*
    ** get the pointer to the payload of the buffer
    */
    header_size_p  = (uint32_t*) ruc_buf_getPayload(xmit_buf);
    arg_p = (uint8_t*)(header_size_p+1);  
    /*
    ** create the xdr_mem structure for encoding the message
    */
    bufsize = (int)ruc_buf_getMaxPayloadLen(xmit_buf);
    xdrmem_create(&xdrs,(char*)arg_p,bufsize,XDR_ENCODE);
    /*
    ** fill in the rpc header
    */
    call_msg.rm_direction = CALL;
    /*
    ** allocate a xid for the transaction 
    */
	call_msg.rm_xid             = rozofs_tx_alloc_xid(rozofs_tx_ctx_p); 
	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
	/* XXX: prog and vers have been long historically :-( */
	call_msg.rm_call.cb_prog = (uint32_t)prog;
	call_msg.rm_call.cb_vers = (uint32_t)vers;
	if (! xdr_callhdr(&xdrs, &call_msg))
    {
       /*
       ** THIS MUST NOT HAPPEN
       */
       TX_STATS(ROZOFS_TX_ENCODING_ERROR);
       errno = EPROTO;
       goto error;	
    }
    /*
    ** insert the procedure number, NULL credential and verifier
    */
    XDR_PUTINT32(&xdrs, (int32_t *)&opcode);
    XDR_PUTINT32(&xdrs, (int32_t *)&null_val);
    XDR_PUTINT32(&xdrs, (int32_t *)&null_val);
    XDR_PUTINT32(&xdrs, (int32_t *)&null_val);
    XDR_PUTINT32(&xdrs, (int32_t *)&null_val);
        
    /*
    ** ok now call the procedure to encode the message
    */
    if ((*encode_fct)(&xdrs,msg2encode_p) == FALSE)
    {
       TX_STATS(ROZOFS_TX_ENCODING_ERROR);
       errno = EPROTO;
       goto error;
    }
    /*
    ** Now get the current length and fill the header of the message
    */
    position = XDR_GETPOS(&xdrs);
    /*
    ** add the extra_len if any
    */
    position +=extra_len;
    /*
    ** update the length of the message : must be in network order
    */
    *header_size_p = htonl(0x80000000 | position);
    /*
    ** set the payload length in the xmit buffer
    */
    int total_len = sizeof(*header_size_p)+ position;
    ruc_buf_setPayloadLen(xmit_buf,total_len);
    /*
    ** store the receive call back and its associated parameter
    */
    rozofs_tx_ctx_p->recv_cbk   = recv_cbk;
    rozofs_tx_ctx_p->user_param = user_ctx_p;    
    rozofs_tx_write_opaque_data(rozofs_tx_ctx_p,1,1);  /* lock */
    rozofs_tx_write_opaque_data(rozofs_tx_ctx_p,2,sock_p->availability_param);  /* lock */
    rozofs_tx_write_opaque_data(rozofs_tx_ctx_p,3,sock_idx_in_lbg);  /* lock */
    /*
    ** now send the message
    */
    ret = af_unix_generic_stream_send(sock_p,xmit_buf); 
    if (ret < 0)
    {
       TX_STATS(ROZOFS_TX_SEND_ERROR);
       errno = EFAULT;
      goto error;  
    }
    TX_STATS(ROZOFS_TX_SEND);
    /*
    ** just iunlock the context and don't care about the end of transaction
    ** the transaction might end because of a direct error sending (tcp 
    ** disconnection)
    **
    ** By not releasing the tx context the end of the transaction ends upon receiving
    ** the tx timer expiration
    */
    rozofs_tx_write_opaque_data(rozofs_tx_ctx_p,1,0);  /* unlock */    
    /*
    ** OK, so now finish by starting the guard timer
    */
    rozofs_tx_start_timer(rozofs_tx_ctx_p,applicative_tmo_sec);  
    return 0;  
    
  error:
    if (rozofs_tx_ctx_p != NULL) rozofs_tx_free_from_ptr(rozofs_tx_ctx_p);
    return -1;    
}
Example #22
0
 /**
*  API to configure a load balancing group.
   The load balancing group must have been created previously with north_lbg_create_no_conf() 
  
 @param none
 
  @retval >= reference of the load balancer object
  @retval < 0 error (out of context ??)
*/
int north_lbg_configure_af_inet(int lbg_idx,char *name,
                                uint32_t src_ipaddr_host,
                                uint16_t src_port_host,
                                north_remote_ip_list_t *remote_ip_p,
                                int family,int  nb_instances,af_unix_socket_conf_t *usr_conf_p, int local)
{
  north_lbg_ctx_t  *lbg_p;
  int    i;
  north_lbg_entry_ctx_t *entry_p;
  
  af_unix_socket_conf_t *conf_p;
  
  lbg_p = north_lbg_getObjCtx_p(lbg_idx);
  if (lbg_p == NULL) 
  {
    warning("north_lbg_configure_af_inet: no such instance %d ",lbg_idx);
    return -1;
  }
  
  lbg_p->local = local;  
  conf_p = &lbg_p->lbg_conf;
  memcpy(conf_p,usr_conf_p,sizeof(af_unix_socket_conf_t));

  if (lbg_p->state != NORTH_LBG_DEPENDENCY)
  {
    warning("north_lbg_configure_af_inet: unexpected state %d ",lbg_p->state);
    return -1;  
  }
  if (nb_instances == 0)
  {
    /*
    ** no instances!!
    */
    warning("north_lbg_configure_af_inet: no instance for lbg %d ",lbg_idx);
    return -1;   
  }
  if (nb_instances >= NORTH__LBG_MAX_ENTRY)
  {
    /*
    ** to many instances!!
    */
    warning("north_lbg_configure_af_inet: too many instances (%d max %d) for lbg %d ",nb_instances,NORTH__LBG_MAX_ENTRY,lbg_idx);
    return -1;   
  }  
  /*
  ** restore the init state
  */
  lbg_p->state  = NORTH_LBG_DOWN;
  
  lbg_p->family = family;
  lbg_p->nb_entries_conf = nb_instances;
  strcpy(lbg_p->name,name);
  /*
  ** install the  callbacks of the load balancer
  */
  /*
  ** install the load balancer callback but keep in the context the 
  ** user callback for deconnection
  */
  lbg_p->userDiscCallBack     = conf_p->userDiscCallBack;
  conf_p->userDiscCallBack    = north_lbg_userDiscCallBack;
  lbg_p->userRcvCallBack      = conf_p->userRcvCallBack;
  conf_p->userRcvCallBack     = north_lbg_userRecvCallBack;

  conf_p->userConnectCallBack = north_lbg_connect_cbk;
  conf_p->userXmitDoneCallBack = north_lbg_userXmiDoneCallBack;

  
  entry_p = lbg_p->entry_tb;
  for (i = 0; i < nb_instances ; i++,entry_p++,remote_ip_p++)
  {

     conf_p->userRef     = entry_p;
     entry_p->sock_ctx_ref = af_inet_sock_client_create(name,
                                                     src_ipaddr_host,
                                                     src_port_host,
                                                     remote_ip_p->remote_ipaddr_host,
                                                     remote_ip_p->remote_port_host,
                                                     conf_p); 
     if (entry_p->sock_ctx_ref >= 0)  
     {
       north_lbg_entry_start_timer(entry_p,ROZOFS_TMR_GET(TMR_TCP_RECONNECT));
       north_lbg_entry_state_change(entry_p,NORTH_LBG_DOWN);
//       entry_p->state = NORTH_LBG_DOWN; 
     }  
  }
  /*
  ** attach the application callback if any is declared
  */
  north_lbg_attach_app_sup_cbk_on_entries(lbg_p);
  
  return (lbg_p->index);

}