summaryrefslogtreecommitdiffstats
path: root/document
diff options
context:
space:
mode:
authorTor Egge <Tor.Egge@broadpark.no>2018-04-03 21:39:23 +0200
committerTor Egge <Tor.Egge@oath.com>2018-04-04 08:35:03 +0000
commit9cb58e26bc840decdbd577e80df42f9c2188c459 (patch)
tree8aa8be088d05f1ac2eaa048f72786fcee57337a7 /document
parent99c4a2573660d7bbb0fea00444a8177f2c8acd43 (diff)
Add DocumentTypeRepoFactory. If config is equal to config for existing repo
then that repo is returned.
Diffstat (limited to 'document')
-rw-r--r--document/CMakeLists.txt1
-rw-r--r--document/src/tests/document_type_repo_factory/CMakeLists.txt10
-rw-r--r--document/src/tests/document_type_repo_factory/document_type_repo_factory_test.cpp52
-rw-r--r--document/src/vespa/document/repo/CMakeLists.txt1
-rw-r--r--document/src/vespa/document/repo/document_type_repo_factory.cpp52
-rw-r--r--document/src/vespa/document/repo/document_type_repo_factory.h45
6 files changed, 161 insertions, 0 deletions
diff --git a/document/CMakeLists.txt b/document/CMakeLists.txt
index fd347ca492d..7de1b0c0b89 100644
--- a/document/CMakeLists.txt
+++ b/document/CMakeLists.txt
@@ -34,6 +34,7 @@ vespa_define_module(
src/tests/annotation
src/tests/base
src/tests/datatype
+ src/tests/document_type_repo_factory
src/tests/fieldvalue
src/tests/predicate
src/tests/repo
diff --git a/document/src/tests/document_type_repo_factory/CMakeLists.txt b/document/src/tests/document_type_repo_factory/CMakeLists.txt
new file mode 100644
index 00000000000..c872559c3b5
--- /dev/null
+++ b/document/src/tests/document_type_repo_factory/CMakeLists.txt
@@ -0,0 +1,10 @@
+# Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+vespa_add_executable(document_document_type_repo_factory_test_app TEST
+ SOURCES
+ document_type_repo_factory_test.cpp
+ DEPENDS
+ document
+ AFTER
+ document_documentconfig
+)
+vespa_add_test(NAME document_document_type_repo_factory_test_app COMMAND document_document_type_repo_factory_test_app)
diff --git a/document/src/tests/document_type_repo_factory/document_type_repo_factory_test.cpp b/document/src/tests/document_type_repo_factory/document_type_repo_factory_test.cpp
new file mode 100644
index 00000000000..a6b6044023e
--- /dev/null
+++ b/document/src/tests/document_type_repo_factory/document_type_repo_factory_test.cpp
@@ -0,0 +1,52 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include <vespa/document/datatype/documenttype.h>
+#include <vespa/document/repo/configbuilder.h>
+#include <vespa/document/repo/documenttyperepo.h>
+#include <vespa/document/repo/document_type_repo_factory.h>
+#include <vespa/vespalib/stllike/string.h>
+#include <vespa/vespalib/testkit/testapp.h>
+
+using vespalib::string;
+using namespace document::config_builder;
+using namespace document;
+
+namespace {
+
+const string type_name = "test";
+const int32_t doc_type_id = 787121340;
+const string header_name = type_name + ".header";
+const string body_name = type_name + ".body";
+
+std::shared_ptr<const DocumenttypesConfig>
+makeDocumentTypesConfig(const string &field_name)
+{
+ document::config_builder::DocumenttypesConfigBuilderHelper builder;
+ builder.document(doc_type_id, type_name,
+ Struct(header_name),
+ Struct(body_name).addField(field_name,
+ DataType::T_STRING));
+ return std::make_shared<const DocumenttypesConfig>(builder.config());
+}
+
+TEST("requireThatEqualConfigsGivesSameRepo")
+{
+ auto config1 = makeDocumentTypesConfig("a");
+ auto config2 = makeDocumentTypesConfig("b");
+ auto config3 = std::make_shared<const DocumenttypesConfig>(*config1);
+ auto config4 = std::make_shared<const DocumenttypesConfig>(*config2);
+ auto repo1 = DocumentTypeRepoFactory::make(*config1);
+ auto repo2 = DocumentTypeRepoFactory::make(*config2);
+ auto repo3 = DocumentTypeRepoFactory::make(*config3);
+ auto repo4 = DocumentTypeRepoFactory::make(*config4);
+ EXPECT_NOT_EQUAL(repo1, repo2);
+ EXPECT_EQUAL(repo1, repo3);
+ EXPECT_NOT_EQUAL(repo1, repo4);
+ EXPECT_NOT_EQUAL(repo2, repo3);
+ EXPECT_EQUAL(repo2, repo4);
+ EXPECT_NOT_EQUAL(repo3, repo4);
+}
+
+}
+
+TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/document/src/vespa/document/repo/CMakeLists.txt b/document/src/vespa/document/repo/CMakeLists.txt
index b5042ebd4b6..48265ca15b2 100644
--- a/document/src/vespa/document/repo/CMakeLists.txt
+++ b/document/src/vespa/document/repo/CMakeLists.txt
@@ -3,6 +3,7 @@ vespa_add_library(document_repo OBJECT
SOURCES
configbuilder.cpp
documenttyperepo.cpp
+ document_type_repo_factory.cpp
fixedtyperepo.cpp
DEPENDS
AFTER
diff --git a/document/src/vespa/document/repo/document_type_repo_factory.cpp b/document/src/vespa/document/repo/document_type_repo_factory.cpp
new file mode 100644
index 00000000000..61a515f5566
--- /dev/null
+++ b/document/src/vespa/document/repo/document_type_repo_factory.cpp
@@ -0,0 +1,52 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "document_type_repo_factory.h"
+#include "documenttyperepo.h"
+#include <vespa/document/config/config-documenttypes.h>
+#include <functional>
+
+namespace document {
+
+std::mutex DocumentTypeRepoFactory::_mutex;
+DocumentTypeRepoFactory::DocumentTypeRepoMap DocumentTypeRepoFactory::_repos;
+
+/*
+ * Class handling deletion of document type repo after last reference is gone.
+ */
+class DocumentTypeRepoFactory::Deleter
+{
+public:
+ void operator()(DocumentTypeRepo *repoRawPtr) const noexcept {
+ deleteRepo(repoRawPtr);
+ }
+};
+
+void
+DocumentTypeRepoFactory::deleteRepo(DocumentTypeRepo *repoRawPtr) noexcept
+{
+ std::unique_ptr<const DocumentTypeRepo> repo(repoRawPtr);
+ std::lock_guard guard(_mutex);
+ _repos.erase(repo.get());
+}
+
+std::shared_ptr<const DocumentTypeRepo>
+DocumentTypeRepoFactory::make(const DocumenttypesConfig &config)
+{
+ std::lock_guard guard(_mutex);
+ // Return existing instance if config matches
+ for (const auto &entry : _repos) {
+ const auto repo = entry.second.repo.lock();
+ const auto &repoConfig = *entry.second.config;
+ if (repo && repoConfig == config) {
+ return repo;
+ }
+ }
+ auto repoConfig = std::make_unique<const DocumenttypesConfig>(config);
+ auto repoup1 = std::make_unique<DocumentTypeRepo>(*repoConfig);
+ auto repoup2 = std::unique_ptr<DocumentTypeRepo, Deleter>(repoup1.release(), Deleter());
+ auto repo = std::shared_ptr<const DocumentTypeRepo>(std::move(repoup2));
+ _repos.emplace(repo.get(), DocumentTypeRepoEntry(repo, std::move(repoConfig)));
+ return repo;
+}
+
+}
diff --git a/document/src/vespa/document/repo/document_type_repo_factory.h b/document/src/vespa/document/repo/document_type_repo_factory.h
new file mode 100644
index 00000000000..0c8eecb035d
--- /dev/null
+++ b/document/src/vespa/document/repo/document_type_repo_factory.h
@@ -0,0 +1,45 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#pragma once
+
+#include <memory>
+#include <mutex>
+#include <map>
+
+namespace document {
+
+namespace internal {
+ class InternalDocumenttypesType;
+}
+
+class DocumentTypeRepo;
+
+/*
+ * Factory class for document type repos. Same instance is returned
+ * for equal config.
+ */
+class DocumentTypeRepoFactory {
+ using DocumenttypesConfig = const internal::InternalDocumenttypesType;
+ struct DocumentTypeRepoEntry {
+ std::weak_ptr<const DocumentTypeRepo> repo;
+ std::unique_ptr<const DocumenttypesConfig> config;
+
+ DocumentTypeRepoEntry(std::weak_ptr<const DocumentTypeRepo> repo_in,
+ std::unique_ptr<const DocumenttypesConfig> config_in)
+ : repo(std::move(repo_in)),
+ config(std::move(config_in))
+ {
+ }
+ };
+ using DocumentTypeRepoMap = std::map<const void *, DocumentTypeRepoEntry>;
+ class Deleter;
+
+ static std::mutex _mutex;
+ static DocumentTypeRepoMap _repos;
+
+ static void deleteRepo(DocumentTypeRepo *repoRawPtr) noexcept;
+public:
+ static std::shared_ptr<const DocumentTypeRepo> make(const DocumenttypesConfig &config);
+};
+
+}