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; }
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_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; }