blob: 656e888dab0152ec448cc0263a2c829e4d817c38 [file] [log] [blame]
// Copyright 2018 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.
#include "src/modular/bin/sessionmgr/storage/session_storage.h"
#include <lib/fidl/cpp/clone.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>
#include <unordered_set>
#include "src/modular/bin/sessionmgr/annotations.h"
#include "src/modular/lib/fidl/clone.h"
namespace modular {
SessionStorage::SessionStorage() {}
std::string SessionStorage::CreateStory(std::string story_name,
std::vector<fuchsia::modular::Annotation> annotations) {
// Check if the story already exists. If it does, this whole function should
// behave as a noop.
auto it = story_data_backing_store_.find(story_name);
if (it == story_data_backing_store_.end()) {
fuchsia::modular::internal::StoryData story_data({});
story_data.set_story_name(story_name);
story_data.mutable_story_info()->set_id(story_name);
story_data.mutable_story_info()->set_last_focus_time(0);
story_data.mutable_story_info()->set_annotations(std::move(annotations));
fidl::StringPtr story_name_for_callback = story_name;
fuchsia::modular::internal::StoryData callback_data;
story_data.Clone(&callback_data);
story_data_backing_store_[story_name] = std::move(story_data);
if (on_story_updated_) {
on_story_updated_(std::move(story_name_for_callback), std::move(callback_data));
}
}
return story_name;
}
void SessionStorage::DeleteStory(fidl::StringPtr story_name) {
auto it = story_data_backing_store_.find(story_name);
if (it == story_data_backing_store_.end()) {
return;
}
story_data_backing_store_.erase(it);
story_storage_backing_store_.erase(story_name);
if (on_story_deleted_) {
on_story_deleted_(story_name);
}
return;
}
void SessionStorage::UpdateLastFocusedTimestamp(fidl::StringPtr story_name,
const int64_t ts) {
auto it = story_data_backing_store_.find(story_name);
FX_DCHECK(it != story_data_backing_store_.end())
<< "SessionStorage::UpdateLastFocusedTimestamp was called on story " << story_name
<< " before it was created!";
auto& story_data = it->second;
if (story_data.story_info().last_focus_time() != ts) {
story_data.mutable_story_info()->set_last_focus_time(ts);
if (on_story_updated_) {
on_story_updated_(std::move(story_name), std::move(story_data));
}
}
}
fuchsia::modular::internal::StoryDataPtr SessionStorage::GetStoryData(
fidl::StringPtr story_name) {
fuchsia::modular::internal::StoryDataPtr value{};
auto it = story_data_backing_store_.find(story_name);
if (it != story_data_backing_store_.end()) {
value = fuchsia::modular::internal::StoryData::New();
it->second.Clone(value.get());
}
return value;
}
// Returns a Future vector of StoryData for all stories in this session.
std::vector<fuchsia::modular::internal::StoryData> SessionStorage::GetAllStoryData() {
std::vector<fuchsia::modular::internal::StoryData> vec{};
for (auto it = story_data_backing_store_.begin(); it != story_data_backing_store_.end(); ++it) {
fuchsia::modular::internal::StoryData val;
it->second.Clone(&val);
vec.push_back(std::move(val));
}
return vec;
}
void SessionStorage::UpdateStoryAnnotations(fidl::StringPtr story_name,
std::vector<fuchsia::modular::Annotation> annotations) {
auto it = story_data_backing_store_.find(story_name);
if (it != story_data_backing_store_.end()) {
fuchsia::modular::internal::StoryData& val = it->second;
val.mutable_story_info()->set_annotations(std::move(annotations));
fuchsia::modular::internal::StoryData val_copy;
val.Clone(&val_copy);
if (on_story_updated_) {
on_story_updated_(std::move(story_name), std::move(val_copy));
}
}
}
std::optional<fuchsia::modular::AnnotationError> SessionStorage::MergeStoryAnnotations(
fidl::StringPtr story_name, std::vector<fuchsia::modular::Annotation> annotations) {
// On success, this optional AnnotationError response will have no value (!has_value()).
// Otherwise, the error will be set explicitly, or it is assumed the story is no longer viable
// (default NOT_FOUND).
std::optional<fuchsia::modular::AnnotationError> error = std::nullopt;
// Get story data for this story, if it exists. If not, then return
// NOT_FOUND.
auto it = story_data_backing_store_.find(story_name);
if (it == story_data_backing_store_.end()) {
// If the story doesn't exist, it was deleted.
error = fuchsia::modular::AnnotationError::NOT_FOUND;
} else {
auto& story_data = it->second;
// Merge annotations.
auto new_annotations =
story_data.story_info().has_annotations()
? annotations::Merge(std::move(*story_data.mutable_story_info()->mutable_annotations()),
std::move(annotations))
: std::move(annotations);
// Mutate story in-place.
if (new_annotations.size() > fuchsia::modular::MAX_ANNOTATIONS_PER_STORY) {
error = fuchsia::modular::AnnotationError::TOO_MANY_ANNOTATIONS;
} else {
story_data.mutable_story_info()->set_annotations(std::move(new_annotations));
}
// No need to write story data back to map because we modified it in place.
}
return error;
}
std::shared_ptr<StoryStorage> SessionStorage::GetStoryStorage(fidl::StringPtr story_name) {
std::shared_ptr<StoryStorage> value(nullptr);
auto data_it = story_data_backing_store_.find(story_name);
if (data_it != story_data_backing_store_.end()) {
auto it = story_storage_backing_store_.find(story_name);
if (it == story_storage_backing_store_.end()) {
// If no refcounted StoryStorage exists for this story yet, create and insert one.
story_storage_backing_store_[story_name] = std::make_shared<StoryStorage>();
}
value = story_storage_backing_store_[story_name];
}
return value;
}
} // namespace modular