|
|
|
@ -1176,61 +1176,89 @@ const char *param_get_backup_file()
@@ -1176,61 +1176,89 @@ const char *param_get_backup_file()
|
|
|
|
|
return param_backup_file; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int param_save_file_internal(const char *filename) |
|
|
|
|
static int param_export_internal(int fd, param_filter_func filter); |
|
|
|
|
static int param_verify(int fd); |
|
|
|
|
|
|
|
|
|
int param_save_default() |
|
|
|
|
{ |
|
|
|
|
int res = PX4_ERROR; |
|
|
|
|
int attempts = 5; |
|
|
|
|
PX4_DEBUG("param_save_default"); |
|
|
|
|
int shutdown_lock_ret = px4_shutdown_lock(); |
|
|
|
|
|
|
|
|
|
if (shutdown_lock_ret != 0) { |
|
|
|
|
PX4_ERR("px4_shutdown_lock() failed (%i)", shutdown_lock_ret); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
while (res != OK && attempts > 0) { |
|
|
|
|
// write parameters to file
|
|
|
|
|
int fd = ::open(filename, O_RDWR | O_CREAT, PX4_O_MODE_666); |
|
|
|
|
// take the file lock
|
|
|
|
|
do {} while (px4_sem_wait(¶m_sem_save) != 0); |
|
|
|
|
|
|
|
|
|
if (fd > -1) { |
|
|
|
|
res = param_export(fd, nullptr); |
|
|
|
|
::close(fd); |
|
|
|
|
param_lock_reader(); |
|
|
|
|
|
|
|
|
|
int res = PX4_ERROR; |
|
|
|
|
const char *filename = param_get_default_file(); |
|
|
|
|
|
|
|
|
|
if (filename) { |
|
|
|
|
static constexpr int MAX_ATTEMPTS = 3; |
|
|
|
|
|
|
|
|
|
for (int attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) { |
|
|
|
|
// write parameters to file
|
|
|
|
|
int fd = ::open(filename, O_WRONLY | O_CREAT, PX4_O_MODE_666); |
|
|
|
|
|
|
|
|
|
if (fd > -1) { |
|
|
|
|
perf_begin(param_export_perf); |
|
|
|
|
res = param_export_internal(fd, nullptr); |
|
|
|
|
perf_end(param_export_perf); |
|
|
|
|
::close(fd); |
|
|
|
|
|
|
|
|
|
if (res == PX4_OK) { |
|
|
|
|
// reopen file to verify
|
|
|
|
|
int fd_verify = ::open(filename, O_RDONLY, PX4_O_MODE_666); |
|
|
|
|
res = param_verify(fd_verify); |
|
|
|
|
::close(fd_verify); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (res == PX4_OK) { |
|
|
|
|
return PX4_OK; |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
PX4_ERR("param_export failed, retrying %d", attempts); |
|
|
|
|
PX4_ERR("parameter export to %s failed (%d) attempt %d", filename, res, attempt); |
|
|
|
|
px4_usleep(10000); // wait at least 10 milliseconds before trying again
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
PX4_ERR("failed to open param file %s, retrying %d", filename, attempts); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
attempts--; |
|
|
|
|
} else { |
|
|
|
|
perf_begin(param_export_perf); |
|
|
|
|
res = flash_param_save(nullptr); |
|
|
|
|
perf_end(param_export_perf); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (res != OK) { |
|
|
|
|
PX4_ERR("failed to write parameters to file: %s", filename); |
|
|
|
|
} |
|
|
|
|
if (res != PX4_OK) { |
|
|
|
|
PX4_ERR("param export failed (%d)", res); |
|
|
|
|
|
|
|
|
|
return PX4_ERROR; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
params_unsaved.reset(); |
|
|
|
|
|
|
|
|
|
int param_save_default() |
|
|
|
|
{ |
|
|
|
|
int res = PX4_ERROR; |
|
|
|
|
const char *filename = param_get_default_file(); |
|
|
|
|
// backup file
|
|
|
|
|
if (param_backup_file) { |
|
|
|
|
int fd_backup_file = ::open(param_backup_file, O_WRONLY | O_CREAT, PX4_O_MODE_666); |
|
|
|
|
|
|
|
|
|
if (filename) { |
|
|
|
|
res = param_save_file_internal(filename); |
|
|
|
|
if (fd_backup_file > -1) { |
|
|
|
|
int backup_export_ret = param_export_internal(fd_backup_file, nullptr); |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
param_lock_writer(); |
|
|
|
|
perf_begin(param_export_perf); |
|
|
|
|
res = flash_param_save(nullptr); |
|
|
|
|
params_unsaved.reset(); |
|
|
|
|
perf_end(param_export_perf); |
|
|
|
|
param_unlock_writer(); |
|
|
|
|
if (backup_export_ret != 0) { |
|
|
|
|
PX4_ERR("backup parameter export to %s failed (%d)", param_backup_file, backup_export_ret); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
::close(fd_backup_file); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// backup file
|
|
|
|
|
if (param_backup_file) { |
|
|
|
|
param_save_file_internal(param_backup_file); |
|
|
|
|
param_unlock_reader(); |
|
|
|
|
px4_sem_post(¶m_sem_save); |
|
|
|
|
|
|
|
|
|
if (shutdown_lock_ret == 0) { |
|
|
|
|
px4_shutdown_unlock(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return res; |
|
|
|
@ -1335,6 +1363,8 @@ static int param_verify_callback(bson_decoder_t decoder, bson_node_t node)
@@ -1335,6 +1363,8 @@ static int param_verify_callback(bson_decoder_t decoder, bson_node_t node)
|
|
|
|
|
|
|
|
|
|
static int param_verify(int fd) |
|
|
|
|
{ |
|
|
|
|
PX4_DEBUG("param_verify"); |
|
|
|
|
|
|
|
|
|
if (fd < 0) { |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
@ -1375,27 +1405,13 @@ static int param_verify(int fd)
@@ -1375,27 +1405,13 @@ static int param_verify(int fd)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int |
|
|
|
|
param_export(int fd, param_filter_func filter) |
|
|
|
|
param_export(const char *filename, param_filter_func filter) |
|
|
|
|
{ |
|
|
|
|
int result = -1; |
|
|
|
|
perf_begin(param_export_perf); |
|
|
|
|
|
|
|
|
|
if (fd < 0) { |
|
|
|
|
param_lock_writer(); |
|
|
|
|
// flash_param_save() will take the shutdown lock
|
|
|
|
|
result = flash_param_save(filter); |
|
|
|
|
params_unsaved.reset(); |
|
|
|
|
param_unlock_writer(); |
|
|
|
|
perf_end(param_export_perf); |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
param_wbuf_s *s = nullptr; |
|
|
|
|
bson_encoder_s encoder{}; |
|
|
|
|
PX4_DEBUG("param_export"); |
|
|
|
|
|
|
|
|
|
int shutdown_lock_ret = px4_shutdown_lock(); |
|
|
|
|
|
|
|
|
|
if (shutdown_lock_ret) { |
|
|
|
|
if (shutdown_lock_ret != 0) { |
|
|
|
|
PX4_ERR("px4_shutdown_lock() failed (%i)", shutdown_lock_ret); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1404,10 +1420,41 @@ param_export(int fd, param_filter_func filter)
@@ -1404,10 +1420,41 @@ param_export(int fd, param_filter_func filter)
|
|
|
|
|
|
|
|
|
|
param_lock_reader(); |
|
|
|
|
|
|
|
|
|
int fd = ::open(filename, O_RDWR | O_CREAT, PX4_O_MODE_666); |
|
|
|
|
int result = PX4_ERROR; |
|
|
|
|
|
|
|
|
|
perf_begin(param_export_perf); |
|
|
|
|
|
|
|
|
|
if (fd > -1) { |
|
|
|
|
result = param_export_internal(fd, filter); |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
result = flash_param_save(filter); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
perf_end(param_export_perf); |
|
|
|
|
|
|
|
|
|
param_unlock_reader(); |
|
|
|
|
px4_sem_post(¶m_sem_save); |
|
|
|
|
|
|
|
|
|
if (shutdown_lock_ret == 0) { |
|
|
|
|
px4_shutdown_unlock(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// internal parameter export, caller is responsible for locking
|
|
|
|
|
static int param_export_internal(int fd, param_filter_func filter) |
|
|
|
|
{ |
|
|
|
|
PX4_DEBUG("param_export_internal"); |
|
|
|
|
|
|
|
|
|
int result = -1; |
|
|
|
|
param_wbuf_s *s = nullptr; |
|
|
|
|
bson_encoder_s encoder{}; |
|
|
|
|
uint8_t bson_buffer[256]; |
|
|
|
|
|
|
|
|
|
if (bson_encoder_init_buf_file(&encoder, fd, &bson_buffer, sizeof(bson_buffer)) != 0) { |
|
|
|
|
result = -1; |
|
|
|
|
goto out; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1484,33 +1531,12 @@ param_export(int fd, param_filter_func filter)
@@ -1484,33 +1531,12 @@ param_export(int fd, param_filter_func filter)
|
|
|
|
|
out: |
|
|
|
|
|
|
|
|
|
if (result == 0) { |
|
|
|
|
if (bson_encoder_fini(&encoder) == PX4_OK) { |
|
|
|
|
// verify exported bson
|
|
|
|
|
if (param_verify(fd) == 0) { |
|
|
|
|
if (!filter) { |
|
|
|
|
params_unsaved.reset(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
result = -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
if (bson_encoder_fini(&encoder) != PX4_OK) { |
|
|
|
|
PX4_ERR("BSON encoder finalize failed"); |
|
|
|
|
result = -1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
param_unlock_reader(); |
|
|
|
|
|
|
|
|
|
px4_sem_post(¶m_sem_save); |
|
|
|
|
|
|
|
|
|
if (shutdown_lock_ret == 0) { |
|
|
|
|
px4_shutdown_unlock(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
perf_end(param_export_perf); |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1542,7 +1568,7 @@ param_import_callback(bson_decoder_t decoder, bson_node_t node)
@@ -1542,7 +1568,7 @@ param_import_callback(bson_decoder_t decoder, bson_node_t node)
|
|
|
|
|
if (param_type(param) == PARAM_TYPE_INT32) { |
|
|
|
|
int32_t i = node->i32; |
|
|
|
|
param_set_internal(param, &i, true, true); |
|
|
|
|
PX4_DEBUG("Imported %s with value %d", param_name(param), i); |
|
|
|
|
PX4_DEBUG("Imported %s with value %" PRIi32, param_name(param), i); |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
PX4_WARN("unexpected type for %s", node->name); |
|
|
|
@ -1639,18 +1665,20 @@ param_import_internal(int fd)
@@ -1639,18 +1665,20 @@ param_import_internal(int fd)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
PX4_ERR("param import failed (%d) attempt %d, retrying", result, attempt); |
|
|
|
|
PX4_ERR("param import failed (%d) attempt %d", result, attempt); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
PX4_ERR("param import bson decoder init failed attempt %d, retrying", attempt); |
|
|
|
|
PX4_ERR("param import bson decoder init failed (attempt %d)", attempt); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (lseek(fd, 0, SEEK_SET) != 0) { |
|
|
|
|
PX4_ERR("import lseek failed (%d)", errno); |
|
|
|
|
} |
|
|
|
|
if (attempt != MAX_ATTEMPTS) { |
|
|
|
|
if (lseek(fd, 0, SEEK_SET) != 0) { |
|
|
|
|
PX4_ERR("import lseek failed (%d)", errno); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
px4_usleep(10000); // wait at least 10 milliseconds before trying again
|
|
|
|
|
px4_usleep(10000); // wait at least 10 milliseconds before trying again
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return -1; |
|
|
|
|