Skip to content

Commit

Permalink
Force save implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
crsib committed Feb 20, 2024
1 parent fa6b6de commit 671b14f
Show file tree
Hide file tree
Showing 12 changed files with 67 additions and 59 deletions.
9 changes: 8 additions & 1 deletion libraries/lib-cloud-audiocom/sync/AsynchronousOperation.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ class TrackList;

namespace cloud::audiocom::sync
{
enum class UploadMode
{
Normal,
CreateNew,
ForceOverwrite,
};

struct ProjectUploadData final
{
std::vector<uint8_t> ProjectSnapshot;
Expand All @@ -30,7 +37,7 @@ class ProjectUploadOperation /* not final */
public:
virtual ~ProjectUploadOperation() = default;

virtual void Start(const ProjectUploadData& data) = 0;
virtual void Start(UploadMode mode, const ProjectUploadData& data) = 0;
virtual void Cancel() = 0;
virtual bool IsCompleted() const = 0;
}; // class AsynchronousOperation
Expand Down
2 changes: 2 additions & 0 deletions libraries/lib-cloud-audiocom/sync/CloudSyncUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,8 @@ std::string Serialize(const ProjectForm& form)

document.AddMember("blocks", hashesArray, document.GetAllocator());

document.AddMember("force", form.Force, document.GetAllocator());

StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
document.Accept(writer);
Expand Down
1 change: 1 addition & 0 deletions libraries/lib-cloud-audiocom/sync/CloudSyncUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct ProjectForm final
std::string Name;
std::string HeadSnapshotId;
SampleBlockHashes Hashes;
bool Force {};
};


Expand Down
14 changes: 8 additions & 6 deletions libraries/lib-cloud-audiocom/sync/LocalProjectSnapshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,11 @@ struct LocalProjectSnapshot::ProjectBlocksLock final : private BlockHashCache

LocalProjectSnapshot::LocalProjectSnapshot(
Tag, const ServiceConfig& config, const OAuthService& oauthService,
ProjectCloudExtension& extension, bool forceCreateNewProject)
ProjectCloudExtension& extension)
: mProjectCloudExtension { extension }
, mWeakProject { extension.GetProject() }
, mServiceConfig { config }
, mOAuthService { oauthService }
, mForceCreateNewProject { forceCreateNewProject }
{
}

Expand All @@ -220,15 +219,15 @@ LocalProjectSnapshot::~LocalProjectSnapshot()

std::shared_ptr<LocalProjectSnapshot> LocalProjectSnapshot::Create(
const ServiceConfig& config, const OAuthService& oauthService,
ProjectCloudExtension& extension, bool forceCreateNewProject)
ProjectCloudExtension& extension)
{
auto project = extension.GetProject().lock();

if (!project)
return {};

auto snapshot = std::make_shared<LocalProjectSnapshot>(
Tag {}, config, oauthService, extension, forceCreateNewProject);
Tag {}, config, oauthService, extension);

snapshot->mProjectBlocksLock = std::make_unique<ProjectBlocksLock>(
extension, *project,
Expand Down Expand Up @@ -262,9 +261,10 @@ std::shared_ptr<AudacityProject> LocalProjectSnapshot::GetProject()
return mWeakProject.lock();
}

void LocalProjectSnapshot::Start(const ProjectUploadData& data)
void LocalProjectSnapshot::Start(UploadMode mode, const ProjectUploadData& data)
{
mProjectData = data;
mUploadMode = mode;
UpdateProjectSnapshot();
}

Expand Down Expand Up @@ -382,7 +382,7 @@ void LocalProjectSnapshot::UpdateProjectSnapshot()
}

const bool isCloudProject = mProjectCloudExtension.IsCloudProject();
const bool createNew = mForceCreateNewProject || !isCloudProject;
const bool createNew = mUploadMode == UploadMode::CreateNew || !isCloudProject;

ProjectForm projectForm;

Expand All @@ -403,6 +403,8 @@ void LocalProjectSnapshot::UpdateProjectSnapshot()
mServiceConfig.GetCreateSnapshotUrl(
mProjectCloudExtension.GetCloudProjectId());

projectForm.Force = !createNew && mUploadMode == UploadMode::ForceOverwrite;

auto request = Request(url);

request.setHeader(
Expand Down
9 changes: 5 additions & 4 deletions libraries/lib-cloud-audiocom/sync/LocalProjectSnapshot.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,18 @@ class CLOUD_AUDIOCOM_API LocalProjectSnapshot final :
public:
LocalProjectSnapshot(
Tag, const ServiceConfig& config, const OAuthService& oauthService,
ProjectCloudExtension& extension, bool forceCreateNewSnapshot);
ProjectCloudExtension& extension);
~LocalProjectSnapshot();

static std::shared_ptr<LocalProjectSnapshot> Create(
const ServiceConfig& config, const OAuthService& oauthService,
ProjectCloudExtension& extension, bool forceCreateNewProject = false);
ProjectCloudExtension& extension);

bool IsCompleted() const override;

std::shared_ptr<AudacityProject> GetProject();

void Start(const ProjectUploadData& projectData) override;
void Start(UploadMode mode, const ProjectUploadData& projectData) override;
void Cancel() override;

using OnSnapshotCreatedCallback = std::function<void(const std::optional<CreateSnapshotResponse>&)>;
Expand Down Expand Up @@ -102,8 +102,9 @@ class CLOUD_AUDIOCOM_API LocalProjectSnapshot final :
std::mutex mOnSnapshotCreatedCallbacksMutex;
std::vector<OnSnapshotCreatedCallback> mOnSnapshotCreatedCallbacks;

UploadMode mUploadMode { UploadMode::Normal };

std::atomic<bool> mCompleted { false };

const bool mForceCreateNewProject;
};
} // namespace cloud::audiocom::sync
24 changes: 12 additions & 12 deletions libraries/lib-cloud-audiocom/sync/ProjectCloudExtension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,13 @@ void ProjectCloudExtension::OnBlocksHashed(
// It is safe to start the upload right away
if (operation.get() == element)
{
uploadOperation.Start(element->Data);
auto mode = UploadMode::Normal;
{
auto lock = std::lock_guard { mIdentifiersMutex };
std::swap(mode, mNextUploadMode);
}

uploadOperation.Start(mode, element->Data);
return;
}
// There is a pending operation, wait for it to finish
Expand Down Expand Up @@ -205,8 +211,6 @@ void ProjectCloudExtension::OnSnapshotCreated(

mProjectId = response.Project.Id;
mSnapshotId = response.Snapshot.Id;

mProjectDetached = false;
}

auto lock = std::lock_guard { mUploadQueueMutex };
Expand All @@ -226,7 +230,9 @@ void ProjectCloudExtension::OnSnapshotCreated(
if (!operation->ReadyForUpload)
return;

operation->Operation->Start(operation->Data);
// All saves queued during the upload should act as if they were
// just project updates
operation->Operation->Start(UploadMode::Normal, operation->Data);
}

UnsafeUpdateProgress();
Expand Down Expand Up @@ -600,17 +606,11 @@ bool ProjectCloudExtension::IsPendingCloudSave() const
return mPendingCloudSave;
}

void ProjectCloudExtension::MarkProjectDetached()
void ProjectCloudExtension::SetUploadModeForNextSave(UploadMode mode)
{
auto lock = std::lock_guard { mIdentifiersMutex };

mProjectDetached = true;
}

bool ProjectCloudExtension::IsProjectDetached() const
{
auto lock = std::lock_guard { mIdentifiersMutex };
return mProjectDetached;
mNextUploadMode = mode;
}

bool CloudStatusChangedMessage::IsSyncing() const noexcept
Expand Down
31 changes: 17 additions & 14 deletions libraries/lib-cloud-audiocom/sync/ProjectCloudExtension.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#include <unordered_map>
#include <vector>

#include "ClientData.h"
#include "Observer.h"

#include "AsynchronousOperation.h"
#include "CloudSyncError.h"
#include "CloudSyncUtils.h"

Expand Down Expand Up @@ -52,8 +53,7 @@ struct CLOUD_AUDIOCOM_API CloudStatusChangedMessage final
bool IsSyncing() const noexcept;
};

class CLOUD_AUDIOCOM_API ProjectCloudExtension final :
public ClientData::Base
class CLOUD_AUDIOCOM_API ProjectCloudExtension final : public ClientData::Base
{
public:
explicit ProjectCloudExtension(AudacityProject& project);
Expand All @@ -69,12 +69,14 @@ class CLOUD_AUDIOCOM_API ProjectCloudExtension final :
//! This method is called from the UI thread
void OnSyncStarted();
//! This method is called from the UI thread
void OnUploadOperationCreated(std::shared_ptr<ProjectUploadOperation> uploadOperation);
void OnUploadOperationCreated(
std::shared_ptr<ProjectUploadOperation> uploadOperation);
//! This method is called not from the UI thread
void OnBlocksHashed(ProjectUploadOperation& uploadOperation);
//! This method is called from the network thread
void OnSnapshotCreated(const ProjectUploadOperation& uploadOperation, const
CreateSnapshotResponse& response);
void OnSnapshotCreated(
const ProjectUploadOperation& uploadOperation,
const CreateSnapshotResponse& response);
//! This method is called from the network thread
void OnProjectDataUploaded(const ProjectUploadOperation& uploadOperation);
//! This method is called from the network thread
Expand All @@ -83,8 +85,8 @@ class CLOUD_AUDIOCOM_API ProjectCloudExtension final :
bool successful);
//! This method is called from any thread
void OnSyncCompleted(
const ProjectUploadOperation* uploadOperation, std::optional<CloudSyncError>
error);
const ProjectUploadOperation* uploadOperation,
std::optional<CloudSyncError> error);

void CancelSync();

Expand All @@ -109,13 +111,13 @@ class CLOUD_AUDIOCOM_API ProjectCloudExtension final :
int64_t GetSavesCountSinceMixdown() const;

Observer::Subscription SubscribeStatusChanged(
std::function<void(const CloudStatusChangedMessage&)> callback, bool onUIThread);
std::function<void(const CloudStatusChangedMessage&)> callback,
bool onUIThread);

void MarkPendingCloudSave();
bool IsPendingCloudSave() const;

void MarkProjectDetached();
bool IsProjectDetached() const;
void SetUploadModeForNextSave(UploadMode mode);

private:
struct UploadQueueElement;
Expand All @@ -128,8 +130,8 @@ class CLOUD_AUDIOCOM_API ProjectCloudExtension final :

void MarkProjectSynced(bool success);

UploadQueueElement* UnsafeFindUploadQueueElement(
const ProjectUploadOperation& uploadOperation);
UploadQueueElement*
UnsafeFindUploadQueueElement(const ProjectUploadOperation& uploadOperation);
const UploadQueueElement* UnsafeFindUploadQueueElement(
const ProjectUploadOperation& uploadOperation) const;

Expand All @@ -149,9 +151,10 @@ class CLOUD_AUDIOCOM_API ProjectCloudExtension final :
std::unique_ptr<CloudStatusChangedNotifier> mUIStateNotifier;
std::atomic<bool> mUINotificationPending { false };

UploadMode mNextUploadMode { UploadMode::Normal };

bool mSuppressAutoDownload { false };
bool mPendingCloudSave { false };
bool mNeedsMixdownSync { false };
bool mProjectDetached { false };
};
} // namespace cloud::audiocom::sync
3 changes: 1 addition & 2 deletions modules/mod-cloud-audiocom/CloudProjectFileIOExtensions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,7 @@ class IOExtension final : public ProjectFileIOExtension
return;

auto snapshot = LocalProjectSnapshot::Create(
GetServiceConfig(), GetOAuthService(), projectCloudExtension,
projectCloudExtension.IsProjectDetached());
GetServiceConfig(), GetOAuthService(), projectCloudExtension);

if (snapshot != nullptr)
// This operation is blocking, but that is expected
Expand Down
6 changes: 2 additions & 4 deletions modules/mod-cloud-audiocom/CloudProjectUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ bool SyncCloudProject(
return true;
}

void SaveToCloud(AudacityProject& project, SaveMode mode)
void SaveToCloud(AudacityProject& project, UploadMode mode)
{
ASSERT_MAIN_THREAD();

Expand All @@ -237,9 +237,7 @@ void SaveToCloud(AudacityProject& project, SaveMode mode)
if (!projectCloudExtension.IsCloudProject())
projectCloudExtension.MarkPendingCloudSave();

if (mode == SaveMode::SaveNew)
projectCloudExtension.MarkProjectDetached();

projectCloudExtension.SetUploadModeForNextSave(mode);
ProjectFileManager::Get(project).Save();
}

Expand Down
11 changes: 3 additions & 8 deletions modules/mod-cloud-audiocom/CloudProjectUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include <string_view>
#include <memory>

#include "sync/AsynchronousOperation.h"

class AudacityProject;

namespace cloud::audiocom::sync
Expand All @@ -26,14 +28,7 @@ void OpenProjectFromCloud(
bool SyncCloudProject(
AudacityProject& project, std::string_view path, bool force = false);

enum class SaveMode
{
Normal,
SaveNew,
ForceSave
};

void SaveToCloud(AudacityProject& project, SaveMode mode);
void SaveToCloud(AudacityProject& project, UploadMode mode);

bool HandleProjectLink(std::string_view link);

Expand Down
4 changes: 2 additions & 2 deletions modules/mod-cloud-audiocom/menus/Menus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ using namespace cloud::audiocom::sync;

void OnSaveToCloud(const CommandContext& context)
{
SaveToCloud(context.project, SaveMode::Normal);
SaveToCloud(context.project, UploadMode::Normal);
}

void OnOpenFromCloud(const CommandContext& context)
Expand All @@ -38,7 +38,7 @@ void OnOpenFromCloud(const CommandContext& context)
void OnUpdateMixdown(const CommandContext& context)
{
ProjectCloudExtension::Get(context.project).MarkNeedsMixdownSync();
SaveToCloud(context.project, SaveMode::Normal);
SaveToCloud(context.project, UploadMode::Normal);
}
const ReservedCommandFlag& IsCloudProjectFlag()
{
Expand Down
Loading

0 comments on commit 671b14f

Please sign in to comment.