void * ngx_pool_get_ctx(ngx_pool_t *pool, ngx_uint_t index) { ngx_uint_t hash; uint32_t key; ngx_pool_context_node_t *node; hash = (ngx_uint_t) pool + index; key = ngx_murmur_hash2((u_char *)&hash, sizeof(hash)) % ngx_pool_context_hash_size; node = ngx_pool_context_hash[key]; while (node) { if (node->pool == pool && node->index == index) { return node->data; } node = node->next; } return NULL; }
static ngx_int_t ngx_http_split_clients_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_http_split_clients_ctx_t *ctx = (ngx_http_split_clients_ctx_t *) data; uint32_t hash; ngx_str_t val; ngx_uint_t i; ngx_http_split_clients_part_t *part; *v = ngx_http_variable_null_value; if (ngx_http_complex_value(r, &ctx->value, &val) != NGX_OK) { return NGX_OK; } hash = ngx_murmur_hash2(val.data, val.len); part = ctx->parts.elts; for (i = 0; i < ctx->parts.nelts; i++) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http split: %uD %uD", hash, part[i].percent); if (hash < part[i].percent || part[i].percent == 0) { *v = part[i].value; return NGX_OK; } } return NGX_OK; }
ngx_int_t ngx_pool_set_ctx(ngx_pool_t *pool, ngx_uint_t index, void *data) { ngx_uint_t hash; uint32_t key; ngx_pool_context_node_t *node; ngx_pool_cleanup_t *cln; hash = (ngx_uint_t) pool + index; key = ngx_murmur_hash2((u_char *)&hash, sizeof(hash)) % ngx_pool_context_hash_size; node = ngx_pool_context_hash[key]; while (node) { if (node->pool == pool && node->index == index) { node->data = data; return NGX_OK; } node = node->next; } cln = ngx_pool_cleanup_add(pool, sizeof(ngx_pool_context_node_t)); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_pool_context_cleanup; node = cln->data; node->prev = NULL; node->next = NULL; node->pool = pool; node->index = index; node->data = data; ngx_pool_context_link(&ngx_pool_context_hash[key], node); return NGX_OK; }
ngx_http_tfs_rcs_info_t * ngx_http_tfs_rcs_lookup(ngx_http_tfs_rc_ctx_t *ctx, ngx_str_t appkey) { ngx_int_t rc; ngx_uint_t hash; ngx_rbtree_node_t *node, *sentinel; ngx_http_tfs_rcs_info_t *tr; node = ctx->sh->rbtree.root; sentinel = ctx->sh->rbtree.sentinel; hash = ngx_murmur_hash2(appkey.data, appkey.len); while (node != sentinel) { if (hash < node->key) { node = node->left; continue; } if (hash > node->key) { node = node->right; continue; } /* hash == node->key */ tr = (ngx_http_tfs_rcs_info_t *) &node->color; rc = ngx_memn2cmp(appkey.data, tr->appkey.data, appkey.len, tr->appkey.len); if (rc == 0) { ngx_queue_remove(&tr->queue); ngx_queue_insert_head(&ctx->sh->queue, &tr->queue); return tr; } node = (rc < 0) ? node->left : node->right; } return NULL; }
static ngx_int_t ngx_http_upstream_init_chash_peer(ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *us) { ngx_str_t hash_value; ngx_http_upstream_chash_srv_conf_t *ucscf; ngx_http_upstream_chash_peer_data_t *uchpd; ucscf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_consistent_hash_module); if (ucscf == NULL) { return NGX_ERROR; } uchpd = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_chash_peer_data_t)); if (uchpd == NULL) { return NGX_ERROR; } uchpd->ucscf = ucscf; if (ngx_http_script_run(r, &hash_value, ucscf->lengths->elts, 0, ucscf->values->elts) == NULL) { return NGX_ERROR; } uchpd->hash = ngx_murmur_hash2(hash_value.data, hash_value.len); r->upstream->peer.get = ngx_http_upstream_get_chash_peer; r->upstream->peer.free = ngx_http_upstream_free_chash_peer; r->upstream->peer.data = uchpd; #if (NGX_HTTP_SSL) r->upstream->peer.set_session = ngx_http_upstream_chash_set_peer_session; r->upstream->peer.save_session = ngx_http_upstream_chash_save_peer_session; #endif return NGX_OK; }
ngx_http_reqstat_rbnode_t * ngx_http_reqstat_rbtree_lookup(ngx_shm_zone_t *shm_zone, ngx_str_t *val) { size_t size, len; uint32_t hash; ngx_int_t rc, excess; ngx_time_t *tp; ngx_msec_t now; ngx_queue_t *q; ngx_msec_int_t ms; ngx_rbtree_node_t *node, *sentinel; ngx_http_reqstat_ctx_t *ctx; ngx_http_reqstat_rbnode_t *rs; ctx = shm_zone->data; hash = ngx_murmur_hash2(val->data, val->len); node = ctx->sh->rbtree.root; sentinel = ctx->sh->rbtree.sentinel; tp = ngx_timeofday(); now = (ngx_msec_t) (tp->sec * 1000 + tp->msec); ngx_shmtx_lock(&ctx->shpool->mutex); while (node != sentinel) { if (hash < node->key) { node = node->left; continue; } if (hash > node->key) { node = node->right; continue; } /* hash == node->key */ rs = (ngx_http_reqstat_rbnode_t *) &node->color; /* len < node->len */ if (val->len < (size_t) rs->len) { node = node->left; continue; } rc = ngx_strncmp(val->data, rs->data, (size_t) rs->len); if (rc == 0) { ms = (ngx_msec_int_t) (now - rs->last_visit); rs->excess = rs->excess - ngx_abs(ms) * ctx->recycle_rate / 1000 + 1000; rs->last_visit = now; if (rs->excess > 0) { ngx_queue_remove(&rs->visit); ngx_queue_insert_head(&ctx->sh->visit, &rs->visit); } ngx_log_debug2(NGX_LOG_DEBUG_CORE, shm_zone->shm.log, 0, "reqstat lookup exist: %*s", rs->len, rs->data); ngx_shmtx_unlock(&ctx->shpool->mutex); return rs; } node = (rc < 0) ? node->left : node->right; } rc = 0; node = NULL; size = offsetof(ngx_rbtree_node_t, color) + offsetof(ngx_http_reqstat_rbnode_t, data) + ctx->key_len; if (ctx->alloc_already_fail == 0) { node = ngx_slab_alloc_locked(ctx->shpool, size); if (node == NULL) { ctx->alloc_already_fail = 1; } } if (node == NULL) { /* try to free a vacant node */ q = ngx_queue_last(&ctx->sh->visit); rs = ngx_queue_data(q, ngx_http_reqstat_rbnode_t, visit); ms = (ngx_msec_int_t) (now - rs->last_visit); excess = rs->excess - ngx_abs(ms) * ctx->recycle_rate / 1000; ngx_log_debug3(NGX_LOG_DEBUG_CORE, shm_zone->shm.log, 0, "reqstat lookup try recycle: %*s, %d", rs->len, rs->data, excess); if (excess < 0) { rc = 1; node = (ngx_rbtree_node_t *) ((char *) rs - offsetof(ngx_rbtree_node_t, color)); ngx_rbtree_delete(&ctx->sh->rbtree, node); ngx_queue_remove(&rs->visit); ngx_log_debug2(NGX_LOG_DEBUG_CORE, shm_zone->shm.log, 0, "reqstat lookup recycle: %*s", rs->len, rs->data); rs->conn_total = 0; ngx_memzero((void *) &rs->bytes_in, size - offsetof(ngx_rbtree_node_t, color) - offsetof(ngx_http_reqstat_rbnode_t, bytes_in)); } else { ngx_shmtx_unlock(&ctx->shpool->mutex); return NULL; } } node->key = hash; rs = (ngx_http_reqstat_rbnode_t *) &node->color; len = ngx_min(ctx->key_len, (ssize_t) val->len); ngx_memcpy(rs->data, val->data, len); rs->len = len; ngx_rbtree_insert(&ctx->sh->rbtree, node); ngx_queue_insert_head(&ctx->sh->visit, &rs->visit); if (!rc) { ngx_queue_insert_head(&ctx->sh->queue, &rs->queue); } rs->last_visit = now; rs->excess = 1000; ngx_log_debug2(NGX_LOG_DEBUG_CORE, shm_zone->shm.log, 0, "reqstat lookup build: %*s", rs->len, rs->data); ngx_shmtx_unlock(&ctx->shpool->mutex); return rs; }
ngx_int_t ngx_http_connection_pool_get(ngx_peer_connection_t *pc, void *data) { u_char pc_addr[32] = {'\0'}; ngx_uint_t bucket_id, hash; ngx_queue_t *q, *cache, *free; ngx_connection_t *c; ngx_http_connection_pool_t *p; ngx_http_connection_pool_elt_t *item; p = data; #if (NGX_DEBUG) p->count--; #endif ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get keepalive peer"); p->failed = 0; hash = ngx_murmur_hash2((u_char *) pc->sockaddr, pc->socklen); bucket_id = hash % p->bucket_count; cache = &p->cache[bucket_id]; free = &p->free[bucket_id]; ngx_sprintf(pc_addr, "%s:%d", inet_ntoa(((struct sockaddr_in*)(pc->sockaddr))->sin_addr), ntohs(((struct sockaddr_in*)(pc->sockaddr))->sin_port)); for (q = ngx_queue_head(cache); q != ngx_queue_sentinel(cache); q = ngx_queue_next(q)) { item = ngx_queue_data(q, ngx_http_connection_pool_elt_t, queue); c = item->connection; if (ngx_memn2cmp((u_char *) &item->sockaddr, (u_char *) pc->sockaddr, item->socklen, pc->socklen) == 0) { ngx_queue_remove(q); ngx_queue_insert_head(free, q); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get keepalive peer: using connection %p", c); c->idle = 0; c->log = pc->log; c->read->log = pc->log; c->write->log = pc->log; c->pool->log = pc->log; pc->connection = c; pc->cached = 1; item->free = free; return NGX_DONE; } } return NGX_OK; }
void ngx_http_connection_pool_free(ngx_peer_connection_t *pc, void *data, ngx_uint_t state) { ngx_http_connection_pool_t *p = data; ngx_http_connection_pool_elt_t *item; ngx_uint_t hash, bucket_id; ngx_queue_t *q, *cache, *free; ngx_connection_t *c; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "free keepalive peer"); /* remember failed state - peer.free() may be called more than once */ if (state & NGX_PEER_FAILED) { p->failed = 1; } /* cache valid connections */ c = pc->connection; if (p->failed || c == NULL || c->read->eof || c->read->error || c->read->timedout || c->write->error || c->write->timedout) { return; } if (ngx_handle_read_event(c->read, 0) != NGX_OK) { return; } #if (NGX_DEBUG) p->count++; #endif ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "free keepalive peer: saving connection %p", c); hash = ngx_murmur_hash2((u_char *) pc->sockaddr, pc->socklen); bucket_id = hash % p->bucket_count; cache = &p->cache[bucket_id]; free = &p->free[bucket_id]; if (ngx_queue_empty(free)) { q = ngx_queue_last(cache); ngx_queue_remove(q); item = ngx_queue_data(q, ngx_http_connection_pool_elt_t, queue); ngx_http_connection_pool_close(item->connection); } else { q = ngx_queue_head(free); ngx_queue_remove(q); item = ngx_queue_data(q, ngx_http_connection_pool_elt_t, queue); } item->connection = c; item->free = free; ngx_queue_insert_head(cache, q); pc->connection = NULL; if (c->read->timer_set) { ngx_del_timer(c->read); } if (c->write->timer_set) { ngx_del_timer(c->write); } c->write->handler = ngx_http_connection_pool_dummy_handler; c->read->handler = ngx_http_connection_pool_close_handler; c->data = item; c->idle = 1; c->log = ngx_cycle->log; c->read->log = ngx_cycle->log; c->write->log = ngx_cycle->log; c->pool->log = ngx_cycle->log; item->socklen = pc->socklen; ngx_memcpy(&item->sockaddr, pc->sockaddr, pc->socklen); if (c->read->ready) { ngx_http_connection_pool_close_handler(c->read); } }
static ngx_int_t ngx_http_upstream_init_chash(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) { u_char hash_buf[256]; ngx_int_t j, weight; ngx_uint_t sid, id, hash_len; ngx_uint_t i, n, *number, rnindex; ngx_http_upstream_rr_peer_t *peer; ngx_http_upstream_rr_peers_t *peers; ngx_http_upstream_chash_server_t *server; ngx_http_upstream_chash_srv_conf_t *ucscf; if (ngx_http_upstream_init_round_robin(cf, us) == NGX_ERROR) { return NGX_ERROR; } ucscf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_consistent_hash_module); if (ucscf == NULL) { return NGX_ERROR; } us->peer.init = ngx_http_upstream_init_chash_peer; peers = (ngx_http_upstream_rr_peers_t *) us->peer.data; if (peers == NULL) { return NGX_ERROR; } n = peers->number; ucscf->number = 0; ucscf->real_node = ngx_pcalloc(cf->pool, n * sizeof(ngx_http_upstream_chash_server_t**)); if (ucscf->real_node == NULL) { return NGX_ERROR; } for (i = 0; i < n; i++) { ucscf->number += peers->peer[i].weight * NGX_CHASH_VIRTUAL_NODE_NUMBER; ucscf->real_node[i] = ngx_pcalloc(cf->pool, (peers->peer[i].weight * NGX_CHASH_VIRTUAL_NODE_NUMBER + 1) * sizeof(ngx_http_upstream_chash_server_t*)); if (ucscf->real_node[i] == NULL) { return NGX_ERROR; } } ucscf->servers = ngx_pcalloc(cf->pool, (ucscf->number + 1) * sizeof(ngx_http_upstream_chash_server_t)); if (ucscf->servers == NULL) { return NGX_ERROR; } ucscf->d_servers = ngx_pcalloc(cf->pool, (ucscf->number + 1) * sizeof(ngx_http_upstream_chash_down_server_t)); if (ucscf->d_servers == NULL) { return NGX_ERROR; } ucscf->number = 0; for (i = 0; i < n; i++) { peer = &peers->peer[i]; sid = (ngx_uint_t) ngx_atoi(peer->id.data, peer->id.len); if (sid == (ngx_uint_t) NGX_ERROR || sid > 65535) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0, "server id %d", sid); ngx_snprintf(hash_buf, 256, "%V%Z", &peer->name); hash_len = ngx_strlen(hash_buf); sid = ngx_murmur_hash2(hash_buf, hash_len); } weight = peer->weight * NGX_CHASH_VIRTUAL_NODE_NUMBER; if (weight >= 1 << 14) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, "weigth[%d] is too large, is must be less than %d", weight / NGX_CHASH_VIRTUAL_NODE_NUMBER, (1 << 14) / NGX_CHASH_VIRTUAL_NODE_NUMBER); weight = 1 << 14; } for (j = 0; j < weight; j++) { server = &ucscf->servers[++ucscf->number]; server->peer = peer; server->rnindex = i; id = sid * 256 * 16 + j; server->hash = ngx_murmur_hash2((u_char *) (&id), 4); } } ngx_qsort(ucscf->servers + 1, ucscf->number, sizeof(ngx_http_upstream_chash_server_t), (const void *)ngx_http_upstream_chash_cmp); number = ngx_calloc(n * sizeof(ngx_uint_t), cf->log); if (number == NULL) { return NGX_ERROR; } for (i = 1; i <= ucscf->number; i++) { ucscf->servers[i].index = i; ucscf->d_servers[i].id = i; rnindex = ucscf->servers[i].rnindex; ucscf->real_node[rnindex][number[rnindex]] = &ucscf->servers[i]; number[rnindex]++; } ngx_free(number); ucscf->tree = ngx_pcalloc(cf->pool, sizeof(ngx_segment_tree_t)); if (ucscf->tree == NULL) { return NGX_ERROR; } ngx_segment_tree_init(ucscf->tree, ucscf->number, cf->pool); ucscf->tree->build(ucscf->tree, 1, 1, ucscf->number); ngx_queue_init(&ucscf->down_servers); return NGX_OK; }
static ngx_int_t ngx_http_tfs_create_info_node(ngx_http_tfs_t *t, ngx_http_tfs_rc_ctx_t *rc_ctx, u_char *data, ngx_str_t appkey) { u_char *p; size_t n; uint32_t len; ngx_int_t rc; ngx_rbtree_node_t *node; ngx_http_tfs_rcs_info_t *rc_info_node; rc_info_node = NULL; n = offsetof(ngx_rbtree_node_t, color) + sizeof(ngx_http_tfs_rcs_info_t); node = ngx_slab_alloc_locked(rc_ctx->shpool, n); if (node == NULL) { ngx_http_tfs_expire_and_alloc(node, n); } rc_info_node = (ngx_http_tfs_rcs_info_t *) &node->color; node->key = ngx_murmur_hash2(appkey.data, appkey.len); rc_info_node->appkey.data = ngx_slab_alloc_locked(rc_ctx->shpool, appkey.len); if (rc_info_node->appkey.data == NULL) { ngx_http_tfs_rc_server_expire(rc_ctx); rc_info_node->appkey.data = ngx_slab_alloc_locked(rc_ctx->shpool, appkey.len); if (rc_info_node->appkey.data == NULL) { goto login_error; } } ngx_memcpy(rc_info_node->appkey.data, appkey.data, appkey.len); rc_info_node->appkey.len = appkey.len; /* parse session id */ len = *((uint32_t *) data); p = data + sizeof(uint32_t); if (len <= 0) { rc_info_node->session_id.len = 0; goto login_error; } rc_info_node->session_id.len = len - 1; rc_info_node->session_id.data = ngx_slab_alloc_locked(rc_ctx->shpool, len); if (rc_info_node->session_id.data == NULL) { ngx_http_tfs_rc_server_expire(rc_ctx); rc_info_node->session_id.data = ngx_slab_alloc_locked(rc_ctx->shpool, rc_info_node->session_id.len); if (rc_info_node->session_id.data == NULL) { goto login_error; } } ngx_memcpy(rc_info_node->session_id.data, p, rc_info_node->session_id.len); p += rc_info_node->session_id.len + 1; /* parse rc info */ rc = ngx_http_tfs_parse_rc_info(rc_info_node, rc_ctx, p); if (rc == NGX_ERROR) { goto login_error; } t->rc_info_node = rc_info_node; ngx_rbtree_insert(&rc_ctx->sh->rbtree, node); ngx_queue_insert_head(&rc_ctx->sh->queue, &rc_info_node->queue); ngx_queue_insert_tail(&rc_ctx->sh->kp_queue, &rc_info_node->kp_queue); return NGX_OK; login_error: ngx_http_tfs_rc_server_destroy_node(rc_ctx, rc_info_node); t->rc_info_node = NULL; return NGX_ERROR; }
static ngx_int_t ngx_http_tfs_parse_rc_info(ngx_http_tfs_rcs_info_t *rc_info_node, ngx_http_tfs_rc_ctx_t *rc_ctx, u_char *data) { u_char *p; uint8_t is_master; uint32_t cluster_id, cluster_id_len, len; ngx_int_t dup_info_size, rc; ngx_uint_t i, j; ngx_http_tfs_group_info_t *group_info; ngx_http_tfs_logical_cluster_t *logical_cluster; ngx_http_tfs_physical_cluster_t *physical_cluster; ngx_http_tfs_cluster_group_info_t *cluster_group_info, *cluster_group_info2; ngx_http_tfs_tair_server_addr_info_t *dup_server_info; p = data; /* rc servers count */ rc_info_node->rc_servers_count = *((uint32_t *) p); p += sizeof(uint32_t); if (rc_info_node->rc_servers_count > 0) { rc_info_node->rc_servers = ngx_slab_alloc_locked(rc_ctx->shpool, rc_info_node->rc_servers_count * sizeof(uint64_t)); if (rc_info_node->rc_servers == NULL) { ngx_http_tfs_expire_and_alloc(rc_info_node->rc_servers, rc_info_node->rc_servers_count * sizeof(uint64_t)); } ngx_memcpy(rc_info_node->rc_servers, p, rc_info_node->rc_servers_count * sizeof(uint64_t)); p += sizeof(uint64_t) * rc_info_node->rc_servers_count; } /* logical cluster count */ rc_info_node->logical_cluster_count = *((uint32_t *) p); p += sizeof(uint32_t); logical_cluster = rc_info_node->logical_clusters; for (i = 0; i < rc_info_node->logical_cluster_count; i++) { logical_cluster->need_duplicate = *p; p += sizeof(uint8_t); if (logical_cluster->need_duplicate) { len = *((uint32_t *) p); p += sizeof(uint32_t); if (len > 0) { dup_info_size = len - 1; dup_server_info = &logical_cluster->dup_server_info; rc = ngx_http_tfs_parse_tair_server_addr_info(dup_server_info, p, dup_info_size, rc_ctx->shpool, 1); if (rc == NGX_ERROR) { return NGX_ERROR; } logical_cluster->dup_server_addr_hash = ngx_murmur_hash2(p, dup_info_size); p += dup_info_size + 1; rc_info_node->need_duplicate = 1; } } logical_cluster->rw_cluster_count = *((uint32_t *) p); p += sizeof(uint32_t); physical_cluster = logical_cluster->rw_clusters; for (j = 0; j < logical_cluster->rw_cluster_count; j++) { /* cluster stat */ physical_cluster->cluster_stat = *((uint32_t *) p); p += sizeof(uint32_t); /* access type */ physical_cluster->access_type = *((uint32_t *) p); p += sizeof(uint32_t); /* cluster id */ len = *((uint32_t *) p); if (len <= 0) { physical_cluster->cluster_id_text.len = 0; return NGX_ERROR; } physical_cluster->cluster_id_text.len = len - 1; p += sizeof(uint32_t); physical_cluster->cluster_id_text.data = ngx_slab_alloc_locked(rc_ctx->shpool, physical_cluster->cluster_id_text.len); if (physical_cluster->cluster_id_text.data == NULL) { ngx_http_tfs_expire_and_alloc(physical_cluster->cluster_id_text.data, physical_cluster->cluster_id_text.len); } ngx_memcpy(physical_cluster->cluster_id_text.data, p, physical_cluster->cluster_id_text.len); /* this cluster id need get from ns */ physical_cluster->cluster_id = 0; p += physical_cluster->cluster_id_text.len + 1; /* name server vip */ len = *((uint32_t *) p); if (len <= 0) { physical_cluster->ns_vip_text.len = 0; return NGX_ERROR; } physical_cluster->ns_vip_text.len = len - 1; p += sizeof(uint32_t); physical_cluster->ns_vip_text.data = ngx_slab_alloc_locked(rc_ctx->shpool, physical_cluster->ns_vip_text.len); if (physical_cluster->ns_vip_text.data == NULL) { ngx_http_tfs_expire_and_alloc(physical_cluster->ns_vip_text.data, physical_cluster->ns_vip_text.len); } ngx_memcpy(physical_cluster->ns_vip_text.data, p, physical_cluster->ns_vip_text.len); p += physical_cluster->ns_vip_text.len + 1; ngx_http_tfs_parse_inet(&physical_cluster->ns_vip_text, &physical_cluster->ns_vip); physical_cluster++; } logical_cluster++; } /* report interval */ rc_info_node->report_interval = *((uint32_t *) p); p += sizeof(uint32_t); /* modify time */ rc_info_node->modify_time = *((uint64_t *) p); p += sizeof(uint64_t); /* root server */ rc_info_node->meta_root_server = *((uint64_t *) p); p += sizeof(uint64_t); /* remote block cache */ len = *((uint32_t *) p); p += sizeof(uint32_t); rc_info_node->remote_block_cache_info.len = 0; if (len > 0) { rc_info_node->remote_block_cache_info.len = len - 1; rc_info_node->remote_block_cache_info.data = ngx_slab_alloc_locked(rc_ctx->shpool, rc_info_node->remote_block_cache_info.len); if (rc_info_node->remote_block_cache_info.data == NULL) { ngx_http_tfs_expire_and_alloc(rc_info_node->remote_block_cache_info.data, rc_info_node->remote_block_cache_info.len); } ngx_memcpy(rc_info_node->remote_block_cache_info.data, p, len - 1); p += len; } /* unlink & update cluster */ rc_info_node->unlink_cluster_count = *((uint32_t *) p); p += sizeof(uint32_t); cluster_group_info = rc_info_node->unlink_clusters; for (i = 0; i < rc_info_node->unlink_cluster_count; i++) { /* skip cluster_stat */ p += sizeof(uint32_t); /* skip access type */ p += sizeof(uint32_t); cluster_id_len = *((uint32_t *) p); p += sizeof(uint32_t); cluster_id = ngx_http_tfs_get_cluster_id(p); is_master = ngx_http_tfs_cluster_is_master(p); p += cluster_id_len; for (j = 0; j < i; j++) { cluster_group_info2 = &rc_info_node->unlink_clusters[j]; if (cluster_group_info2->cluster_id == cluster_id) { break; } } if (j >= i) { group_info = &cluster_group_info[i].group_info[0]; cluster_group_info[i].info_count = 1; cluster_group_info[i].group_count = 0; cluster_group_info[i].cluster_id = cluster_id; group_info->is_master = is_master; } else { group_info = &cluster_group_info2->group_info[cluster_group_info2->info_count++]; group_info->is_master = is_master; } /* name server vip */ len = *((uint32_t *) p); if (len <= 0) { group_info->ns_vip_text.len = 0; return NGX_ERROR; } group_info->ns_vip_text.len = len - 1; p += sizeof(uint32_t); group_info->ns_vip_text.data = ngx_slab_alloc_locked(rc_ctx->shpool, group_info->ns_vip_text.len); if (group_info->ns_vip_text.data == NULL) { ngx_http_tfs_expire_and_alloc(group_info->ns_vip_text.data, group_info->ns_vip_text.len); } memcpy(group_info->ns_vip_text.data, p, group_info->ns_vip_text.len); group_info->group_seq = -1; p += len; ngx_http_tfs_parse_inet(&group_info->ns_vip_text, &group_info->ns_vip); } /* use remote cache flag */ rc_info_node->use_remote_block_cache = *((uint32_t *) p); return NGX_OK; }
ngx_int_t ngx_http_tfs_get_remote_block_cache_instance( ngx_http_tfs_remote_block_cache_ctx_t *ctx, ngx_str_t *server_addr) { size_t server_addr_len; uint32_t server_addr_hash; ngx_int_t rc, i; ngx_str_t *st, *group_name; ngx_array_t config_server; ngx_http_tfs_t *t; ngx_http_tfs_tair_instance_t *instance; ngx_http_tfs_tair_server_addr_info_t server_addr_info; if (server_addr->len == 0 || server_addr->data == NULL) { return NGX_ERROR; } t = ctx->data; server_addr_len = server_addr->len; server_addr_hash = ngx_murmur_hash2(server_addr->data, server_addr_len); instance = ctx->tair_instance; if (instance->server != NULL) { if (instance->server_addr_hash == server_addr_hash) { return NGX_OK; } ngx_http_etair_destory_server(instance->server, (ngx_cycle_t *) ngx_cycle); instance->server = NULL; } rc = ngx_http_tfs_parse_tair_server_addr_info(&server_addr_info, server_addr->data, server_addr_len, t->pool, 0); if (rc == NGX_ERROR) { return NGX_ERROR; } rc = ngx_array_init(&config_server, t->pool, NGX_HTTP_TFS_TAIR_CONFIG_SERVER_COUNT, sizeof(ngx_str_t)); if (rc == NGX_ERROR) { return NGX_ERROR; } for (i = 0; i < NGX_HTTP_TFS_TAIR_CONFIG_SERVER_COUNT; i++) { if (server_addr_info.server[i].len > 0 ) { st = (ngx_str_t *) ngx_array_push(&config_server); *st = server_addr_info.server[i]; } } group_name = &server_addr_info.server[NGX_HTTP_TFS_TAIR_CONFIG_SERVER_COUNT]; instance->server = ngx_http_etair_create_server(group_name, &config_server, t->main_conf->tair_timeout, (ngx_cycle_t *) ngx_cycle); if (instance->server == NULL) { return NGX_ERROR; } instance->server_addr_hash = server_addr_hash; instance->area = server_addr_info.area; return NGX_OK; }