|
|
@@ -157,6 +157,10 @@ static std::string read_etag(const std::string & path) {
|
|
|
return none;
|
|
|
}
|
|
|
|
|
|
+static bool is_http_status_ok(int status) {
|
|
|
+ return status >= 200 && status < 400;
|
|
|
+}
|
|
|
+
|
|
|
#ifdef LLAMA_USE_CURL
|
|
|
|
|
|
//
|
|
|
@@ -306,12 +310,14 @@ static bool common_download_head(CURL * curl,
|
|
|
}
|
|
|
|
|
|
// download one single file from remote URL to local path
|
|
|
-static bool common_download_file_single_online(const std::string & url,
|
|
|
+// returns status code or -1 on error
|
|
|
+static int common_download_file_single_online(const std::string & url,
|
|
|
const std::string & path,
|
|
|
const std::string & bearer_token,
|
|
|
const common_header_list & custom_headers) {
|
|
|
static const int max_attempts = 3;
|
|
|
static const int retry_delay_seconds = 2;
|
|
|
+
|
|
|
for (int i = 0; i < max_attempts; ++i) {
|
|
|
std::string etag;
|
|
|
|
|
|
@@ -371,7 +377,7 @@ static bool common_download_file_single_online(const std::string & url,
|
|
|
LOG_WRN("%s: deleting previous downloaded file: %s\n", __func__, path.c_str());
|
|
|
if (remove(path.c_str()) != 0) {
|
|
|
LOG_ERR("%s: unable to delete file: %s\n", __func__, path.c_str());
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -380,14 +386,14 @@ static bool common_download_file_single_online(const std::string & url,
|
|
|
if (std::filesystem::exists(path_temporary)) {
|
|
|
if (remove(path_temporary.c_str()) != 0) {
|
|
|
LOG_ERR("%s: unable to delete file: %s\n", __func__, path_temporary.c_str());
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (std::filesystem::exists(path)) {
|
|
|
if (remove(path.c_str()) != 0) {
|
|
|
LOG_ERR("%s: unable to delete file: %s\n", __func__, path.c_str());
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -414,23 +420,27 @@ static bool common_download_file_single_online(const std::string & url,
|
|
|
|
|
|
long http_code = 0;
|
|
|
curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, &http_code);
|
|
|
- if (http_code < 200 || http_code >= 400) {
|
|
|
+
|
|
|
+ int status = static_cast<int>(http_code);
|
|
|
+ if (!is_http_status_ok(http_code)) {
|
|
|
LOG_ERR("%s: invalid http status code received: %ld\n", __func__, http_code);
|
|
|
- return false;
|
|
|
+ return status; // TODO: maybe only return on certain codes
|
|
|
}
|
|
|
|
|
|
if (rename(path_temporary.c_str(), path.c_str()) != 0) {
|
|
|
LOG_ERR("%s: unable to rename file: %s to %s\n", __func__, path_temporary.c_str(), path.c_str());
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
+
|
|
|
+ return static_cast<int>(http_code);
|
|
|
} else {
|
|
|
LOG_INF("%s: using cached file: %s\n", __func__, path.c_str());
|
|
|
- }
|
|
|
|
|
|
- break;
|
|
|
+ return 304; // Not Modified - fake cached response
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- return true;
|
|
|
+ return -1; // max attempts reached
|
|
|
}
|
|
|
|
|
|
std::pair<long, std::vector<char>> common_remote_get_content(const std::string & url, const common_remote_params & params) {
|
|
|
@@ -625,7 +635,8 @@ static bool common_pull_file(httplib::Client & cli,
|
|
|
}
|
|
|
|
|
|
// download one single file from remote URL to local path
|
|
|
-static bool common_download_file_single_online(const std::string & url,
|
|
|
+// returns status code or -1 on error
|
|
|
+static int common_download_file_single_online(const std::string & url,
|
|
|
const std::string & path,
|
|
|
const std::string & bearer_token,
|
|
|
const common_header_list & custom_headers) {
|
|
|
@@ -659,8 +670,10 @@ static bool common_download_file_single_online(const std::string & url,
|
|
|
LOG_WRN("%s: HEAD invalid http status code received: %d\n", __func__, head ? head->status : -1);
|
|
|
if (file_exists) {
|
|
|
LOG_INF("%s: Using cached file (HEAD failed): %s\n", __func__, path.c_str());
|
|
|
- return true;
|
|
|
+ return 304; // 304 Not Modified - fake cached response
|
|
|
}
|
|
|
+ return head->status; // cannot use cached file, return raw status code
|
|
|
+ // TODO: maybe retry only on certain codes
|
|
|
}
|
|
|
|
|
|
std::string etag;
|
|
|
@@ -692,12 +705,12 @@ static bool common_download_file_single_online(const std::string & url,
|
|
|
if (file_exists) {
|
|
|
if (!should_download_from_scratch) {
|
|
|
LOG_INF("%s: using cached file: %s\n", __func__, path.c_str());
|
|
|
- return true;
|
|
|
+ return 304; // 304 Not Modified - fake cached response
|
|
|
}
|
|
|
LOG_WRN("%s: deleting previous downloaded file: %s\n", __func__, path.c_str());
|
|
|
if (remove(path.c_str()) != 0) {
|
|
|
LOG_ERR("%s: unable to delete file: %s\n", __func__, path.c_str());
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -709,7 +722,7 @@ static bool common_download_file_single_online(const std::string & url,
|
|
|
existing_size = std::filesystem::file_size(path_temporary);
|
|
|
} else if (remove(path_temporary.c_str()) != 0) {
|
|
|
LOG_ERR("%s: unable to delete file: %s\n", __func__, path_temporary.c_str());
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -730,15 +743,16 @@ static bool common_download_file_single_online(const std::string & url,
|
|
|
|
|
|
if (std::rename(path_temporary.c_str(), path.c_str()) != 0) {
|
|
|
LOG_ERR("%s: unable to rename file: %s to %s\n", __func__, path_temporary.c_str(), path.c_str());
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
if (!etag.empty()) {
|
|
|
write_etag(path, etag);
|
|
|
}
|
|
|
- break;
|
|
|
+
|
|
|
+ return head->status; // TODO: use actual GET status?
|
|
|
}
|
|
|
|
|
|
- return true;
|
|
|
+ return -1; // max attempts reached
|
|
|
}
|
|
|
|
|
|
std::pair<long, std::vector<char>> common_remote_get_content(const std::string & url,
|
|
|
@@ -777,22 +791,22 @@ std::pair<long, std::vector<char>> common_remote_get_content(const std::string
|
|
|
|
|
|
#if defined(LLAMA_USE_CURL) || defined(LLAMA_USE_HTTPLIB)
|
|
|
|
|
|
-static bool common_download_file_single(const std::string & url,
|
|
|
- const std::string & path,
|
|
|
- const std::string & bearer_token,
|
|
|
- bool offline,
|
|
|
- const common_header_list & headers) {
|
|
|
+int common_download_file_single(const std::string & url,
|
|
|
+ const std::string & path,
|
|
|
+ const std::string & bearer_token,
|
|
|
+ bool offline,
|
|
|
+ const common_header_list & headers) {
|
|
|
if (!offline) {
|
|
|
return common_download_file_single_online(url, path, bearer_token, headers);
|
|
|
}
|
|
|
|
|
|
if (!std::filesystem::exists(path)) {
|
|
|
LOG_ERR("%s: required file is not available in cache (offline mode): %s\n", __func__, path.c_str());
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
LOG_INF("%s: using cached file (offline mode): %s\n", __func__, path.c_str());
|
|
|
- return true;
|
|
|
+ return 304; // Not Modified - fake cached response
|
|
|
}
|
|
|
|
|
|
// download multiple files from remote URLs to local paths
|
|
|
@@ -810,7 +824,8 @@ static bool common_download_file_multiple(const std::vector<std::pair<std::strin
|
|
|
std::async(
|
|
|
std::launch::async,
|
|
|
[&bearer_token, offline, &headers](const std::pair<std::string, std::string> & it) -> bool {
|
|
|
- return common_download_file_single(it.first, it.second, bearer_token, offline, headers);
|
|
|
+ const int http_status = common_download_file_single(it.first, it.second, bearer_token, offline, headers);
|
|
|
+ return is_http_status_ok(http_status);
|
|
|
},
|
|
|
item
|
|
|
)
|
|
|
@@ -837,7 +852,8 @@ bool common_download_model(const common_params_model & model,
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- if (!common_download_file_single(model.url, model.path, bearer_token, offline, headers)) {
|
|
|
+ const int http_status = common_download_file_single(model.url, model.path, bearer_token, offline, headers);
|
|
|
+ if (!is_http_status_ok(http_status)) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@@ -975,7 +991,7 @@ common_hf_file_res common_get_hf_file(const std::string & hf_repo_with_tag,
|
|
|
} else if (res_code == 401) {
|
|
|
throw std::runtime_error("error: model is private or does not exist; if you are accessing a gated model, please provide a valid HF token");
|
|
|
} else {
|
|
|
- throw std::runtime_error(string_format("error from HF API, response code: %ld, data: %s", res_code, res_str.c_str()));
|
|
|
+ throw std::runtime_error(string_format("error from HF API (%s), response code: %ld, data: %s", url.c_str(), res_code, res_str.c_str()));
|
|
|
}
|
|
|
|
|
|
// check response
|
|
|
@@ -1094,7 +1110,8 @@ std::string common_docker_resolve_model(const std::string & docker) {
|
|
|
std::string local_path = fs_get_cache_file(model_filename);
|
|
|
|
|
|
const std::string blob_url = url_prefix + "/blobs/" + gguf_digest;
|
|
|
- if (!common_download_file_single(blob_url, local_path, token, false, {})) {
|
|
|
+ const int http_status = common_download_file_single(blob_url, local_path, token, false, {});
|
|
|
+ if (!is_http_status_ok(http_status)) {
|
|
|
throw std::runtime_error("Failed to download Docker Model");
|
|
|
}
|
|
|
|
|
|
@@ -1120,6 +1137,14 @@ std::string common_docker_resolve_model(const std::string &) {
|
|
|
throw std::runtime_error("download functionality is not enabled in this build");
|
|
|
}
|
|
|
|
|
|
+int common_download_file_single(const std::string &,
|
|
|
+ const std::string &,
|
|
|
+ const std::string &,
|
|
|
+ bool,
|
|
|
+ const common_header_list &) {
|
|
|
+ throw std::runtime_error("download functionality is not enabled in this build");
|
|
|
+}
|
|
|
+
|
|
|
#endif // LLAMA_USE_CURL || LLAMA_USE_HTTPLIB
|
|
|
|
|
|
std::vector<common_cached_model_info> common_list_cached_models() {
|