Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}