ngx_int_t ngx_http_tfs_process_rs(ngx_http_tfs_t *t) { ngx_int_t rc; ngx_buf_t *b; ngx_http_tfs_inet_t *addr; ngx_http_tfs_header_t *header; ngx_http_tfs_peer_connection_t *tp; 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_root_server_parse_message(t); if (rc != NGX_OK) { return rc; } t->state += 1; ngx_http_tfs_set_custom_initial_parameters(t); addr = ngx_http_tfs_select_meta_server(t); ngx_http_tfs_peer_set_addr(t->pool, &t->tfs_peer_servers[NGX_HTTP_TFS_META_SERVER], addr); return NGX_OK; }
static void ngx_http_tfs_remote_block_cache_get_handler(ngx_http_tair_key_value_t *kv, ngx_int_t rc, void *data) { u_char *p, *q; uint32_t ds_count; ngx_http_tfs_t *t; ngx_http_tfs_inet_t *addr; ngx_http_tfs_segment_data_t *segment_data; ngx_http_tfs_block_cache_key_t key; ngx_http_tfs_block_cache_value_t value; ngx_http_tfs_remote_block_cache_ctx_t *ctx = data; t = ctx->data; segment_data = &t->file.segment_data[t->file.segment_index]; if (rc == NGX_HTTP_ETAIR_SUCCESS) { q = kv->key.data; p = kv->value->data; if (p != NULL && (kv->value->len > NGX_HTTP_TFS_REMOTE_BLOCK_CACHE_VALUE_BASE_SIZE)) { key.ns_addr = *(uint64_t *)q; q += sizeof(uint64_t); key.block_id = *(uint32_t *)q; ds_count = *(uint32_t *)p; p += sizeof(uint32_t); if (ds_count > 0) { segment_data->block_info.ds_count = ds_count; segment_data->block_info.ds_addrs = ngx_pcalloc(t->pool, sizeof(ngx_http_tfs_inet_t) * ds_count); if (segment_data->block_info.ds_addrs == NULL) { ngx_http_tfs_finalize_request(t->data, t, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } ngx_memcpy(segment_data->block_info.ds_addrs, p, ds_count * sizeof(ngx_http_tfs_inet_t)); /* insert local block cache */ if (t->block_cache_ctx.use_cache & NGX_HTTP_TFS_LOCAL_BLOCK_CACHE) { value.ds_count = ds_count; value.ds_addrs = (uint64_t *)segment_data->block_info.ds_addrs; ngx_http_tfs_local_block_cache_insert( t->block_cache_ctx.local_ctx, t->log, &key, &value); } /* skip GET_BLK_INFO state */ t->state += 1; segment_data->cache_hit = NGX_HTTP_TFS_REMOTE_BLOCK_CACHE; /* select data server */ addr = ngx_http_tfs_select_data_server(t, segment_data); ngx_http_tfs_peer_set_addr(t->pool, &t->tfs_peer_servers[NGX_HTTP_TFS_DATA_SERVER], addr); } else { /* remote block cache invalid, need remove it */ ngx_http_tfs_remote_block_cache_remove(ctx, t->pool, t->log, &key); } } } else { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, t->log, 0, "lookup remote block cache, " "ns addr: %V, block id: %uD not found", &t->name_server_addr_text, segment_data->segment_info.block_id); } ngx_http_tfs_finalize_state(t, NGX_OK); }
ngx_int_t ngx_http_tfs_process_ms(ngx_http_tfs_t *t) { ngx_buf_t *b; ngx_int_t rc, dir_levels, parent_dir_len; ngx_chain_t *cl, **ll; ngx_http_tfs_header_t *header; 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_meta_server_parse_message(t); if (rc == NGX_ERROR) { return NGX_ERROR; } b->pos += header->len; /* need update meta table */ if (rc == NGX_HTTP_TFS_EXIT_LEASE_EXPIRED || rc == NGX_HTTP_TFS_EXIT_TABLE_VERSION_ERROR) { t->state = NGX_HTTP_TFS_STATE_ACTION_GET_META_TABLE; ngx_http_tfs_clear_buf(b); ngx_http_tfs_peer_set_addr(t->pool, &t->tfs_peer_servers[NGX_HTTP_TFS_ROOT_SERVER], (ngx_http_tfs_inet_t *)&t->loc_conf->meta_root_server); ngx_log_error(NGX_LOG_DEBUG, t->log, 0, "need update meta table, rc: %i", rc); return NGX_OK; } /* parent dir not exist, recursive create them */ if (rc == NGX_HTTP_TFS_EXIT_PARENT_EXIST_ERROR && t->r_ctx.recursive) { switch (t->r_ctx.action.code) { case NGX_HTTP_TFS_ACTION_CREATE_DIR: case NGX_HTTP_TFS_ACTION_CREATE_FILE: case NGX_HTTP_TFS_ACTION_MOVE_DIR: case NGX_HTTP_TFS_ACTION_MOVE_FILE: if (t->dir_lens == NULL) { parent_dir_len = ngx_http_tfs_get_parent_dir(&t->last_file_path, &dir_levels); t->dir_lens = ngx_pcalloc(t->pool, sizeof(ngx_int_t) * dir_levels); if (t->dir_lens == NULL) { return NGX_ERROR; } t->last_dir_level = 0; t->dir_lens[0] = t->last_file_path.len; } else { parent_dir_len = ngx_http_tfs_get_parent_dir(&t->last_file_path, NULL); } t->last_dir_level++; t->dir_lens[t->last_dir_level] = parent_dir_len; t->last_file_path.len = t->dir_lens[t->last_dir_level]; t->orig_action = t->r_ctx.action.code; /* temporarily modify */ t->r_ctx.action.code = NGX_HTTP_TFS_ACTION_CREATE_DIR; return NGX_OK; } } /* parent dir may be created by others * during the recursive creating process */ if (rc == NGX_HTTP_TFS_EXIT_TARGET_EXIST_ERROR && t->last_dir_level > 0) { rc = NGX_OK; } if (rc == NGX_OK || rc == NGX_DECLINED) { switch (t->r_ctx.action.code) { case NGX_HTTP_TFS_ACTION_CREATE_DIR: case NGX_HTTP_TFS_ACTION_CREATE_FILE: case NGX_HTTP_TFS_ACTION_MOVE_DIR: case NGX_HTTP_TFS_ACTION_MOVE_FILE: if (t->dir_lens != NULL) { if (t->last_dir_level > 0) { if (t->last_dir_level == 1) { t->r_ctx.action.code = t->orig_action; } t->last_file_path.len = t->dir_lens[--(t->last_dir_level)]; return NGX_OK; } } case NGX_HTTP_TFS_ACTION_REMOVE_DIR: t->state = NGX_HTTP_TFS_STATE_ACTION_DONE; return NGX_DONE; case NGX_HTTP_TFS_ACTION_REMOVE_FILE: switch (t->state) { case NGX_HTTP_TFS_STATE_REMOVE_GET_FRAG_INFO: if (rc == NGX_DECLINED) { t->state = NGX_HTTP_TFS_STATE_REMOVE_NOTIFY_MS; ngx_http_tfs_clear_buf(b); return NGX_OK; } t->state = NGX_HTTP_TFS_STATE_REMOVE_GET_BLK_INFO; break; case NGX_HTTP_TFS_STATE_REMOVE_NOTIFY_MS: t->state = NGX_HTTP_TFS_STATE_REMOVE_DONE; return NGX_DONE; } break; case NGX_HTTP_TFS_ACTION_LS_FILE: if (t->r_ctx.chk_exist == NGX_HTTP_TFS_NO && t->meta_info.file_count > 0) { /* need json output */ for (cl = t->out_bufs, ll = &t->out_bufs; cl; cl = cl->next) { ll = &cl->next; } cl = ngx_http_tfs_json_custom_file_info(t->json_output, &t->meta_info, t->r_ctx.file_type); if (cl == NULL) { return NGX_ERROR; } *ll = cl; } t->state = NGX_HTTP_TFS_STATE_ACTION_DONE; return NGX_DONE; case NGX_HTTP_TFS_ACTION_READ_FILE: if (rc == NGX_DECLINED || (t->r_ctx.chk_file_hole && !t->file.still_have)) { if (t->r_ctx.chk_file_hole) { /* need json output */ if (t->file_holes.nelts > 0) { t->json_output = ngx_http_tfs_json_init(t->log, t->pool); if (t->json_output == NULL) { return NGX_ERROR; } for (cl = t->out_bufs, ll = &t->out_bufs; cl; cl = cl->next) { ll = &cl->next; } cl = ngx_http_tfs_json_file_hole_info(t->json_output, &t->file_holes); if (cl == NULL) { return NGX_ERROR; } *ll = cl; } } t->state = NGX_HTTP_TFS_STATE_READ_DONE; return NGX_DONE; } if (t->r_ctx.chk_file_hole) { ngx_http_tfs_clear_buf(b); return NGX_OK; } t->state = NGX_HTTP_TFS_STATE_READ_GET_BLK_INFO; break; case NGX_HTTP_TFS_ACTION_WRITE_FILE: switch (t->state) { case NGX_HTTP_TFS_STATE_WRITE_CLUSTER_ID_MS: t->state = NGX_HTTP_TFS_STATE_WRITE_CLUSTER_ID_NS; break; case NGX_HTTP_TFS_STATE_WRITE_WRITE_MS: if (t->file.left_length == 0) { t->state = NGX_HTTP_TFS_STATE_WRITE_DONE; return NGX_DONE; } t->state = NGX_HTTP_TFS_STATE_WRITE_GET_BLK_INFO; } break; default: return NGX_ERROR; } /* NGX_OK */ /* only select once */ if (t->name_server_addr_text.len == 0) { rc = ngx_http_tfs_select_name_server(t, t->rc_info_node, &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; } ngx_http_tfs_peer_set_addr(t->pool, &t->tfs_peer_servers[NGX_HTTP_TFS_NAME_SERVER], &t->name_server_addr); /* skip get cluster id from ns */ if (t->r_ctx.action.code == NGX_HTTP_TFS_ACTION_WRITE_FILE && t->state == NGX_HTTP_TFS_STATE_WRITE_CLUSTER_ID_NS) { logical_cluster = &t->rc_info_node->logical_clusters[t->logical_cluster_index]; physical_cluster = &logical_cluster->rw_clusters[t->rw_cluster_index]; if (physical_cluster->cluster_id > 0) { if (t->file.cluster_id == 0) { t->file.cluster_id = physical_cluster->cluster_id; } else if (t->file.cluster_id != physical_cluster->cluster_id) { ngx_log_error(NGX_LOG_ERR, t->log, 0, "error, cluster id conflict: " "%uD(ns) <> %uD(ms)", physical_cluster->cluster_id, t->file.cluster_id); return NGX_ERROR; } t->state = NGX_HTTP_TFS_STATE_WRITE_GET_BLK_INFO; } } } if (t->r_ctx.action.code == NGX_HTTP_TFS_ACTION_READ_FILE) { /* lookup block cache */ t->block_cache_ctx.curr_lookup_cache = NGX_HTTP_TFS_LOCAL_BLOCK_CACHE; t->decline_handler = ngx_http_tfs_batch_lookup_block_cache; return NGX_DECLINED; } return NGX_OK; } return rc; }
ngx_int_t ngx_http_tfs_retry_ns(ngx_http_tfs_t *t) { ngx_int_t rc; ngx_http_tfs_peer_connection_t *tp; tp = t->tfs_peer; tp->peer.free(&tp->peer, tp->peer.data, 0); if (!t->retry_curr_ns) { t->rw_cluster_index++; rc = ngx_http_tfs_select_name_server(t, t->rc_info_node, &t->name_server_addr, &t->name_server_addr_text); if (rc == NGX_ERROR) { return NGX_HTTP_TFS_EXIT_SERVER_OBJECT_NOT_FOUND; } ngx_http_tfs_peer_set_addr(t->pool, &t->tfs_peer_servers[NGX_HTTP_TFS_NAME_SERVER], &t->name_server_addr); ngx_http_tfs_reset_segment_data(t); } else { t->retry_curr_ns = NGX_HTTP_TFS_NO; } switch (t->r_ctx.action.code) { case NGX_HTTP_TFS_ACTION_READ_FILE: case NGX_HTTP_TFS_ACTION_STAT_FILE: /* lookup block cache */ if (t->block_cache_ctx.curr_lookup_cache != NGX_HTTP_TFS_NO_BLOCK_CACHE) { if (!t->parent && (t->r_ctx.version == 2 || (t->is_large_file && !t->is_process_meta_seg))) { t->decline_handler = ngx_http_tfs_batch_lookup_block_cache; } else { t->decline_handler = ngx_http_tfs_lookup_block_cache; } return t->decline_handler(t); } break; case NGX_HTTP_TFS_ACTION_WRITE_FILE: /* update not allow retry */ if (t->r_ctx.is_raw_update) { return NGX_ERROR; } /* stat failed, do not dedup, save new tfs file and do not save tair */ if (t->is_stat_dup_file) { t->is_stat_dup_file = NGX_HTTP_TFS_NO; t->use_dedup = NGX_HTTP_TFS_NO; t->state = NGX_HTTP_TFS_STATE_WRITE_CLUSTER_ID_NS; t->file.segment_data[0].segment_info.block_id = 0; t->file.segment_data[0].segment_info.file_id = 0; } } if (ngx_http_tfs_reinit(t->data, t) != NGX_OK) { return NGX_ERROR; } ngx_http_tfs_connect(t); 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; }
ngx_int_t ngx_http_tfs_process_ms_ls_dir(ngx_http_tfs_t *t) { ngx_buf_t *b; ngx_int_t rc; ngx_chain_t *cl, **ll; ngx_http_tfs_ms_ls_response_t *fake_rsp; ngx_http_tfs_peer_connection_t *tps; ngx_http_tfs_peer_connection_t *tp; ngx_http_tfs_custom_meta_info_t *meta_info; tp = t->tfs_peer; b = &tp->body_buffer; tps = t->tfs_peer_servers; if (t->length != ngx_buf_size(b) && b->last != b->end) { return NGX_AGAIN; } rc = ngx_http_tfs_meta_server_parse_message(t); if (rc == NGX_ERROR) { return NGX_ERROR; } /* need update meta table */ if (rc == NGX_HTTP_TFS_EXIT_LEASE_EXPIRED || rc == NGX_HTTP_TFS_EXIT_TABLE_VERSION_ERROR) { t->state = NGX_HTTP_TFS_STATE_ACTION_GET_META_TABLE; ngx_http_tfs_clear_buf(b); ngx_http_tfs_peer_set_addr(t->pool, &tps[NGX_HTTP_TFS_ROOT_SERVER], (ngx_http_tfs_inet_t *) &t->loc_conf->meta_root_server); ngx_log_error(NGX_LOG_DEBUG, t->log, 0, "need update meta table, rc: %i", rc); return NGX_OK; } if (rc == NGX_OK) { if (t->length == 0) { if (!t->r_ctx.chk_exist) { if (t->file.still_have) { ngx_http_tfs_clear_buf(b); return NGX_OK; } if (t->meta_info.file_count > 0) { /* need json output */ for (cl = t->out_bufs, ll = &t->out_bufs; cl; cl = cl->next) { ll = &cl->next; } cl = ngx_http_tfs_json_custom_file_info(t->json_output, &t->meta_info, t->r_ctx.file_type); if (cl == NULL) { return NGX_ERROR; } *ll = cl; } } t->state = NGX_HTTP_TFS_STATE_ACTION_DONE; return NGX_DONE; } /* t->length > 0 */ /* find current meta_info */ for(meta_info = &t->meta_info; meta_info->next; meta_info = meta_info->next); if (meta_info->rest_file_count > 0) { /* fake next ls_dir response head */ fake_rsp = (ngx_http_tfs_ms_ls_response_t *) b->start; fake_rsp->still_have = 1; fake_rsp->count = meta_info->rest_file_count; b->last = ngx_movemem(b->start + sizeof(ngx_http_tfs_ms_ls_response_t), b->pos, ngx_buf_size(b)); b->pos = b->start; /* FIXME: fake len will be minus later, ugly */ t->length += ngx_buf_size(b); return NGX_AGAIN; } } return rc; }
ngx_int_t ngx_http_tfs_retry_ds(ngx_http_tfs_t *t) { ngx_int_t rc; ngx_http_tfs_inet_t *addr; ngx_http_tfs_segment_data_t *segment_data; ngx_http_tfs_peer_connection_t *tp; tp = t->tfs_peer; tp->peer.free(&tp->peer, tp->peer.data, 0); segment_data = &t->file.segment_data[t->file.segment_index]; addr = ngx_http_tfs_select_data_server(t, segment_data); if (addr == NULL) { switch(t->r_ctx.action.code) { case NGX_HTTP_TFS_ACTION_STAT_FILE: t->state = NGX_HTTP_TFS_STATE_STAT_GET_BLK_INFO; break; case NGX_HTTP_TFS_ACTION_READ_FILE: t->state = NGX_HTTP_TFS_STATE_READ_GET_BLK_INFO; break; case NGX_HTTP_TFS_ACTION_REMOVE_FILE: if (t->is_large_file && t->is_process_meta_seg) { return NGX_HTTP_TFS_EXIT_SERVER_OBJECT_NOT_FOUND; } /* TODO: dedup */ return NGX_ERROR; case NGX_HTTP_TFS_ACTION_WRITE_FILE: /* update not allow retry */ if (t->r_ctx.is_raw_update) { return NGX_ERROR; } /* stat retry_ds failed, do not dedup, * save new tfs file and do not save tair */ if (t->is_stat_dup_file) { t->is_stat_dup_file = NGX_HTTP_TFS_NO; t->use_dedup = NGX_HTTP_TFS_NO; t->state = NGX_HTTP_TFS_STATE_WRITE_CLUSTER_ID_NS; t->file.segment_data[0].segment_info.block_id = 0; t->file.segment_data[0].segment_info.file_id = 0; t->retry_curr_ns = NGX_HTTP_TFS_YES; } else { /* allow retry other writable clusters */ if (++t->retry_count <= NGX_HTTP_TFS_MAX_RETRY_COUNT) { t->retry_curr_ns = NGX_HTTP_TFS_YES; } t->state = NGX_HTTP_TFS_STATE_WRITE_GET_BLK_INFO; segment_data->segment_info.block_id = 0; segment_data->segment_info.file_id = 0; segment_data->write_file_number = 0; segment_data->segment_info.crc = 0; /* reset all write data from orig_data */ segment_data->data = NULL; rc = ngx_chain_add_copy_with_buf(t->pool, &segment_data->data, segment_data->orig_data); if (rc == NGX_ERROR) { return NGX_ERROR; } t->file.left_length = segment_data->segment_info.size; segment_data->oper_offset = 0; segment_data->oper_size = ngx_min(t->file.left_length, NGX_HTTP_TFS_MAX_FRAGMENT_SIZE); } break; default: return NGX_ERROR; } t->tfs_peer = ngx_http_tfs_select_peer(t); if (t->tfs_peer == NULL) { return NGX_ERROR; } t->recv_chain->buf = &t->header_buffer; t->recv_chain->next->buf = &t->tfs_peer->body_buffer; /* reset ds retry count */ segment_data->ds_retry = 0; if (t->retry_handler == NULL) { return NGX_ERROR; } return t->retry_handler(t); } ngx_http_tfs_peer_set_addr(t->pool, &t->tfs_peer_servers[NGX_HTTP_TFS_DATA_SERVER], addr); if (ngx_http_tfs_reinit(t->data, t) != NGX_OK) { return NGX_ERROR; } ngx_http_tfs_connect(t); return NGX_OK; }