uint64_t cch_cityhash64_with_seed (const char *buf, size_t len, uint64_t seed) { #ifdef HAVE_CITYHASH64WITHSEED return CityHash64WithSeed(buf, len, seed); #else feature_failure(__func__); #endif }
static void svc_dg_checksum(struct svc_req *req, void *data, size_t length) { req->rq_cksum = #if 1 /* CithHash64 is -substantially- faster than crc32c from FreeBSD * SCTP, so prefer it until fast crc32c bests it */ CityHash64WithSeed(data, MIN(256, length), 103); #else calculate_crc32c(0, data, MIN(256, length)); #endif }
static void compute_buffer_cksum(RECSTREAM *rstrm) { #if 1 /* CithHash64 is -substantially- faster than crc32c from FreeBSD * SCTP, so prefer it until fast crc32c bests it */ rstrm->cksum = CityHash64WithSeed(rstrm->in_base, MIN(rstrm->cklen, rstrm->offset), 103); #else rstrm->cksum = calculate_crc32c(0, rstrm->in_base, MIN(rstrm->cklen, rstrm->offset)); #endif }
/** * @brief Find and reference a DRC to process the supplied svc_req. * * @param[in] req The svc_req being processed. * * @return The ref'd DRC if sucessfully located, else NULL. */ static /* inline */ drc_t * nfs_dupreq_get_drc(struct svc_req *req) { enum drc_type dtype = get_drc_type(req); drc_t *drc = NULL; bool drc_check_expired = false; switch (dtype) { case DRC_UDP_V234: LogFullDebug(COMPONENT_DUPREQ, "ref shared UDP DRC"); drc = &(drc_st->udp_drc); DRC_ST_LOCK(); (void)nfs_dupreq_ref_drc(drc); DRC_ST_UNLOCK(); goto out; case DRC_TCP_V4: case DRC_TCP_V3: /* Idempotent address, no need for lock; * xprt will be valid as long as svc_req. */ drc = (drc_t *)req->rq_xprt->xp_u2; if (drc) { /* found, no danger of removal */ LogFullDebug(COMPONENT_DUPREQ, "ref DRC=%p for xprt=%p", drc, req->rq_xprt); PTHREAD_MUTEX_lock(&drc->mtx); /* LOCKED */ } else { drc_t drc_k; struct rbtree_x_part *t = NULL; struct opr_rbtree_node *ndrc = NULL; drc_t *tdrc = NULL; memset(&drc_k, 0, sizeof(drc_k)); drc_k.type = dtype; /* Since the drc can last longer than the xprt, * copy the address. Read operation of constant data, * no xprt lock required. */ (void)copy_xprt_addr(&drc_k.d_u.tcp.addr, req->rq_xprt); drc_k.d_u.tcp.hk = CityHash64WithSeed((char *)&drc_k.d_u.tcp.addr, sizeof(sockaddr_t), 911); { char str[SOCK_NAME_MAX]; sprint_sockaddr(&drc_k.d_u.tcp.addr, str, sizeof(str)); LogFullDebug(COMPONENT_DUPREQ, "get drc for addr: %s", str); } t = rbtx_partition_of_scalar(&drc_st->tcp_drc_recycle_t, drc_k.d_u.tcp.hk); DRC_ST_LOCK(); ndrc = opr_rbtree_lookup(&t->t, &drc_k.d_u.tcp.recycle_k); if (ndrc) { /* reuse old DRC */ tdrc = opr_containerof(ndrc, drc_t, d_u.tcp.recycle_k); PTHREAD_MUTEX_lock(&tdrc->mtx); /* LOCKED */ if (tdrc->flags & DRC_FLAG_RECYCLE) { TAILQ_REMOVE(&drc_st->tcp_drc_recycle_q, tdrc, d_u.tcp.recycle_q); --(drc_st->tcp_drc_recycle_qlen); tdrc->flags &= ~DRC_FLAG_RECYCLE; } drc = tdrc; LogFullDebug(COMPONENT_DUPREQ, "recycle TCP DRC=%p for xprt=%p", tdrc, req->rq_xprt); } if (!drc) { drc = alloc_tcp_drc(dtype); LogFullDebug(COMPONENT_DUPREQ, "alloc new TCP DRC=%p for xprt=%p", drc, req->rq_xprt); /* assign addr */ memcpy(&drc->d_u.tcp.addr, &drc_k.d_u.tcp.addr, sizeof(sockaddr_t)); /* assign already-computed hash */ drc->d_u.tcp.hk = drc_k.d_u.tcp.hk; PTHREAD_MUTEX_lock(&drc->mtx); /* LOCKED */ /* xprt ref */ drc->refcnt = 1; /* insert dict */ opr_rbtree_insert(&t->t, &drc->d_u.tcp.recycle_k); } DRC_ST_UNLOCK(); drc->d_u.tcp.recycle_time = 0; (void)nfs_dupreq_ref_drc(drc); /* xprt ref */ /* try to expire unused DRCs somewhat in proportion to * new connection arrivals */ drc_check_expired = true; LogFullDebug(COMPONENT_DUPREQ, "after ref drc %p refcnt==%u ", drc, drc->refcnt); /* Idempotent address, no need for lock; * set once here, never changes. * No other fields are modified. * Assumes address stores are atomic. */ req->rq_xprt->xp_u2 = (void *)drc; } break; default: /* XXX error */ break; } /* call path ref */ (void)nfs_dupreq_ref_drc(drc); PTHREAD_MUTEX_unlock(&drc->mtx); if (drc_check_expired) drc_free_expired(); out: return drc; }
void process_batch(struct ndn_name *name_lo, int *dst_ports, struct ndn_bucket *ht) { char *name[BATCH_SIZE]; int i[BATCH_SIZE]; int c_i[BATCH_SIZE]; int bkt_2[BATCH_SIZE]; int bkt_1[BATCH_SIZE]; int bkt_num[BATCH_SIZE]; int terminate[BATCH_SIZE]; int prefix_match_found[BATCH_SIZE]; uint64_t prefix_hash[BATCH_SIZE]; uint16_t tag[BATCH_SIZE]; struct ndn_slot *slots[BATCH_SIZE]; int8_t _dst_port[BATCH_SIZE]; uint64_t _hash[BATCH_SIZE]; int I = 0; // batch index void *batch_rips[BATCH_SIZE]; // goto targets int iMask = 0; // No packet is done yet int temp_index; for(temp_index = 0; temp_index < BATCH_SIZE; temp_index ++) { batch_rips[temp_index] = &&fpp_start; } fpp_start: name[I] = name_lo[I].name; FPP_PSS(name[I], fpp_label_1); fpp_label_1: /**< URL char iterator and slot iterator */ terminate[I] = 0; /**< Stop processing this URL? */ prefix_match_found[I] = 0; /**< Stop this hash-table lookup ? */ /**< For names that we cannot find, dst_port is -1 */ dst_ports[I] = -1; for(c_i[I] = 0; name[I][c_i[I]] != 0; c_i[I] ++) { if(name[I][c_i[I]] == '/') { break; } } c_i[I] ++; for(; name[I][c_i[I]] != 0; c_i[I] ++) { if(name[I][c_i[I]] != '/') { continue; } prefix_hash[I] = CityHash64WithSeed(name[I], c_i[I] + 1, NDN_SEED); tag[I] = prefix_hash[I] >> 48; /**< name[0] -> name[c_i] is a prefix of length c_i + 1 */ for(bkt_num[I] = 1; bkt_num[I] <= 2; bkt_num[I] ++) { if(bkt_num[I] == 1) { bkt_1[I] = prefix_hash[I] & NDN_NUM_BKT_; FPP_PSS(&ht[bkt_1[I]], fpp_label_2); fpp_label_2: slots[I] = ht[bkt_1[I]].slots; } else { bkt_2[I] = (bkt_1[I] ^ CityHash64((char *) &tag[I], 2)) & NDN_NUM_BKT_; FPP_PSS(&ht[bkt_2[I]], fpp_label_3); fpp_label_3: slots[I] = ht[bkt_2[I]].slots; } /**< Now, "slots" points to an ndn_bucket. Find a valid slot * with a matching tag. */ for(i[I] = 0; i[I] < NDN_NUM_SLOTS; i[I] ++) { _dst_port[I] = slots[I][i[I]].dst_port; _hash[I] = slots[I][i[I]].cityhash; if(_dst_port[I] >= 0 && _hash[I] == prefix_hash[I]) { /**< Record the dst port: this may get overwritten by * longer prefix matches later */ dst_ports[I] = slots[I][i[I]].dst_port; if(slots[I][i[I]].is_terminal == 1) { /**< A terminal FIB entry: we're done! */ terminate[I] = 1; } prefix_match_found[I] = 1; break; } } /**< Stop the hash-table lookup for name[0 ... c_i] */ if(prefix_match_found[I] == 1) { break; } } /**< Stop processing the name if we found a terminal FIB entry */ if(terminate[I] == 1) { break; } } /**< Loop over URL characters ends here */ /**< Loop over batch ends here */ fpp_end: batch_rips[I] = &&fpp_end; iMask = FPP_SET(iMask, I); if(iMask == (1 << BATCH_SIZE) - 1) { return; } I = (I + 1) & BATCH_SIZE_; goto *batch_rips[I]; }
static void CityHash64_test ( const void * key, int len, uint32_t seed, void *out) { *(uint64*)out = CityHash64WithSeed((const char *)key,len,seed); }
/** * @brief Find and reference a DRC to process the supplied svc_req. * * @param[in] req The svc_req being processed. * * @return The ref'd DRC if sucessfully located, else NULL. */ static /* inline */ drc_t * nfs_dupreq_get_drc(struct svc_req *req) { enum drc_type dtype = get_drc_type(req); gsh_xprt_private_t *xu = (gsh_xprt_private_t *) req->rq_xprt->xp_u1; drc_t *drc = NULL; bool drc_check_expired = false; switch (dtype) { case DRC_UDP_V234: LogFullDebug(COMPONENT_DUPREQ, "ref shared UDP DRC"); drc = &(drc_st->udp_drc); DRC_ST_LOCK(); (void)nfs_dupreq_ref_drc(drc); DRC_ST_UNLOCK(); goto out; break; case DRC_TCP_V4: case DRC_TCP_V3: pthread_mutex_lock(&req->rq_xprt->xp_lock); if (xu->drc) { drc = xu->drc; LogFullDebug(COMPONENT_DUPREQ, "ref DRC=%p for xprt=%p", drc, req->rq_xprt); pthread_mutex_lock(&drc->mtx); /* LOCKED */ } else { drc_t drc_k; struct rbtree_x_part *t = NULL; struct opr_rbtree_node *ndrc = NULL; drc_t *tdrc = NULL; memset(&drc_k, 0, sizeof(drc_k)); drc_k.type = dtype; (void)copy_xprt_addr(&drc_k.d_u.tcp.addr, req->rq_xprt); drc_k.d_u.tcp.hk = CityHash64WithSeed((char *)&drc_k.d_u.tcp.addr, sizeof(sockaddr_t), 911); { char str[512]; sprint_sockaddr(&drc_k.d_u.tcp.addr, str, 512); LogFullDebug(COMPONENT_DUPREQ, "get drc for addr: %s", str); } t = rbtx_partition_of_scalar(&drc_st->tcp_drc_recycle_t, drc_k.d_u.tcp.hk); DRC_ST_LOCK(); ndrc = opr_rbtree_lookup(&t->t, &drc_k.d_u.tcp.recycle_k); if (ndrc) { /* reuse old DRC */ tdrc = opr_containerof(ndrc, drc_t, d_u.tcp.recycle_k); pthread_mutex_lock(&tdrc->mtx); /* LOCKED */ if (tdrc->flags & DRC_FLAG_RECYCLE) { TAILQ_REMOVE(&drc_st->tcp_drc_recycle_q, tdrc, d_u.tcp.recycle_q); --(drc_st->tcp_drc_recycle_qlen); tdrc->flags &= ~DRC_FLAG_RECYCLE; } drc = tdrc; LogFullDebug(COMPONENT_DUPREQ, "recycle TCP DRC=%p for xprt=%p", tdrc, req->rq_xprt); } if (!drc) { drc = alloc_tcp_drc(dtype); LogFullDebug(COMPONENT_DUPREQ, "alloc new TCP DRC=%p for xprt=%p", drc, req->rq_xprt); /* assign addr */ memcpy(&drc->d_u.tcp.addr, &drc_k.d_u.tcp.addr, sizeof(sockaddr_t)); /* assign already-computed hash */ drc->d_u.tcp.hk = drc_k.d_u.tcp.hk; pthread_mutex_lock(&drc->mtx); /* LOCKED */ /* xprt ref */ drc->refcnt = 1; /* insert dict */ opr_rbtree_insert(&t->t, &drc->d_u.tcp.recycle_k); } DRC_ST_UNLOCK(); drc->d_u.tcp.recycle_time = 0; /* xprt drc */ (void)nfs_dupreq_ref_drc(drc); /* xu ref */ /* try to expire unused DRCs somewhat in proportion to * new connection arrivals */ drc_check_expired = true; LogFullDebug(COMPONENT_DUPREQ, "after ref drc %p refcnt==%u ", drc, drc->refcnt); xu->drc = drc; } pthread_mutex_unlock(&req->rq_xprt->xp_lock); break; default: /* XXX error */ break; } /* call path ref */ (void)nfs_dupreq_ref_drc(drc); pthread_mutex_unlock(&drc->mtx); if (drc_check_expired) drc_free_expired(); out: return drc; }
foreach(batch_index, BATCH_SIZE) { char *name = name_lo[batch_index].name; if(batch_index != BATCH_SIZE - 1) { __builtin_prefetch(name_lo[batch_index + 1].name, 0, 3); } int c_i, i; /**< URL char iterator and slot iterator */ int bkt_num, bkt_1, bkt_2; int terminate = 0; /**< Stop processing this URL? */ int prefix_match_found = 0; /**< Stop this hash-table lookup ? */ /**< For names that we cannot find, dst_port is -1 */ dst_ports[batch_index] = -1; for(c_i = 0; name[c_i] != 0; c_i ++) { if(name[c_i] == '/') { break; } } c_i ++; for(; name[c_i] != 0; c_i ++) { if(name[c_i] != '/') { continue; } uint64_t prefix_hash = CityHash64WithSeed(name, c_i + 1, NDN_SEED); uint16_t tag = prefix_hash >> 48; struct ndn_slot *slots; /**< name[0] -> name[c_i] is a prefix of length c_i + 1 */ for(bkt_num = 1; bkt_num <= 2; bkt_num ++) { if(bkt_num == 1) { bkt_1 = prefix_hash & NDN_NUM_BKT_; FPP_EXPENSIVE(&ht[bkt_1]); slots = ht[bkt_1].slots; } else { bkt_2 = (bkt_1 ^ CityHash64((char *) &tag, 2)) & NDN_NUM_BKT_; FPP_EXPENSIVE(&ht[bkt_2]); slots = ht[bkt_2].slots; } /**< Now, "slots" points to an ndn_bucket. Find a valid slot * with a matching tag. */ for(i = 0; i < NDN_NUM_SLOTS; i ++) { int8_t _dst_port = slots[i].dst_port; uint64_t _hash = slots[i].cityhash; if(_dst_port >= 0 && _hash == prefix_hash) { /**< Record the dst port: this may get overwritten by * longer prefix matches later */ dst_ports[batch_index] = slots[i].dst_port; if(slots[i].is_terminal == 1) { /**< A terminal FIB entry: we're done! */ terminate = 1; } prefix_match_found = 1; break; } } /**< Stop the hash-table lookup for name[0 ... c_i] */ if(prefix_match_found == 1) { break; } } /**< Stop processing the name if we found a terminal FIB entry */ if(terminate == 1) { break; } } /**< Loop over URL characters ends here */ } /**< Loop over batch ends here */