更新时间:2026-07-13 GMT+08:00
批量恢复归档或深度归档存储对象(C SDK)
开发过程中,您有任何问题可以在GitHub上提交issue,或者在华为云对象存储服务论坛中发帖求助。
代码示例
本示例用于批量恢复归档或深度归档存储的对象。 归档或深度归档类型的对象处于冷冻状态无法直接访问,需要先提交恢复请求,等待恢复完成后才能访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include "eSDKOBS.h" #define MAX_KEY_LEN 1024 #define MAX_TASK 10000 typedef struct { char source_key[MAX_KEY_LEN]; char target_key[MAX_KEY_LEN]; } copy_task; typedef struct { int total; int success; int failed; char failed_keys[100][MAX_KEY_LEN]; int failed_count; pthread_mutex_t mutex; } batch_result; static batch_result g_result = {0, 0, 0, {{0}}, 0, PTHREAD_MUTEX_INITIALIZER}; static copy_task *g_tasks = NULL; static int g_task_count = 0; static int g_task_index = 0; static pthread_mutex_t g_task_mutex = PTHREAD_MUTEX_INITIALIZER; static obs_status copy_object_properties_callback(const obs_response_properties *properties, void *callback_data) { (void)properties; (void)callback_data; return OBS_STATUS_OK; } static void copy_object_complete_callback(obs_status status, const obs_error_details *error, void *callback_data) { (void)error; copy_task *task = (copy_task *)callback_data; char *source_key = task ? task->source_key : "unknown"; char *target_key = task ? task->target_key : "unknown"; pthread_mutex_lock(&g_result.mutex); if (status == OBS_STATUS_OK) { g_result.success++; printf("[SUCCESS] copy %s -> %s\n", source_key, target_key); } else { g_result.failed++; if (g_result.failed_count < 100) { strncpy(g_result.failed_keys[g_result.failed_count], source_key, MAX_KEY_LEN - 1); g_result.failed_keys[g_result.failed_count][MAX_KEY_LEN - 1] = '\0'; g_result.failed_count++; } printf("[FAILED] copy %s: %s\n", source_key, obs_get_status_name(status)); } pthread_mutex_unlock(&g_result.mutex); } typedef struct { copy_task *tasks; int max_count; int current_count; size_t prefix_len; const char *target_prefix; obs_status ret_status; } list_cb_data; static obs_status list_objects_callback(int is_truncated, const char *next_marker, int contents_count, const obs_list_objects_content *contents, int common_prefixes_count, const char **common_prefixes, void *callback_data) { (void)is_truncated; (void)next_marker; (void)common_prefixes_count; (void)common_prefixes; list_cb_data *data = (list_cb_data *)callback_data; for (int i = 0; i < contents_count && data->current_count < data->max_count; i++) { memset(&data->tasks[data->current_count], 0, sizeof(copy_task)); strncpy(data->tasks[data->current_count].source_key, contents[i].key, MAX_KEY_LEN - 1); snprintf(data->tasks[data->current_count].target_key, MAX_KEY_LEN, "%s%s", data->target_prefix, contents[i].key + data->prefix_len); data->current_count++; } return OBS_STATUS_OK; } static void list_complete_callback(obs_status status, const obs_error_details *error, void *callback_data) { (void)error; list_cb_data *data = (list_cb_data *)callback_data; data->ret_status = status; } static void *worker_thread(void *arg) { obs_options *options_ptr = (obs_options *)arg; const char *bucket_name = (const char *)options_ptr->bucket_options.bucket_name; while (1) { pthread_mutex_lock(&g_task_mutex); if (g_task_index >= g_task_count) { pthread_mutex_unlock(&g_task_mutex); break; } int idx = g_task_index++; pthread_mutex_unlock(&g_task_mutex); copy_task *task = &g_tasks[idx]; obs_copy_destination_object_info dest_info; memset(&dest_info, 0, sizeof(dest_info)); dest_info.destination_bucket = bucket_name; dest_info.destination_key = task->target_key; obs_response_handler handler = { copy_object_properties_callback, copy_object_complete_callback }; copy_object(options_ptr, task->source_key, NULL, &dest_info, 1, NULL, 0, &handler, task); } return NULL; } int main() { const char *BUCKET_NAME = "example-bucket-name"; const char *PREFIX = "test/source/"; const char *TARGET_PREFIX = "backup/"; int THREAD_NUM = 8; obs_status status = obs_initialize(OBS_INIT_ALL); if (status != OBS_STATUS_OK) { printf("obs_initialize failed: %s\n", obs_get_status_name(status)); return 1; } obs_options options; init_obs_options(&options); // host_name填写桶所在的endpoint, 此处以华北-北京四为例,其他地区请按实际情况填写。 options.bucket_options.host_name = "obs.cn-north-4.myhuaweicloud.com"; options.bucket_options.access_key = getenv("ACCESS_KEY_ID"); options.bucket_options.secret_access_key = getenv("SECRET_ACCESS_KEY"); options.bucket_options.bucket_name = (char *)BUCKET_NAME; printf("\nListing objects with prefix '%s'...\n", PREFIX); g_tasks = (copy_task *)malloc(sizeof(copy_task) * MAX_TASK); if (!g_tasks) { printf("Failed to allocate memory\n"); obs_deinitialize(); return 1; } list_cb_data cb_data = {g_tasks, MAX_TASK, 0, strlen(PREFIX), TARGET_PREFIX, OBS_STATUS_BUTT}; obs_list_objects_handler list_handler = { { NULL, list_complete_callback }, list_objects_callback }; list_bucket_objects(&options, PREFIX, NULL, NULL, 1000, &list_handler, &cb_data); if (cb_data.ret_status != OBS_STATUS_OK) { printf("list_bucket_objects failed: %s\n", obs_get_status_name(cb_data.ret_status)); free(g_tasks); obs_deinitialize(); return 1; } g_task_count = cb_data.current_count; if (g_task_count == 0) { printf("No objects found with prefix '%s'\n", PREFIX); free(g_tasks); obs_deinitialize(); return 0; } printf("Found %d objects to copy\n", g_task_count); g_result.total = g_task_count; g_result.success = 0; g_result.failed = 0; g_result.failed_count = 0; g_task_index = 0; pthread_t threads[THREAD_NUM]; for (int i = 0; i < THREAD_NUM; i++) { pthread_create(&threads[i], NULL, worker_thread, &options); } for (int i = 0; i < THREAD_NUM; i++) { pthread_join(threads[i], NULL); } printf("\n========== Batch Copy Summary ==========\n"); printf("Total: %d\n", g_result.total); printf("Success: %d\n", g_result.success); printf("Failed: %d\n", g_result.failed); if (g_result.failed_count > 0) { printf("\nFailed objects:\n"); for (int i = 0; i < g_result.failed_count; i++) { printf(" - %s\n", g_result.failed_keys[i]); } } printf("==========================================\n"); free(g_tasks); obs_deinitialize(); return 0; } |
相关链接
- 关于恢复归档存储对象的API说明,请参见恢复归档或深度归档存储对象。
- 更多关于恢复归档存储对象的代码示例,请参见Github示例。
- 恢复归档对象过程中返回的错误码含义、问题原因及处理措施可参考OBS错误码。
父主题: 下载对象(C SDK)