/* Register a new hook callback */ int fd_hook_register ( uint32_t type_mask, void (*fd_hook_cb)(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata), void *regdata, struct fd_hook_data_hdl *data_hdl, struct fd_hook_hdl ** handler ) { struct fd_hook_hdl * newhdl = NULL; int i; TRACE_ENTRY("%x %p %p %p %p", type_mask, fd_hook_cb, regdata, data_hdl, handler); CHECK_PARAMS( fd_hook_cb && handler ); CHECK_MALLOC( newhdl = malloc(sizeof(struct fd_hook_hdl)) ); memset(newhdl, 0, sizeof(struct fd_hook_hdl)); newhdl->fd_hook_cb = fd_hook_cb; newhdl->regdata = regdata; newhdl->data_hdl = data_hdl; for (i=0; i <= HOOK_LAST; i++) { fd_list_init(&newhdl->chain[i], newhdl); if (type_mask & (1<<i)) { CHECK_POSIX( pthread_rwlock_wrlock(&HS_array[i].rwlock) ); fd_list_insert_before( &HS_array[i].sentinel, &newhdl->chain[i]); CHECK_POSIX( pthread_rwlock_unlock(&HS_array[i].rwlock) ); } } *handler = newhdl; return 0; }
/* Initialize the array of sentinels for the hooks */ int fd_hooks_init(void) { int i; for (i=0; i <= HOOK_LAST; i++) { fd_list_init(&HS_array[i].sentinel, NULL); CHECK_POSIX( pthread_rwlock_init(&HS_array[i].rwlock, NULL) ); } return 0; }
/* Alloc / reinit a peer structure. if *ptr is not NULL, it must already point to a valid struct fd_peer. */ int fd_peer_alloc(struct fd_peer ** ptr) { struct fd_peer *p; TRACE_ENTRY("%p", ptr); CHECK_PARAMS(ptr); if (*ptr) { p = *ptr; } else { CHECK_MALLOC( p = malloc(sizeof(struct fd_peer)) ); *ptr = p; } /* Now initialize the content */ memset(p, 0, sizeof(struct fd_peer)); fd_list_init(&p->p_hdr.chain, p); fd_list_init(&p->p_hdr.info.pi_endpoints, p); fd_list_init(&p->p_hdr.info.runtime.pir_apps, p); p->p_eyec = EYEC_PEER; CHECK_POSIX( pthread_mutex_init(&p->p_state_mtx, NULL) ); fd_list_init(&p->p_actives, p); fd_list_init(&p->p_expiry, p); CHECK_FCT( fd_fifo_new(&p->p_tosend, 5) ); CHECK_FCT( fd_fifo_new(&p->p_tofailover, 0) ); p->p_hbh = lrand48(); fd_list_init(&p->p_sr.srs, p); fd_list_init(&p->p_sr.exp, p); CHECK_POSIX( pthread_mutex_init(&p->p_sr.mtx, NULL) ); CHECK_POSIX( pthread_cond_init(&p->p_sr.cnd, NULL) ); fd_list_init(&p->p_connparams, p); return 0; }
/* Return the location of the permsgdata area corresponding to this handle, after eventually having created it. Return NULL in case of failure */ static struct fd_hook_permsgdata * get_or_create_pmd(struct fd_msg_pmdl *pmdl, struct fd_hook_data_hdl * h) { struct fd_hook_permsgdata * ret = NULL; struct fd_list * li; CHECK_POSIX_DO( pthread_mutex_lock(&pmdl->lock), ); if (pmdl->sentinel.o == NULL) { pmdl->sentinel.o = pmdl_free; } /* Search in the list for an item with the same handle. The list is ordered by this handle */ for (li=pmdl->sentinel.next; li != &pmdl->sentinel; li = li->next) { struct pmd_list_item * pli = (struct pmd_list_item *) li; if (pli->hdl == h) ret = &pli->pmd; if (pli->hdl >= h) break; } if (!ret) { /* we need to create a new one and insert before li */ struct pmd_list_item * pli; CHECK_MALLOC_DO( pli = malloc(sizeof_pmd(h)), ); if (pli) { memset(pli, 0, sizeof_pmd(h)); fd_list_init(&pli->chain, pli); pli->hdl = h; ret = &pli->pmd; if (h->pmd_init_cb) { (*h->pmd_init_cb)(ret); } fd_list_insert_before(li, &pli->chain); } } CHECK_POSIX_DO( pthread_mutex_unlock(&pmdl->lock), ); return ret; }