@@ -34,27 +34,50 @@ ObjectDescriptorImpl::ObjectDescriptorImpl(
3434 OpenStreamFactory make_stream,
3535 google::storage::v2::BidiReadObjectSpec read_object_spec,
3636 std::shared_ptr<OpenStream> stream, Options options)
37- : resume_policy_ (std::move(resume_policy)),
37+ : resume_policy_prototype_ (std::move(resume_policy)),
3838 make_stream_ (std::move(make_stream)),
3939 read_object_spec_(std::move(read_object_spec)),
40- stream_(std::move(stream)),
41- options_(std::move(options)) {}
40+ options_(std::move(options)) {
41+ streams_.push_back (
42+ Stream{std::move (stream), {}, resume_policy_prototype_->clone ()});
43+ }
4244
43- ObjectDescriptorImpl::~ObjectDescriptorImpl () { stream_->Cancel (); }
45+ ObjectDescriptorImpl::~ObjectDescriptorImpl () {
46+ for (auto const & stream : streams_) {
47+ stream.stream ->Cancel ();
48+ }
49+ }
4450
4551void ObjectDescriptorImpl::Start (
4652 google::storage::v2::BidiReadObjectResponse first_response) {
4753 OnRead (std::move (first_response));
4854}
4955
50- void ObjectDescriptorImpl::Cancel () { stream_->Cancel (); }
56+ void ObjectDescriptorImpl::Cancel () {
57+ for (auto const & stream : streams_) {
58+ stream.stream ->Cancel ();
59+ }
60+ }
5161
5262absl::optional<google::storage::v2::Object> ObjectDescriptorImpl::metadata ()
5363 const {
5464 std::unique_lock<std::mutex> lk (mu_);
5565 return metadata_;
5666}
5767
68+ void ObjectDescriptorImpl::MakeSubsequentStream () {
69+ auto request = google::storage::v2::BidiReadObjectRequest{};
70+
71+ *request.mutable_read_object_spec () = read_object_spec_;
72+ auto stream_result = make_stream_ (std::move (request)).get ();
73+
74+ std::unique_lock<std::mutex> lk (mu_);
75+ streams_.push_back (Stream{
76+ std::move (stream_result->stream ), {}, resume_policy_prototype_->clone ()});
77+ lk.unlock ();
78+ OnRead (std::move (stream_result->first_response ));
79+ }
80+
5881std::unique_ptr<storage_experimental::AsyncReaderConnection>
5982ObjectDescriptorImpl::Read (ReadParams p) {
6083 std::shared_ptr<storage::internal::HashFunction> hash_function =
@@ -69,7 +92,7 @@ ObjectDescriptorImpl::Read(ReadParams p) {
6992
7093 std::unique_lock<std::mutex> lk (mu_);
7194 auto const id = ++read_id_generator_;
72- active_ranges_ .emplace (id, range);
95+ streams_. back (). active_ranges .emplace (id, range);
7396 auto & read_range = *next_request_.add_read_ranges ();
7497 read_range.set_read_id (id);
7598 read_range.set_read_offset (p.start );
@@ -85,8 +108,10 @@ ObjectDescriptorImpl::Read(ReadParams p) {
85108}
86109
87110void ObjectDescriptorImpl::Flush (std::unique_lock<std::mutex> lk) {
88- if (write_pending_ || next_request_.read_ranges ().empty ()) return ;
89- write_pending_ = true ;
111+ if (streams_.back ().write_pending || next_request_.read_ranges ().empty ()) {
112+ return ;
113+ }
114+ streams_.back ().write_pending = true ;
90115 google::storage::v2::BidiReadObjectRequest request;
91116 request.Swap (&next_request_);
92117
@@ -102,7 +127,7 @@ void ObjectDescriptorImpl::Flush(std::unique_lock<std::mutex> lk) {
102127void ObjectDescriptorImpl::OnWrite (bool ok) {
103128 std::unique_lock<std::mutex> lk (mu_);
104129 if (!ok) return DoFinish (std::move (lk));
105- write_pending_ = false ;
130+ streams_. back (). write_pending = false ;
106131 Flush (std::move (lk));
107132}
108133
@@ -146,9 +171,11 @@ void ObjectDescriptorImpl::OnRead(
146171
147172void ObjectDescriptorImpl::CleanupDoneRanges (
148173 std::unique_lock<std::mutex> const &) {
149- for (auto i = active_ranges_.begin (); i != active_ranges_.end ();) {
174+ if (streams_.empty ()) return ;
175+ auto & active_ranges = streams_.back ().active_ranges ;
176+ for (auto i = active_ranges.begin (); i != active_ranges.end ();) {
150177 if (i->second ->IsDone ()) {
151- i = active_ranges_ .erase (i);
178+ i = active_ranges .erase (i);
152179 } else {
153180 ++i;
154181 }
@@ -185,12 +212,12 @@ void ObjectDescriptorImpl::Resume(google::rpc::Status const& proto_status) {
185212 ApplyRedirectErrors (read_object_spec_, proto_status);
186213 auto request = google::storage::v2::BidiReadObjectRequest{};
187214 *request.mutable_read_object_spec () = read_object_spec_;
188- for (auto const & kv : active_ranges_ ) {
215+ for (auto const & kv : streams_. back (). active_ranges ) {
189216 auto range = kv.second ->RangeForResume (kv.first );
190217 if (!range) continue ;
191218 *request.add_read_ranges () = *std::move (range);
192219 }
193- write_pending_ = true ;
220+ streams_. back (). write_pending = true ;
194221 lk.unlock ();
195222 make_stream_ (std::move (request)).then ([w = WeakFromThis ()](auto f) {
196223 if (auto self = w.lock ()) self->OnResume (f.get ());
@@ -200,7 +227,8 @@ void ObjectDescriptorImpl::Resume(google::rpc::Status const& proto_status) {
200227void ObjectDescriptorImpl::OnResume (StatusOr<OpenStreamResult> result) {
201228 if (!result) return OnFinish (std::move (result).status ());
202229 std::unique_lock<std::mutex> lk (mu_);
203- stream_ = std::move (result->stream );
230+ streams_.push_back (
231+ Stream{std::move (result->stream ), {}, resume_policy_prototype_->clone ()});
204232 // TODO(#15105) - this should be done without release the lock.
205233 Flush (std::move (lk));
206234 OnRead (std::move (result->first_response ));
@@ -211,7 +239,6 @@ bool ObjectDescriptorImpl::IsResumable(
211239 for (auto const & any : proto_status.details ()) {
212240 auto error = google::storage::v2::BidiReadObjectError{};
213241 if (!any.UnpackTo (&error)) continue ;
214- auto ranges = CopyActiveRanges ();
215242 for (auto const & range : CopyActiveRanges ()) {
216243 for (auto const & range_error : error.read_range_errors ()) {
217244 if (range.first != range_error.read_id ()) continue ;
@@ -221,8 +248,8 @@ bool ObjectDescriptorImpl::IsResumable(
221248 CleanupDoneRanges (std::unique_lock<std::mutex>(mu_));
222249 return true ;
223250 }
224-
225- return resume_policy_ ->OnFinish (status) ==
251+ std::unique_lock<std::mutex> lk (mu_);
252+ return streams_. back (). resume_policy ->OnFinish (status) ==
226253 storage_experimental::ResumePolicy::kContinue ;
227254}
228255
0 commit comments