Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Firestore/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Unreleased
- [changed] Prepare Firestore cache to support session token.

# 11.3.0
- [changed] Improve efficiency of memory persistence when processing a large number of writes. (#13572)

Expand Down
44 changes: 44 additions & 0 deletions Firestore/Example/Firestore.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions Firestore/core/src/local/globals_cache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* @license
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef FIRESTORE_CORE_SRC_LOCAL_GLOBALS_CACHE_H_
#define FIRESTORE_CORE_SRC_LOCAL_GLOBALS_CACHE_H_

#include "Firestore/core/src/nanopb/byte_string.h"

using firebase::firestore::nanopb::ByteString;

namespace firebase {
namespace firestore {
namespace local {

/**
* General purpose cache for global values.
*
* Global state that cuts across components should be saved here. Following are
* contained herein:
*
* `sessionToken` tracks server interaction across Listen and Write streams.
* This facilitates cache synchronization and invalidation.
*/
class GlobalsCache {
public:
virtual ~GlobalsCache() = default;

/**
* Gets session token.
*/
virtual ByteString GetSessionToken() const = 0;

/**
* Sets session token.
*/
virtual void SetSessionToken(const ByteString& session_token) = 0;
};

} // namespace local
} // namespace firestore
} // namespace firebase

#endif // FIRESTORE_CORE_SRC_LOCAL_GLOBALS_CACHE_H_
57 changes: 57 additions & 0 deletions Firestore/core/src/local/leveldb_globals_cache.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <string>

#include "Firestore/core/src/local/leveldb_globals_cache.h"
#include "Firestore/core/src/local/leveldb_key.h"
#include "Firestore/core/src/local/leveldb_persistence.h"

namespace firebase {
namespace firestore {
namespace local {

namespace {

const char* kSessionToken = "session_token";

}

LevelDbGlobalsCache::LevelDbGlobalsCache(LevelDbPersistence* db)
: db_(NOT_NULL(db)) {
}

ByteString LevelDbGlobalsCache::GetSessionToken() const {
auto key = LevelDbGlobalKey::Key(kSessionToken);

std::string encoded;
auto done = db_->current_transaction()->Get(key, &encoded);

if (!done.ok()) {
return ByteString();
}

return ByteString(encoded);
}

void LevelDbGlobalsCache::SetSessionToken(const ByteString& session_token) {
auto key = LevelDbGlobalKey::Key(kSessionToken);
db_->current_transaction()->Put(key, session_token.ToString());
}

} // namespace local
} // namespace firestore
} // namespace firebase
52 changes: 52 additions & 0 deletions Firestore/core/src/local/leveldb_globals_cache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef FIRESTORE_CORE_SRC_LOCAL_LEVELDB_GLOBALS_CACHE_H_
#define FIRESTORE_CORE_SRC_LOCAL_LEVELDB_GLOBALS_CACHE_H_

#include "Firestore/core/src/local/globals_cache.h"

namespace firebase {
namespace firestore {
namespace local {

class LevelDbPersistence;

class LevelDbGlobalsCache : public GlobalsCache {
public:
/** Creates a new bundle cache in the given LevelDB. */
explicit LevelDbGlobalsCache(LevelDbPersistence* db);

/**
* Gets session token.
*/
ByteString GetSessionToken() const override;

/**
* Sets session token.
*/
void SetSessionToken(const ByteString& session_token) override;

private:
// The LevelDbGlobalsCache is owned by LevelDbPersistence.
LevelDbPersistence* db_ = nullptr;
};

} // namespace local
} // namespace firestore
} // namespace firebase

#endif // FIRESTORE_CORE_SRC_LOCAL_LEVELDB_GLOBALS_CACHE_H_
36 changes: 36 additions & 0 deletions Firestore/core/src/local/leveldb_key.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ namespace local {
namespace {

const char* kVersionGlobalTable = "version";
const char* kGlobalsTable = "globals";
const char* kMutationsTable = "mutation";
const char* kDocumentMutationsTable = "document_mutation";
const char* kMutationQueuesTable = "mutation_queue";
Expand Down Expand Up @@ -159,6 +160,11 @@ enum ComponentLabel {
*/
DataMigrationName = 25,

/**
* The name of a global.
*/
GlobalName = 26,

/**
* A path segment describes just a single segment in a resource path. Path
* segments that occur sequentially in a key represent successive segments in
Expand Down Expand Up @@ -245,6 +251,10 @@ class Reader {
return ReadLabeledString(ComponentLabel::BundleId);
}

std::string ReadGlobalName() {
return ReadLabeledString(ComponentLabel::GlobalName);
}

std::string ReadQueryName() {
return ReadLabeledString(ComponentLabel::QueryName);
}
Expand Down Expand Up @@ -718,6 +728,10 @@ class Writer {
WriteLabeledString(ComponentLabel::TableName, table_name);
}

void WriteGlobalName(absl::string_view global_name) {
WriteLabeledString(ComponentLabel::GlobalName, global_name);
}

void WriteBatchId(model::BatchId batch_id) {
WriteLabeledInt32(ComponentLabel::BatchId, batch_id);
}
Expand Down Expand Up @@ -1206,6 +1220,28 @@ bool LevelDbRemoteDocumentReadTimeKey::Decode(absl::string_view key) {
return reader.ok();
}

std::string LevelDbGlobalKey::KeyPrefix() {
Writer writer;
writer.WriteTableName(kGlobalsTable);
return writer.result();
}

std::string LevelDbGlobalKey::Key(absl::string_view global_name) {
Writer writer;
writer.WriteTableName(kGlobalsTable);
writer.WriteGlobalName(global_name);
writer.WriteTerminator();
return writer.result();
}

bool LevelDbGlobalKey::Decode(absl::string_view key) {
Reader reader{key};
reader.ReadTableNameMatching(kGlobalsTable);
global_name_ = reader.ReadGlobalName();
reader.ReadTerminator();
return reader.ok();
}

std::string LevelDbBundleKey::KeyPrefix() {
Writer writer;
writer.WriteTableName(kBundlesTable);
Expand Down
35 changes: 35 additions & 0 deletions Firestore/core/src/local/leveldb_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,41 @@ class LevelDbNamedQueryKey {
std::string name_;
};

/**
* A key in the globals table, storing the name of the global value.
*/
class LevelDbGlobalKey {
public:
/**
* Creates a key prefix that points just before the first key of the table.
*/
static std::string KeyPrefix();

/**
* Creates a key that points to the key for the given name of global value.
*/
static std::string Key(absl::string_view global_name);

/**
* Decodes the given complete key, storing the decoded values in this
* instance.
*
* @return true if the key successfully decoded, false otherwise. If false is
* returned, this instance is in an undefined state until the next call to
* `Decode()`.
*/
ABSL_MUST_USE_RESULT
bool Decode(absl::string_view key);

/** The name that serves as identifier for global value for this entry. */
const std::string& global_name() const {
return global_name_;
}

private:
std::string global_name_;
};

/**
* A key in the index_configuration table, storing the index definition proto,
* and the collection (group) it applies to.
Expand Down
5 changes: 5 additions & 0 deletions Firestore/core/src/local/leveldb_persistence.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ LevelDbPersistence::LevelDbPersistence(std::unique_ptr<leveldb::DB> db,
reference_delegate_ =
absl::make_unique<LevelDbLruReferenceDelegate>(this, lru_params);
bundle_cache_ = absl::make_unique<LevelDbBundleCache>(this, &serializer_);
globals_cache_ = absl::make_unique<LevelDbGlobalsCache>(this);

// TODO(gsoltis): set up a leveldb transaction for these operations.
target_cache_->Start();
Expand Down Expand Up @@ -250,6 +251,10 @@ LevelDbTargetCache* LevelDbPersistence::target_cache() {
return target_cache_.get();
}

LevelDbGlobalsCache* LevelDbPersistence::globals_cache() {
return globals_cache_.get();
}

LevelDbRemoteDocumentCache* LevelDbPersistence::remote_document_cache() {
return document_cache_.get();
}
Expand Down
4 changes: 4 additions & 0 deletions Firestore/core/src/local/leveldb_persistence.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "Firestore/core/src/credentials/user.h"
#include "Firestore/core/src/local/leveldb_bundle_cache.h"
#include "Firestore/core/src/local/leveldb_document_overlay_cache.h"
#include "Firestore/core/src/local/leveldb_globals_cache.h"
#include "Firestore/core/src/local/leveldb_index_manager.h"
#include "Firestore/core/src/local/leveldb_lru_reference_delegate.h"
#include "Firestore/core/src/local/leveldb_migrations.h"
Expand Down Expand Up @@ -84,6 +85,8 @@ class LevelDbPersistence : public Persistence {

LevelDbBundleCache* bundle_cache() override;

LevelDbGlobalsCache* globals_cache() override;

LevelDbDocumentOverlayCache* GetDocumentOverlayCache(
const credentials::User& user) override;
LevelDbOverlayMigrationManager* GetOverlayMigrationManager(
Expand Down Expand Up @@ -154,6 +157,7 @@ class LevelDbPersistence : public Persistence {
bool started_ = false;

std::unique_ptr<LevelDbBundleCache> bundle_cache_;
std::unique_ptr<LevelDbGlobalsCache> globals_cache_;
std::unordered_map<std::string, std::unique_ptr<LevelDbDocumentOverlayCache>>
document_overlay_caches_;
std::unordered_map<std::string,
Expand Down
33 changes: 33 additions & 0 deletions Firestore/core/src/local/memory_globals_cache.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "Firestore/core/src/local/memory_globals_cache.h"

namespace firebase {
namespace firestore {
namespace local {

ByteString MemoryGlobalsCache::GetSessionToken() const {
return session_token_;
}

void MemoryGlobalsCache::SetSessionToken(const ByteString& session_token) {
session_token_ = session_token;
}

} // namespace local
} // namespace firestore
} // namespace firebase
Loading
Loading