aboutsummaryrefslogtreecommitdiff
path: root/pw_software_update/bundled_update_service.cc
diff options
context:
space:
mode:
Diffstat (limited to 'pw_software_update/bundled_update_service.cc')
-rw-r--r--pw_software_update/bundled_update_service.cc386
1 files changed, 182 insertions, 204 deletions
diff --git a/pw_software_update/bundled_update_service.cc b/pw_software_update/bundled_update_service.cc
index dcb71048a..cbbc67e4f 100644
--- a/pw_software_update/bundled_update_service.cc
+++ b/pw_software_update/bundled_update_service.cc
@@ -12,79 +12,89 @@
// License for the specific language governing permissions and limitations under
// the License.
-#include "pw_software_update/config.h"
+#define PW_LOG_MODULE_NAME "PWSU"
+#define PW_LOG_LEVEL PW_LOG_LEVEL_WARN
-#define PW_LOG_LEVEL PW_SOFTWARE_UPDATE_CONFIG_LOG_LEVEL
+#include "pw_software_update/bundled_update_service.h"
#include <mutex>
#include <string_view>
#include "pw_log/log.h"
#include "pw_result/result.h"
-#include "pw_software_update/bundled_update_service.h"
+#include "pw_software_update/config.h"
#include "pw_software_update/manifest_accessor.h"
#include "pw_software_update/update_bundle.pwpb.h"
#include "pw_status/status.h"
#include "pw_status/status_with_size.h"
#include "pw_status/try.h"
+#include "pw_string/string_builder.h"
#include "pw_string/util.h"
+#include "pw_sync/borrow.h"
#include "pw_sync/mutex.h"
#include "pw_tokenizer/tokenize.h"
-// TODO(keir): Convert all the CHECKs in the RPC service to gracefully report
-// errors.
-#define SET_ERROR(res, message, ...) \
- do { \
- PW_LOG_ERROR(message, __VA_ARGS__); \
- if (!IsFinished()) { \
- Finish(res); \
- size_t note_size = sizeof(status_.note.bytes); \
- PW_TOKENIZE_TO_BUFFER( \
- status_.note.bytes, &(note_size), message, __VA_ARGS__); \
- status_.note.size = note_size; \
- status_.has_note = true; \
- } \
- } while (false)
-
namespace pw::software_update {
namespace {
+using BorrowedStatus =
+ sync::BorrowedPointer<pw_software_update_BundledUpdateStatus, sync::Mutex>;
+using BundledUpdateState = pw_software_update_BundledUpdateState_Enum;
+using BundledUpdateStatus = pw_software_update_BundledUpdateStatus;
-constexpr std::string_view kTopLevelTargetsName = "targets";
-
+// TODO(keir): Convert all the CHECKs in the RPC service to gracefully report
+// errors.
+#define SET_ERROR(res, message, ...) \
+ do { \
+ PW_LOG_ERROR(message, __VA_ARGS__); \
+ if (!IsFinished()) { \
+ Finish(res); \
+ { \
+ BorrowedStatus borrowed_status = status_.acquire(); \
+ size_t note_size = sizeof(borrowed_status->note.bytes); \
+ PW_TOKENIZE_TO_BUFFER( \
+ borrowed_status->note.bytes, &(note_size), message, __VA_ARGS__); \
+ borrowed_status->note.size = note_size; \
+ borrowed_status->has_note = true; \
+ } \
+ } \
+ } while (false)
} // namespace
-Status BundledUpdateService::GetStatus(
- const pw_protobuf_Empty&,
- pw_software_update_BundledUpdateStatus& response) {
- std::lock_guard lock(mutex_);
- response = status_;
+Status BundledUpdateService::GetStatus(const pw_protobuf_Empty&,
+ BundledUpdateStatus& response) {
+ response = *status_.acquire();
return OkStatus();
}
Status BundledUpdateService::Start(
const pw_software_update_StartRequest& request,
- pw_software_update_BundledUpdateStatus& response) {
+ BundledUpdateStatus& response) {
std::lock_guard lock(mutex_);
// Check preconditions.
- if (status_.state != pw_software_update_BundledUpdateState_Enum_INACTIVE) {
+ const BundledUpdateState state = status_.acquire()->state;
+ if (state != pw_software_update_BundledUpdateState_Enum_INACTIVE) {
SET_ERROR(pw_software_update_BundledUpdateResult_Enum_UNKNOWN_ERROR,
"Start() can only be called from INACTIVE state. "
"Current state: %d. Abort() then Reset() must be called first",
- static_cast<int>(status_.state));
- response = status_;
+ static_cast<int>(state));
+ response = *status_.acquire();
return Status::FailedPrecondition();
}
- PW_DCHECK(!status_.has_transfer_id);
- PW_DCHECK(!status_.has_result);
- PW_DCHECK(status_.current_state_progress_hundreth_percent == 0);
- PW_DCHECK(status_.bundle_filename[0] == '\0');
- PW_DCHECK(status_.note.size == 0);
+
+ {
+ BorrowedStatus borrowed_status = status_.acquire();
+ PW_DCHECK(!borrowed_status->has_transfer_id);
+ PW_DCHECK(!borrowed_status->has_result);
+ PW_DCHECK(borrowed_status->current_state_progress_hundreth_percent == 0);
+ PW_DCHECK(borrowed_status->bundle_filename[0] == '\0');
+ PW_DCHECK(borrowed_status->note.size == 0);
+ }
// Notify the backend of pending transfer.
if (const Status status = backend_.BeforeUpdateStart(); !status.ok()) {
SET_ERROR(pw_software_update_BundledUpdateResult_Enum_UNKNOWN_ERROR,
"Backend error on BeforeUpdateStart()");
- response = status_;
+ response = *status_.acquire();
return status;
}
@@ -95,60 +105,70 @@ Status BundledUpdateService::Start(
if (!possible_transfer_id.ok()) {
SET_ERROR(pw_software_update_BundledUpdateResult_Enum_TRANSFER_FAILED,
"Couldn't enable bundle transfer");
- response = status_;
+ response = *status_.acquire();
return possible_transfer_id.status();
}
// Update state.
- status_.transfer_id = possible_transfer_id.value();
- status_.has_transfer_id = true;
- if (request.has_bundle_filename) {
- const StatusWithSize sws = string::Copy(request.bundle_filename,
- status_.bundle_filename,
- sizeof(status_.bundle_filename));
- PW_DCHECK_OK(sws.status(),
- "bundle_filename options max_sizes do not match");
- status_.has_bundle_filename = true;
- }
- status_.state = pw_software_update_BundledUpdateState_Enum_TRANSFERRING;
- response = status_;
+ {
+ BorrowedStatus borrowed_status = status_.acquire();
+ borrowed_status->transfer_id = possible_transfer_id.value();
+ borrowed_status->has_transfer_id = true;
+ if (request.has_bundle_filename) {
+ const StatusWithSize sws =
+ string::Copy(request.bundle_filename,
+ borrowed_status->bundle_filename,
+ sizeof(borrowed_status->bundle_filename));
+ PW_DCHECK_OK(sws.status(),
+ "bundle_filename options max_sizes do not match");
+ borrowed_status->has_bundle_filename = true;
+ }
+ borrowed_status->state =
+ pw_software_update_BundledUpdateState_Enum_TRANSFERRING;
+ response = *borrowed_status;
+ }
return OkStatus();
}
-Status BundledUpdateService::SetTransferred(
- const pw_protobuf_Empty&,
- ::pw_software_update_BundledUpdateStatus& response) {
- if (status_.state !=
- pw_software_update_BundledUpdateState_Enum_TRANSFERRING &&
- status_.state != pw_software_update_BundledUpdateState_Enum_INACTIVE) {
+Status BundledUpdateService::SetTransferred(const pw_protobuf_Empty&,
+ BundledUpdateStatus& response) {
+ const BundledUpdateState state = status_.acquire()->state;
+
+ if (state != pw_software_update_BundledUpdateState_Enum_TRANSFERRING &&
+ state != pw_software_update_BundledUpdateState_Enum_INACTIVE) {
SET_ERROR(pw_software_update_BundledUpdateResult_Enum_UNKNOWN_ERROR,
"SetTransferred() can only be called from TRANSFERRING or "
"INACTIVE state. State: %d",
- static_cast<int>(status_.state));
- response = status_;
+ static_cast<int>(state));
+ response = *status_.acquire();
return OkStatus();
}
+
NotifyTransferSucceeded();
- response = status_;
+
+ response = *status_.acquire();
return OkStatus();
}
// TODO: Check for "ABORTING" state and bail if it's set.
void BundledUpdateService::DoVerify() {
std::lock_guard guard(mutex_);
- if (status_.state == pw_software_update_BundledUpdateState_Enum_VERIFIED) {
+ const BundledUpdateState state = status_.acquire()->state;
+
+ if (state == pw_software_update_BundledUpdateState_Enum_VERIFIED) {
return; // Already done!
}
// Ensure we're in the right state.
- if (status_.state != pw_software_update_BundledUpdateState_Enum_TRANSFERRED) {
+ if (state != pw_software_update_BundledUpdateState_Enum_TRANSFERRED) {
SET_ERROR(pw_software_update_BundledUpdateResult_Enum_VERIFY_FAILED,
"DoVerify() must be called from TRANSFERRED state. State: %d",
- static_cast<int>(status_.state));
+ static_cast<int>(state));
return;
}
- status_.state = pw_software_update_BundledUpdateState_Enum_VERIFYING;
+ status_.acquire()->state =
+ pw_software_update_BundledUpdateState_Enum_VERIFYING;
// Notify backend about pending verify.
if (const Status status = backend_.BeforeBundleVerify(); !status.ok()) {
@@ -167,7 +187,7 @@ void BundledUpdateService::DoVerify() {
bundle_open_ = true;
// Have the backend verify the user_manifest if present.
- if (!backend_.VerifyManifest(bundle_.GetManifestAccessor()).ok()) {
+ if (!backend_.VerifyManifest(bundle_.GetManifest()).ok()) {
SET_ERROR(pw_software_update_BundledUpdateResult_Enum_VERIFY_FAILED,
"Backend::VerifyUserManifest() failed");
return;
@@ -180,30 +200,29 @@ void BundledUpdateService::DoVerify() {
"Backend::AfterBundleVerified() failed");
return;
}
- status_.state = pw_software_update_BundledUpdateState_Enum_VERIFIED;
+ status_.acquire()->state =
+ pw_software_update_BundledUpdateState_Enum_VERIFIED;
}
-Status BundledUpdateService::Verify(
- const pw_protobuf_Empty&,
- pw_software_update_BundledUpdateStatus& response) {
+Status BundledUpdateService::Verify(const pw_protobuf_Empty&,
+ BundledUpdateStatus& response) {
std::lock_guard lock(mutex_);
+ const BundledUpdateState state = status_.acquire()->state;
// Already done? Bail.
- if (status_.state == pw_software_update_BundledUpdateState_Enum_VERIFIED) {
+ if (state == pw_software_update_BundledUpdateState_Enum_VERIFIED) {
PW_LOG_DEBUG("Skipping verify since already verified");
return OkStatus();
}
// TODO: Remove the transferring permitted state here ASAP.
// Ensure we're in the right state.
- if ((status_.state !=
- pw_software_update_BundledUpdateState_Enum_TRANSFERRING) &&
- (status_.state !=
- pw_software_update_BundledUpdateState_Enum_TRANSFERRED)) {
+ if ((state != pw_software_update_BundledUpdateState_Enum_TRANSFERRING) &&
+ (state != pw_software_update_BundledUpdateState_Enum_TRANSFERRED)) {
SET_ERROR(pw_software_update_BundledUpdateResult_Enum_VERIFY_FAILED,
"Verify() must be called from TRANSFERRED state. State: %d",
- static_cast<int>(status_.state));
- response = status_;
+ static_cast<int>(state));
+ response = *status_.acquire();
return Status::FailedPrecondition();
}
@@ -230,35 +249,34 @@ Status BundledUpdateService::Verify(
if (!status.ok()) {
SET_ERROR(pw_software_update_BundledUpdateResult_Enum_VERIFY_FAILED,
"Unable to equeue apply to work queue");
- response = status_;
+ response = *status_.acquire();
return status;
}
work_enqueued_ = true;
- response = status_;
+ response = *status_.acquire();
return OkStatus();
}
-Status BundledUpdateService::Apply(
- const pw_protobuf_Empty&,
- pw_software_update_BundledUpdateStatus& response) {
+Status BundledUpdateService::Apply(const pw_protobuf_Empty&,
+ BundledUpdateStatus& response) {
std::lock_guard lock(mutex_);
+ const BundledUpdateState state = status_.acquire()->state;
// We do not wait to go into a finished error state if we're already
// applying, instead just let them know that yes we are working on it --
// hold on.
- if (status_.state == pw_software_update_BundledUpdateState_Enum_APPLYING) {
+ if (state == pw_software_update_BundledUpdateState_Enum_APPLYING) {
PW_LOG_DEBUG("Apply is already active");
return OkStatus();
}
- if ((status_.state !=
- pw_software_update_BundledUpdateState_Enum_TRANSFERRED) &&
- (status_.state != pw_software_update_BundledUpdateState_Enum_VERIFIED)) {
+ if ((state != pw_software_update_BundledUpdateState_Enum_TRANSFERRED) &&
+ (state != pw_software_update_BundledUpdateState_Enum_VERIFIED)) {
SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
"Apply() must be called from TRANSFERRED or VERIFIED state. "
"State: %d",
- static_cast<int>(status_.state));
+ static_cast<int>(state));
return Status::FailedPrecondition();
}
@@ -286,7 +304,7 @@ Status BundledUpdateService::Apply(
if (!status.ok()) {
SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
"Unable to equeue apply to work queue");
- response = status_;
+ response = *status_.acquire();
return status;
}
work_enqueued_ = true;
@@ -296,59 +314,18 @@ Status BundledUpdateService::Apply(
void BundledUpdateService::DoApply() {
std::lock_guard guard(mutex_);
+ const BundledUpdateState state = status_.acquire()->state;
PW_LOG_DEBUG("Attempting to apply the update");
- if (status_.state != pw_software_update_BundledUpdateState_Enum_VERIFIED) {
+ if (state != pw_software_update_BundledUpdateState_Enum_VERIFIED) {
SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
"Apply() must be called from VERIFIED state. State: %d",
- static_cast<int>(status_.state));
- return;
- }
- status_.state = pw_software_update_BundledUpdateState_Enum_APPLYING;
-
- protobuf::StringToMessageMap signed_targets_metadata_map =
- bundle_.GetDecoder().AsStringToMessageMap(static_cast<uint32_t>(
- pw::software_update::UpdateBundle::Fields::TARGETS_METADATA));
- if (const Status status = signed_targets_metadata_map.status();
- !status.ok()) {
- SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
- "Update bundle does not contain the targets_metadata map: %d",
- static_cast<int>(status.code()));
- return;
- }
-
- // There should only be one element in the map, which is the top-level
- // targets metadata.
- protobuf::Message signed_targets_metadata =
- signed_targets_metadata_map[kTopLevelTargetsName];
- if (const Status status = signed_targets_metadata.status(); !status.ok()) {
- SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
- "The targets_metadata map does not contain the targets entry: %d",
- static_cast<int>(status.code()));
+ static_cast<int>(state));
return;
}
- protobuf::Message targets_metadata = signed_targets_metadata.AsMessage(
- static_cast<uint32_t>(pw::software_update::SignedTargetsMetadata::Fields::
- SERIALIZED_TARGETS_METADATA));
- if (const Status status = targets_metadata.status(); !status.ok()) {
- SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
- "The targets targets_metadata entry does not contain the "
- "serialized_target_metadata: %d",
- static_cast<int>(status.code()));
- return;
- }
-
- protobuf::RepeatedMessages target_files =
- targets_metadata.AsRepeatedMessages(static_cast<uint32_t>(
- pw::software_update::TargetsMetadata::Fields::TARGET_FILES));
- if (const Status status = target_files.status(); !status.ok()) {
- SET_ERROR(
- pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
- "The serialized_target_metadata does not contain target_files: %d",
- static_cast<int>(status.code()));
- return;
- }
+ status_.acquire()->state =
+ pw_software_update_BundledUpdateState_Enum_APPLYING;
if (const Status status = backend_.BeforeApply(); !status.ok()) {
SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
@@ -357,53 +334,25 @@ void BundledUpdateService::DoApply() {
return;
}
- // In order to report apply progress, quickly scan to see how many bytes will
- // be applied.
- size_t target_file_bytes_to_apply = 0;
- protobuf::StringToBytesMap target_payloads =
- bundle_.GetDecoder().AsStringToBytesMap(static_cast<uint32_t>(
- pw::software_update::UpdateBundle::Fields::TARGET_PAYLOADS));
- if (!target_payloads.status().ok()) {
- SET_ERROR(
- pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
- "Failed to iterate the UpdateBundle target_payloads map entries: %d",
- static_cast<int>(target_payloads.status().code()));
- return;
- }
- for (pw::protobuf::StringToBytesMapEntry target_payload : target_payloads) {
- protobuf::Bytes target_payload_bytes = target_payload.Value();
- if (!target_payload_bytes.status().ok()) {
- SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
- "Failed to read a UpdateBundle target_payloads map entry: %d",
- static_cast<int>(target_payload_bytes.status().code()));
- return;
- }
- target_file_bytes_to_apply +=
- target_payload_bytes.GetBytesReader().ConservativeReadLimit();
- }
+ // In order to report apply progress, quickly scan to see how many bytes
+ // will be applied.
+ Result<uint64_t> total_payload_bytes = bundle_.GetTotalPayloadSize();
+ PW_CHECK_OK(total_payload_bytes.status());
+ size_t target_file_bytes_to_apply =
+ static_cast<size_t>(total_payload_bytes.value());
+
+ protobuf::RepeatedMessages target_files =
+ bundle_.GetManifest().GetTargetFiles();
+ PW_CHECK_OK(target_files.status());
size_t target_file_bytes_applied = 0;
for (pw::protobuf::Message file_name : target_files) {
- // TODO: Use a config.h parameter for this.
- constexpr size_t kFileNameMaxSize = 32;
- std::array<std::byte, kFileNameMaxSize> buf = {};
+ std::array<std::byte, MAX_TARGET_NAME_LENGTH> buf = {};
protobuf::String name = file_name.AsString(static_cast<uint32_t>(
pw::software_update::TargetFile::Fields::FILE_NAME));
- if (!name.status().ok()) {
- SET_ERROR(
- pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
- "The serialized_target_metadata failed to iterate target files: %d",
- static_cast<int>(name.status().code()));
- return;
- }
+ PW_CHECK_OK(name.status());
const Result<ByteSpan> read_result = name.GetBytesReader().Read(buf);
- if (!read_result.ok()) {
- SET_ERROR(
- pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
- "The serialized_target_metadata failed to read target filename: %d",
- static_cast<int>(read_result.status().code()));
- return;
- }
+ PW_CHECK_OK(read_result.status());
const ConstByteSpan file_name_span = read_result.value();
const std::string_view file_name_view(
reinterpret_cast<const char*>(file_name_span.data()),
@@ -411,8 +360,23 @@ void BundledUpdateService::DoApply() {
if (file_name_view.compare(kUserManifestTargetFileName) == 0) {
continue; // user_manifest is not applied by the backend.
}
+ // Try to get an IntervalReader for the current file.
stream::IntervalReader file_reader =
bundle_.GetTargetPayload(file_name_view);
+ if (file_reader.status().IsNotFound()) {
+ PW_LOG_INFO(
+ "Contents of file %s missing from bundle; ignoring",
+ pw::MakeString<MAX_TARGET_NAME_LENGTH>(file_name_view).c_str());
+ continue;
+ }
+ if (!file_reader.ok()) {
+ SET_ERROR(pw_software_update_BundledUpdateResult_Enum_APPLY_FAILED,
+ "Could not open contents of file %s from bundle; "
+ "aborting update apply phase",
+ static_cast<int>(file_reader.status().code()));
+ return;
+ }
+
const size_t bundle_offset = file_reader.start();
if (const Status status = backend_.ApplyTargetFile(
file_name_view, file_reader, bundle_offset);
@@ -431,9 +395,10 @@ void BundledUpdateService::DoApply() {
target_file_bytes_to_apply,
static_cast<unsigned long>(progress_hundreth_percent / 100));
{
- status_.current_state_progress_hundreth_percent =
+ BorrowedStatus borrowed_status = status_.acquire();
+ borrowed_status->current_state_progress_hundreth_percent =
progress_hundreth_percent;
- status_.has_current_state_progress_hundreth_percent = true;
+ borrowed_status->has_current_state_progress_hundreth_percent = true;
}
}
@@ -452,49 +417,53 @@ void BundledUpdateService::DoApply() {
Finish(pw_software_update_BundledUpdateResult_Enum_SUCCESS);
}
-Status BundledUpdateService::Abort(
- const pw_protobuf_Empty&,
- pw_software_update_BundledUpdateStatus& response) {
+Status BundledUpdateService::Abort(const pw_protobuf_Empty&,
+ BundledUpdateStatus& response) {
std::lock_guard lock(mutex_);
- if (status_.state == pw_software_update_BundledUpdateState_Enum_APPLYING) {
+ const BundledUpdateState state = status_.acquire()->state;
+
+ if (state == pw_software_update_BundledUpdateState_Enum_APPLYING) {
return Status::FailedPrecondition();
}
- if (status_.state == pw_software_update_BundledUpdateState_Enum_INACTIVE ||
- status_.state == pw_software_update_BundledUpdateState_Enum_FINISHED) {
+ if (state == pw_software_update_BundledUpdateState_Enum_INACTIVE ||
+ state == pw_software_update_BundledUpdateState_Enum_FINISHED) {
SET_ERROR(pw_software_update_BundledUpdateResult_Enum_UNKNOWN_ERROR,
"Tried to abort when already INACTIVE or FINISHED");
return Status::FailedPrecondition();
}
// TODO: Switch abort to async; this state change isn't externally visible.
- status_.state = pw_software_update_BundledUpdateState_Enum_ABORTING;
+ status_.acquire()->state =
+ pw_software_update_BundledUpdateState_Enum_ABORTING;
SET_ERROR(pw_software_update_BundledUpdateResult_Enum_ABORTED,
"Update abort requested");
- response = status_;
+ response = *status_.acquire();
return OkStatus();
}
-Status BundledUpdateService::Reset(
- const pw_protobuf_Empty&,
- pw_software_update_BundledUpdateStatus& response) {
+Status BundledUpdateService::Reset(const pw_protobuf_Empty&,
+ BundledUpdateStatus& response) {
std::lock_guard lock(mutex_);
+ const BundledUpdateState state = status_.acquire()->state;
- if (status_.state == pw_software_update_BundledUpdateState_Enum_INACTIVE) {
+ if (state == pw_software_update_BundledUpdateState_Enum_INACTIVE) {
return OkStatus(); // Already done.
}
- if (status_.state != pw_software_update_BundledUpdateState_Enum_FINISHED) {
+ if (state != pw_software_update_BundledUpdateState_Enum_FINISHED) {
SET_ERROR(
pw_software_update_BundledUpdateResult_Enum_UNKNOWN_ERROR,
"Reset() must be called from FINISHED or INACTIVE state. State: %d",
- static_cast<int>(status_.state));
- response = status_;
+ static_cast<int>(state));
+ response = *status_.acquire();
return Status::FailedPrecondition();
}
- status_ = {};
- status_.state = pw_software_update_BundledUpdateState_Enum_INACTIVE;
+ {
+ *status_.acquire() = {
+ .state = pw_software_update_BundledUpdateState_Enum_INACTIVE};
+ }
// Reset the bundle.
if (bundle_open_) {
@@ -503,37 +472,41 @@ Status BundledUpdateService::Reset(
bundle_open_ = false;
}
- response = status_;
+ response = *status_.acquire();
return OkStatus();
}
void BundledUpdateService::NotifyTransferSucceeded() {
std::lock_guard lock(mutex_);
+ const BundledUpdateState state = status_.acquire()->state;
- if (status_.state !=
- pw_software_update_BundledUpdateState_Enum_TRANSFERRING) {
+ if (state != pw_software_update_BundledUpdateState_Enum_TRANSFERRING) {
// This can happen if the update gets Abort()'d during the transfer and
// the transfer completes successfully.
PW_LOG_WARN(
"Got transfer succeeded notification when not in TRANSFERRING state. "
"State: %d",
- static_cast<int>(status_.state));
+ static_cast<int>(state));
}
- if (status_.has_transfer_id) {
+
+ const bool transfer_ongoing = status_.acquire()->has_transfer_id;
+ if (transfer_ongoing) {
backend_.DisableBundleTransferHandler();
- status_.has_transfer_id = false;
+ status_.acquire()->has_transfer_id = false;
} else {
PW_LOG_WARN("No ongoing transfer found, forcefully set TRANSFERRED.");
}
- status_.state = pw_software_update_BundledUpdateState_Enum_TRANSFERRED;
+ status_.acquire()->state =
+ pw_software_update_BundledUpdateState_Enum_TRANSFERRED;
}
void BundledUpdateService::Finish(
pw_software_update_BundledUpdateResult_Enum result) {
if (result == pw_software_update_BundledUpdateResult_Enum_SUCCESS) {
- status_.current_state_progress_hundreth_percent = 0;
- status_.has_current_state_progress_hundreth_percent = false;
+ BorrowedStatus borrowed_status = status_.acquire();
+ borrowed_status->current_state_progress_hundreth_percent = 0;
+ borrowed_status->has_current_state_progress_hundreth_percent = false;
} else {
// In the case of error, notify backend that we're about to abort the
// software update.
@@ -541,10 +514,11 @@ void BundledUpdateService::Finish(
}
// Turn down the transfer if one is in progress.
- if (status_.has_transfer_id) {
+ const bool transfer_ongoing = status_.acquire()->has_transfer_id;
+ if (transfer_ongoing) {
backend_.DisableBundleTransferHandler();
}
- status_.has_transfer_id = false;
+ status_.acquire()->has_transfer_id = false;
// Close out any open bundles.
if (bundle_open_) {
@@ -552,9 +526,13 @@ void BundledUpdateService::Finish(
PW_CHECK_OK(bundle_.Close());
bundle_open_ = false;
}
- status_.state = pw_software_update_BundledUpdateState_Enum_FINISHED;
- status_.result = result;
- status_.has_result = true;
+ {
+ BorrowedStatus borrowed_status = status_.acquire();
+ borrowed_status->state =
+ pw_software_update_BundledUpdateState_Enum_FINISHED;
+ borrowed_status->result = result;
+ borrowed_status->has_result = true;
+ }
}
} // namespace pw::software_update