blob: 93cb011cb0fb72aa0a97e4e2a6546ad377bb474b [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PERIDOT_BIN_LEDGER_CLOUD_SYNC_IMPL_BATCH_UPLOAD_H_
#define PERIDOT_BIN_LEDGER_CLOUD_SYNC_IMPL_BATCH_UPLOAD_H_
#include <functional>
#include <memory>
#include <vector>
#include <fuchsia/ledger/cloud/cpp/fidl.h>
#include <lib/fit/function.h>
#include <lib/fxl/macros.h>
#include <lib/fxl/memory/weak_ptr.h>
#include "peridot/bin/ledger/encryption/public/encryption_service.h"
#include "peridot/bin/ledger/fidl/include/types.h"
#include "peridot/bin/ledger/storage/public/commit.h"
#include "peridot/bin/ledger/storage/public/page_storage.h"
namespace cloud_sync {
// Uploads a batch of commits along with unsynced storage objects and marks
// the uploaded artifacts as synced.
//
// Contract: The class doesn't reason about objects referenced by each commit,
// and instead uploads each unsynced object present in storage at the moment of
// calling Start(). Unsynced objects are marked as synced as they are uploaded.
// The commits in the batch are uploaded in one network request once all objects
// are uploaded.
//
// Usage: call Start() to kick off the upload. |on_done| is called after the
// upload is successfully completed. |on_error| will be called at most once
// after each error. Each time after |on_error| is called the client can
// call Retry() once to retry the upload.
// TODO(ppi): rather than DCHECK on storage errors, take separate callbacks for
// network and disk errors and let PageSync decide on how to handle each.
//
// Lifetime: if BatchUpload is deleted between Start() and |on_done| being
// called, it has to be deleted along with |storage| and |cloud_provider|, which
// otherwise can retain callbacks for pending uploads. This isn't a problem as
// long as the lifetime of page storage and page sync is managed together.
class BatchUpload {
public:
// In case of error in BatchUpload, ErrorType defines whether the error that
// occurred is temporary (from cloud or auth provider), or permanent (from
// storage or from encryption).
enum class ErrorType {
PERMANENT,
TEMPORARY,
};
BatchUpload(storage::PageStorage* storage,
encryption::EncryptionService* encryption_service,
cloud_provider::PageCloudPtr* page_cloud,
std::vector<std::unique_ptr<const storage::Commit>> commits,
fit::closure on_done, fit::function<void(ErrorType)> on_error,
unsigned int max_concurrent_uploads = 10);
~BatchUpload();
// Starts a new upload attempt. Results are reported through |on_done|
// and |on_error| passed in the constructor. Can be called only once.
void Start();
// Retries the attempt to upload the commit batch. Each time after |on_error|
// is called, the client can retry by calling this method.
void Retry();
private:
void StartObjectUpload();
void UploadNextObject();
// Retrieves the content of the given object and uploads it.
void GetObjectContentAndUpload(storage::ObjectIdentifier object_identifier,
std::string object_name);
// Uploads the given object.
void UploadObject(storage::ObjectIdentifier object_identifier,
std::string object_name,
std::unique_ptr<const storage::Object> object);
// Uploads the given object.
void UploadEncryptedObject(storage::ObjectIdentifier object_identifier,
std::string object_name, std::string content);
// Filters already synced commits.
void FilterAndUploadCommits();
// Uploads the commits.
void UploadCommits();
// Notifies an error when trying to upload the given object.
void EnqueueForRetryAndSignalError(
storage::ObjectIdentifier object_identifier);
storage::PageStorage* const storage_;
encryption::EncryptionService* const encryption_service_;
cloud_provider::PageCloudPtr* const page_cloud_;
std::vector<std::unique_ptr<const storage::Commit>> commits_;
fit::closure on_done_;
fit::function<void(ErrorType)> on_error_;
const unsigned int max_concurrent_uploads_;
// All remaining object ids to be uploaded along with this batch of commits.
std::vector<storage::ObjectIdentifier> remaining_object_identifiers_;
// Number of object uploads currently in progress.
unsigned int current_uploads_ = 0u;
// Number of object being handled, including those being uploaded and those
// whose metadata are being updated in storage.
unsigned int current_objects_handled_ = 0u;
bool started_ = false;
bool errored_ = false;
// If an error has occurred while handling the objects, |error_types_|
// stores the type of error.
ErrorType error_type_ = ErrorType::TEMPORARY;
// Must be the last member.
fxl::WeakPtrFactory<BatchUpload> weak_ptr_factory_;
FXL_DISALLOW_COPY_AND_ASSIGN(BatchUpload);
};
} // namespace cloud_sync
#endif // PERIDOT_BIN_LEDGER_CLOUD_SYNC_IMPL_BATCH_UPLOAD_H_