Exemple #1
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;
}
Exemple #2
0
/**
* that callback is called upon the successful transmission of a buffer
  Depending on the inuse value of the buffer, the application can
  either release the message or queue it in its local xmit queue.
  The main purpose of queueing the message is to address the case of
  a disconnection of the remote end in order to re-balance the buffer
  on another equivalent destinatio
 

 @param userRef : pointer to a load balancer entry
 @param socket_context_ref: socket context reference
 @param bufRef : pointer to the packet buffer on which the error has been encountered
  
 @retval none
*/
void  north_lbg_userXmiDoneCallBack(void *userRef,uint32_t socket_context_ref,void *bufRef)
{
    int8_t inuse;
    
   north_lbg_entry_ctx_t *entry_p = (north_lbg_entry_ctx_t*)userRef;

    /*
    ** check the inuse value of the buffer, if inuse is 1, then release it
    */
    inuse = ruc_buf_inuse_get(bufRef);
    if (inuse < 0)
    {
//#warning  inuse MUST never be negative so EXIT !!!!!
     fatal("fatal error on buffer management: inuse counter %d",inuse );          
    }
    if (inuse == 1) 
    {
       ruc_buf_freeBuffer(bufRef);  
    } 
    else
    {
      /*
      ** queue it to the local xmit list of the entry 
      */
      ruc_objInsertTail((ruc_obj_desc_t*)&entry_p->xmitList,(ruc_obj_desc_t*)bufRef);    
    } 
}
Exemple #3
0
/*-----------------------------------------------
 **   north_lbg_alloc

 **  create a Transaction context
 **   That function tries to allocate a free PDP
 **   context. In case of success, it returns the
 **   index of the Transaction context.
 **
@param     : recli index
@param       relayCref : RELAY-C ref of the context
@retval   : MS controller reference (if OK)
@retval    NULL if out of context.
 */
north_lbg_ctx_t *north_lbg_alloc() {
    north_lbg_ctx_t *p;

    /*
     **  Get the first free context
     */
    if ((p = (north_lbg_ctx_t*) ruc_objGetFirst((ruc_obj_desc_t*) north_lbg_context_freeListHead))
            == (north_lbg_ctx_t*) NULL) {
        /*
         ** out of Transaction context descriptor try to free some MS
         ** context that are out of date 
         */
        severe( "NOT ABLE TO GET an AF_UNIX CONTEXT" );
        return NULL;
    }
    /*
     **  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);
    /*
     ** insert in the active list the new element created
     */
    ruc_objInsertTail((ruc_obj_desc_t*) & north_lbg_context_activeListHead, (ruc_obj_desc_t*) p);
    return p;
}
Exemple #4
0
/*----------------------------------------------
**   Declare a server
**----------------------------------------------
**  IN :
**     . name : name of the server
**     . nbEvent : number of events generated
**                 by the server
**
**  OUT : Server reference or -1
**-----------------------------------------------
*/
uint32_t ruc_observer_declareServer(char * name, uint32_t nbEvent) {
  RUC_OBSERVER_SERVER_T     * pSrv;
  uint32_t                      idx;

  if (ruc_observer_initDone == FALSE) {
    ERRFAT "OBSERVER not initialised" ENDERRFAT;
    return -1;
  }

  /*
  ** get the first element from the free list
  */
  pSrv = (RUC_OBSERVER_SERVER_T*)ruc_objGetFirst((ruc_obj_desc_t*) ruc_observer_server_freeListHead);
  if (pSrv == (RUC_OBSERVER_SERVER_T* )NULL) {
    ERRFAT "Out of server context" ENDERRFAT;
    return -1;
  }
  /*
  **  remove the context from the free list
  */
  ruc_objRemove(&pSrv->link);
  /*
  **  store the callback pointer,the user Reference and priority
  */

  strncpy(pSrv->name,name,RUC_OBSERVER_NAME_MAX);
  pSrv->name[RUC_OBSERVER_NAME_MAX-1] = 0;
  pSrv->nbEvent = nbEvent;

  /*
  ** Allocate an event table
   */
  pSrv->pEventTbl = (RUC_OBSERVER_EVENT_T *)malloc(nbEvent*sizeof(RUC_OBSERVER_EVENT_T));
  if (pSrv->pEventTbl == (RUC_OBSERVER_EVENT_T*)NULL) {
    /*
    ** out of memory
    */
    ERRFAT "Out of memory" ENDERRFAT;
    return -1;
  }
  /*
  **  initialize each event
  */
  for (idx=0; idx < nbEvent; idx++) {
    pSrv->pEventTbl[idx].event = idx;
    pSrv->pEventTbl[idx].pnextCur = NULL;
    ruc_listHdrInit(&pSrv->pEventTbl[idx].head);
  }

  /*
  **  insert in the server active list
  */
  ruc_objInsertTail(&ruc_observer_server_activeList.link, &pSrv->link);

  return (pSrv->ref);
}
Exemple #5
0
/**
   delete a AF_UNIX context

   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     : MS Index
@retval   : RUC_OK : context has been deleted
@retval     RUC_NOK : out of limit index.
 */
uint32_t af_unix_free_from_idx(uint32_t af_unix_ctx_id) {
    af_unix_ctx_generic_t *p;

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

    /*
    ** Take care of the current index of the show
    */
    if (next_display_af_unix_ctx == (ruc_obj_desc_t*)p) {
      ruc_objGetNext(&af_unix_context_activeListHead.link, &next_display_af_unix_ctx);
    }
    
    /*
     ** remove it from the active list
     */
    ruc_objRemove((ruc_obj_desc_t*) p);
    

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


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

    return RUC_OK;

}
Exemple #6
0
/**
   delete a  context
   
   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     : index of the context
   @retval   : RUC_OK : context has been deleted
   @retval     RUC_NOK : out of limit index.
 */
uint32_t geo_proc_free_from_idx(uint32_t context_id) {
    geo_proc_ctx_t *p;

    if (context_id >= geo_proc_context_count) {
        /*
         ** index is out of limits
         */
        return RUC_NOK;
    }
    /*
    ** get the reference from idx
    */
    p = geo_proc_getObjCtx_p(context_id);
    /*
    ** stop the timer
    */
    geo_proc_stop_timer(p);
    /*
     ** remove it from the active list
     */
    ruc_objRemove((ruc_obj_desc_t*) p);
    /*
    ** clear the local reference and remote reference
    */
    p->local_ref.u32 = 0;
    p->remote_ref = 0;
    if (p->record_buf_p != NULL)
    {
      free(p->record_buf_p);
      p->record_buf_p = NULL;
    }
    /*
     **  insert it in the free list
     */
    geo_proc_context_allocated--;
    p->free = TRUE;
    ruc_objInsertTail((ruc_obj_desc_t*) geo_proc_context_freeListHead,
            (ruc_obj_desc_t*) p);

    return RUC_OK;
}
Exemple #7
0
/*
**----------------------------------------------
**  geo_ctx_tmr_start
**----------------------------------------------
**
**  charging timer service starting request
**    
**  IN : p_refTim   : reference of the timer cell to use
**       date_s     : requested time out date, in seconds
**       p_callBack : client call back to call at time out
**       cBParam    : client parameter to provide at time out
**
**  OUT : OK/NOK
**
**-----------------------------------------------
*/
uint32_t  geo_ctx_tmr_start (uint8_t   tmr_slot,
                        geo_ctx_tmr_cell_t *p_refTim, 
                        uint32_t  date_s,
                        geo_ctx_tmr_callBack_t p_callBack,
                        void *cBParam
			)
{
     uint32_t ret;       
     
     if (tmr_slot >= GEO_CTX_TMR_SLOT_MAX)
     {
        severe( "geo_ctx_tmr_start : slot out of range : %d ",tmr_slot );
	return RUC_NOK;
     }
    /*
    ** timer cell dequeing from its current queue
    ** This dequeing is always attempted, even if not queued
    ** As the list primitive is protected, no initial check 
    ** need to be done
    */
    ruc_objRemove((ruc_obj_desc_t *)p_refTim);

    /*
    ** initialize context
    */
    p_refTim->date_s = date_s + geo_ctx_time();
    p_refTim->date_s &= GEO_CTX_TIMER_MAX_DATE;
    p_refTim->delay = date_s;
    
    p_refTim->p_callBack = p_callBack;
    p_refTim->cBParam = cBParam;


    ret=ruc_objInsertTail(&geo_ctx_tmr.queue[tmr_slot],(ruc_obj_desc_t*)p_refTim);
    if(ret!=RUC_OK){
        severe( "Pb while inserting cell in queue, ret=%u", ret );
        return(RUC_NOK);
    }
    return(RUC_OK);
}
Exemple #8
0
/**
*   Search if there is already a pending lookup for the same object

    @param buffer: rozofs fuse context
    @param parent: inode parent
    @param name: name to look for
    
    @retval 1 : found
    @retval 0: not found
*/
int rozofs_lookup_insert_queue(void *buffer,fuse_ino_t parent, const char *name,fuse_req_t req,int trc_idx,int lookup_flags)
{
   ruc_obj_desc_t   * phead;
   ruc_obj_desc_t   * elt;
   ruc_obj_desc_t   * pnext;
   rozofs_fuse_save_ctx_t *fuse_save_ctx_p;  
   uint32_t hash; 
   /*
    ** scan the pending lookup request searching for the same request (ino+name)
    */
   hash = dentry_hash(parent,(char*)name);
   phead = &rozofs_lookup_queue[hash%ROZOFS_MAX_LKUP_QUEUE];   
   pnext = (ruc_obj_desc_t*)NULL;
   while ((elt = ruc_objGetNext(phead, &pnext)) != NULL) 
   {
      /*
      ** Check if the inode and the name are the same
      */
      fuse_save_ctx_p = (rozofs_fuse_save_ctx_t*)ruc_buf_getPayload(elt); 
      if (fuse_save_ctx_p->parent != parent) continue;
      if (strcmp(name,fuse_save_ctx_p->name) !=0) continue;
      /*
      ** it is the same request: so queue it on the current one if there is enough room
      */
      if (fuse_save_ctx_p->lkup_cpt < ROZOFS_MAX_PENDING_LKUP)
      {
         fuse_save_ctx_p->lookup_tb[fuse_save_ctx_p->lkup_cpt].req = req;
         fuse_save_ctx_p->lookup_tb[fuse_save_ctx_p->lkup_cpt].trc_idx = trc_idx;
         fuse_save_ctx_p->lookup_tb[fuse_save_ctx_p->lkup_cpt].flags = lookup_flags;
	 fuse_save_ctx_p->lkup_cpt++;
	 return 1;
      }
    }
    /*
    ** this a new request: insert it in the global pending list
    */
    ruc_objInsertTail(phead,(ruc_obj_desc_t*)buffer);   
    return 0;
}
Exemple #9
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;

}
Exemple #10
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;
}
Exemple #11
0
/**
ruc_obj_desc_t *ruc_listCreate_shared(uint32_t nbElements,uint32 size)

   creation of a double linked list. The input arguments
    are the number of elements and the size of an element.

   it is mandatory that the element includes ruc_obj_desc_t
    at the beginning of its structure.

   @param  nbElements : number of elements to create
   @param  size  : size of the structure of an element (including the size of ruc_obj_desc_t).
   @param key: key of the shared memory

   @retval <> NULL: pointer to the head of list
   @retval == NULL: out of memory

  note : the number of elements must not include the head of
         list.
*/
ruc_obj_desc_t *ruc_listCreate_shared(uint32_t nbElements,uint32_t size,key_t key)
{

  ruc_obj_desc_t *p,*phead;
  uint32_t   listId;
  uint8_t    *pbyte;
  int i;
  int shmid;

  RUC_LIST_TRC("listCreate_in_shared",nbElements,size,-1,-1);
  /*
  **  reject the creation if the size is less than the
  **  ruc_obj_desc_t structure size
  */
  if (size < sizeof(ruc_obj_desc_t))
  {
    RUC_WARNING(-1);
    return (ruc_obj_desc_t*)NULL;
  }
  /*
  **  if the size is not long word aligned, adjust the size
  **  to do it.
  */
  if ((size & 0x3) != 0)
  {
     size = ((size & (~0x3)) + 4 );
  }
  /*
  ** test that the size does not exceed 32 bits
  */
  {
    uint32_t nbElementOrig;
    uint32_t memRequested;

    nbElementOrig = nbElements+1;
    if (nbElementOrig == 0)
    {
      RUC_WARNING(-1);
      return (ruc_obj_desc_t*)NULL;
    }

    memRequested = size*(nbElementOrig);
    nbElementOrig = memRequested/size;
    if (nbElementOrig != (nbElements+1))
    {
      /*
      ** overlap
      */
      RUC_LIST_TRC("listCreate_err",nbElementOrig,nbElements,-1,-1);
      RUC_WARNING(-1);
      return (ruc_obj_desc_t*)NULL;
    }
  }
  /*
  ** create the shared memory
  */
  if ((shmid = shmget(key, size*(nbElements+1), IPC_CREAT | 0666)) < 0) {
      perror("shmget");
      RUC_WARNING(errno);
      return (ruc_obj_desc_t*)NULL;
  }
  /*
  * Now we attach the segment to our data space.
  */
  if ((p =(ruc_obj_desc_t *) shmat(shmid, NULL, 0)) == (ruc_obj_desc_t *) -1)
  {
    perror("shmat");
    RUC_WARNING(errno);
    return (ruc_obj_desc_t*)NULL;
  }

  /*
  ** get the list Id for the new list
  */
  listId = ruc_getListId();
  /*
  ** store the reference of the shared memory
  */
  ruc_list_shmid_table[listId] = shmid;
  /*
  ** head of list initialization
  */
  phead = p;
  phead->ps     = phead;
  phead->pp     = phead;
  phead->sysRef = p;
  phead->type   = RUC_LIST_HEAD;
  phead->countOrObjId = nbElements ;
  phead->eltSize =  size;
  phead->usrEvtCode = 0;
  phead->listId = listId;

  pbyte = (uint8_t*)p;
  for (i = 0; i < nbElements; i++)
  {
    pbyte +=size;
    p = (ruc_obj_desc_t*)pbyte;
    /*
    **  initialize the element header
    */
    ruc_listEltInit(p);
    p->sysRef = phead;
    p->type   = RUC_LIST_ELEM;
    p->listId = phead->listId;
     /*
     **  insert in the list
     */
    ruc_objInsertTail(phead,p);
  }
  RUC_LIST_TRC("listCreate_out",nbElements,size,phead,phead->listId);
  return phead;
}