mirror of
https://github.com/firebase/firebase-ios-sdk
synced 2026-11-10 22:45:59 +05:45
* Start work on leveldb transactions
* Style
* Working API. Not plumbed in yet
* Move files into correct place
* Wrangling file locations and associations
* Tests pass
* Add some comments
* style
* Fix copyright
* Rewrite iterator internals to handle deletion-while-iterating. Also add tests for same
* Switch to strings instead of slices
* Style
* More style fixes
* Start switching writegroup over
* Swap out write group tracking for transaction usage
* Style
* Response to feedback before updating docs
* Style
* Add comment
* Initialize version_
* Satisfy the linter
* Start switching writegroup over
* Swap out write group tracking for transaction usage
* Style
* Checkpoint before implementing BatchDescription
* Style
* Initial plumbing for leveldb local parts
* Add model::BatchId
* Port leveldb_key.{h,cc}
* Add string StartsWith
* Add leveldb_key_test.cc to the project
* Revert back to using leveldb::Slice for read/describe
These operations universally operate on keys obtained from leveldb so
it's actually unhelpful to force all the callers to make
absl::string_views from them.
* Everything passing
* Drop unused function
* Style
* STart work on reads
* Swap reads in queryCache to use transactions
* Fix up tests of querycache
* Drop commented out code
* Cleanup
* Style
* Fix up for passing tests
* style
* Renaming
* Style
* Start work on ToString for transactions
* Add ToString() method to LevelDbTransaction
* Style
* lint
* Fix includes, drop runTransaction
* current_transaction -> currentTransaction
* LevelDbTransaction::NewIterator now returns a unique_ptr
* Style
* Revert addition of util::StartsWith
* Add log line
* Style
* Add log line
* Style
* Add debug log line for commits, drop unused BatchDescription
* STart work on reads
* Swap reads in queryCache to use transactions
* Start on remote documents
* Transition mutation queue and remote documents to use transactions
* Style
* Make everything pass
* Make everything pass
* Make it compile
* Style
* Style
* Revert name change, use DefaultReadOptions()
* Style
* Handle iterators returning bad statuses
138 lines
4.8 KiB
Plaintext
138 lines
4.8 KiB
Plaintext
/*
|
|
* Copyright 2017 Google
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#import "Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.h"
|
|
|
|
#include <leveldb/db.h>
|
|
#include <leveldb/write_batch.h>
|
|
#include <string>
|
|
|
|
#import "Firestore/Protos/objc/firestore/local/MaybeDocument.pbobjc.h"
|
|
#import "Firestore/Source/Core/FSTQuery.h"
|
|
#import "Firestore/Source/Local/FSTLevelDB.h"
|
|
#import "Firestore/Source/Local/FSTLevelDBKey.h"
|
|
#import "Firestore/Source/Local/FSTLocalSerializer.h"
|
|
#import "Firestore/Source/Local/FSTWriteGroup.h"
|
|
#import "Firestore/Source/Model/FSTDocument.h"
|
|
#import "Firestore/Source/Model/FSTDocumentDictionary.h"
|
|
#import "Firestore/Source/Model/FSTDocumentSet.h"
|
|
#import "Firestore/Source/Util/FSTAssert.h"
|
|
#include "Firestore/core/src/firebase/firestore/local/leveldb_transaction.h"
|
|
|
|
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
|
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
using firebase::firestore::local::LevelDbTransaction;
|
|
using firebase::firestore::model::DocumentKey;
|
|
using leveldb::DB;
|
|
using leveldb::Status;
|
|
|
|
@interface FSTLevelDBRemoteDocumentCache ()
|
|
|
|
@property(nonatomic, strong, readonly) FSTLocalSerializer *serializer;
|
|
|
|
@end
|
|
|
|
@implementation FSTLevelDBRemoteDocumentCache {
|
|
FSTLevelDB *_db;
|
|
}
|
|
|
|
- (instancetype)initWithDB:(FSTLevelDB *)db serializer:(FSTLocalSerializer *)serializer {
|
|
if (self = [super init]) {
|
|
_db = db;
|
|
_serializer = serializer;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)shutdown {
|
|
}
|
|
|
|
- (void)addEntry:(FSTMaybeDocument *)document group:(FSTWriteGroup *)group {
|
|
std::string key = [self remoteDocumentKey:document.key];
|
|
[group setMessage:[self.serializer encodedMaybeDocument:document] forKey:key];
|
|
}
|
|
|
|
- (void)removeEntryForKey:(const DocumentKey &)documentKey group:(FSTWriteGroup *)group {
|
|
std::string key = [self remoteDocumentKey:documentKey];
|
|
[group removeMessageForKey:key];
|
|
}
|
|
|
|
- (nullable FSTMaybeDocument *)entryForKey:(const DocumentKey &)documentKey {
|
|
std::string key = [FSTLevelDBRemoteDocumentKey keyWithDocumentKey:documentKey];
|
|
std::string value;
|
|
Status status = _db.currentTransaction->Get(key, &value);
|
|
if (status.IsNotFound()) {
|
|
return nil;
|
|
} else if (status.ok()) {
|
|
return [self decodeMaybeDocument:value withKey:documentKey];
|
|
} else {
|
|
FSTFail(@"Fetch document for key (%s) failed with status: %s", documentKey.ToString().c_str(),
|
|
status.ToString().c_str());
|
|
}
|
|
}
|
|
|
|
- (FSTDocumentDictionary *)documentsMatchingQuery:(FSTQuery *)query {
|
|
FSTDocumentDictionary *results = [FSTDocumentDictionary documentDictionary];
|
|
|
|
// Documents are ordered by key, so we can use a prefix scan to narrow down
|
|
// the documents we need to match the query against.
|
|
std::string startKey = [FSTLevelDBRemoteDocumentKey keyPrefixWithResourcePath:query.path];
|
|
auto it = _db.currentTransaction->NewIterator();
|
|
it->Seek(startKey);
|
|
|
|
FSTLevelDBRemoteDocumentKey *currentKey = [[FSTLevelDBRemoteDocumentKey alloc] init];
|
|
for (; it->Valid() && [currentKey decodeKey:it->key()]; it->Next()) {
|
|
FSTMaybeDocument *maybeDoc =
|
|
[self decodeMaybeDocument:it->value() withKey:currentKey.documentKey];
|
|
if (!query.path.IsPrefixOf(maybeDoc.key.path())) {
|
|
break;
|
|
} else if ([maybeDoc isKindOfClass:[FSTDocument class]]) {
|
|
results = [results dictionaryBySettingObject:(FSTDocument *)maybeDoc forKey:maybeDoc.key];
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
- (std::string)remoteDocumentKey:(const DocumentKey &)key {
|
|
return [FSTLevelDBRemoteDocumentKey keyWithDocumentKey:key];
|
|
}
|
|
|
|
- (FSTMaybeDocument *)decodeMaybeDocument:(absl::string_view)encoded
|
|
withKey:(const DocumentKey &)documentKey {
|
|
NSData *data = [[NSData alloc] initWithBytesNoCopy:(void *)encoded.data()
|
|
length:encoded.size()
|
|
freeWhenDone:NO];
|
|
|
|
NSError *error;
|
|
FSTPBMaybeDocument *proto = [FSTPBMaybeDocument parseFromData:data error:&error];
|
|
if (!proto) {
|
|
FSTFail(@"FSTPBMaybeDocument failed to parse: %@", error);
|
|
}
|
|
|
|
FSTMaybeDocument *maybeDocument = [self.serializer decodedMaybeDocument:proto];
|
|
FSTAssert([maybeDocument.key isEqualToKey:documentKey],
|
|
@"Read document has key (%s) instead of expected key (%s).",
|
|
maybeDocument.key.ToString().c_str(), documentKey.ToString().c_str());
|
|
return maybeDocument;
|
|
}
|
|
|
|
@end
|
|
|
|
NS_ASSUME_NONNULL_END
|