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_process_ns(ngx_http_tfs_t *t) { uint32_t cluster_id; ngx_buf_t *b; ngx_int_t rc; ngx_str_t *cluster_id_text; ngx_http_tfs_inet_t *addr; ngx_http_tfs_header_t *header; ngx_http_tfs_rcs_info_t *rc_info; ngx_http_tfs_peer_connection_t *tp; ngx_http_tfs_logical_cluster_t *logical_cluster; ngx_http_tfs_physical_cluster_t *physical_cluster; header = (ngx_http_tfs_header_t *) t->header; tp = t->tfs_peer; b = &tp->body_buffer; if (ngx_buf_size(b) < header->len) { return NGX_AGAIN; } rc = ngx_http_tfs_name_server_parse_message(t); ngx_http_tfs_clear_buf(b); if (rc == NGX_ERROR) { return rc; } if (rc <= NGX_HTTP_TFS_EXIT_GENERAL_ERROR) { return NGX_HTTP_TFS_AGAIN; } switch (t->r_ctx.action.code) { case NGX_HTTP_TFS_ACTION_STAT_FILE: t->state = NGX_HTTP_TFS_STATE_STAT_STAT_FILE; break; case NGX_HTTP_TFS_ACTION_READ_FILE: if (!t->parent && (t->r_ctx.version == 2 || (t->is_large_file && !t->is_process_meta_seg))) { t->decline_handler = ngx_http_tfs_batch_process_start; return NGX_DECLINED; } t->state = NGX_HTTP_TFS_STATE_READ_READ_DATA; break; case NGX_HTTP_TFS_ACTION_WRITE_FILE: switch(t->state) { case NGX_HTTP_TFS_STATE_WRITE_CLUSTER_ID_NS: /* save cluster id */ if (t->loc_conf->upstream->enable_rcs) { rc_info = t->rc_info_node; logical_cluster = &rc_info->logical_clusters[t->logical_cluster_index]; physical_cluster = &logical_cluster->rw_clusters[t->rw_cluster_index]; /* check ns cluster id with rc configure */ cluster_id_text = &physical_cluster->cluster_id_text; cluster_id = ngx_http_tfs_get_cluster_id(cluster_id_text->data); if (t->file.cluster_id != cluster_id) { ngx_log_error(NGX_LOG_ERR, t->log, 0, "error, cluster id conflict: " "%uD(ns) <> %uD(rcs)", t->file.cluster_id, cluster_id); return NGX_ERROR; } physical_cluster->cluster_id = t->file.cluster_id; } else { t->main_conf->cluster_id = t->file.cluster_id; } t->state = NGX_HTTP_TFS_STATE_WRITE_GET_BLK_INFO; return rc; case NGX_HTTP_TFS_STATE_WRITE_GET_GROUP_COUNT: if (t->group_count != 1) { t->state = NGX_HTTP_TFS_STATE_WRITE_GET_GROUP_SEQ; return rc; } /* group_count == 1, maybe able to make choice */ t->group_seq = 0; case NGX_HTTP_TFS_STATE_WRITE_GET_GROUP_SEQ: rc_info = t->rc_info_node; ngx_http_tfs_rcs_set_group_info_by_addr(rc_info, t->group_count, t->group_seq, t->name_server_addr); rc = ngx_http_tfs_select_name_server(t, rc_info, &t->name_server_addr, &t->name_server_addr_text); if (rc == NGX_ERROR) { return NGX_HTTP_TFS_EXIT_SERVER_OBJECT_NOT_FOUND; } tp->peer.free(&tp->peer, tp->peer.data, 0); ngx_http_tfs_peer_set_addr(t->pool, &t->tfs_peer_servers[NGX_HTTP_TFS_NAME_SERVER], &t->name_server_addr); return rc; case NGX_HTTP_TFS_STATE_WRITE_GET_BLK_INFO: if (t->is_stat_dup_file) { t->state = NGX_HTTP_TFS_STATE_WRITE_STAT_DUP_FILE; } else if (t->is_rolling_back) { t->state = NGX_HTTP_TFS_STATE_WRITE_DELETE_DATA; } else { if (!t->parent && (t->r_ctx.version == 2 || (t->is_large_file && !t->is_process_meta_seg))) { t->decline_handler = ngx_http_tfs_batch_process_start; return NGX_DECLINED; } t->state = NGX_HTTP_TFS_STATE_WRITE_CREATE_FILE_NAME; } break; } break; case NGX_HTTP_TFS_ACTION_REMOVE_FILE: switch (t->state) { case NGX_HTTP_TFS_STATE_REMOVE_GET_GROUP_COUNT: /* maybe able to make choice */ if (t->group_count != 1) { t->state = NGX_HTTP_TFS_STATE_REMOVE_GET_GROUP_SEQ; } /* group_count == 1, maybe able to make choice */ t->group_seq = 0; case NGX_HTTP_TFS_STATE_REMOVE_GET_GROUP_SEQ: rc_info = t->rc_info_node; ngx_http_tfs_rcs_set_group_info_by_addr(rc_info, t->group_count, t->group_seq, t->name_server_addr); rc = ngx_http_tfs_select_name_server(t, rc_info, &t->name_server_addr, &t->name_server_addr_text); if (rc == NGX_ERROR) { /* in order to return 404 */ return NGX_HTTP_TFS_EXIT_SERVER_OBJECT_NOT_FOUND; } tp->peer.free(&tp->peer, tp->peer.data, 0); ngx_http_tfs_peer_set_addr(t->pool, &t->tfs_peer_servers[NGX_HTTP_TFS_NAME_SERVER], &t->name_server_addr); return rc; case NGX_HTTP_TFS_STATE_REMOVE_GET_BLK_INFO: if (t->is_large_file && t->r_ctx.unlink_type == NGX_HTTP_TFS_UNLINK_DELETE && t->meta_segment_data == NULL) { t->state = NGX_HTTP_TFS_STATE_REMOVE_READ_META_SEGMENT; } else if (t->is_stat_dup_file) { t->state = NGX_HTTP_TFS_STATE_REMOVE_STAT_FILE; } else { t->state = NGX_HTTP_TFS_STATE_REMOVE_DELETE_DATA; } } break; } addr = ngx_http_tfs_select_data_server(t, &t->file.segment_data[t->file.segment_index]); if (addr == NULL) { return NGX_ERROR; } ngx_http_tfs_peer_set_addr(t->pool, &t->tfs_peer_servers[NGX_HTTP_TFS_DATA_SERVER], addr); return rc; }