mirror of
https://gitee.com/openharmony/request_request
synced 2024-11-23 15:00:48 +00:00
按需启停优化需求
Change-Id: I38634d9f19680fa7fee741508a29674cea18b273 Signed-off-by: shawnluxy <luxinyi4@huawei.com>
This commit is contained in:
parent
4088fecdb4
commit
837d54e145
@ -47,7 +47,8 @@
|
||||
"distributed_notification_service",
|
||||
"c_utils",
|
||||
"netstack",
|
||||
"ylong_runtime"
|
||||
"ylong_runtime",
|
||||
"storage_service"
|
||||
],
|
||||
"third_party": [
|
||||
"curl",
|
||||
|
@ -65,12 +65,14 @@ request_deps = [
|
||||
request_external_deps = [
|
||||
"ability_base:zuri",
|
||||
"ability_runtime:abilitykit_native",
|
||||
"ability_runtime:app_context",
|
||||
"ability_runtime:data_ability_helper",
|
||||
"ability_runtime:napi_base_context",
|
||||
"c_utils:utils",
|
||||
"hilog:libhilog",
|
||||
"ipc:ipc_single",
|
||||
"napi:ace_napi",
|
||||
"storage_service:storage_manager_acl",
|
||||
]
|
||||
|
||||
ohos_shared_library("request") {
|
||||
|
@ -23,6 +23,10 @@
|
||||
namespace OHOS::Request {
|
||||
static constexpr uint32_t TOKEN_MAX_BYTES = 2048;
|
||||
static constexpr uint32_t TOKEN_MIN_BYTES = 8;
|
||||
static constexpr int ACL_SUCC = 0;
|
||||
static const std::string SA_PERMISSION_RWX = "g:3815:rwx";
|
||||
static const std::string SA_PERMISSION_X = "g:3815:x";
|
||||
static const std::string SA_PERMISSION_CLEAN = "g:3815:---";
|
||||
class JsInitialize {
|
||||
public:
|
||||
JsInitialize() = default;
|
||||
@ -32,6 +36,7 @@ public:
|
||||
static void CreatProperties(napi_env env, napi_value &self, napi_value config, JsTask *task);
|
||||
static napi_status GetContext(napi_env env, napi_value value,
|
||||
std::shared_ptr<OHOS::AbilityRuntime::Context>& context);
|
||||
static bool GetBaseDir(std::string &baseDir);
|
||||
private:
|
||||
static ExceptionError InitParam(napi_env env, napi_value* argv,
|
||||
std::shared_ptr<OHOS::AbilityRuntime::Context> &context, Config &config);
|
||||
|
@ -46,11 +46,15 @@ public:
|
||||
|
||||
static void ClearTaskMap(const std::string &key);
|
||||
static void AddTaskMap(const std::string &key, JsTask* task);
|
||||
static bool SetPathPermission(const std::string &filepath);
|
||||
static void RemovePathMap(const std::string &filepath);
|
||||
static void ClearTaskContext(const std::string &key);
|
||||
|
||||
Config config_;
|
||||
static std::mutex taskMutex_;
|
||||
static std::map<std::string, JsTask*> taskMap_;
|
||||
static std::mutex pathMutex_;
|
||||
static std::map<std::string, int32_t> pathMap_;
|
||||
std::mutex listenerMutex_;
|
||||
std::map<std::string, std::vector<sptr<RequestNotify>>> listenerMap_;
|
||||
private:
|
||||
@ -94,6 +98,8 @@ private:
|
||||
static bool ParseTouch(napi_env env, size_t argc, napi_value *argv, std::shared_ptr<TouchContext> context);
|
||||
static int64_t ParseBefore(napi_env env, napi_value value);
|
||||
static int64_t ParseAfter(napi_env env, napi_value value, int64_t before);
|
||||
static void AddPathMap(const std::string &filepath, const std::string &baseDir);
|
||||
static void ResetDirAccess(const std::string &filepath);
|
||||
static void AddTaskContextMap(const std::string &key, std::shared_ptr<ContextInfo> context);
|
||||
static void UnrefTaskContextMap(std::shared_ptr<ContextInfo> context);
|
||||
static void UvUnrefTaskContext(uv_work_t *work, int status);
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include <cstring>
|
||||
#include <regex>
|
||||
#include <securec.h>
|
||||
#include <fstream>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "js_common.h"
|
||||
#include "log.h"
|
||||
@ -28,7 +30,6 @@ static constexpr const char *PARAM_KEY_DESCRIPTION = "description";
|
||||
static constexpr const char *PARAM_KEY_NETWORKTYPE = "networkType";
|
||||
static constexpr const char *PARAM_KEY_FILE_PATH = "filePath";
|
||||
static constexpr const char *PARAM_KEY_BACKGROUND = "background";
|
||||
static constexpr uint32_t FILE_PERMISSION = 0644;
|
||||
static constexpr uint32_t TITLE_MAXIMUM = 256;
|
||||
static constexpr uint32_t DESCRIPTION_MAXIMUM = 1024;
|
||||
static constexpr uint32_t URL_MAXIMUM = 2048;
|
||||
@ -126,6 +127,21 @@ napi_status JsInitialize::GetContext(napi_env env, napi_value value,
|
||||
return napi_ok;
|
||||
}
|
||||
|
||||
bool JsInitialize::GetBaseDir(std::string &baseDir)
|
||||
{
|
||||
auto context = AbilityRuntime::Context::GetApplicationContext();
|
||||
if (context == nullptr) {
|
||||
REQUEST_HILOGE("AppContext is null.");
|
||||
return false;
|
||||
}
|
||||
baseDir = context->GetBaseDir();
|
||||
if (baseDir.empty()) {
|
||||
REQUEST_HILOGE("Base dir not found.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ExceptionError JsInitialize::CheckFilePath(const std::shared_ptr<OHOS::AbilityRuntime::Context> &context,
|
||||
Config &config)
|
||||
{
|
||||
@ -150,6 +166,9 @@ ExceptionError JsInitialize::CheckFilePath(const std::shared_ptr<OHOS::AbilityRu
|
||||
if (file.name.empty()) {
|
||||
file.name = "file";
|
||||
}
|
||||
if (!JsTask::SetPathPermission(file.uri)) {
|
||||
return { .code = E_FILE_IO, .errInfo = "set path permission fail" };
|
||||
}
|
||||
err = GetFD(path, config, file.fd);
|
||||
if (err.code != E_OK) {
|
||||
return err;
|
||||
@ -184,11 +203,16 @@ ExceptionError JsInitialize::CheckUploadBodyFiles(Config &config, const std::str
|
||||
|
||||
int32_t bodyFd = open(fileName.c_str(), O_TRUNC | O_RDWR);
|
||||
if (bodyFd < 0) {
|
||||
bodyFd = open(fileName.c_str(), O_CREAT | O_RDWR, FILE_PERMISSION);
|
||||
bodyFd = open(fileName.c_str(), O_CREAT | O_RDWR);
|
||||
if (bodyFd < 0) {
|
||||
return { .code = E_FILE_IO, .errInfo = "Failed to open file errno " + std::to_string(errno) };
|
||||
}
|
||||
}
|
||||
|
||||
if (bodyFd >= 0) {
|
||||
chmod(fileName.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | S_IWOTH);
|
||||
}
|
||||
|
||||
config.bodyFds.push_back(bodyFd);
|
||||
config.bodyFileNames.push_back(fileName);
|
||||
}
|
||||
@ -202,8 +226,12 @@ ExceptionError JsInitialize::GetFD(const std::string &path, const Config &config
|
||||
if (fd >= 0) {
|
||||
REQUEST_HILOGD("File already exists");
|
||||
if (config.action == Action::UPLOAD) {
|
||||
chmod(path.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
return error;
|
||||
} else {
|
||||
chmod(path.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | S_IWOTH);
|
||||
}
|
||||
|
||||
if (config.version == Version::API10 && config.overwrite) {
|
||||
return error;
|
||||
}
|
||||
@ -214,10 +242,11 @@ ExceptionError JsInitialize::GetFD(const std::string &path, const Config &config
|
||||
ExceptionErrorCode code = config.version == Version::API10 ? E_FILE_IO : E_FILE_PATH;
|
||||
return { .code = code, .errInfo = "Failed to open file errno " + std::to_string(errno) };
|
||||
}
|
||||
fd = open(path.c_str(), O_CREAT | O_RDWR, FILE_PERMISSION);
|
||||
fd = open(path.c_str(), O_CREAT | O_RDWR);
|
||||
if (fd < 0) {
|
||||
return { .code = E_FILE_IO, .errInfo = "Failed to open file errno " + std::to_string(errno) };
|
||||
}
|
||||
chmod(path.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | S_IWOTH);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <securec.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "async_call.h"
|
||||
#include "js_initialize.h"
|
||||
@ -29,6 +30,8 @@
|
||||
#include "request_event.h"
|
||||
#include "request_manager.h"
|
||||
#include "upload/upload_task_napiV5.h"
|
||||
#include "storage_acl.h"
|
||||
using namespace OHOS::StorageDaemon;
|
||||
|
||||
namespace OHOS::Request {
|
||||
constexpr int64_t MILLISECONDS_IN_ONE_DAY = 24 * 60 * 60 * 1000;
|
||||
@ -40,6 +43,8 @@ std::mutex JsTask::requestFileMutex_;
|
||||
thread_local napi_ref JsTask::requestFileCtor = nullptr;
|
||||
std::mutex JsTask::taskMutex_;
|
||||
std::map<std::string, JsTask *> JsTask::taskMap_;
|
||||
std::mutex JsTask::pathMutex_;
|
||||
std::map<std::string, int32_t> JsTask::pathMap_;
|
||||
std::mutex JsTask::taskContextMutex_;
|
||||
std::map<std::string, std::shared_ptr<JsTask::ContextInfo>> JsTask::taskContextMap_;
|
||||
|
||||
@ -670,6 +675,88 @@ void JsTask::ClearTaskMap(const std::string &key)
|
||||
taskMap_.erase(it);
|
||||
}
|
||||
|
||||
bool JsTask::SetPathPermission(const std::string &filepath)
|
||||
{
|
||||
std::string baseDir;
|
||||
if (!JsInitialize::GetBaseDir(baseDir) || filepath.find(baseDir) == std::string::npos) {
|
||||
REQUEST_HILOGE("File dir not found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
AddPathMap(filepath, baseDir);
|
||||
for (auto it : pathMap_) {
|
||||
if (it.second <= 0) {
|
||||
continue;
|
||||
}
|
||||
if (AclSetAccess(it.first, SA_PERMISSION_X) != ACL_SUCC) {
|
||||
REQUEST_HILOGE("AclSetAccess Parent Dir Failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string childDir = filepath.substr(0, filepath.rfind("/"));
|
||||
if (AclSetAccess(childDir, SA_PERMISSION_RWX) != ACL_SUCC) {
|
||||
REQUEST_HILOGE("AclSetAccess Child Dir Failed.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void JsTask::AddPathMap(const std::string &filepath, const std::string &baseDir)
|
||||
{
|
||||
std::string childDir(filepath);
|
||||
std::string parentDir;
|
||||
while (childDir.length() > baseDir.length()) {
|
||||
parentDir = childDir.substr(0, childDir.rfind("/"));
|
||||
std::lock_guard<std::mutex> lockGuard(JsTask::pathMutex_);
|
||||
auto it = pathMap_.find(parentDir);
|
||||
if (it == pathMap_.end()) {
|
||||
pathMap_[parentDir] = 1;
|
||||
} else {
|
||||
pathMap_[parentDir] += 1;
|
||||
}
|
||||
childDir = parentDir;
|
||||
}
|
||||
}
|
||||
|
||||
void JsTask::ResetDirAccess(const std::string &filepath)
|
||||
{
|
||||
int ret = AclSetAccess(filepath, SA_PERMISSION_CLEAN);
|
||||
if (ret != ACL_SUCC) {
|
||||
REQUEST_HILOGE("AclSetAccess Reset Dir Failed.");
|
||||
}
|
||||
}
|
||||
|
||||
void JsTask::RemovePathMap(const std::string &filepath)
|
||||
{
|
||||
std::string baseDir;
|
||||
if (!JsInitialize::GetBaseDir(baseDir) || filepath.find(baseDir) == std::string::npos) {
|
||||
REQUEST_HILOGE("File dir not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (chmod(filepath.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) != 0) {
|
||||
REQUEST_HILOGE("File remove WOTH access Failed.");
|
||||
}
|
||||
|
||||
std::string childDir(filepath);
|
||||
std::string parentDir;
|
||||
while (childDir.length() > baseDir.length()) {
|
||||
parentDir = childDir.substr(0, childDir.rfind("/"));
|
||||
std::lock_guard<std::mutex> lockGuard(JsTask::pathMutex_);
|
||||
auto it = pathMap_.find(parentDir);
|
||||
if (it != pathMap_.end()) {
|
||||
if (pathMap_[parentDir] <= 1) {
|
||||
pathMap_.erase(parentDir);
|
||||
ResetDirAccess(parentDir);
|
||||
} else {
|
||||
pathMap_[parentDir] -= 1;
|
||||
}
|
||||
}
|
||||
childDir = parentDir;
|
||||
}
|
||||
}
|
||||
|
||||
void JsTask::ClearTaskContext(const std::string &key)
|
||||
{
|
||||
std::lock_guard<std::mutex> lockGuard(JsTask::taskContextMutex_);
|
||||
|
@ -200,6 +200,9 @@ void NotifyStub::OnDone(MessageParcel &data)
|
||||
return;
|
||||
}
|
||||
RequestEvent::AddCache(taskInfo->tid, taskInfo);
|
||||
for (auto &file : taskInfo->files) {
|
||||
JsTask::RemovePathMap(file.uri);
|
||||
}
|
||||
JsTask::ClearTaskContext(taskInfo->tid);
|
||||
}
|
||||
} // namespace OHOS::Request
|
||||
|
@ -88,7 +88,6 @@ void RequestServiceProxy::GetVectorData(const Config &config, MessageParcel &dat
|
||||
data.WriteString(file.uri);
|
||||
data.WriteString(file.filename);
|
||||
data.WriteString(file.type);
|
||||
data.WriteFileDescriptor(file.fd);
|
||||
data.WriteInt32(static_cast<int32_t>(errno));
|
||||
}
|
||||
|
||||
@ -97,15 +96,16 @@ void RequestServiceProxy::GetVectorData(const Config &config, MessageParcel &dat
|
||||
close(file.fd);
|
||||
}
|
||||
}
|
||||
|
||||
// Response Bodys fds.
|
||||
data.WriteUint32(config.bodyFds.size());
|
||||
for (const auto &fd : config.bodyFds) {
|
||||
data.WriteFileDescriptor(fd);
|
||||
if (fd > 0) {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
for (const auto &name : config.bodyFileNames) {
|
||||
data.WriteString(name);
|
||||
}
|
||||
|
||||
data.WriteUint32(config.headers.size());
|
||||
for (const auto &header : config.headers) {
|
||||
|
@ -6,7 +6,15 @@
|
||||
"libpath": "libdownload_server.dylib.so",
|
||||
"run-on-create": false,
|
||||
"distributed": false,
|
||||
"dump_level": 1
|
||||
"dump_level": 1,
|
||||
"start-on-demand": {
|
||||
"commonevent": [
|
||||
{
|
||||
"name": "usual.event.CONNECTIVITY_CHANGE",
|
||||
"value": "3"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -114,6 +114,7 @@ ohos_shared_library("request_service_c") {
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/c_event_handler.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/c_request_database.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/c_string_wrapper.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/c_task_config.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/c_task_info.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/common_event_notify.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/get_calling_bundle.cpp",
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "c_filter.h"
|
||||
#include "c_progress.h"
|
||||
#include "c_task_info.h"
|
||||
#include "c_task_config.h"
|
||||
#include "rdb_errno.h"
|
||||
#include "rdb_helper.h"
|
||||
#include "rdb_open_callback.h"
|
||||
@ -65,7 +66,8 @@ constexpr const char *CREATE_REQUEST_TABLE1 = "CREATE TABLE IF NOT EXISTS reques
|
||||
"processed TEXT, "
|
||||
"extras TEXT, "
|
||||
"form_items_len INTEGER, "
|
||||
"file_specs_len INTEGER)";
|
||||
"file_specs_len INTEGER, "
|
||||
"body_file_names_len INTEGER)";
|
||||
|
||||
constexpr const char *CREATE_REQUEST_TABLE2 = "CREATE TABLE IF NOT EXISTS task_info_attachment "
|
||||
"(id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
@ -78,7 +80,40 @@ constexpr const char *CREATE_REQUEST_TABLE2 = "CREATE TABLE IF NOT EXISTS task_i
|
||||
"file_name TEXT, "
|
||||
"mime_type TEXT, "
|
||||
"reason INTEGER, "
|
||||
"message TEXT)";
|
||||
"message TEXT, "
|
||||
"body_file_name TEXT)";
|
||||
|
||||
constexpr const char *CREATE_REQUEST_TABLE3 = "CREATE TABLE IF NOT EXISTS request_task_config "
|
||||
"(id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"task_id INTEGER, "
|
||||
"uid INTEGER, "
|
||||
"action INTEGER, "
|
||||
"mode INTEGER, "
|
||||
"cover INTEGER, "
|
||||
"network INTEGER, "
|
||||
"meterd INTEGER, "
|
||||
"roaming INTEGER, "
|
||||
"retry INTEGER, "
|
||||
"redirect INTEGER, "
|
||||
"idx INTEGER, "
|
||||
"begins INTEGER, "
|
||||
"ends INTEGER, "
|
||||
"gauge INTEGER, "
|
||||
"precise INTEGER, "
|
||||
"background INTEGER, "
|
||||
"bundle TEXT, "
|
||||
"url TEXT, "
|
||||
"titile TEXT, "
|
||||
"description TEXT, "
|
||||
"method TEXT, "
|
||||
"headers TEXT, "
|
||||
"data TEXT, "
|
||||
"token TEXT, "
|
||||
"extras TEXT, "
|
||||
"version INTEGER, "
|
||||
"form_items_len INTEGER, "
|
||||
"file_specs_len INTEGER, "
|
||||
"body_file_names_len INTEGER)";
|
||||
|
||||
class RequestDataBase {
|
||||
public:
|
||||
@ -89,6 +124,7 @@ public:
|
||||
bool Update(const OHOS::NativeRdb::ValuesBucket values, const OHOS::NativeRdb::AbsRdbPredicates &predicates);
|
||||
std::shared_ptr<OHOS::NativeRdb::ResultSet> Query(const OHOS::NativeRdb::AbsRdbPredicates &predicates,
|
||||
const std::vector<std::string> &columns);
|
||||
bool Delete(const OHOS::NativeRdb::AbsRdbPredicates &predicates);
|
||||
bool BeginTransaction();
|
||||
bool Commit();
|
||||
bool RollBack();
|
||||
@ -134,6 +170,17 @@ int QueryTaskInfoAttachment(const OHOS::NativeRdb::RdbPredicates &rdbPredicates,
|
||||
int64_t fileSpecsLen);
|
||||
CTaskInfo *BuildCTaskInfo(const TaskInfo &taskInfo);
|
||||
CProgress BuildCProgress(const Progress &progress);
|
||||
bool HasTaskConfigRecord(uint32_t taskId);
|
||||
bool RecordRequestTaskConfig(CTaskConfig *taskConfig);
|
||||
void GetCommonTaskConfig(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, TaskConfig &taskConfig);
|
||||
CTaskConfig **QueryAllTaskConfig();
|
||||
int QueryTaskConfigLen();
|
||||
int QueryRequestTaskConfig(const OHOS::NativeRdb::RdbPredicates &rdbPredicates, std::vector<TaskConfig> &taskConfigs);
|
||||
int QueryTaskConfigAttachment(const OHOS::NativeRdb::RdbPredicates &rdbPredicates, TaskConfig &taskConfig,
|
||||
int64_t formItemsLen, int64_t fileSpecsLen, int64_t bodyFileNamesLen);
|
||||
CTaskConfig **BuildCTaskConfigs(const std::vector<TaskConfig> &taskConfigs);
|
||||
bool CleanTaskConfigTable(uint32_t taskId, uint64_t uid);
|
||||
void DeleteCTaskConfigs(CTaskConfig **ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
98
services/service/rust/src/c_wrapper/include/c_task_config.h
Normal file
98
services/service/rust/src/c_wrapper/include/c_task_config.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef C_TASK_CONFIG_H
|
||||
#define C_TASK_CONFIG_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "c_form_item.h"
|
||||
#include "c_string_wrapper.h"
|
||||
|
||||
struct CommonTaskConfig {
|
||||
uint32_t taskId;
|
||||
uint64_t uid;
|
||||
uint8_t action;
|
||||
uint8_t mode;
|
||||
bool cover;
|
||||
uint8_t network;
|
||||
bool meterd;
|
||||
bool roaming;
|
||||
bool retry;
|
||||
bool redirect;
|
||||
uint32_t index;
|
||||
uint64_t begins;
|
||||
int64_t ends;
|
||||
bool gauge;
|
||||
bool precise;
|
||||
bool background;
|
||||
};
|
||||
|
||||
struct CStringMap {
|
||||
CStringWrapper key;
|
||||
CStringWrapper value;
|
||||
};
|
||||
|
||||
struct CTaskConfig {
|
||||
CStringWrapper bundle;
|
||||
CStringWrapper url;
|
||||
CStringWrapper title;
|
||||
CStringWrapper description;
|
||||
CStringWrapper method;
|
||||
CStringWrapper headers;
|
||||
CStringWrapper data;
|
||||
CStringWrapper token;
|
||||
CStringWrapper extras;
|
||||
uint8_t version;
|
||||
CFormItem *formItemsPtr;
|
||||
uint32_t formItemsLen;
|
||||
CFileSpec *fileSpecsPtr;
|
||||
uint32_t fileSpecsLen;
|
||||
CStringWrapper *bodyFileNamesPtr;
|
||||
uint32_t bodyFileNamesLen;
|
||||
CommonTaskConfig commonData;
|
||||
};
|
||||
|
||||
struct TaskConfig {
|
||||
std::string bundle;
|
||||
std::string url;
|
||||
std::string title;
|
||||
std::string description;
|
||||
std::string method;
|
||||
std::string headers;
|
||||
std::string data;
|
||||
std::string token;
|
||||
std::string extras;
|
||||
uint8_t version;
|
||||
std::vector<FormItem> formItems;
|
||||
std::vector<FileSpec> fileSpecs;
|
||||
std::vector<std::string> bodyFileNames;
|
||||
CommonTaskConfig commonData;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void DeleteCTaskConfig(CTaskConfig *ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // C_TASK_CONFIG_H
|
@ -60,6 +60,8 @@ struct CTaskInfo {
|
||||
uint32_t formItemsLen;
|
||||
CFileSpec *fileSpecsPtr;
|
||||
uint32_t fileSpecsLen;
|
||||
CStringWrapper *bodyFileNamesPtr;
|
||||
uint32_t bodyFileNamesLen;
|
||||
CStringWrapper title;
|
||||
CStringWrapper description;
|
||||
CStringWrapper mimeType;
|
||||
@ -76,6 +78,7 @@ struct TaskInfo {
|
||||
std::string token;
|
||||
std::vector<FormItem> formItems;
|
||||
std::vector<FileSpec> fileSpecs;
|
||||
std::vector<std::string> bodyFileNames;
|
||||
std::string title;
|
||||
std::string description;
|
||||
std::string mimeType;
|
||||
@ -98,6 +101,7 @@ extern "C" {
|
||||
|
||||
void DeleteCFormItem(CFormItem *ptr);
|
||||
void DeleteCFileSpec(CFileSpec *ptr);
|
||||
void DeleteCStringPtr(CStringWrapper *ptr);
|
||||
void DeleteCEachFileStatus(CEachFileStatus *ptr);
|
||||
void DeleteCTaskInfo(CTaskInfo *ptr);
|
||||
|
||||
|
@ -108,6 +108,19 @@ std::shared_ptr<OHOS::NativeRdb::ResultSet> RequestDataBase::Query(const OHOS::N
|
||||
return store_->Query(predicates, columns);
|
||||
}
|
||||
|
||||
bool RequestDataBase::Delete(const OHOS::NativeRdb::AbsRdbPredicates &predicates)
|
||||
{
|
||||
if (store_ == nullptr) {
|
||||
REQUEST_HILOGE("store_ is nullptr");
|
||||
return false;
|
||||
}
|
||||
|
||||
int deletedRows = 0;
|
||||
int ret = store_->Delete(deletedRows, predicates);
|
||||
REQUEST_HILOGI("request database delete ret is %{public}d, rows: %{public}d", ret, deletedRows);
|
||||
return ret == OHOS::NativeRdb::E_OK;
|
||||
}
|
||||
|
||||
int RequestDBOpenCallback::OnCreate(OHOS::NativeRdb::RdbStore &store)
|
||||
{
|
||||
int ret = store.ExecuteSql(CREATE_REQUEST_TABLE1);
|
||||
@ -120,6 +133,11 @@ int RequestDBOpenCallback::OnCreate(OHOS::NativeRdb::RdbStore &store)
|
||||
REQUEST_HILOGE("create table2 error, ret = %{public}d", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = store.ExecuteSql(CREATE_REQUEST_TABLE3);
|
||||
if (ret != OHOS::NativeRdb::E_OK) {
|
||||
REQUEST_HILOGE("create table3 error, ret = %{public}d", ret);
|
||||
return ret;
|
||||
}
|
||||
REQUEST_HILOGI("create table success");
|
||||
return OHOS::NativeRdb::E_OK;
|
||||
}
|
||||
@ -184,6 +202,7 @@ bool WriteRequestTaskInfo(CTaskInfo *taskInfo)
|
||||
insertValues.PutString("extras", std::string(taskInfo->progress.extras.cStr, taskInfo->progress.extras.len));
|
||||
insertValues.PutLong("form_items_len", taskInfo->formItemsLen);
|
||||
insertValues.PutLong("file_specs_len", taskInfo->fileSpecsLen);
|
||||
insertValues.PutLong("body_file_names_len", taskInfo->bodyFileNamesLen);
|
||||
if (!OHOS::Request::RequestDataBase::GetInstance().Insert(std::string("request_task_info"), insertValues)) {
|
||||
REQUEST_HILOGE("insert to request_task_info failed");
|
||||
return false;
|
||||
@ -194,8 +213,8 @@ bool WriteRequestTaskInfo(CTaskInfo *taskInfo)
|
||||
|
||||
bool WriteTaskInfoAttachment(CTaskInfo *taskInfo)
|
||||
{
|
||||
REQUEST_HILOGD("write to task_info_attachment");
|
||||
uint64_t len = std::max(taskInfo->formItemsLen, taskInfo->fileSpecsLen);
|
||||
REQUEST_HILOGI("write to task_info_attachment");
|
||||
uint64_t len = std::max({taskInfo->formItemsLen, taskInfo->fileSpecsLen, taskInfo->bodyFileNamesLen});
|
||||
for (uint64_t i = 0; i < len; i++) {
|
||||
OHOS::NativeRdb::ValuesBucket insertValues;
|
||||
insertValues.PutInt("task_id", taskInfo->commonData.taskId);
|
||||
@ -219,6 +238,10 @@ bool WriteTaskInfoAttachment(CTaskInfo *taskInfo)
|
||||
insertValues.PutString("message", std::string(taskInfo->eachFileStatusPtr[i].message.cStr,
|
||||
taskInfo->eachFileStatusPtr[i].message.len));
|
||||
}
|
||||
if (i < taskInfo->bodyFileNamesLen) {
|
||||
insertValues.PutString("body_file_name",
|
||||
std::string(taskInfo->bodyFileNamesPtr[i].cStr, taskInfo->bodyFileNamesPtr[i].len));
|
||||
}
|
||||
if (!OHOS::Request::RequestDataBase::GetInstance().Insert(std::string("task_info_attachment"), insertValues)) {
|
||||
REQUEST_HILOGE("insert to task_info_attachment failed");
|
||||
return false;
|
||||
@ -565,6 +588,12 @@ CTaskInfo *BuildCTaskInfo(const TaskInfo &taskInfo)
|
||||
eachFileStatusPtr[i].message = WrapperCString(taskInfo.eachFileStatus[i].message);
|
||||
}
|
||||
|
||||
uint32_t bodyFileNamesLen = taskInfo.bodyFileNames.size();
|
||||
CStringWrapper *bodyFileNamesPtr = new CStringWrapper[bodyFileNamesLen];
|
||||
for (uint32_t i = 0; i < bodyFileNamesLen; i++) {
|
||||
bodyFileNamesPtr[i] = WrapperCString(taskInfo.bodyFileNames[i]);
|
||||
}
|
||||
|
||||
CTaskInfo *cTaskInfo = new CTaskInfo;
|
||||
cTaskInfo->bundle = WrapperCString(taskInfo.bundle);
|
||||
cTaskInfo->url = WrapperCString(taskInfo.url);
|
||||
@ -574,6 +603,8 @@ CTaskInfo *BuildCTaskInfo(const TaskInfo &taskInfo)
|
||||
cTaskInfo->formItemsLen = formItemsLen;
|
||||
cTaskInfo->fileSpecsPtr = fileSpecsPtr;
|
||||
cTaskInfo->fileSpecsLen = fileSpecsLen;
|
||||
cTaskInfo->bodyFileNamesPtr = bodyFileNamesPtr;
|
||||
cTaskInfo->bodyFileNamesLen = bodyFileNamesLen;
|
||||
cTaskInfo->title = WrapperCString(taskInfo.title);
|
||||
cTaskInfo->description = WrapperCString(taskInfo.description);
|
||||
cTaskInfo->mimeType = WrapperCString(taskInfo.mimeType);
|
||||
@ -592,4 +623,303 @@ CProgress BuildCProgress(const Progress &progress)
|
||||
.processed = WrapperCString(progress.processed),
|
||||
.extras = WrapperCString(progress.extras),
|
||||
};
|
||||
}
|
||||
|
||||
bool HasTaskConfigRecord(uint32_t taskId)
|
||||
{
|
||||
OHOS::NativeRdb::RdbPredicates rdbPredicates("request_task_config");
|
||||
rdbPredicates.EqualTo("task_id", std::to_string(taskId));
|
||||
auto resultSet = OHOS::Request::RequestDataBase::GetInstance().Query(rdbPredicates, { "task_id" });
|
||||
if (resultSet == nullptr) {
|
||||
REQUEST_HILOGE("TaskConfig result set is nullptr");
|
||||
return false;
|
||||
}
|
||||
int rowCount = 0;
|
||||
if (resultSet->GetRowCount(rowCount) != OHOS::NativeRdb::E_OK) {
|
||||
REQUEST_HILOGE("TaskConfig result count row failed");
|
||||
return false;
|
||||
}
|
||||
if (rowCount == 0) {
|
||||
return false;
|
||||
}
|
||||
REQUEST_HILOGI("has the task record in task_config database");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RecordRequestTaskConfig(CTaskConfig *taskConfig)
|
||||
{
|
||||
REQUEST_HILOGI("write to request_task_config");
|
||||
OHOS::NativeRdb::ValuesBucket insertValues;
|
||||
insertValues.PutLong("task_id", taskConfig->commonData.taskId);
|
||||
insertValues.PutLong("uid", taskConfig->commonData.uid);
|
||||
insertValues.PutInt("action", taskConfig->commonData.action);
|
||||
insertValues.PutInt("mode", taskConfig->commonData.mode);
|
||||
insertValues.PutInt("cover", taskConfig->commonData.cover);
|
||||
insertValues.PutInt("network", taskConfig->commonData.network);
|
||||
insertValues.PutInt("meterd", taskConfig->commonData.meterd);
|
||||
insertValues.PutInt("roaming", taskConfig->commonData.roaming);
|
||||
insertValues.PutInt("retry", taskConfig->commonData.retry);
|
||||
insertValues.PutInt("redirect", taskConfig->commonData.redirect);
|
||||
insertValues.PutLong("idx", taskConfig->commonData.index);
|
||||
insertValues.PutLong("begins", taskConfig->commonData.begins);
|
||||
insertValues.PutLong("ends", taskConfig->commonData.ends);
|
||||
insertValues.PutInt("gauge", taskConfig->commonData.gauge);
|
||||
insertValues.PutInt("precise", taskConfig->commonData.precise);
|
||||
insertValues.PutInt("background", taskConfig->commonData.background);
|
||||
insertValues.PutString("bundle", std::string(taskConfig->bundle.cStr, taskConfig->bundle.len));
|
||||
insertValues.PutString("url", std::string(taskConfig->url.cStr, taskConfig->url.len));
|
||||
insertValues.PutString("titile", std::string(taskConfig->title.cStr, taskConfig->title.len));
|
||||
insertValues.PutString("description", std::string(taskConfig->description.cStr, taskConfig->description.len));
|
||||
insertValues.PutString("method", std::string(taskConfig->method.cStr, taskConfig->method.len));
|
||||
insertValues.PutString("headers", std::string(taskConfig->headers.cStr, taskConfig->headers.len));
|
||||
insertValues.PutString("data", std::string(taskConfig->data.cStr, taskConfig->data.len));
|
||||
insertValues.PutString("token", std::string(taskConfig->token.cStr, taskConfig->token.len));
|
||||
insertValues.PutString("extras", std::string(taskConfig->extras.cStr, taskConfig->extras.len));
|
||||
insertValues.PutInt("version", taskConfig->version);
|
||||
insertValues.PutLong("form_items_len", taskConfig->formItemsLen);
|
||||
insertValues.PutLong("file_specs_len", taskConfig->fileSpecsLen);
|
||||
insertValues.PutLong("body_file_names_len", taskConfig->bodyFileNamesLen);
|
||||
if (!OHOS::Request::RequestDataBase::GetInstance().Insert(std::string("request_task_config"), insertValues)) {
|
||||
REQUEST_HILOGE("insert to request_task_config failed");
|
||||
return false;
|
||||
}
|
||||
REQUEST_HILOGI("insert to request_task_config success");
|
||||
return true;
|
||||
}
|
||||
|
||||
void GetCommonTaskConfig(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, TaskConfig &taskConfig)
|
||||
{
|
||||
int64_t taskId = 0;
|
||||
int64_t uid = 0;
|
||||
int action = 0;
|
||||
int mode = 0;
|
||||
int cover = 0;
|
||||
int network = 0;
|
||||
int meterd = 0;
|
||||
int roaming = 0;
|
||||
int retry = 0;
|
||||
int redirect = 0;
|
||||
int64_t index = 0;
|
||||
int64_t begins = 0;
|
||||
int64_t ends = 0;
|
||||
int gauge = 0;
|
||||
int precise = 0;
|
||||
int background = 0;
|
||||
|
||||
resultSet->GetLong(0, taskId);
|
||||
taskConfig.commonData.taskId = static_cast<uint32_t>(taskId);
|
||||
resultSet->GetLong(1, uid);
|
||||
taskConfig.commonData.uid = static_cast<uint64_t>(uid);
|
||||
resultSet->GetInt(2, action);
|
||||
taskConfig.commonData.action = static_cast<uint8_t>(action);
|
||||
resultSet->GetInt(3, mode);
|
||||
taskConfig.commonData.mode = static_cast<uint8_t>(mode);
|
||||
resultSet->GetInt(4, cover);
|
||||
taskConfig.commonData.cover = static_cast<bool>(cover);
|
||||
resultSet->GetInt(5, network);
|
||||
taskConfig.commonData.network = static_cast<uint8_t>(network);
|
||||
resultSet->GetInt(6, meterd);
|
||||
taskConfig.commonData.meterd = static_cast<bool>(meterd);
|
||||
resultSet->GetInt(7, roaming);
|
||||
taskConfig.commonData.roaming = static_cast<bool>(roaming);
|
||||
resultSet->GetInt(8, retry);
|
||||
taskConfig.commonData.retry = static_cast<bool>(retry);
|
||||
resultSet->GetInt(9, redirect);
|
||||
taskConfig.commonData.redirect = static_cast<bool>(redirect);
|
||||
resultSet->GetLong(10, index);
|
||||
taskConfig.commonData.index = static_cast<uint32_t>(index);
|
||||
resultSet->GetLong(11, begins);
|
||||
taskConfig.commonData.begins = static_cast<uint64_t>(begins);
|
||||
resultSet->GetLong(12, ends);
|
||||
taskConfig.commonData.ends = static_cast<int64_t>(ends);
|
||||
resultSet->GetInt(13, gauge);
|
||||
taskConfig.commonData.gauge = static_cast<bool>(gauge);
|
||||
resultSet->GetInt(14, precise);
|
||||
taskConfig.commonData.precise = static_cast<bool>(precise);
|
||||
resultSet->GetInt(15, background);
|
||||
taskConfig.commonData.background = static_cast<bool>(background);
|
||||
}
|
||||
|
||||
CTaskConfig **QueryAllTaskConfig()
|
||||
{
|
||||
OHOS::NativeRdb::RdbPredicates rdbPredicates("request_task_config");
|
||||
std::vector<TaskConfig> taskConfigs;
|
||||
if (QueryRequestTaskConfig(rdbPredicates, taskConfigs) == OHOS::Request::QUERY_ERR) {
|
||||
return nullptr;
|
||||
}
|
||||
return BuildCTaskConfigs(taskConfigs);
|
||||
}
|
||||
|
||||
int QueryTaskConfigLen()
|
||||
{
|
||||
OHOS::NativeRdb::RdbPredicates rdbPredicates("request_task_config");
|
||||
auto resultSet = OHOS::Request::RequestDataBase::GetInstance().Query(rdbPredicates, { "task_id", "uid" });
|
||||
int len = 0;
|
||||
if (resultSet == nullptr || resultSet->GetRowCount(len) != OHOS::NativeRdb::E_OK) {
|
||||
REQUEST_HILOGE("Get TaskConfigs length failed");
|
||||
return OHOS::Request::QUERY_ERR;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int QueryRequestTaskConfig(const OHOS::NativeRdb::RdbPredicates &rdbPredicates, std::vector<TaskConfig> &taskConfigs)
|
||||
{
|
||||
auto resultSet = OHOS::Request::RequestDataBase::GetInstance().Query(rdbPredicates,
|
||||
{ "task_id", "uid", "action", "mode", "cover", "network", "meterd", "roaming", "retry", "redirect", "idx",
|
||||
"begins", "ends", "gauge", "precise", "background", "bundle", "url", "titile", "description", "method",
|
||||
"headers", "data", "token", "extras", "version",
|
||||
"form_items_len", "file_specs_len", "body_file_names_len" });
|
||||
int rowCount = 0;
|
||||
if (resultSet == nullptr || resultSet->GetRowCount(rowCount) != OHOS::NativeRdb::E_OK) {
|
||||
REQUEST_HILOGE("TaskConfig result set is nullptr or get row count failed");
|
||||
return OHOS::Request::QUERY_ERR;
|
||||
}
|
||||
for (auto i = 0; i < rowCount; i++) {
|
||||
if (resultSet->GoToRow(i) != OHOS::NativeRdb::E_OK) {
|
||||
REQUEST_HILOGE("TaskConfig result set go to %{public}d row failed", i);
|
||||
return OHOS::Request::QUERY_ERR;
|
||||
}
|
||||
TaskConfig taskConfig;
|
||||
int version = 0;
|
||||
int64_t formItemsLen = 0;
|
||||
int64_t fileSpecsLen = 0;
|
||||
int64_t bodyFileNamesLen = 0;
|
||||
GetCommonTaskConfig(resultSet, taskConfig);
|
||||
resultSet->GetString(16, taskConfig.bundle);
|
||||
resultSet->GetString(17, taskConfig.url);
|
||||
resultSet->GetString(18, taskConfig.title);
|
||||
resultSet->GetString(19, taskConfig.description);
|
||||
resultSet->GetString(20, taskConfig.method);
|
||||
resultSet->GetString(21, taskConfig.headers);
|
||||
resultSet->GetString(22, taskConfig.data);
|
||||
resultSet->GetString(23, taskConfig.token);
|
||||
resultSet->GetString(24, taskConfig.extras);
|
||||
resultSet->GetInt(25, version);
|
||||
taskConfig.version = static_cast<uint8_t>(version);
|
||||
resultSet->GetLong(26, formItemsLen);
|
||||
resultSet->GetLong(27, fileSpecsLen);
|
||||
resultSet->GetLong(28, bodyFileNamesLen);
|
||||
OHOS::NativeRdb::RdbPredicates rdbPredicates("task_info_attachment");
|
||||
rdbPredicates.EqualTo("task_id", std::to_string(taskConfig.commonData.taskId))
|
||||
->And()->EqualTo("uid", std::to_string(taskConfig.commonData.uid));
|
||||
if (QueryTaskConfigAttachment(rdbPredicates, taskConfig, formItemsLen, fileSpecsLen, bodyFileNamesLen)
|
||||
== OHOS::Request::QUERY_ERR) {
|
||||
return OHOS::Request::QUERY_ERR;
|
||||
}
|
||||
taskConfigs.push_back(std::move(taskConfig));
|
||||
}
|
||||
resultSet->Close();
|
||||
return OHOS::Request::QUERY_OK;
|
||||
}
|
||||
|
||||
int QueryTaskConfigAttachment(const OHOS::NativeRdb::RdbPredicates &rdbPredicates, TaskConfig &taskConfig,
|
||||
int64_t formItemsLen, int64_t fileSpecsLen, int64_t bodyFileNamesLen)
|
||||
{
|
||||
auto resultSet = OHOS::Request::RequestDataBase::GetInstance().Query(rdbPredicates,
|
||||
{ "form_item_name", "value", "file_spec_name", "path", "file_name", "mime_type", "body_file_name" });
|
||||
if (resultSet == nullptr) {
|
||||
REQUEST_HILOGE("ConfigAttach result set is nullptr");
|
||||
return OHOS::Request::QUERY_ERR;
|
||||
}
|
||||
int rowCount = 0;
|
||||
if (resultSet->GetRowCount(rowCount) != OHOS::NativeRdb::E_OK) {
|
||||
REQUEST_HILOGI("query task_config_attachment get row count failed");
|
||||
}
|
||||
int64_t len = std::max({formItemsLen, fileSpecsLen, bodyFileNamesLen});
|
||||
if (rowCount != len) {
|
||||
REQUEST_HILOGI("query task_config_attachment row count %{public}d != max len %{public}lld", rowCount, len);
|
||||
return OHOS::Request::QUERY_ERR;
|
||||
}
|
||||
for (int64_t i = 0; i < len; i++) {
|
||||
if (resultSet->GoToRow(i) != OHOS::NativeRdb::E_OK) {
|
||||
REQUEST_HILOGE("ConfigAttach result set go to %{public}" PRId64 "row failed", i);
|
||||
return OHOS::Request::QUERY_ERR;
|
||||
}
|
||||
if (i < formItemsLen) {
|
||||
FormItem formItem;
|
||||
resultSet->GetString(0, formItem.name);
|
||||
resultSet->GetString(1, formItem.value);
|
||||
taskConfig.formItems.push_back(std::move(formItem));
|
||||
}
|
||||
if (i < fileSpecsLen) {
|
||||
FileSpec fileSpec;
|
||||
resultSet->GetString(2, fileSpec.name);
|
||||
resultSet->GetString(3, fileSpec.path);
|
||||
resultSet->GetString(4, fileSpec.fileName);
|
||||
resultSet->GetString(5, fileSpec.mimeType);
|
||||
taskConfig.fileSpecs.push_back(std::move(fileSpec));
|
||||
}
|
||||
if (i < bodyFileNamesLen) {
|
||||
std::string bodyFileName;
|
||||
resultSet->GetString(6, bodyFileName);
|
||||
taskConfig.bodyFileNames.push_back(std::move(bodyFileName));
|
||||
}
|
||||
}
|
||||
resultSet->Close();
|
||||
return OHOS::Request::QUERY_OK;
|
||||
}
|
||||
|
||||
CTaskConfig **BuildCTaskConfigs(const std::vector<TaskConfig> &taskConfigs)
|
||||
{
|
||||
CTaskConfig **cTaskConfigs = new CTaskConfig *[taskConfigs.size()];
|
||||
for (unsigned int i = 0; i < taskConfigs.size(); i++) {
|
||||
CTaskConfig *cTaskConfig = new CTaskConfig;
|
||||
TaskConfig taskConfig = taskConfigs[i];
|
||||
cTaskConfig->bundle = WrapperCString(taskConfig.bundle);
|
||||
cTaskConfig->url = WrapperCString(taskConfig.url);
|
||||
cTaskConfig->title = WrapperCString(taskConfig.title);
|
||||
cTaskConfig->description = WrapperCString(taskConfig.description);
|
||||
cTaskConfig->method = WrapperCString(taskConfig.method);
|
||||
cTaskConfig->headers = WrapperCString(taskConfig.headers);
|
||||
cTaskConfig->data = WrapperCString(taskConfig.data);
|
||||
cTaskConfig->token = WrapperCString(taskConfig.token);
|
||||
cTaskConfig->extras = WrapperCString(taskConfig.extras);
|
||||
cTaskConfig->version = taskConfig.version;
|
||||
|
||||
uint32_t formItemsLen = taskConfig.formItems.size();
|
||||
CFormItem *formItemsPtr = new CFormItem[formItemsLen];
|
||||
for (uint32_t j = 0; j < formItemsLen; j++) {
|
||||
formItemsPtr[j].name = WrapperCString(taskConfig.formItems[j].name);
|
||||
formItemsPtr[j].value = WrapperCString(taskConfig.formItems[j].value);
|
||||
}
|
||||
uint32_t fileSpecsLen = taskConfig.fileSpecs.size();
|
||||
CFileSpec *fileSpecsPtr = new CFileSpec[fileSpecsLen];
|
||||
for (uint32_t j = 0; j < fileSpecsLen; j++) {
|
||||
fileSpecsPtr[j].name = WrapperCString(taskConfig.fileSpecs[j].name);
|
||||
fileSpecsPtr[j].path = WrapperCString(taskConfig.fileSpecs[j].path);
|
||||
fileSpecsPtr[j].fileName = WrapperCString(taskConfig.fileSpecs[j].fileName);
|
||||
fileSpecsPtr[j].mimeType = WrapperCString(taskConfig.fileSpecs[j].mimeType);
|
||||
}
|
||||
uint32_t bodyFileNamesLen = taskConfig.bodyFileNames.size();
|
||||
CStringWrapper *bodyFileNamesPtr = new CStringWrapper[bodyFileNamesLen];
|
||||
for (uint32_t j = 0; j < bodyFileNamesLen; j++) {
|
||||
bodyFileNamesPtr[j] = WrapperCString(taskConfig.bodyFileNames[j]);
|
||||
}
|
||||
|
||||
cTaskConfig->formItemsPtr = formItemsPtr;
|
||||
cTaskConfig->formItemsLen = formItemsLen;
|
||||
cTaskConfig->fileSpecsPtr = fileSpecsPtr;
|
||||
cTaskConfig->fileSpecsLen = fileSpecsLen;
|
||||
cTaskConfig->bodyFileNamesPtr = bodyFileNamesPtr;
|
||||
cTaskConfig->bodyFileNamesLen = bodyFileNamesLen;
|
||||
cTaskConfig->commonData = taskConfig.commonData;
|
||||
cTaskConfigs[i] = std::move(cTaskConfig);
|
||||
}
|
||||
return cTaskConfigs;
|
||||
}
|
||||
|
||||
bool CleanTaskConfigTable(uint32_t taskId, uint64_t uid)
|
||||
{
|
||||
OHOS::NativeRdb::RdbPredicates predicates("request_task_config");
|
||||
predicates.EqualTo("task_id", std::to_string(taskId))->And()->EqualTo("uid", std::to_string(uid));
|
||||
if (OHOS::Request::RequestDataBase::GetInstance().Delete(predicates)) {
|
||||
REQUEST_HILOGE("task_config table deleted task_id: %{public}u", taskId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeleteCTaskConfigs(CTaskConfig **ptr)
|
||||
{
|
||||
delete[] ptr;
|
||||
}
|
21
services/service/rust/src/c_wrapper/source/c_task_config.cpp
Normal file
21
services/service/rust/src/c_wrapper/source/c_task_config.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "c_task_config.h"
|
||||
|
||||
void DeleteCTaskConfig(CTaskConfig *ptr)
|
||||
{
|
||||
delete[] ptr;
|
||||
}
|
@ -25,6 +25,11 @@ void DeleteCFileSpec(CFileSpec *ptr)
|
||||
delete[] ptr;
|
||||
}
|
||||
|
||||
void DeleteCStringPtr(CStringWrapper *ptr)
|
||||
{
|
||||
delete[] ptr;
|
||||
}
|
||||
|
||||
void DeleteCEachFileStatus(CEachFileStatus *ptr)
|
||||
{
|
||||
delete[] ptr;
|
||||
|
@ -91,6 +91,24 @@ pub enum State {
|
||||
ANY = 0x61,
|
||||
}
|
||||
|
||||
impl From<u8> for State {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
0 => State::INITIALIZED,
|
||||
16 => State::WAITING,
|
||||
32 => State::RUNNING,
|
||||
33 => State::RETRYING,
|
||||
48 => State::PAUSED,
|
||||
49 => State::STOPPED,
|
||||
64 => State::COMPLETED,
|
||||
65 => State::FAILED,
|
||||
80 => State::REMOVED,
|
||||
96 => State::CREATED,
|
||||
_ => State::ANY,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[repr(i32)]
|
||||
pub enum ApplicationState {
|
||||
|
@ -16,7 +16,7 @@
|
||||
#![allow(unused_variables)]
|
||||
// C interface for check permission
|
||||
use super::{enumration::*, progress::RequestTaskMsg, form_item::CFileSpec,
|
||||
form_item::CFormItem, task_info::*, c_string_wrapper::*, filter::*};
|
||||
form_item::CFormItem, task_info::*, task_config::*, c_string_wrapper::*, filter::*};
|
||||
use std::ffi::{c_char, c_void};
|
||||
|
||||
type APPSTATECB = extern "C" fn(i32, i32);
|
||||
@ -38,6 +38,9 @@ extern "C" {
|
||||
pub fn GetNetworkInfo() -> *const NetworkInfo;
|
||||
pub fn GetTopBundleName() -> CStringWrapper;
|
||||
pub fn DeleteCTaskInfo(ptr: *const CTaskInfo);
|
||||
pub fn DeleteCTaskConfig(ptr: *const CTaskConfig);
|
||||
pub fn DeleteCTaskConfigs(ptr: *const*const CTaskConfig);
|
||||
pub fn DeleteCStringPtr(ptr: *const CStringWrapper);
|
||||
pub fn DeleteChar(ptr: *const c_char);
|
||||
pub fn DeleteCFormItem(ptr: *const CFormItem);
|
||||
pub fn DeleteCFileSpec(ptr: *const CFileSpec);
|
||||
@ -49,6 +52,11 @@ extern "C" {
|
||||
pub fn Touch(taskId: u32, uid: u64, token: CStringWrapper) -> *const CTaskInfo;
|
||||
pub fn Query(taskId: u32, queryAction: Action) -> *const CTaskInfo;
|
||||
pub fn Search(filter: CFilter) -> CVectorWrapper;
|
||||
pub fn HasTaskConfigRecord(taskId: u32) -> bool;
|
||||
pub fn RecordRequestTaskConfig(taskConfig: *const CTaskConfig) -> bool;
|
||||
pub fn QueryAllTaskConfig() -> *const*const CTaskConfig;
|
||||
pub fn QueryTaskConfigLen() -> i32;
|
||||
pub fn CleanTaskConfigTable(taskId: u32, uid: u64) -> bool;
|
||||
pub fn RequestIsSystemAPI(tokenId: u64) -> bool;
|
||||
pub fn GetCallingBundle(tokenId: u64) -> CStringWrapper;
|
||||
pub fn PublishStateChangeEvents(bundleName: *const c_char, bundleNameLen: u32, taskId: u32, state: i32);
|
||||
|
@ -80,6 +80,10 @@ impl RequestServiceInterface for RequestService {
|
||||
let description: String = data.read()?;
|
||||
let data_base: String = data.read()?;
|
||||
|
||||
let bundle = RequestAbility::get_ability_instance().get_calling_bundle();
|
||||
let mut task_id: u32 = 0;
|
||||
let uid: u64 = get_calling_uid();
|
||||
|
||||
let mut form_items = Vec::<FormItem>::new();
|
||||
let form_size: u32 = data.read()?;
|
||||
if form_size > data.get_readable_bytes() {
|
||||
@ -106,8 +110,13 @@ impl RequestServiceInterface for RequestService {
|
||||
let path: String = data.read()?;
|
||||
let file_name: String = data.read()?;
|
||||
let mime_type: String = data.read()?;
|
||||
let fd = data.read::<FileDesc>()?;
|
||||
files.push(File::from(fd));
|
||||
if action == Action::UPLOAD{
|
||||
let file = RequestAbility::open_file_readonly(uid, &bundle, &path)?;
|
||||
files.push(file);
|
||||
} else {
|
||||
let file = RequestAbility::open_file_readwrite(uid, &bundle, &path)?;
|
||||
files.push(file);
|
||||
}
|
||||
let fd_error: i32 = data.read()?;
|
||||
file_specs.push(FileSpec {
|
||||
name,
|
||||
@ -120,9 +129,12 @@ impl RequestServiceInterface for RequestService {
|
||||
// Response Bodys fd.
|
||||
let body_file_size: u32 = data.read()?;
|
||||
let mut body_files = Vec::new();
|
||||
let mut body_file_names: Vec<String> = Vec::new();
|
||||
for i in 0..body_file_size {
|
||||
let fd = data.read::<FileDesc>()?;
|
||||
body_files.push(File::from(fd));
|
||||
let file_name: String = data.read()?;
|
||||
let body_file = RequestAbility::open_file_readwrite(uid, &bundle, &file_name)?;
|
||||
body_file_names.push(file_name);
|
||||
body_files.push(body_file);
|
||||
}
|
||||
|
||||
let header_size: u32 = data.read()?;
|
||||
@ -150,7 +162,7 @@ impl RequestServiceInterface for RequestService {
|
||||
let value: String = data.read()?;
|
||||
extras.insert(key, value);
|
||||
}
|
||||
let bundle = RequestAbility::get_ability_instance().get_calling_bundle();
|
||||
|
||||
let task_config = TaskConfig {
|
||||
bundle,
|
||||
url,
|
||||
@ -164,7 +176,10 @@ impl RequestServiceInterface for RequestService {
|
||||
version,
|
||||
form_items,
|
||||
file_specs,
|
||||
body_file_names,
|
||||
common_data: CommonTaskConfig {
|
||||
task_id ,
|
||||
uid ,
|
||||
action,
|
||||
mode,
|
||||
cover,
|
||||
@ -182,7 +197,6 @@ impl RequestServiceInterface for RequestService {
|
||||
},
|
||||
};
|
||||
debug!(LOG_LABEL, "files {:?}", @public(files));
|
||||
let mut task_id: u32 = 0;
|
||||
let ret =
|
||||
RequestAbility::get_ability_instance().construct(task_config, files, body_files, &mut task_id);
|
||||
let remote_object: RemoteObj = data.read::<RemoteObj>()?;
|
||||
@ -552,7 +566,7 @@ impl RequestServiceInterface for RequestService {
|
||||
|
||||
/// start
|
||||
pub fn start() {
|
||||
RequestAbility::get_ability_instance().start();
|
||||
RequestAbility::get_ability_instance();
|
||||
}
|
||||
|
||||
/// stop
|
||||
|
@ -30,6 +30,7 @@ use std::{
|
||||
collections::HashMap,
|
||||
fmt::Debug,
|
||||
fs::File,
|
||||
fs::OpenOptions,
|
||||
mem::MaybeUninit,
|
||||
result::Result,
|
||||
string::String,
|
||||
@ -66,6 +67,7 @@ impl RequestAbility {
|
||||
monitor_network();
|
||||
monitor_app_state();
|
||||
monitor_task();
|
||||
ylong_runtime::spawn(restore_all_tasks());
|
||||
ylong_runtime::spawn(unload_sa());
|
||||
TaskManager::get_instance().dump_all_task_info();
|
||||
0
|
||||
@ -106,13 +108,13 @@ impl RequestAbility {
|
||||
let version = config.version.clone();
|
||||
let error = TaskManager::get_instance().construct_task(
|
||||
Arc::new(config),
|
||||
get_calling_uid(),
|
||||
uid,
|
||||
task_id,
|
||||
files,
|
||||
body_files,
|
||||
);
|
||||
if version != Version::API10 {
|
||||
TaskManager::get_instance().start(get_calling_uid(), *task_id);
|
||||
TaskManager::get_instance().start(uid, *task_id);
|
||||
}
|
||||
error
|
||||
}
|
||||
@ -282,6 +284,7 @@ impl RequestAbility {
|
||||
ServerRunState::NoStart,
|
||||
Mutex::new(HashMap::new()),
|
||||
));
|
||||
REQUESTABILITY.as_mut().unwrap().start();
|
||||
});
|
||||
REQUESTABILITY.as_mut().unwrap()
|
||||
}
|
||||
@ -529,4 +532,32 @@ impl RequestAbility {
|
||||
task.file_total_size.load(Ordering::SeqCst),
|
||||
task.progress.lock().unwrap().common_data.total_processed, task.conf.url).as_bytes());
|
||||
}
|
||||
|
||||
pub fn convert_path(&self, uid: u64, bundle: &str, path: &str) -> String {
|
||||
let uuid = uid / 200000;
|
||||
let base = "/data/storage/el2/base/";
|
||||
format!("/data/app/el2/{}/base/{}/{}", uuid, bundle, path.replace(base, ""))
|
||||
}
|
||||
|
||||
pub fn open_file_readwrite(uid: u64, bundle: &String, path: &String) -> IpcResult<File> {
|
||||
match OpenOptions::new().read(true).write(true).truncate(true)
|
||||
.open(RequestAbility::get_ability_instance().convert_path(uid, &bundle, &path)) {
|
||||
Ok(file) => { Ok(file) },
|
||||
Err(e) => {
|
||||
error!(LOG_LABEL, "open_file_readwrite failed, err is {:?}", e);
|
||||
Err(IpcStatusCode::Failed)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open_file_readonly(uid: u64, bundle: &String, path: &String) -> IpcResult<File> {
|
||||
match OpenOptions::new().read(true)
|
||||
.open(RequestAbility::get_ability_instance().convert_path(uid, &bundle, &path)) {
|
||||
Ok(file) => { Ok(file) },
|
||||
Err(e) => {
|
||||
error!(LOG_LABEL, "open_file_readonly failed, err is {:?}", e);
|
||||
Err(IpcStatusCode::Failed)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
use std::{ffi::CString, ffi::c_char, fs::File, pin::Pin, thread::sleep, time::Duration, cell::UnsafeCell};
|
||||
use super::{
|
||||
enumration::*, progress::*, task_info::*, task_config::*, task_manager::*, utils::*, request_binding::*,
|
||||
log::LOG_LABEL,
|
||||
log::LOG_LABEL, request_service_ability::*,
|
||||
};
|
||||
use crate::trace::TraceScope;
|
||||
use crate::sys_event::{SysEvent, build_number_param, build_str_param};
|
||||
@ -100,6 +100,7 @@ pub struct RequestTask {
|
||||
seek_flag: AtomicBool,
|
||||
range_request: AtomicBool,
|
||||
range_response: AtomicBool,
|
||||
restored: AtomicBool,
|
||||
skip_bytes: AtomicU64,
|
||||
upload_counts: AtomicU32,
|
||||
client: Option<Client>,
|
||||
@ -333,6 +334,7 @@ impl RequestTask {
|
||||
seek_flag: AtomicBool::new(false),
|
||||
range_request: AtomicBool::new(false),
|
||||
range_response: AtomicBool::new(false),
|
||||
restored: AtomicBool::new(false),
|
||||
skip_bytes: AtomicU64::new(0),
|
||||
upload_counts: AtomicU32::new(0),
|
||||
client: None,
|
||||
@ -344,6 +346,80 @@ impl RequestTask {
|
||||
task
|
||||
}
|
||||
|
||||
pub fn restore_task(conf: Arc<TaskConfig>, info: TaskInfo) -> Self {
|
||||
let progress_index = info.progress.common_data.index;
|
||||
let uid = info.common_data.uid;
|
||||
let action = conf.common_data.action;
|
||||
let mut files: Vec<File> = Vec::new();
|
||||
let mut body_files: Vec<File> = Vec::new();
|
||||
for fs in &conf.file_specs {
|
||||
if action == Action::UPLOAD {
|
||||
match RequestAbility::open_file_readonly(uid, &conf.bundle, &fs.path) {
|
||||
Ok(file) => { files.push(file); },
|
||||
Err(e) => { error!(LOG_LABEL, "open file RO failed, err is {:?}", e); },
|
||||
}
|
||||
} else {
|
||||
match RequestAbility::open_file_readwrite(uid, &conf.bundle, &fs.path) {
|
||||
Ok(file) => { files.push(file); },
|
||||
Err(e) => { error!(LOG_LABEL, "open file RW failed, err is {:?}", e); },
|
||||
}
|
||||
}
|
||||
}
|
||||
for name in &conf.body_file_names {
|
||||
match RequestAbility::open_file_readwrite(uid, &conf.bundle, &name) {
|
||||
Ok(body_file) => { body_files.push(body_file); },
|
||||
Err(e) => { error!(LOG_LABEL, "open body_file failed, err is {:?}", e); },
|
||||
}
|
||||
}
|
||||
let file_count = files.len();
|
||||
let mut task = RequestTask {
|
||||
conf,
|
||||
uid,
|
||||
task_id: info.common_data.task_id,
|
||||
ctime: info.common_data.ctime,
|
||||
files: Files(UnsafeCell::new(
|
||||
files.into_iter().map(|f| YlongFile::new(f)).collect(),
|
||||
)),
|
||||
body_files: BodyFiles(UnsafeCell::new(
|
||||
body_files.into_iter().map(|f| Some(YlongFile::new(f))).collect(),
|
||||
)),
|
||||
mime_type: Mutex::new(info.mime_type),
|
||||
progress: Mutex::new(info.progress.clone()),
|
||||
tries: AtomicU32::new(info.common_data.tries),
|
||||
status: Mutex::new(TaskStatus {
|
||||
waitting_network_time: None,
|
||||
mtime: get_current_timestamp(),
|
||||
state: State::from(info.progress.common_data.state),
|
||||
reason: Reason::from(info.common_data.reason),
|
||||
}),
|
||||
retry: AtomicBool::new(info.common_data.retry),
|
||||
get_file_info: AtomicBool::new(false),
|
||||
retry_for_request: AtomicBool::new(false),
|
||||
retry_for_speed: AtomicBool::new(false),
|
||||
code: Mutex::new(vec![Reason::Default; file_count]),
|
||||
background_notify_time: AtomicU64::new(get_current_timestamp()),
|
||||
file_total_size: AtomicI64::new(-1),
|
||||
resume: AtomicBool::new(false),
|
||||
seek_flag: AtomicBool::new(false),
|
||||
range_request: AtomicBool::new(false),
|
||||
range_response: AtomicBool::new(false),
|
||||
restored: AtomicBool::new(true),
|
||||
skip_bytes: AtomicU64::new(0),
|
||||
upload_counts: AtomicU32::new(progress_index as u32),
|
||||
client: None,
|
||||
};
|
||||
task.client = task.build_client();
|
||||
match action {
|
||||
Action::UPLOAD =>
|
||||
task.file_total_size.store(task.get_upload_file_total_size() as i64, Ordering::SeqCst),
|
||||
Action::DOWNLOAD =>
|
||||
task.file_total_size.store(info.progress.sizes[progress_index] as i64, Ordering::SeqCst),
|
||||
_ => {}
|
||||
}
|
||||
task
|
||||
|
||||
}
|
||||
|
||||
pub fn build_notify_data(&self) -> NotifyData {
|
||||
let mut vec = Vec::new();
|
||||
let size = self.conf.file_specs.len();
|
||||
@ -581,7 +657,9 @@ impl RequestTask {
|
||||
match len {
|
||||
Ok(v) => {
|
||||
let mut guard = self.progress.lock().unwrap();
|
||||
guard.sizes[0] = v;
|
||||
if !self.restored.load(Ordering::SeqCst) {
|
||||
guard.sizes[0] = v;
|
||||
}
|
||||
self.file_total_size.store(v, Ordering::SeqCst);
|
||||
debug!(LOG_LABEL, "the download task content-length is {}", @public(v));
|
||||
}
|
||||
@ -827,9 +905,7 @@ impl RequestTask {
|
||||
if state == State::WAITING {
|
||||
self.record_waitting_network_time();
|
||||
}
|
||||
if self.conf.version == Version::API10 {
|
||||
self.record_task_info();
|
||||
}
|
||||
self.record_task_info();
|
||||
self.state_change_notify(state);
|
||||
true
|
||||
}
|
||||
@ -925,6 +1001,7 @@ impl RequestTask {
|
||||
token: self.conf.token.clone(),
|
||||
form_items: self.conf.form_items.clone(),
|
||||
file_specs: self.conf.file_specs.clone(),
|
||||
body_file_names: self.conf.body_file_names.clone(),
|
||||
title: self.conf.title.clone(),
|
||||
description: self.conf.description.clone(),
|
||||
mime_type: {
|
||||
|
@ -13,12 +13,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use super::{enumration::*, form_item::*};
|
||||
use super::{c_string_wrapper::*, enumration::*, form_item::*, utils::*, request_binding::*};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct CommonTaskConfig {
|
||||
pub task_id: u32,
|
||||
pub uid: u64,
|
||||
pub action: Action,
|
||||
pub mode: Mode,
|
||||
pub cover: bool,
|
||||
@ -49,5 +51,153 @@ pub struct TaskConfig {
|
||||
pub version: Version,
|
||||
pub form_items: Vec<FormItem>,
|
||||
pub file_specs: Vec<FileSpec>,
|
||||
pub body_file_names: Vec<String>,
|
||||
pub common_data: CommonTaskConfig,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CommonCTaskConfig {
|
||||
pub task_id: u32,
|
||||
pub uid: u64,
|
||||
pub action: u8,
|
||||
pub mode: u8,
|
||||
pub cover: bool,
|
||||
pub network: u8,
|
||||
pub metered: bool,
|
||||
pub roaming: bool,
|
||||
pub retry: bool,
|
||||
pub redirect: bool,
|
||||
pub index: u32,
|
||||
pub begins: u64,
|
||||
pub ends: i64,
|
||||
pub gauge: bool,
|
||||
pub precise: bool,
|
||||
pub background: bool,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CTaskConfig {
|
||||
pub bundle: CStringWrapper,
|
||||
pub url: CStringWrapper,
|
||||
pub title: CStringWrapper,
|
||||
pub description: CStringWrapper,
|
||||
pub method: CStringWrapper,
|
||||
pub headers: CStringWrapper,
|
||||
pub data: CStringWrapper,
|
||||
pub token: CStringWrapper,
|
||||
pub extras: CStringWrapper,
|
||||
pub version: u8,
|
||||
pub form_items_ptr: *const CFormItem,
|
||||
pub form_items_len: u32,
|
||||
pub file_specs_ptr: *const CFileSpec,
|
||||
pub file_specs_len: u32,
|
||||
pub body_file_names_ptr: *const CStringWrapper,
|
||||
pub body_file_names_len: u32,
|
||||
pub common_data: CommonCTaskConfig,
|
||||
}
|
||||
|
||||
impl TaskConfig {
|
||||
fn build_vec<A, B, C>(ptr: *const A, len: usize, func: C) -> Vec<B> where C: Fn(&A) -> B,
|
||||
{
|
||||
if ptr.is_null() || len == 0 {
|
||||
return Vec::<B>::new();
|
||||
}
|
||||
let slice = unsafe { std::slice::from_raw_parts(ptr, len) };
|
||||
slice.iter().map(|x| func(x)).collect()
|
||||
}
|
||||
|
||||
pub fn to_c_struct(&self, task_id: u32, uid: u64) -> CTaskConfig {
|
||||
let form_items: Vec<CFormItem> = self.form_items.iter().map(|x| x.to_c_struct()).collect();
|
||||
let file_specs: Vec<CFileSpec> = self.file_specs.iter().map(|x| x.to_c_struct()).collect();
|
||||
let body_file_names: Vec<CStringWrapper> = self.body_file_names.iter()
|
||||
.map(|x| CStringWrapper::from(x)).collect();
|
||||
CTaskConfig {
|
||||
bundle: CStringWrapper::from(&self.bundle),
|
||||
url: CStringWrapper::from(&self.url),
|
||||
title: CStringWrapper::from(&self.title),
|
||||
description: CStringWrapper::from(&self.description),
|
||||
method: CStringWrapper::from(&self.method),
|
||||
headers: CStringWrapper::from(&hashmap_to_string(&self.headers)),
|
||||
data: CStringWrapper::from(&self.data),
|
||||
token: CStringWrapper::from(&self.token),
|
||||
extras: CStringWrapper::from(&hashmap_to_string(&self.extras)),
|
||||
version: self.version as u8,
|
||||
form_items_ptr: form_items.as_ptr() as *const CFormItem,
|
||||
form_items_len: form_items.len() as u32,
|
||||
file_specs_ptr: file_specs.as_ptr() as *const CFileSpec,
|
||||
file_specs_len: file_specs.len() as u32,
|
||||
body_file_names_ptr: body_file_names.as_ptr() as *const CStringWrapper,
|
||||
body_file_names_len: body_file_names.len() as u32,
|
||||
common_data: CommonCTaskConfig {
|
||||
task_id,
|
||||
uid,
|
||||
action: self.common_data.action as u8,
|
||||
mode: self.common_data.mode as u8,
|
||||
cover: self.common_data.cover,
|
||||
network: self.common_data.network as u8,
|
||||
metered: self.common_data.metered,
|
||||
roaming: self.common_data.roaming,
|
||||
retry: self.common_data.retry,
|
||||
redirect: self.common_data.redirect,
|
||||
index: self.common_data.index,
|
||||
begins: self.common_data.begins,
|
||||
ends: self.common_data.ends,
|
||||
gauge: self.common_data.gauge,
|
||||
precise: self.common_data.precise,
|
||||
background: self.common_data.background,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_c_struct(c_struct: &CTaskConfig) -> Self {
|
||||
let task_config = TaskConfig {
|
||||
bundle: c_struct.bundle.to_string(),
|
||||
url: c_struct.url.to_string(),
|
||||
title: c_struct.title.to_string(),
|
||||
description: c_struct.description.to_string(),
|
||||
method: c_struct.method.to_string(),
|
||||
headers: string_to_hashmap(&mut c_struct.headers.to_string()),
|
||||
data: c_struct.data.to_string(),
|
||||
token: c_struct.token.to_string(),
|
||||
extras: string_to_hashmap(&mut c_struct.extras.to_string()),
|
||||
version: Version::from(c_struct.version),
|
||||
form_items: Self::build_vec(
|
||||
c_struct.form_items_ptr,
|
||||
c_struct.form_items_len as usize,
|
||||
FormItem::from_c_struct,
|
||||
),
|
||||
file_specs: Self::build_vec(
|
||||
c_struct.file_specs_ptr,
|
||||
c_struct.file_specs_len as usize,
|
||||
FileSpec::from_c_struct,
|
||||
),
|
||||
body_file_names: Self::build_vec(
|
||||
c_struct.body_file_names_ptr,
|
||||
c_struct.body_file_names_len as usize,
|
||||
CStringWrapper::to_string,
|
||||
),
|
||||
common_data: CommonTaskConfig {
|
||||
task_id: c_struct.common_data.task_id,
|
||||
uid: c_struct.common_data.uid,
|
||||
action: Action::from(c_struct.common_data.action),
|
||||
mode: Mode::from(c_struct.common_data.mode),
|
||||
cover: c_struct.common_data.cover,
|
||||
network: Network::from(c_struct.common_data.network),
|
||||
metered: c_struct.common_data.metered,
|
||||
roaming: c_struct.common_data.roaming,
|
||||
retry: c_struct.common_data.retry,
|
||||
redirect: c_struct.common_data.redirect,
|
||||
index: c_struct.common_data.index,
|
||||
begins: c_struct.common_data.begins,
|
||||
ends: c_struct.common_data.ends,
|
||||
gauge: c_struct.common_data.gauge,
|
||||
precise: c_struct.common_data.precise,
|
||||
background: c_struct.common_data.background,
|
||||
},
|
||||
};
|
||||
unsafe { DeleteCFormItem(c_struct.form_items_ptr) };
|
||||
unsafe { DeleteCFileSpec(c_struct.file_specs_ptr) };
|
||||
unsafe { DeleteCStringPtr(c_struct.body_file_names_ptr) };
|
||||
task_config
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ pub struct TaskInfo {
|
||||
pub token: String,
|
||||
pub form_items: Vec<FormItem>,
|
||||
pub file_specs: Vec<FileSpec>,
|
||||
pub body_file_names: Vec<String>,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub mime_type: String,
|
||||
@ -101,6 +102,8 @@ pub struct CTaskInfo {
|
||||
pub form_items_len: u32,
|
||||
pub file_specs_ptr: *const CFileSpec,
|
||||
pub file_specs_len: u32,
|
||||
pub body_file_names_ptr: *const CStringWrapper,
|
||||
pub body_file_names_len: u32,
|
||||
pub title: CStringWrapper,
|
||||
pub description: CStringWrapper,
|
||||
pub mime_type: CStringWrapper,
|
||||
@ -113,6 +116,7 @@ pub struct CTaskInfo {
|
||||
pub struct InfoSet {
|
||||
pub form_items: Vec<CFormItem>,
|
||||
pub file_specs: Vec<CFileSpec>,
|
||||
pub body_file_names: Vec<CStringWrapper>,
|
||||
pub sizes: String,
|
||||
pub processed: String,
|
||||
pub extras: String,
|
||||
@ -124,6 +128,7 @@ impl TaskInfo {
|
||||
InfoSet {
|
||||
form_items: self.form_items.iter().map(|x| x.to_c_struct()).collect(),
|
||||
file_specs: self.file_specs.iter().map(|x| x.to_c_struct()).collect(),
|
||||
body_file_names: self.body_file_names.iter().map(|x| CStringWrapper::from(x)).collect(),
|
||||
sizes: format!("{:?}", self.progress.sizes),
|
||||
processed: format!("{:?}", self.progress.processed),
|
||||
extras: hashmap_to_string(&self.extras),
|
||||
@ -156,6 +161,8 @@ impl TaskInfo {
|
||||
form_items_len: info.form_items.len() as u32,
|
||||
file_specs_ptr: info.file_specs.as_ptr() as *const CFileSpec,
|
||||
file_specs_len: info.file_specs.len() as u32,
|
||||
body_file_names_ptr: info.body_file_names.as_ptr() as *const CStringWrapper,
|
||||
body_file_names_len: info.body_file_names.len() as u32,
|
||||
title: CStringWrapper::from(&self.title),
|
||||
description: CStringWrapper::from(&self.description),
|
||||
mime_type: CStringWrapper::from(&self.mime_type),
|
||||
@ -184,6 +191,11 @@ impl TaskInfo {
|
||||
c_struct.file_specs_len as usize,
|
||||
FileSpec::from_c_struct,
|
||||
),
|
||||
body_file_names: Self::build_vec(
|
||||
c_struct.body_file_names_ptr,
|
||||
c_struct.body_file_names_len as usize,
|
||||
CStringWrapper::to_string,
|
||||
),
|
||||
title: c_struct.title.to_string(),
|
||||
description: c_struct.description.to_string(),
|
||||
mime_type: c_struct.mime_type.to_string(),
|
||||
@ -197,6 +209,7 @@ impl TaskInfo {
|
||||
};
|
||||
unsafe { DeleteCFormItem(c_struct.form_items_ptr) };
|
||||
unsafe { DeleteCFileSpec(c_struct.file_specs_ptr) };
|
||||
unsafe { DeleteCStringPtr(c_struct.body_file_names_ptr) };
|
||||
unsafe { DeleteCEachFileStatus(c_struct.each_file_status_ptr) };
|
||||
task_info
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ static MILLISECONDS_IN_ONE_MONTH: u64 = 30 * 24 * 60 * 60 * 1000;
|
||||
static MILLISECONDS_IN_ONE_SECONDS: u64 = 1000;
|
||||
static REQUEST_SERVICE_ID: i32 = 3706;
|
||||
static WAITTING_RETRY_INTERVAL: u64 = 10;
|
||||
static WAITTING_RESTORE_INTERVAL: u64 = 7;
|
||||
static DUMP_INTERVAL: u64 = 5 * 60;
|
||||
|
||||
type AppTask = HashMap<u32, Arc<RequestTask>>;
|
||||
@ -48,6 +49,7 @@ pub struct TaskManager {
|
||||
pub front_app_uid: Option<u64>,
|
||||
pub front_notify_time: u64,
|
||||
pub unloading: AtomicBool,
|
||||
pub restoring: AtomicBool,
|
||||
pub api10_background_task_count: AtomicU32,
|
||||
pub recording_rdb_num: AtomicU32,
|
||||
task_handles: Mutex<HashMap<u32, JoinHandle<()>>>,
|
||||
@ -107,6 +109,7 @@ impl TaskManager {
|
||||
front_app_uid: None,
|
||||
front_notify_time: get_current_timestamp(),
|
||||
unloading: AtomicBool::new(false),
|
||||
restoring: AtomicBool::new(false),
|
||||
api10_background_task_count: AtomicU32::new(0),
|
||||
recording_rdb_num: AtomicU32::new(0),
|
||||
task_handles: Mutex::new(HashMap::<u32, JoinHandle<()>>::new()),
|
||||
@ -733,6 +736,97 @@ impl TaskManager {
|
||||
}
|
||||
vec
|
||||
}
|
||||
|
||||
pub fn network_check_unload_sa(&self, guard: &MutexGuard<HashMap<u64, AppTask>>) -> bool {
|
||||
let mut need_unload = false;
|
||||
for (_, app_task) in guard.iter() {
|
||||
for (_, task) in app_task.iter() {
|
||||
let state = task.status.lock().unwrap().state;
|
||||
if state == State::COMPLETED || state == State::FAILED
|
||||
|| state == State::REMOVED || state == State::STOPPED {
|
||||
need_unload = true;
|
||||
} else if (state == State::WAITING || state == State::PAUSED)
|
||||
&& (!task.is_satisfied_configuration() || unsafe { !IsOnline() }) {
|
||||
need_unload = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return need_unload;
|
||||
}
|
||||
|
||||
pub fn record_all_task_config(&self, guard: &MutexGuard<HashMap<u64, AppTask>>) {
|
||||
debug!(LOG_LABEL, "record all task config into database");
|
||||
self.recording_rdb_num.fetch_add(1, Ordering::SeqCst);
|
||||
for (_, app_task) in guard.iter() {
|
||||
for (_, task) in app_task.iter() {
|
||||
if unsafe { HasTaskConfigRecord(task.task_id) } {
|
||||
continue;
|
||||
}
|
||||
let state = task.status.lock().unwrap().state;
|
||||
if state != State::WAITING && state != State::PAUSED {
|
||||
continue;
|
||||
}
|
||||
let task_config = task.conf.as_ref().clone();
|
||||
let c_task_config = task_config.to_c_struct(task.task_id, task.uid);
|
||||
let ret = unsafe { RecordRequestTaskConfig(&c_task_config) };
|
||||
info!(LOG_LABEL, "insert taskConfig DB ret is {}", @public(ret));
|
||||
}
|
||||
}
|
||||
self.recording_rdb_num.fetch_sub(1, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
pub fn query_all_task_config(&self) -> Option<Vec<Arc<TaskConfig>>> {
|
||||
debug!(LOG_LABEL, "query all task config in database");
|
||||
let mut task_config_list: Vec<Arc<TaskConfig>> = Vec::new();
|
||||
let c_config_list_len = unsafe { QueryTaskConfigLen() };
|
||||
if c_config_list_len <= 0 {
|
||||
debug!(LOG_LABEL, "no task config in database");
|
||||
return None;
|
||||
}
|
||||
let c_task_config_list = unsafe { QueryAllTaskConfig() };
|
||||
if c_task_config_list.is_null() {
|
||||
return None;
|
||||
}
|
||||
let c_task_config_ptrs = unsafe { std::slice::from_raw_parts(c_task_config_list, c_config_list_len as usize) };
|
||||
for c_task_config in c_task_config_ptrs.iter() {
|
||||
let task_config = TaskConfig::from_c_struct(unsafe { &**c_task_config });
|
||||
task_config_list.push(Arc::new(task_config));
|
||||
unsafe { DeleteCTaskConfig(*c_task_config) };
|
||||
}
|
||||
unsafe { DeleteCTaskConfigs(c_task_config_list) };
|
||||
Some(task_config_list)
|
||||
}
|
||||
|
||||
pub fn restore_task(&mut self, task: Arc<RequestTask>) {
|
||||
if task.conf.common_data.mode == Mode::FRONTEND {
|
||||
self.global_front_task = Some(task);
|
||||
return;
|
||||
}
|
||||
if task.conf.version == Version::API10 {
|
||||
self.api10_background_task_count.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
let mut guard = self.task_map.lock().unwrap();
|
||||
let uid = task.uid;
|
||||
let task_id = task.task_id;
|
||||
if self.get_task(uid, task_id, &guard).is_some() {
|
||||
return;
|
||||
}
|
||||
let app_task = guard.get_mut(&uid);
|
||||
match app_task {
|
||||
Some(map) => {
|
||||
map.insert(task_id, task);
|
||||
debug!(LOG_LABEL, "restore task into exist app_map success");
|
||||
}
|
||||
None => {
|
||||
let mut app_task = AppTask::new();
|
||||
app_task.insert(task_id, task);
|
||||
guard.insert(uid, app_task);
|
||||
debug!(LOG_LABEL, "restore task into new app_map success");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn unload_sa() {
|
||||
@ -744,12 +838,16 @@ pub async fn unload_sa() {
|
||||
Ok(guard) => {
|
||||
let total_task_count = task_manager.get_total_task_count(&guard);
|
||||
let recording_rdb_num = task_manager.recording_rdb_num.load(Ordering::SeqCst);
|
||||
if total_task_count != 0 || recording_rdb_num != 0 {
|
||||
let only_network_unsat = task_manager.network_check_unload_sa(&guard);
|
||||
if (total_task_count != 0 && !only_network_unsat) || recording_rdb_num != 0 {
|
||||
info!(LOG_LABEL, "total_task_count is {}, recording_rdb_num is {}",
|
||||
@public(total_task_count), @public(recording_rdb_num));
|
||||
continue;
|
||||
}
|
||||
task_manager.unloading.store(true, Ordering::SeqCst);
|
||||
if total_task_count != 0 {
|
||||
task_manager.record_all_task_config(&guard);
|
||||
}
|
||||
info!(LOG_LABEL, "unload SA");
|
||||
let samgr_proxy = get_systemability_manager();
|
||||
let res = samgr_proxy.unload_systemability(REQUEST_SERVICE_ID);
|
||||
@ -808,6 +906,37 @@ async fn remove_task_from_map(task: Arc<RequestTask>) {
|
||||
task_manager.process_waitting_task(remove_task.uid, remove_task.conf.version, &guard);
|
||||
}
|
||||
|
||||
pub async fn restore_all_tasks() {
|
||||
let task_manager = TaskManager::get_instance();
|
||||
if task_manager.restoring.load(Ordering::SeqCst) {
|
||||
return;
|
||||
}
|
||||
task_manager.restoring.store(true, Ordering::SeqCst);
|
||||
if let Some(config_list) = task_manager.query_all_task_config() {
|
||||
info!(LOG_LABEL, "RSA query task config list len: {} in database", @public(config_list.len()));
|
||||
for config in config_list.iter() {
|
||||
debug!(LOG_LABEL, "RSA query task config is {:?}", @public(config));
|
||||
let uid = config.common_data.uid;
|
||||
let task_id = config.common_data.task_id;
|
||||
let token = config.token.clone();
|
||||
if let Some(task_info) = task_manager.touch(uid, task_id, token) {
|
||||
let state = State::from(task_info.progress.common_data.state);
|
||||
if state != State::WAITING && state != State::PAUSED {
|
||||
continue;
|
||||
}
|
||||
let request_task = RequestTask::restore_task(config.clone(), task_info);
|
||||
let task = Arc::new(request_task);
|
||||
task_manager.restore_task(task.clone());
|
||||
if unsafe { IsOnline() } {
|
||||
resume_waiting_task(task.clone(), uid, WAITTING_RESTORE_INTERVAL);
|
||||
}
|
||||
}
|
||||
unsafe { CleanTaskConfigTable(task_id, uid) };
|
||||
}
|
||||
}
|
||||
task_manager.restoring.store(false, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
pub fn monitor_network() {
|
||||
debug!(LOG_LABEL, "monitor_network");
|
||||
unsafe {
|
||||
@ -822,26 +951,29 @@ extern "C" fn net_work_change_callback() {
|
||||
for (uid, app_task) in guard.iter() {
|
||||
let uid = *uid;
|
||||
for (_, task) in app_task.iter() {
|
||||
let task = task.clone();
|
||||
let state = task.status.lock().unwrap().state;
|
||||
if unsafe { IsOnline() } {
|
||||
if state == State::WAITING && task.is_satisfied_configuration() {
|
||||
info!(LOG_LABEL, "Begin try resume task as network condition resume");
|
||||
task.resume.store(true, Ordering::SeqCst);
|
||||
ylong_runtime::spawn(async move {
|
||||
sleep(Duration::from_secs(WAITTING_RETRY_INTERVAL)).await;
|
||||
let manager = TaskManager::get_instance();
|
||||
let guard = manager.task_map.lock().unwrap();
|
||||
let notify_data = task.build_notify_data();
|
||||
TaskManager::get_instance().front_notify("resume".into(), ¬ify_data);
|
||||
manager.start_inner(uid, task.clone(), guard);
|
||||
});
|
||||
}
|
||||
resume_waiting_task(task.clone(), uid, WAITTING_RETRY_INTERVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resume_waiting_task(task: Arc<RequestTask>, uid: u64, interval: u64) {
|
||||
let state = task.status.lock().unwrap().state;
|
||||
if state == State::WAITING && task.is_satisfied_configuration() {
|
||||
info!(LOG_LABEL, "Begin try resume task as network condition resume");
|
||||
task.resume.store(true, Ordering::SeqCst);
|
||||
ylong_runtime::spawn(async move {
|
||||
sleep(Duration::from_secs(interval)).await;
|
||||
let manager = TaskManager::get_instance();
|
||||
let guard = manager.task_map.lock().unwrap();
|
||||
let notify_data = task.build_notify_data();
|
||||
TaskManager::get_instance().front_notify("resume".into(), ¬ify_data);
|
||||
manager.start_inner(uid, task.clone(), guard);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn monitor_app_state() {
|
||||
debug!(LOG_LABEL, "monitor_app_state");
|
||||
unsafe {
|
||||
|
Loading…
Reference in New Issue
Block a user