From 3cbdbf2652202a3473271ed298ff50e5797cce68 Mon Sep 17 00:00:00 2001 From: Greg Soltis Date: Tue, 30 Jan 2018 14:36:22 -0800 Subject: Schema migrations for LevelDB (#728) * Implement schema versions * Style fixes * newlines, copyrights, assumptions * Fix nullability * Raw ptr -> shared_ptr * kVersionTableGlobal -> kVersionGlobalTable * Drop utils, move into static methods * Drop extra include * Add a few more comments * Move version constant into migrations file * formatting? * Fix comment --- Firestore/Source/Local/FSTLevelDBQueryCache.mm | 82 +++++++++++--------------- 1 file changed, 33 insertions(+), 49 deletions(-) (limited to 'Firestore/Source/Local/FSTLevelDBQueryCache.mm') diff --git a/Firestore/Source/Local/FSTLevelDBQueryCache.mm b/Firestore/Source/Local/FSTLevelDBQueryCache.mm index 46af918..b3f4822 100644 --- a/Firestore/Source/Local/FSTLevelDBQueryCache.mm +++ b/Firestore/Source/Local/FSTLevelDBQueryCache.mm @@ -22,6 +22,7 @@ #import "Firestore/Protos/objc/firestore/local/Target.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/FSTQueryData.h" @@ -39,17 +40,6 @@ using leveldb::Slice; using leveldb::Status; using leveldb::WriteOptions; -/** - * Returns a standard set of read options. - * - * For now this is paranoid, but perhaps disable that in production builds. - */ -static ReadOptions GetStandardReadOptions() { - ReadOptions options; - options.verify_checksums = true; - return options; -} - @interface FSTLevelDBQueryCache () /** A write-through cached copy of the metadata for the query cache. */ @@ -70,6 +60,29 @@ static ReadOptions GetStandardReadOptions() { FSTSnapshotVersion *_lastRemoteSnapshotVersion; } ++ (nullable FSTPBTargetGlobal *)readTargetMetadataFromDB:(std::shared_ptr)db { + std::string key = [FSTLevelDBTargetGlobalKey key]; + std::string value; + Status status = db->Get([FSTLevelDB standardReadOptions], key, &value); + if (status.IsNotFound()) { + return nil; + } else if (!status.ok()) { + FSTFail(@"metadataForKey: failed loading key %s with status: %s", key.c_str(), + status.ToString().c_str()); + } + + NSData *data = + [[NSData alloc] initWithBytesNoCopy:(void *)value.data() length:value.size() freeWhenDone:NO]; + + NSError *error; + FSTPBTargetGlobal *proto = [FSTPBTargetGlobal parseFromData:data error:&error]; + if (!proto) { + FSTFail(@"FSTPBTargetGlobal failed to parse: %@", error); + } + + return proto; +} + - (instancetype)initWithDB:(std::shared_ptr)db serializer:(FSTLocalSerializer *)serializer { if (self = [super init]) { FSTAssert(db, @"db must not be NULL"); @@ -80,11 +93,10 @@ static ReadOptions GetStandardReadOptions() { } - (void)start { - std::string key = [FSTLevelDBTargetGlobalKey key]; - FSTPBTargetGlobal *metadata = [self metadataForKey:key]; - if (!metadata) { - metadata = [FSTPBTargetGlobal message]; - } + FSTPBTargetGlobal *metadata = [FSTLevelDBQueryCache readTargetMetadataFromDB:_db]; + FSTAssert( + metadata != nil, + @"Found nil metadata, expected schema to be at version 0 which ensures metadata existence"); _lastRemoteSnapshotVersion = [self.serializer decodedVersion:metadata.lastRemoteSnapshotVersion]; self.metadata = metadata; @@ -156,34 +168,6 @@ static ReadOptions GetStandardReadOptions() { [group removeMessageForKey:indexKey]; } -/** - * Looks up the query global metadata associated with the given key. - * - * @return the parsed protocol buffer message or nil if the row referenced by the given key does - * not exist. - */ -- (nullable FSTPBTargetGlobal *)metadataForKey:(const std::string &)key { - std::string value; - Status status = _db->Get(GetStandardReadOptions(), key, &value); - if (status.IsNotFound()) { - return nil; - } else if (!status.ok()) { - FSTFail(@"metadataForKey: failed loading key %s with status: %s", key.c_str(), - status.ToString().c_str()); - } - - NSData *data = - [[NSData alloc] initWithBytesNoCopy:(void *)value.data() length:value.size() freeWhenDone:NO]; - - NSError *error; - FSTPBTargetGlobal *proto = [FSTPBTargetGlobal parseFromData:data error:&error]; - if (!proto) { - FSTFail(@"FSTPBTargetGlobal failed to parse: %@", error); - } - - return proto; -} - /** * Parses the given bytes as an FSTPBTarget protocol buffer and then converts to the equivalent * query data. @@ -206,7 +190,7 @@ static ReadOptions GetStandardReadOptions() { // Note that this is a scan rather than a get because canonicalIDs are not required to be unique // per target. Slice canonicalID = StringView(query.canonicalID); - std::unique_ptr indexItererator(_db->NewIterator(GetStandardReadOptions())); + std::unique_ptr indexItererator(_db->NewIterator([FSTLevelDB standardReadOptions])); std::string indexPrefix = [FSTLevelDBQueryTargetKey keyPrefixWithCanonicalID:canonicalID]; indexItererator->Seek(indexPrefix); @@ -214,7 +198,7 @@ static ReadOptions GetStandardReadOptions() { // unique and ordered, so when scanning a table prefixed by exactly one canonicalID, all the // targetIDs will be unique and in order. std::string targetPrefix = [FSTLevelDBTargetKey keyPrefix]; - std::unique_ptr targetIterator(_db->NewIterator(GetStandardReadOptions())); + std::unique_ptr targetIterator(_db->NewIterator([FSTLevelDB standardReadOptions])); FSTLevelDBQueryTargetKey *rowKey = [[FSTLevelDBQueryTargetKey alloc] init]; for (; indexItererator->Valid(); indexItererator->Next()) { @@ -286,7 +270,7 @@ static ReadOptions GetStandardReadOptions() { - (void)removeMatchingKeysForTargetID:(FSTTargetID)targetID group:(FSTWriteGroup *)group { std::string indexPrefix = [FSTLevelDBTargetDocumentKey keyPrefixWithTargetID:targetID]; - std::unique_ptr indexIterator(_db->NewIterator(GetStandardReadOptions())); + std::unique_ptr indexIterator(_db->NewIterator([FSTLevelDB standardReadOptions])); indexIterator->Seek(indexPrefix); FSTLevelDBTargetDocumentKey *rowKey = [[FSTLevelDBTargetDocumentKey alloc] init]; @@ -309,7 +293,7 @@ static ReadOptions GetStandardReadOptions() { - (FSTDocumentKeySet *)matchingKeysForTargetID:(FSTTargetID)targetID { std::string indexPrefix = [FSTLevelDBTargetDocumentKey keyPrefixWithTargetID:targetID]; - std::unique_ptr indexIterator(_db->NewIterator(GetStandardReadOptions())); + std::unique_ptr indexIterator(_db->NewIterator([FSTLevelDB standardReadOptions])); indexIterator->Seek(indexPrefix); FSTDocumentKeySet *result = [FSTDocumentKeySet keySet]; @@ -332,7 +316,7 @@ static ReadOptions GetStandardReadOptions() { - (BOOL)containsKey:(FSTDocumentKey *)key { std::string indexPrefix = [FSTLevelDBDocumentTargetKey keyPrefixWithResourcePath:key.path]; - std::unique_ptr indexIterator(_db->NewIterator(GetStandardReadOptions())); + std::unique_ptr indexIterator(_db->NewIterator([FSTLevelDB standardReadOptions])); indexIterator->Seek(indexPrefix); if (indexIterator->Valid()) { -- cgit v1.2.3