Files
firebase-ios-sdk/Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.mm
T

134 lines
4.6 KiB
Plaintext
Raw Normal View History

2017-10-03 08:55:22 -07:00
/*
* 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"
2017-10-03 08:55:22 -07:00
#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/FSTLocalSerializer.h"
#import "Firestore/Source/Model/FSTDocument.h"
#import "Firestore/Source/Model/FSTDocumentDictionary.h"
#import "Firestore/Source/Model/FSTDocumentSet.h"
2018-08-08 12:34:03 -07:00
#include "Firestore/core/src/firebase/firestore/local/leveldb_key.h"
#include "Firestore/core/src/firebase/firestore/local/leveldb_transaction.h"
2018-03-23 17:52:01 -04:00
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
#include "Firestore/core/src/firebase/firestore/util/hard_assert.h"
#include "leveldb/db.h"
#include "leveldb/write_batch.h"
2018-03-23 17:52:01 -04:00
2017-10-03 08:55:22 -07:00
NS_ASSUME_NONNULL_BEGIN
2018-08-08 12:34:03 -07:00
using firebase::firestore::local::LevelDbRemoteDocumentKey;
using firebase::firestore::local::LevelDbTransaction;
2018-03-23 17:52:01 -04:00
using firebase::firestore::model::DocumentKey;
2017-10-03 08:55:22 -07:00
using leveldb::DB;
using leveldb::Status;
@interface FSTLevelDBRemoteDocumentCache ()
@property(nonatomic, strong, readonly) FSTLocalSerializer *serializer;
@end
@implementation FSTLevelDBRemoteDocumentCache {
FSTLevelDB *_db;
2017-10-03 08:55:22 -07:00
}
- (instancetype)initWithDB:(FSTLevelDB *)db serializer:(FSTLocalSerializer *)serializer {
2017-10-03 08:55:22 -07:00
if (self = [super init]) {
_db = db;
_serializer = serializer;
}
return self;
}
2018-03-29 08:55:10 -07:00
- (void)addEntry:(FSTMaybeDocument *)document {
2017-10-03 08:55:22 -07:00
std::string key = [self remoteDocumentKey:document.key];
2018-03-29 08:55:10 -07:00
_db.currentTransaction->Put(key, [self.serializer encodedMaybeDocument:document]);
2017-10-03 08:55:22 -07:00
}
2018-03-29 08:55:10 -07:00
- (void)removeEntryForKey:(const DocumentKey &)documentKey {
2017-10-03 08:55:22 -07:00
std::string key = [self remoteDocumentKey:documentKey];
2018-03-29 08:55:10 -07:00
_db.currentTransaction->Delete(key);
2017-10-03 08:55:22 -07:00
}
2018-03-23 17:52:01 -04:00
- (nullable FSTMaybeDocument *)entryForKey:(const DocumentKey &)documentKey {
2018-08-08 12:34:03 -07:00
std::string key = LevelDbRemoteDocumentKey::Key(documentKey);
2017-10-03 08:55:22 -07:00
std::string value;
Status status = _db.currentTransaction->Get(key, &value);
2017-10-03 08:55:22 -07:00
if (status.IsNotFound()) {
return nil;
} else if (status.ok()) {
return [self decodeMaybeDocument:value withKey:documentKey];
2017-10-03 08:55:22 -07:00
} else {
HARD_FAIL("Fetch document for key (%s) failed with status: %s", documentKey.ToString(),
status.ToString());
2017-10-03 08:55:22 -07:00
}
}
- (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.
2018-08-08 12:34:03 -07:00
std::string startKey = LevelDbRemoteDocumentKey::KeyPrefix(query.path);
auto it = _db.currentTransaction->NewIterator();
2017-10-03 08:55:22 -07:00
it->Seek(startKey);
2018-08-08 12:34:03 -07:00
LevelDbRemoteDocumentKey currentKey;
for (; it->Valid() && currentKey.Decode(it->key()); it->Next()) {
2017-10-03 08:55:22 -07:00
FSTMaybeDocument *maybeDoc =
2018-08-08 12:34:03 -07:00
[self decodeMaybeDocument:it->value() withKey:currentKey.document_key()];
if (!query.path.IsPrefixOf(maybeDoc.key.path())) {
break;
} else if ([maybeDoc isKindOfClass:[FSTDocument class]]) {
2017-10-03 08:55:22 -07:00
results = [results dictionaryBySettingObject:(FSTDocument *)maybeDoc forKey:maybeDoc.key];
}
}
return results;
}
2018-03-23 17:52:01 -04:00
- (std::string)remoteDocumentKey:(const DocumentKey &)key {
2018-08-08 12:34:03 -07:00
return LevelDbRemoteDocumentKey::Key(key);
2017-10-03 08:55:22 -07:00
}
- (FSTMaybeDocument *)decodeMaybeDocument:(absl::string_view)encoded
withKey:(const DocumentKey &)documentKey {
NSData *data = [[NSData alloc] initWithBytesNoCopy:(void *)encoded.data()
length:encoded.size()
freeWhenDone:NO];
2017-10-03 08:55:22 -07:00
NSError *error;
FSTPBMaybeDocument *proto = [FSTPBMaybeDocument parseFromData:data error:&error];
if (!proto) {
HARD_FAIL("FSTPBMaybeDocument failed to parse: %s", error);
2017-10-03 08:55:22 -07:00
}
FSTMaybeDocument *maybeDocument = [self.serializer decodedMaybeDocument:proto];
HARD_ASSERT(maybeDocument.key == documentKey,
"Read document has key (%s) instead of expected key (%s).",
maybeDocument.key.ToString(), documentKey.ToString());
2017-10-03 08:55:22 -07:00
return maybeDocument;
}
@end
NS_ASSUME_NONNULL_END