aboutsummaryrefslogtreecommitdiff
path: root/icing/store
diff options
context:
space:
mode:
authorTim Barron <tjbarron@google.com>2020-03-20 20:54:58 +0000
committerTim Barron <tjbarron@google.com>2020-03-23 17:56:12 +0000
commit11e1bec607a0b702d0c851d36f9a1985cdccd764 (patch)
tree9aa5e94ff2c3e85e1b85133f5ddb9d60e33fbf96 /icing/store
parentec12927cf000c9b3a8d103e2dfaf847429c52c21 (diff)
downloadicing-11e1bec607a0b702d0c851d36f9a1985cdccd764.tar.gz
Copy over changes made to Google3 codebase in Icing.
Change-Id: Ic4e7a964ced111738cca80e078b3e03759c19ccf
Diffstat (limited to 'icing/store')
-rw-r--r--icing/store/document-store.cc87
-rw-r--r--icing/store/document-store.h17
-rw-r--r--icing/store/document-store_test.cc74
3 files changed, 128 insertions, 50 deletions
diff --git a/icing/store/document-store.cc b/icing/store/document-store.cc
index f5b94d0..ce6f61c 100644
--- a/icing/store/document-store.cc
+++ b/icing/store/document-store.cc
@@ -817,11 +817,7 @@ libtextclassifier3::Status DocumentStore::Delete(
const std::string_view name_space, const std::string_view uri) {
// Try to get the DocumentId first
auto document_id_or = GetDocumentId(name_space, uri);
- if (absl_ports::IsNotFound(document_id_or.status())) {
- // No need to delete nonexistent (name_space, uri)
- return libtextclassifier3::Status::OK;
- } else if (!document_id_or.ok()) {
- // Real error
+ if (!document_id_or.ok()) {
return absl_ports::Annotate(
document_id_or.status(),
absl_ports::StrCat("Failed to delete Document. namespace: ", name_space,
@@ -831,15 +827,11 @@ libtextclassifier3::Status DocumentStore::Delete(
// Check if the DocumentId's Document still exists.
DocumentId document_id = document_id_or.ValueOrDie();
auto file_offset_or = DoesDocumentExistAndGetFileOffset(document_id);
- if (absl_ports::IsNotFound(file_offset_or.status())) {
- // No need to delete nonexistent documents
- return libtextclassifier3::Status::OK;
- } else if (!file_offset_or.ok()) {
- // Real error, pass it up
+ if (!file_offset_or.ok()) {
return absl_ports::Annotate(
file_offset_or.status(),
- IcingStringUtil::StringPrintf(
- "Failed to retrieve file offset for DocumentId %d", document_id));
+ absl_ports::StrCat("Failed to delete Document. namespace: ", name_space,
+ ", uri: ", uri));
}
// Update ground truth first.
@@ -852,10 +844,9 @@ libtextclassifier3::Status DocumentStore::Delete(
document_log_->WriteProto(CreateDocumentTombstone(name_space, uri))
.status();
if (!status.ok()) {
- ICING_LOG(ERROR) << status.error_message()
- << "Failed to delete Document. namespace: " << name_space
- << ", uri: " << uri;
- return status;
+ return absl_ports::Annotate(
+ status, absl_ports::StrCat("Failed to delete Document. namespace: ",
+ name_space, ", uri: ", uri));
}
ICING_RETURN_IF_ERROR(
@@ -894,12 +885,11 @@ DocumentStore::GetDocumentFilterData(DocumentId document_id) const {
libtextclassifier3::Status DocumentStore::DeleteByNamespace(
std::string_view name_space) {
auto namespace_id_or = namespace_mapper_->Get(name_space);
- if (absl_ports::IsNotFound(namespace_id_or.status())) {
- // Namespace doesn't exist. Don't need to delete anything.
- return libtextclassifier3::Status::OK;
- } else if (!namespace_id_or.ok()) {
- // Real error, pass it up.
- return namespace_id_or.status();
+ if (!namespace_id_or.ok()) {
+ return absl_ports::Annotate(
+ namespace_id_or.status(),
+ absl_ports::StrCat("Failed to delete by namespace. namespace: ",
+ name_space));
}
// Update ground truth first.
@@ -916,23 +906,31 @@ libtextclassifier3::Status DocumentStore::DeleteByNamespace(
return status;
}
- return UpdateDerivedFilesNamespaceDeleted(name_space);
+ ICING_ASSIGN_OR_RETURN(bool updated_existing_document,
+ UpdateDerivedFilesNamespaceDeleted(name_space));
+ if (!updated_existing_document) {
+ // Treat the fact that no existing documents had this namespace to be the
+ // same as this namespace not existing at all.
+ return absl_ports::NotFoundError(
+ absl_ports::StrCat("Namespace '", name_space, "' doesn't exist"));
+ }
+ return libtextclassifier3::Status::OK;
}
-libtextclassifier3::Status DocumentStore::UpdateDerivedFilesNamespaceDeleted(
- std::string_view name_space) {
+libtextclassifier3::StatusOr<bool>
+DocumentStore::UpdateDerivedFilesNamespaceDeleted(std::string_view name_space) {
auto namespace_id_or = namespace_mapper_->Get(name_space);
- if (absl_ports::IsNotFound(namespace_id_or.status())) {
- // Namespace doesn't exist. Don't need to delete anything.
- return libtextclassifier3::Status::OK;
- } else if (!namespace_id_or.ok()) {
- // Real error, pass it up.
+ if (!namespace_id_or.ok()) {
return namespace_id_or.status();
}
// Guaranteed to have a NamespaceId now.
NamespaceId namespace_id = namespace_id_or.ValueOrDie();
+ // Tracks if there were any existing documents with this namespace that we
+ // will mark as deleted.
+ bool updated_existing_document = false;
+
// Traverse FilterCache and delete all docs that match namespace_id
for (DocumentId document_id = 0; document_id < filter_cache_->num_elements();
++document_id) {
@@ -941,6 +939,10 @@ libtextclassifier3::Status DocumentStore::UpdateDerivedFilesNamespaceDeleted(
ICING_ASSIGN_OR_RETURN(const DocumentFilterData* data,
filter_cache_->Get(document_id));
if (data->namespace_id() == namespace_id) {
+ if (DoesDocumentExist(document_id)) {
+ updated_existing_document = true;
+ }
+
// docid_mapper_->Set can only fail if document_id is < 0
// or >= docid_mapper_->num_elements. So the only possible way to get an
// error here would be if filter_cache_->num_elements >
@@ -950,18 +952,17 @@ libtextclassifier3::Status DocumentStore::UpdateDerivedFilesNamespaceDeleted(
}
}
- return libtextclassifier3::Status::OK;
+ return updated_existing_document;
}
libtextclassifier3::Status DocumentStore::DeleteBySchemaType(
std::string_view schema_type) {
auto schema_type_id_or = schema_store_->GetSchemaTypeId(schema_type);
- if (absl_ports::IsNotFound(schema_type_id_or.status())) {
- // SchemaType doesn't exist. Don't need to delete anything.
- return libtextclassifier3::Status::OK;
- } else if (!schema_type_id_or.ok()) {
- // Real error, pass it up.
- return schema_type_id_or.status();
+ if (!schema_type_id_or.ok()) {
+ return absl_ports::Annotate(
+ schema_type_id_or.status(),
+ absl_ports::StrCat("Failed to delete by schema type. schema_type: ",
+ schema_type));
}
// Update ground truth first.
@@ -1076,7 +1077,11 @@ libtextclassifier3::Status DocumentStore::UpdateSchemaStore(
} else {
// Document is no longer valid with the new SchemaStore. Mark as
// deleted
- ICING_RETURN_IF_ERROR(Delete(document.namespace_(), document.uri()));
+ auto delete_status = Delete(document.namespace_(), document.uri());
+ if (!delete_status.ok() && !absl_ports::IsNotFound(delete_status)) {
+ // Real error, pass up
+ return delete_status;
+ }
}
}
@@ -1167,7 +1172,11 @@ libtextclassifier3::Status DocumentStore::OptimizedUpdateSchemaStore(
if (!document_validator_.Validate(document).ok()) {
// Document is no longer valid with the new SchemaStore. Mark as
// deleted
- ICING_RETURN_IF_ERROR(Delete(document.namespace_(), document.uri()));
+ auto delete_status = Delete(document.namespace_(), document.uri());
+ if (!delete_status.ok() && !absl_ports::IsNotFound(delete_status)) {
+ // Real error, pass up
+ return delete_status;
+ }
}
}
}
diff --git a/icing/store/document-store.h b/icing/store/document-store.h
index 5bb167d..1fafd2a 100644
--- a/icing/store/document-store.h
+++ b/icing/store/document-store.h
@@ -94,6 +94,9 @@ class DocumentStore {
//
// Returns:
// A newly generated document id on success
+ // FAILED_PRECONDITION if schema hasn't been set yet
+ // NOT_FOUND if the schema_type or a property config of the document doesn't
+ // exist in schema
// INTERNAL_ERROR on IO error
libtextclassifier3::StatusOr<DocumentId> Put(const DocumentProto& document);
libtextclassifier3::StatusOr<DocumentId> Put(DocumentProto&& document);
@@ -118,8 +121,11 @@ class DocumentStore {
// INTERNAL_ERROR on IO error
libtextclassifier3::StatusOr<DocumentProto> Get(DocumentId document_id) const;
- // Returns true if there's an existing document associated with the given
- // document id.
+ // Check if a document exists. Existence means it hasn't been deleted and it
+ // hasn't expired yet.
+ //
+ // Returns:
+ // boolean whether a document exists or not
bool DoesDocumentExist(DocumentId document_id) const;
// Deletes the document identified by the given namespace and uri
@@ -129,6 +135,7 @@ class DocumentStore {
//
// Returns:
// OK on success
+ // NOT_FOUND if no document exists with namespace, uri
// INTERNAL_ERROR on IO error
libtextclassifier3::Status Delete(std::string_view name_space,
std::string_view uri);
@@ -178,6 +185,7 @@ class DocumentStore {
//
// Returns:
// OK on success
+ // NOT_FOUND if namespace doesn't exist
// INTERNAL_ERROR on IO error
libtextclassifier3::Status DeleteByNamespace(std::string_view name_space);
@@ -188,6 +196,7 @@ class DocumentStore {
//
// Returns:
// OK on success
+ // NOT_FOUND if schema_type doesn't exist
// INTERNAL_ERROR on IO error
libtextclassifier3::Status DeleteBySchemaType(std::string_view schema_type);
@@ -394,9 +403,9 @@ class DocumentStore {
// called.
//
// Returns:
- // OK on success
+ // bool on whether an existing document was actually updated to be deleted
// INTERNAL_ERROR on IO error
- libtextclassifier3::Status UpdateDerivedFilesNamespaceDeleted(
+ libtextclassifier3::StatusOr<bool> UpdateDerivedFilesNamespaceDeleted(
std::string_view name_space);
// Update derived files that the schema type schema_type_id has been deleted.
diff --git a/icing/store/document-store_test.cc b/icing/store/document-store_test.cc
index e246ca9..f181f8c 100644
--- a/icing/store/document-store_test.cc
+++ b/icing/store/document-store_test.cc
@@ -340,7 +340,7 @@ TEST_F(DocumentStoreTest, GetInvalidDocumentId) {
StatusIs(libtextclassifier3::StatusCode::NOT_FOUND));
}
-TEST_F(DocumentStoreTest, Delete) {
+TEST_F(DocumentStoreTest, DeleteOk) {
ICING_ASSERT_OK_AND_ASSIGN(
std::unique_ptr<DocumentStore> doc_store,
DocumentStore::Create(&filesystem_, document_store_dir_, &fake_clock_,
@@ -352,18 +352,45 @@ TEST_F(DocumentStoreTest, Delete) {
EXPECT_THAT(doc_store->Delete("icing", "email/1"), IsOk());
EXPECT_THAT(doc_store->Get(document_id),
StatusIs(libtextclassifier3::StatusCode::NOT_FOUND));
+}
+
+TEST_F(DocumentStoreTest, DeleteNonexistentDocumentNotFound) {
+ ICING_ASSERT_OK_AND_ASSIGN(
+ std::unique_ptr<DocumentStore> document_store,
+ DocumentStore::Create(&filesystem_, document_store_dir_, &fake_clock_,
+ schema_store_.get()));
// Validates that deleting something non-existing won't append anything to
// ground truth
int64_t ground_truth_size_before = filesystem_.GetFileSize(
absl_ports::StrCat(document_store_dir_, "/document_log").c_str());
- // icing + email/1 has already been deleted.
- EXPECT_THAT(doc_store->Delete("icing", "email/1"), IsOk());
+
+ EXPECT_THAT(
+ document_store->Delete("nonexistent_namespace", "nonexistent_uri"),
+ StatusIs(libtextclassifier3::StatusCode::NOT_FOUND));
+
int64_t ground_truth_size_after = filesystem_.GetFileSize(
absl_ports::StrCat(document_store_dir_, "/document_log").c_str());
EXPECT_THAT(ground_truth_size_before, Eq(ground_truth_size_after));
}
+TEST_F(DocumentStoreTest, DeleteAlreadyDeletedDocumentNotFound) {
+ ICING_ASSERT_OK_AND_ASSIGN(
+ std::unique_ptr<DocumentStore> document_store,
+ DocumentStore::Create(&filesystem_, document_store_dir_, &fake_clock_,
+ schema_store_.get()));
+ ICING_EXPECT_OK(document_store->Put(test_document1_));
+
+ // First time is OK
+ ICING_EXPECT_OK(document_store->Delete(test_document1_.namespace_(),
+ test_document1_.uri()));
+
+ // Deleting it again is NOT_FOUND
+ EXPECT_THAT(document_store->Delete(test_document1_.namespace_(),
+ test_document1_.uri()),
+ StatusIs(libtextclassifier3::StatusCode::NOT_FOUND));
+}
+
TEST_F(DocumentStoreTest, DeleteByNamespaceOk) {
ICING_ASSERT_OK_AND_ASSIGN(
std::unique_ptr<DocumentStore> doc_store,
@@ -403,7 +430,7 @@ TEST_F(DocumentStoreTest, DeleteByNamespaceOk) {
StatusIs(libtextclassifier3::StatusCode::NOT_FOUND));
}
-TEST_F(DocumentStoreTest, DeleteByNamespaceNonexistentNamespaceOk) {
+TEST_F(DocumentStoreTest, DeleteByNamespaceNonexistentNamespaceNotFound) {
ICING_ASSERT_OK_AND_ASSIGN(
std::unique_ptr<DocumentStore> doc_store,
DocumentStore::Create(&filesystem_, document_store_dir_, &fake_clock_,
@@ -414,13 +441,30 @@ TEST_F(DocumentStoreTest, DeleteByNamespaceNonexistentNamespaceOk) {
int64_t ground_truth_size_before = filesystem_.GetFileSize(
absl_ports::StrCat(document_store_dir_, "/document_log").c_str());
- ICING_EXPECT_OK(doc_store->DeleteByNamespace("nonexistent_namespace"));
+ EXPECT_THAT(doc_store->DeleteByNamespace("nonexistent_namespace"),
+ StatusIs(libtextclassifier3::StatusCode::NOT_FOUND));
int64_t ground_truth_size_after = filesystem_.GetFileSize(
absl_ports::StrCat(document_store_dir_, "/document_log").c_str());
EXPECT_THAT(ground_truth_size_before, Eq(ground_truth_size_after));
}
+TEST_F(DocumentStoreTest, DeleteByNamespaceNoExistingDocumentsNotFound) {
+ ICING_ASSERT_OK_AND_ASSIGN(
+ std::unique_ptr<DocumentStore> document_store,
+ DocumentStore::Create(&filesystem_, document_store_dir_, &fake_clock_,
+ schema_store_.get()));
+ ICING_EXPECT_OK(document_store->Put(test_document1_));
+ ICING_EXPECT_OK(document_store->Delete(test_document1_.namespace_(),
+ test_document1_.uri()));
+
+ // At this point, there are no existing documents with the namespace, even
+ // though Icing's derived files know about this namespace. We should still
+ // return NOT_FOUND since nothing existing has this namespace.
+ EXPECT_THAT(document_store->DeleteByNamespace(test_document1_.namespace_()),
+ StatusIs(libtextclassifier3::StatusCode::NOT_FOUND));
+}
+
TEST_F(DocumentStoreTest, DeleteByNamespaceRecoversOk) {
DocumentProto document1 = test_document1_;
document1.set_namespace_("namespace.1");
@@ -568,7 +612,7 @@ TEST_F(DocumentStoreTest, DeleteBySchemaTypeOk) {
IsOkAndHolds(EqualsProto(person_document)));
}
-TEST_F(DocumentStoreTest, DeleteBySchemaTypeNonexistentSchemaTypeOk) {
+TEST_F(DocumentStoreTest, DeleteBySchemaTypeNonexistentSchemaTypeNotFound) {
ICING_ASSERT_OK_AND_ASSIGN(
std::unique_ptr<DocumentStore> document_store,
DocumentStore::Create(&filesystem_, document_store_dir_, &fake_clock_,
@@ -579,7 +623,8 @@ TEST_F(DocumentStoreTest, DeleteBySchemaTypeNonexistentSchemaTypeOk) {
int64_t ground_truth_size_before = filesystem_.GetFileSize(
absl_ports::StrCat(document_store_dir_, "/document_log").c_str());
- ICING_EXPECT_OK(document_store->DeleteBySchemaType("nonexistent_type"));
+ EXPECT_THAT(document_store->DeleteBySchemaType("nonexistent_type"),
+ StatusIs(libtextclassifier3::StatusCode::NOT_FOUND));
int64_t ground_truth_size_after = filesystem_.GetFileSize(
absl_ports::StrCat(document_store_dir_, "/document_log").c_str());
@@ -587,6 +632,21 @@ TEST_F(DocumentStoreTest, DeleteBySchemaTypeNonexistentSchemaTypeOk) {
EXPECT_THAT(ground_truth_size_before, Eq(ground_truth_size_after));
}
+TEST_F(DocumentStoreTest, DeleteBySchemaTypeNoExistingDocumentsOk) {
+ ICING_ASSERT_OK_AND_ASSIGN(
+ std::unique_ptr<DocumentStore> document_store,
+ DocumentStore::Create(&filesystem_, document_store_dir_, &fake_clock_,
+ schema_store_.get()));
+ ICING_EXPECT_OK(document_store->Put(test_document1_));
+ ICING_EXPECT_OK(document_store->Delete(test_document1_.namespace_(),
+ test_document1_.uri()));
+
+ // At this point, there are no existing documents with the schema type, but we
+ // still return OK because the SchemaStore is the ground truth on schemas and
+ // knows about the type
+ ICING_EXPECT_OK(document_store->DeleteBySchemaType(test_document1_.schema()));
+}
+
TEST_F(DocumentStoreTest, DeleteBySchemaTypeRecoversOk) {
SchemaProto schema;
auto type_config = schema.add_types();