From ae015665cd4f0ce4e953ba0c56c4fe404d0772c3 Mon Sep 17 00:00:00 2001 From: Francis Tsui Date: Wed, 6 Aug 2025 18:23:55 -0700 Subject: [PATCH] Set file last modified time. PiperOrigin-RevId: 791926107 --- connections/BUILD | 1 + connections/implementation/internal_payload.h | 11 ++++- .../internal_payload_factory.cc | 23 ++++++++-- connections/implementation/payload_manager.cc | 15 +++---- connections/implementation/payload_manager.h | 4 +- connections/payload.cc | 44 +++++++++---------- connections/payload.h | 9 +++- connections/payload_test.cc | 4 +- 8 files changed, 67 insertions(+), 44 deletions(-) diff --git a/connections/BUILD b/connections/BUILD index b9075fed..10a2a7d3 100644 --- a/connections/BUILD +++ b/connections/BUILD @@ -96,6 +96,7 @@ cc_library( "//proto:connections_enums_cc_proto", "@com_google_absl//absl/functional:any_invocable", "@com_google_absl//absl/random", + "@com_google_absl//absl/time", "@com_google_absl//absl/types:variant", ], ) diff --git a/connections/implementation/internal_payload.h b/connections/implementation/internal_payload.h index 2a841e89..d70e0593 100644 --- a/connections/implementation/internal_payload.h +++ b/connections/implementation/internal_payload.h @@ -16,7 +16,9 @@ #define CORE_INTERNAL_INTERNAL_PAYLOAD_H_ #include +#include +#include "absl/time/time.h" #include "connections/implementation/proto/offline_wire_formats.pb.h" #include "connections/payload.h" #include "internal/platform/byte_array.h" @@ -41,8 +43,13 @@ class InternalPayload { Payload::Id GetId() const; - const std::string& GetParentFolder() { return payload_.GetParentFolder(); } - const std::string& GetFileName() { return payload_.GetFileName(); } + const std::string& GetParentFolder() const { + return payload_.GetParentFolder(); + } + const std::string& GetFileName() const { return payload_.GetFileName(); } + absl::Time GetLastModifiedTime() const { + return payload_.GetLastModifiedTime(); + } // Returns the PayloadType of the Payload to which this object is bound. // diff --git a/connections/implementation/internal_payload_factory.cc b/connections/implementation/internal_payload_factory.cc index 014681eb..cb618cd7 100644 --- a/connections/implementation/internal_payload_factory.cc +++ b/connections/implementation/internal_payload_factory.cc @@ -21,6 +21,8 @@ #include #include "absl/strings/str_cat.h" +#include "absl/time/clock.h" +#include "absl/time/time.h" #include "connections/implementation/internal_payload.h" #include "connections/implementation/proto/offline_wire_formats.pb.h" #include "connections/payload.h" @@ -265,9 +267,11 @@ class OutgoingFileInternalPayload : public InternalPayload { class IncomingFileInternalPayload : public InternalPayload { public: IncomingFileInternalPayload(Payload payload, OutputFile output_file, + absl::Time last_modified_time, std::int64_t total_size) : InternalPayload(std::move(payload)), output_file_(std::move(output_file)), + last_modified_time_(last_modified_time), total_size_(total_size) {} location::nearby::connections::PayloadTransferFrame::PayloadHeader:: @@ -284,7 +288,7 @@ class IncomingFileInternalPayload : public InternalPayload { Exception AttachNextChunk(const ByteArray& chunk) override { if (chunk.Empty()) { // Received null last chunk for incoming payload. - output_file_.Close(); + Close(); return {Exception::kSuccess}; } @@ -296,10 +300,14 @@ class IncomingFileInternalPayload : public InternalPayload { return {Exception::kIo}; } - void Close() override { output_file_.Close(); } + void Close() override { + output_file_.SetLastModifiedTime(last_modified_time_); + output_file_.Close(); + } private: OutputFile output_file_; + absl::Time last_modified_time_; const std::int64_t total_size_; }; @@ -405,6 +413,13 @@ ErrorOr> CreateIncomingInternalPayload( if (frame.payload_header().has_total_size()) { total_size = frame.payload_header().total_size(); } + absl::Time last_modified_time = absl::Now(); + if (frame.payload_header().has_last_modified_timestamp_millis()) { + last_modified_time = absl::FromUnixMillis( + frame.payload_header().last_modified_timestamp_millis()); + VLOG(1) << "Received last modified time: " << last_modified_time + << " for file: " << file_name; + } // These are ordered, the output file must be created first otherwise // there will be no input file to open. @@ -417,7 +432,7 @@ ErrorOr> CreateIncomingInternalPayload( } return {std::make_unique( Payload(payload_id, InputFile(payload_id, total_size)), - std::move(output_file), total_size)}; + std::move(output_file), last_modified_time, total_size)}; } else { OutputFile output_file(file_path); if (!output_file.IsValid()) { @@ -427,7 +442,7 @@ ErrorOr> CreateIncomingInternalPayload( return {std::make_unique( Payload(payload_id, parent_folder, file_name, InputFile(file_path, total_size)), - std::move(output_file), total_size)}; + std::move(output_file), last_modified_time, total_size)}; } } default: diff --git a/connections/implementation/payload_manager.cc b/connections/implementation/payload_manager.cc index 959382a9..8dac70c9 100644 --- a/connections/implementation/payload_manager.cc +++ b/connections/implementation/payload_manager.cc @@ -475,9 +475,8 @@ void PayloadManager::SendPayload(ClientProxy* client, payload_type, resume_offset, internal_payload->GetTotalSize()); - PayloadTransferFrame::PayloadHeader payload_header{CreatePayloadHeader( - *internal_payload, resume_offset, internal_payload->GetParentFolder(), - internal_payload->GetFileName())}; + PayloadTransferFrame::PayloadHeader payload_header{ + CreatePayloadHeader(*internal_payload, resume_offset)}; bool should_continue = true; std::int64_t next_chunk_offset = 0; @@ -754,8 +753,7 @@ int PayloadManager::GetOptimalChunkSize(EndpointIds endpoint_ids) { } PayloadTransferFrame::PayloadHeader PayloadManager::CreatePayloadHeader( - const InternalPayload& internal_payload, size_t offset, - const std::string& parent_folder, const std::string& file_name) { + const InternalPayload& internal_payload, size_t offset) { PayloadTransferFrame::PayloadHeader payload_header; size_t payload_size = internal_payload.GetTotalSize(); @@ -764,14 +762,15 @@ PayloadTransferFrame::PayloadHeader PayloadManager::CreatePayloadHeader( if (internal_payload.GetType() == nearby::connections::PayloadTransferFrame::PayloadTransferFrame:: PayloadHeader::FILE) { - payload_header.set_file_name(file_name); - payload_header.set_parent_folder(parent_folder); + payload_header.set_file_name(internal_payload.GetFileName()); + payload_header.set_parent_folder(internal_payload.GetParentFolder()); + payload_header.set_last_modified_timestamp_millis( + absl::ToUnixMillis(internal_payload.GetLastModifiedTime())); } payload_header.set_total_size(payload_size == InternalPayload::kIndeterminateSize ? InternalPayload::kIndeterminateSize : payload_size - offset); - return payload_header; } diff --git a/connections/implementation/payload_manager.h b/connections/implementation/payload_manager.h index 3f489178..838af4f8 100644 --- a/connections/implementation/payload_manager.h +++ b/connections/implementation/payload_manager.h @@ -311,9 +311,7 @@ class PayloadManager : public EndpointManager::FrameProcessor { int GetOptimalChunkSize(EndpointIds endpoint_ids); location::nearby::connections::PayloadTransferFrame::PayloadHeader - CreatePayloadHeader(const InternalPayload& internal_payload, size_t offset, - const std::string& parent_folder, - const std::string& file_name); + CreatePayloadHeader(const InternalPayload& internal_payload, size_t offset); location::nearby::connections::PayloadTransferFrame::PayloadChunk CreatePayloadChunk(std::int64_t offset, ByteArray body, int index); diff --git a/connections/payload.cc b/connections/payload.cc index c92d38e5..baae0663 100644 --- a/connections/payload.cc +++ b/connections/payload.cc @@ -64,19 +64,11 @@ Payload::Payload(ByteArray&& bytes) Payload::Payload(const ByteArray& bytes) : type_(PayloadType::kBytes), content_(bytes) {} -Payload::Payload(InputFile input_file) - : id_(std::hash()(input_file.GetFilePath())), - file_name_(FormatFileName(input_file.GetFilePath())), - type_(PayloadType::kFile), - content_(std::move(input_file)) {} - Payload::Payload(std::string parent_folder, std::string file_name, - InputFile input_file) - : id_(std::hash()(input_file.GetFilePath())), - parent_folder_(parent_folder), - file_name_(file_name), - type_(PayloadType::kFile), - content_(std::move(input_file)) {} + InputFile input_file) { + Id id = std::hash()(input_file.GetFilePath()); + InitFilePayload(id, parent_folder, file_name, std::move(input_file)); +} Payload::Payload(std::unique_ptr stream) : type_(PayloadType::kStream), content_(std::move(stream)) {} @@ -88,23 +80,29 @@ Payload::Payload(Id id, ByteArray&& bytes) Payload::Payload(Id id, const ByteArray& bytes) : id_(id), type_(PayloadType::kBytes), content_(bytes) {} -Payload::Payload(Id id, InputFile input_file) - : id_(id), - file_name_(FormatFileName(input_file.GetFilePath())), - type_(PayloadType::kFile), - content_(std::move(input_file)) {} +Payload::Payload(Id id, InputFile input_file) { + std::string file_path = input_file.GetFilePath(); + InitFilePayload(id, /*parent_folder=*/"", file_path, std::move(input_file)); +} Payload::Payload(Id id, std::string parent_folder, std::string file_name, - InputFile input_file) - : id_(id), - parent_folder_(parent_folder), - file_name_(file_name), - type_(PayloadType::kFile), - content_(std::move(input_file)) {} + InputFile input_file) { + InitFilePayload(id, parent_folder, file_name, std::move(input_file)); +} Payload::Payload(Id id, std::unique_ptr stream) : id_(id), type_(PayloadType::kStream), content_(std::move(stream)) {} +void Payload::InitFilePayload(Id id, std::string parent_folder, + std::string file_name, InputFile input_file) { + id_ = id; + parent_folder_ = parent_folder; + file_name_ = FormatFileName(file_name); + last_modified_time_ = input_file.GetLastModifiedTime(); + type_ = PayloadType::kFile; + content_ = std::move(input_file); +} + // Returns ByteArray payload, if it has been defined, or empty ByteArray. const ByteArray& Payload::AsBytes() const& { static const ByteArray empty; // NOLINT: function-level static is OK. diff --git a/connections/payload.h b/connections/payload.h index 4c554828..d40b1ba4 100644 --- a/connections/payload.h +++ b/connections/payload.h @@ -18,9 +18,12 @@ #include #include #include +#include #include #include +#include "absl/time/clock.h" +#include "absl/time/time.h" #include "absl/types/variant.h" #include "connections/payload_type.h" #include "internal/platform/byte_array.h" @@ -53,9 +56,7 @@ class Payload { // Constructors for outgoing payloads. explicit Payload(ByteArray&& bytes); - explicit Payload(const ByteArray& bytes); - explicit Payload(InputFile input_file); // InputFile is just "a pointer to a file on your disc", a wrapper around a // file name or file descriptor. It has no understanding that Nearby is going @@ -105,8 +106,11 @@ class Payload { const std::string& GetFileName() const; const std::string& GetParentFolder() const; + absl::Time GetLastModifiedTime() const { return last_modified_time_; } private: + void InitFilePayload(Id id, std::string parent_folder, std::string file_name, + InputFile input_file); PayloadType FindType() const; Id id_{GenerateId()}; @@ -114,6 +118,7 @@ class Payload { std::string parent_folder_; std::string file_name_; + absl::Time last_modified_time_ = absl::Now(); PayloadType type_{FindType()}; Content content_; diff --git a/connections/payload_test.cc b/connections/payload_test.cc index 7a3aad02..e6ec80fc 100644 --- a/connections/payload_test.cc +++ b/connections/payload_test.cc @@ -76,7 +76,7 @@ TEST(PayloadTest, SupportsMultiDotNamedFileType) { constexpr char expected[] = "this.is.a.multidot.file"; InputFile file(expected, 0); - Payload payload(std::move(file)); + Payload payload(/*parent_folder=*/"", expected, std::move(file)); EXPECT_EQ(payload.GetFileName(), expected); } @@ -89,7 +89,7 @@ TEST(PayloadTest, "this.is.a.multidot.backslash.folder.separated.file"; InputFile file(file_name, 0); - Payload payload(std::move(file)); + Payload payload(/*parent_folder=*/"", file_name, std::move(file)); EXPECT_EQ(payload.GetFileName(), expected); }