diff --git a/Podfile.lock b/Podfile.lock index 6fc4c40..44cf2d7 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,14 +1,14 @@ PODS: - - Realm (2.0.1): - - Realm/Headers (= 2.0.1) - - Realm/Headers (2.0.1) + - Realm (2.1.1): + - Realm/Headers (= 2.1.1) + - Realm/Headers (2.1.1) DEPENDENCIES: - Realm (~> 2.0) SPEC CHECKSUMS: - Realm: 0557ee0e4ab4f0936c90e370056d1ed6265f93d6 + Realm: a55959c0b171a5fe5267406d17f314fec3cefaae PODFILE CHECKSUM: 264106bd006862ccc775ed4cb65de9a2512d7150 -COCOAPODS: 1.1.0.rc.2 +COCOAPODS: 1.1.1 diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock index 6fc4c40..44cf2d7 100644 --- a/Pods/Manifest.lock +++ b/Pods/Manifest.lock @@ -1,14 +1,14 @@ PODS: - - Realm (2.0.1): - - Realm/Headers (= 2.0.1) - - Realm/Headers (2.0.1) + - Realm (2.1.1): + - Realm/Headers (= 2.1.1) + - Realm/Headers (2.1.1) DEPENDENCIES: - Realm (~> 2.0) SPEC CHECKSUMS: - Realm: 0557ee0e4ab4f0936c90e370056d1ed6265f93d6 + Realm: a55959c0b171a5fe5267406d17f314fec3cefaae PODFILE CHECKSUM: 264106bd006862ccc775ed4cb65de9a2512d7150 -COCOAPODS: 1.1.0.rc.2 +COCOAPODS: 1.1.1 diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj index 9e0fefc..dbe69f0 100644 --- a/Pods/Pods.xcodeproj/project.pbxproj +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -7,233 +7,241 @@ objects = { /* Begin PBXBuildFile section */ - 009FFC9303097703F79B61193B66BAD2 /* RLMOptionalBase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 25ABD97B85A0A4EFCD3DB372EF367A42 /* RLMOptionalBase.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 043D48C377905C6B5D57758B1D37C45E /* RLMResults.h in Headers */ = {isa = PBXBuildFile; fileRef = DCB7F8D3C434001DEC287625F5FAE924 /* RLMResults.h */; }; - 046FAC0DCEA4E3B42A5E5C28DE94F50D /* weak_realm_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8864E15D52FC228189BA78CA478D44E8 /* weak_realm_notifier.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 048760C43D03E08874506B06B7EF2BA7 /* RLMArray.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = DB875141CED28FC407D7A4738BA2DE05 /* RLMArray.h */; }; - 09D0DFDF8347435BE95D56AE6FDADBCB /* RLMQueryUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = EBDFC5BC545FCBE6B4AF71FE2818ED90 /* RLMQueryUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 09F6233ECAEA6D5E768B65EEEB194438 /* RLMTokenModels.m in Sources */ = {isa = PBXBuildFile; fileRef = 034990FBBE926C95450017780DDE2549 /* RLMTokenModels.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 0DF357FF69DEAC1D3FED3B923140FD42 /* RLMRealm_Dynamic.h in Headers */ = {isa = PBXBuildFile; fileRef = B0B4CBC2DBA8C64954C17C9B1712ABD3 /* RLMRealm_Dynamic.h */; }; - 0F287993F131D182BA941A85C7769922 /* results_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CA1A05864AF04C106ACCBFD60852BD6 /* results_notifier.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 10C39B5D46E881F79013177C9DEB072A /* RLMSyncManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 52201054DED1B93163C58A80BB2DC94F /* RLMSyncManager.h */; }; - 10C47D71057411A27C638DE2D0C4D22A /* RLMProperty.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7E10BDDCD1452430D956D7D35FB82770 /* RLMProperty.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 10E133170F959FEF9913AE3DFAD42C41 /* RLMRealmUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = 39F8AFBC85C45F619757B8863AAF76EA /* RLMRealmUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 1194C66B5AE3A2589CC280DFE085BF8D /* collection_change_builder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F499BD65626016E373C109D2EE8194B2 /* collection_change_builder.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 12717CA85FC64D692BE5F9FF2F56AE7C /* RLMArray.mm in Sources */ = {isa = PBXBuildFile; fileRef = 943D843F536640EE12B8EAFA1A038957 /* RLMArray.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 14AFB23EC73BC008065D06D3778D69B2 /* thread_confined.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C61306AB8513B6408B637E5C032E042 /* thread_confined.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 15672E6EBBB60FD33C720758B6C061D6 /* RLMSyncUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = E350FAEE1CE28DF3F5C95D54F76A8663 /* RLMSyncUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 1609307D58BBF0643A35CFE4ADAB7934 /* RLMPlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = A5CCD9825C816504EEF6840EAEA70F72 /* RLMPlatform.h */; }; - 1647B820844411D553027E67869AE43A /* RLMAuthResponseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A6F512185B5D12F73C4295DCA121267 /* RLMAuthResponseModel.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 168BEA544B848C406D3FC9FB3882E0EE /* index_set.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8022D1416A1403F2AF801D90045A5452 /* index_set.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 1740CA8FB9F7912BD75D644C0F4F2831 /* RLMSyncSession_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 3D61ECDE4E4EA174F578A3DEF987C17C /* RLMSyncSession_Private.h */; }; - 1A18CE94FCB350DD61C4E225CAFB66A6 /* RLMSyncManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7E1BF4F4217B5993AFF70FC53C787628 /* RLMSyncManager.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 1AB09F890CF130E17580119B4199F848 /* RLMSwiftSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 207655DE5C14B2A57A94D5C954011DDE /* RLMSwiftSupport.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 1C7CF7709F1068C2E9A1FEA600F71D9D /* RLMObjectSchema_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 3B955FE3E7BE7FEFE6EF9AE9E6190ECD /* RLMObjectSchema_Private.h */; }; - 1ED10BC5C59606ED64540A1874C43A27 /* RLMSyncUtil_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F7FD2D8A72BC62BAC9A5931BB8C3464 /* RLMSyncUtil_Private.h */; }; - 210D77853ABBF30D95E6DC29660090FB /* RLMSyncManager.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 52201054DED1B93163C58A80BB2DC94F /* RLMSyncManager.h */; }; - 26CD1EEB82053E536F0FE241492EF6F2 /* RLMSyncCredential.m in Sources */ = {isa = PBXBuildFile; fileRef = 3660CB7CF901F80EE595D72D9307E3C9 /* RLMSyncCredential.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 2916E4339CC6FDEC475AD05ED221C857 /* RLMObjectSchema.mm in Sources */ = {isa = PBXBuildFile; fileRef = C64F45A2EE41F6AF3CD60EAB4F47F8C3 /* RLMObjectSchema.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 295900CF8636E9FE9A480D1837CF5139 /* RLMSyncUser.h in Headers */ = {isa = PBXBuildFile; fileRef = FE6BD60C5945F58879F5FB4465F9CA95 /* RLMSyncUser.h */; }; - 2A47E33C5048CDDAC2DEBEE6417ED315 /* Pods-VBB-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 670BBB97DAC0DF3030CDC5E2D40B5024 /* Pods-VBB-dummy.m */; }; - 2B426F9C527CE73A594851504F7F9EDD /* RLMResults_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = CC3074D458C8E4B7B88B55DE244480FB /* RLMResults_Private.h */; }; - 2D85820D45177CDAC8A822E42CA82F33 /* RLMMigration.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = FE8BE2362C2F5AB54077FB69FC5D2239 /* RLMMigration.h */; }; - 30F7AA5E6EBA415049E49E38EB6BEB81 /* RLMMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = FE8BE2362C2F5AB54077FB69FC5D2239 /* RLMMigration.h */; }; - 332351CAE765FE4545CF1AF5154D49AC /* RLMObjectSchema_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B955FE3E7BE7FEFE6EF9AE9E6190ECD /* RLMObjectSchema_Private.h */; }; - 33AD3184091299FAABDBC4E578E877E9 /* RLMSchema_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 38141611BE7DF729928941BA5ED8BC49 /* RLMSchema_Private.h */; }; - 3704706A1290A0D59582E382EE80A274 /* RLMResults.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = DCB7F8D3C434001DEC287625F5FAE924 /* RLMResults.h */; }; - 405F3DCBE38B3B64FBBBB71433C42D64 /* RLMObjectSchema.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = EEAAE9E613DFE79610E529C04D19FD93 /* RLMObjectSchema.h */; }; - 4436ABEDE05178987318AF722C7D78B3 /* RLMSyncUser.mm in Sources */ = {isa = PBXBuildFile; fileRef = 45FAA23D2B88ACEAE13C5819F1F20A54 /* RLMSyncUser.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 45079426CDE485F7432B315D39E64F2E /* RLMResults_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = CC3074D458C8E4B7B88B55DE244480FB /* RLMResults_Private.h */; }; - 4595A4681680F91FB676D959ABD80443 /* RLMSchema.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = F83DF66FA251959174CB98F3E41DF215 /* RLMSchema.h */; }; - 466957D8B94A58B9E077CB545AC0A373 /* RLMObjectBase_Dynamic.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = E0FAFDE4566B1CC34938EFDB139DE1A5 /* RLMObjectBase_Dynamic.h */; }; - 48E83195D65F8079ECF08232996463C6 /* shared_realm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D84036052E8CB24CB40E17886144B336 /* shared_realm.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 4A66E5B8EADEFF2B42B66CBA146D079D /* RLMSchema.h in Headers */ = {isa = PBXBuildFile; fileRef = F83DF66FA251959174CB98F3E41DF215 /* RLMSchema.h */; }; - 4A814DC9D9E3C919EB0B6440ECC79F76 /* RLMUpdateChecker.mm in Sources */ = {isa = PBXBuildFile; fileRef = 32E60FAC5AA32DB30476E57D759ABE49 /* RLMUpdateChecker.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 4B74B7597C3AD5226CEDFC34D253A5E5 /* RLMSyncSession_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D61ECDE4E4EA174F578A3DEF987C17C /* RLMSyncSession_Private.h */; }; - 4C54B6964DA593918F03D6F8BA3AE0D8 /* RLMRealm_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 00A6AC0F9C79B0C691DDB361F7ED9E76 /* RLMRealm_Private.h */; }; - 4CA65141256920C526B050589363C51C /* RLMRealmConfiguration+Sync.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 014469716A1D2CD0219B1E692FFCEE88 /* RLMRealmConfiguration+Sync.h */; }; - 4D8709EF2534A594EEB8A79139AE7E77 /* RLMRealm_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 00A6AC0F9C79B0C691DDB361F7ED9E76 /* RLMRealm_Private.h */; }; - 4E0DBF31B59294CCA9D351A1000BE61D /* RLMListBase.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 519044AC217178621FF363269D6344C2 /* RLMListBase.h */; }; - 4ED964D1A0592AC145D6C14072868365 /* RLMSyncConfiguration_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = D8C27F6A06FBD7BC9D2CAA007D33BF65 /* RLMSyncConfiguration_Private.h */; }; - 4F0D281550F043A72D2510A7306FE36A /* sync_metadata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52CDE0006AE03361D1D46D446377C3EE /* sync_metadata.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 4F1BFB974BB09F1E3A341EA52008CD50 /* RLMSchema.mm in Sources */ = {isa = PBXBuildFile; fileRef = 78B8C8451B740B8F2441708DB434479E /* RLMSchema.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 4F57AF131D77079DBA7D86AC1D5DB8E2 /* handover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B98E7E083A4E91CD57D92F3B66BC0F9 /* handover.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 4F58746405636E81D1B74BB856FB8D2E /* RLMMigration_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 7097776D326A5C6920C043CB3E32C28E /* RLMMigration_Private.h */; }; - 4FAEEB41872BFE1F0224F1A0D29453A1 /* RLMResults.mm in Sources */ = {isa = PBXBuildFile; fileRef = D1963CF370AD94FF8542B49818029E44 /* RLMResults.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 5072AD824D6AD7E3B30F5F5FAA325BA2 /* collection_notifications.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9F872DC760E3A7A913501CDD0E49688B /* collection_notifications.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 5302DED431FC5C0BA69580C4DA6522AC /* external_commit_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA012AC6A1901FE6B7EA71FFA5BF29B4 /* external_commit_helper.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 544E1BACAA0914CEDEB101DB6E9726A9 /* sync_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05A7114F8F766A04D201539C57F60258 /* sync_manager.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 55051F3ABB7B00D559C626C144CFB875 /* RLMObject_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = D51047ABC2AFEE69E43D15A318848A24 /* RLMObject_Private.h */; }; - 556DD7E6D4603C0618602FBFB8AFD4D3 /* RLMAccessor.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 54B811089E20717FBE565C7DFF8959E0 /* RLMAccessor.h */; }; - 55AEF02F4B0D88FBCB7DEBC249E7C8A0 /* RLMCollection.mm in Sources */ = {isa = PBXBuildFile; fileRef = D071D5BA8565046C01C9ACED4E7A6D84 /* RLMCollection.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 5624B9E2392C7880697781A194D60B0A /* RLMRealm.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 5D81C9A7ACBF3EF1D8CFC6F10B626EE6 /* RLMRealm.h */; }; - 56643A709064D5CD283BB1FA211AB84A /* RLMSyncConfiguration.mm in Sources */ = {isa = PBXBuildFile; fileRef = 661739F0FBDC9E8CBC03C9699EB38E89 /* RLMSyncConfiguration.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 5C757868E35D76F281F86DF6A3EB9248 /* RLMPlatform.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = A5CCD9825C816504EEF6840EAEA70F72 /* RLMPlatform.h */; }; - 5CC058E066760D6A15E0E197BD320202 /* Realm.h in Headers */ = {isa = PBXBuildFile; fileRef = 09147D24067FA3848A918BAAEE2C07EB /* Realm.h */; }; - 5D4F419CA7D2F68938A37D3CE9A94B91 /* RLMObject_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = D51047ABC2AFEE69E43D15A318848A24 /* RLMObject_Private.h */; }; - 63ABD9F092F88AB6A497EFF2684EE16F /* RLMSyncConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ED1C41AF7A34E5092BAC9E583ADA1AE /* RLMSyncConfiguration.h */; }; - 63D654B4A872CD960AC8F7910EC8DF44 /* RLMAccessor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0B805AA31413DCF2DEBFE6409971B700 /* RLMAccessor.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 6532C6D910E007016F49C20188190D96 /* RLMObject.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = A27ADBC6D0F1A0029C22B746260CD620 /* RLMObject.h */; }; - 65D870331F885960B0FA671466EEB029 /* RLMSyncFileManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = B9DB85E07728315E010FEC792388CE57 /* RLMSyncFileManager.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 694864831D91F1D033FA1FA724094728 /* RLMRealmConfiguration+Sync.h in Headers */ = {isa = PBXBuildFile; fileRef = 014469716A1D2CD0219B1E692FFCEE88 /* RLMRealmConfiguration+Sync.h */; }; - 6C798E731BDA3F1C6032AA476CBD1808 /* RLMRealmConfiguration_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 48441474D1D8C3B66F967B0E76837062 /* RLMRealmConfiguration_Private.h */; }; - 7044BD9D2B94ED1CDB75B51982EC275B /* RLMListBase.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 519044AC217178621FF363269D6344C2 /* RLMListBase.h */; }; - 70DBB7C7EA6ABB6ABE1286EA7BD582A5 /* RLMSyncConfiguration_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = D8C27F6A06FBD7BC9D2CAA007D33BF65 /* RLMSyncConfiguration_Private.h */; }; - 71CE0EBA96635BA51BF115FC1BE82011 /* RLMRealm.mm in Sources */ = {isa = PBXBuildFile; fileRef = 32829B880D0B8DD45E1D882459CF2D88 /* RLMRealm.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 72AF75A275A6EBBAB857FFF63D9BD2DD /* RLMRealm.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D81C9A7ACBF3EF1D8CFC6F10B626EE6 /* RLMRealm.h */; }; - 74C34BE2B46DC63D1DB1ECACB071FC84 /* transact_log_handler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0485EC23C75C4004E94E2EABA6BE7C59 /* transact_log_handler.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 756B29527A3BB0C5DDEB9FCC7DFEB4AC /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CA6EBC2E57D96052268211209D6AA52 /* Cocoa.framework */; }; - 776B59705B4986805823CA7037A1790F /* RLMCollection.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 6FF63F74A7ADF71500412C2F86F7597C /* RLMCollection.h */; }; - 7A984943AF0AA3B7C2EE09B62273CC36 /* RLMObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A27ADBC6D0F1A0029C22B746260CD620 /* RLMObject.h */; }; - 7C063E56F503B745AE3866FDCEDAAB05 /* RLMSyncSession.mm in Sources */ = {isa = PBXBuildFile; fileRef = DC686D6D9603864D29EA0F2058FAB2CE /* RLMSyncSession.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 7C296329738864259BE74A954327C920 /* Pods-VBBNow-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 442FF1F0DFB50397039D6B4A956361AA /* Pods-VBBNow-dummy.m */; }; - 7E52912667F1F270927C06D44678D852 /* RLMListBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 519044AC217178621FF363269D6344C2 /* RLMListBase.h */; }; - 81A1870BCEA631B08938069F94C923F8 /* RLMRealmConfiguration.mm in Sources */ = {isa = PBXBuildFile; fileRef = 289AFBB1A2545E0525C8783CB4430B64 /* RLMRealmConfiguration.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 8608363EC049C080F037F7227DC19B58 /* RLMObjectSchema.h in Headers */ = {isa = PBXBuildFile; fileRef = EEAAE9E613DFE79610E529C04D19FD93 /* RLMObjectSchema.h */; }; - 9343F0F000A235F81FF81DF56912557D /* object_schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1431EDD4F50DF5FC020C0A75FB4F9DD /* object_schema.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 9465C567C5FACA5BA780EE38C29C0FC0 /* RLMClassInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = C261C8CF818E53F2D3EB0F29DB59877D /* RLMClassInfo.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 94EB706F84F12D62896A687E5247A449 /* RLMSyncSession.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 5138207173D645AD7161144B667D1D88 /* RLMSyncSession.h */; }; - 96EAD28BC5B0C6B9FA0A4BA2D224A2A8 /* RLMObjectStore.h in Headers */ = {isa = PBXBuildFile; fileRef = C92029B18F453CA95D99A21A7DBA7C65 /* RLMObjectStore.h */; }; - 9794EB916D24DC476025DDC90BBCBE2C /* RLMOptionalBase.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = DFF3E07B87AF9496BD5E82F5039E99F8 /* RLMOptionalBase.h */; }; - 9A653104F0A4F059CC2A17A02597F30B /* RLMConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 46D5B0F38D1D1335A0F0C64CB1924BB5 /* RLMConstants.h */; }; - 9A9436B44D911373AB9AF405B5A470F8 /* RLMSyncSessionHandle.mm in Sources */ = {isa = PBXBuildFile; fileRef = 63A49ECE34E65AAE2B43BB73B2737794 /* RLMSyncSessionHandle.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 9C90474C7943EDC97CCFFF54F5BB606D /* results.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8A2F88B75421BB1BAA51BC6DAA226894 /* results.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 9D53CA24F9378C6431F0EA43559D1A8A /* RLMOptionalBase.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = DFF3E07B87AF9496BD5E82F5039E99F8 /* RLMOptionalBase.h */; }; - 9E52C55923C95D151F8CDC2319A014AF /* RLMObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2290AC1CA7EB105C6C316E1CCBCB7092 /* RLMObject.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 9F0C6E80C8B828501B3A98BFCCB52BC3 /* RLMSyncConfiguration.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 2ED1C41AF7A34E5092BAC9E583ADA1AE /* RLMSyncConfiguration.h */; }; - A0207C417267F8D80608CD347AE74431 /* RLMSyncUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = FB5F122BB22DF7FECCC98129F7626EC2 /* RLMSyncUtil.h */; }; - A0E8EA415E181D84DD9E5D1A427244DE /* RLMSyncCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D337A9C1F193E27D99C6EB31B18C6F7 /* RLMSyncCredential.h */; }; - A6CC6C49F5B74F4B5D3E42A2E02AD1B6 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CA6EBC2E57D96052268211209D6AA52 /* Cocoa.framework */; }; - AADB69710892C7587FE5D6A902763897 /* sync_session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 15B2F0FB2718B1150B4B97C2E1D1CA0F /* sync_session.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - AC70C6FE3341A86A863E5BF70FA52101 /* schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB5F8F3612C08944A9FBF99D92590975 /* schema.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - B0AC441B01D8DB5DCCA426E5651AC66E /* RLMNetworkClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8428B5625A18C92C90C87BE598C76E /* RLMNetworkClient.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - B1EEE31F9BB07356685B2A7D049EF1BF /* RLMArray_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 424EA9C5FF9E322C559BD3FD10F9092B /* RLMArray_Private.h */; }; - B265C4151D9E434737B48FB2C145C90F /* collection_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5164B39A8F60C42A1AFF04B540316B7A /* collection_notifier.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - B2EC9D8EDD7510EA39E3FEF2901F4EAB /* RLMMigration.mm in Sources */ = {isa = PBXBuildFile; fileRef = D81269265A61E7F096BAAE0F9ECBC16A /* RLMMigration.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - B3EECF59B103F937622383FFFE23EACE /* RLMObjectStore.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = C92029B18F453CA95D99A21A7DBA7C65 /* RLMObjectStore.h */; }; - B5AC18C25F8FC499143A741BF616D4E4 /* RLMUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = 104BA96F47D6DBBD513718328A0F1D37 /* RLMUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - B8B3850B8A144C9AE501DF24DCBFDB72 /* RLMObjectBase.mm in Sources */ = {isa = PBXBuildFile; fileRef = B32F919064BB5621A476FEC9A530668C /* RLMObjectBase.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - BA8584CB008ED552E19C02C0F1C1FF8A /* RLMProperty.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 6944B6C86719E86FC72FC6723D02E65C /* RLMProperty.h */; }; - BDB7A9F7B1CA3A7FB83484EEE6F056D2 /* RLMObjectBase_Dynamic.h in Headers */ = {isa = PBXBuildFile; fileRef = E0FAFDE4566B1CC34938EFDB139DE1A5 /* RLMObjectBase_Dynamic.h */; }; - BE4CF1EB91E38AAD2E3F626074FA3B7B /* RLMProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 6944B6C86719E86FC72FC6723D02E65C /* RLMProperty.h */; }; - C078D7B810C111EA51CD5A3111D9CCA6 /* RLMConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 12C058B644388DD29B690D5B6D256A3E /* RLMConstants.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - C25EA19DAE982AB53978A64880299AD6 /* RLMSyncCredential.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 6D337A9C1F193E27D99C6EB31B18C6F7 /* RLMSyncCredential.h */; }; - C6C1EA7EE3EAA37FF202B12CBEE33441 /* RLMProperty_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 0C103E061A2B83B5131E18C9F68D1358 /* RLMProperty_Private.h */; }; - C7641E5193DBB4DC8023B532B5515C68 /* RLMObservation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7A310DA12B3F4F661AB508E5E4705E2E /* RLMObservation.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - C8DAAFDDA76EED996EABF4FF5D45E645 /* RLMRealm_Dynamic.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = B0B4CBC2DBA8C64954C17C9B1712ABD3 /* RLMRealm_Dynamic.h */; }; - CCD9217B7FEE3DCBEF777D5DDCAD7C40 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CA6EBC2E57D96052268211209D6AA52 /* Cocoa.framework */; }; - CD465BC37CA2FF8BE789E39975E35E5D /* RLMOptionalBase.h in Headers */ = {isa = PBXBuildFile; fileRef = DFF3E07B87AF9496BD5E82F5039E99F8 /* RLMOptionalBase.h */; }; - CE4031C6487FB4DBFF2040D587D40BB2 /* RLMSyncUser.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = FE6BD60C5945F58879F5FB4465F9CA95 /* RLMSyncUser.h */; }; - CEACC6846D2E72FA5A53D9C5FAB05373 /* RLMObjectBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FDFF56DA8141886E5E4CCD082498AE9 /* RLMObjectBase.h */; }; - D00D1CCB10A1022CFAA608EF5839E01F /* RLMRealmConfiguration.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 9C3C1F04C74D30BB29D88383FA57C0A3 /* RLMRealmConfiguration.h */; }; - D04FDB724FCB57B56451FDA378B3DF81 /* RLMRealmConfiguration+Sync.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2C8E33FA00AB7C9EFC177ECB50B14A90 /* RLMRealmConfiguration+Sync.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - D08E697963D472D7C74AA1B4E3EAA154 /* keychain_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1B10AD3AF9E9007B1ADA4C52747C4719 /* keychain_helper.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - D1B464A7B701D06CE68EA1E4D16AE82B /* RLMRealmConfiguration_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 48441474D1D8C3B66F967B0E76837062 /* RLMRealmConfiguration_Private.h */; }; - D4D62CCD84EFE66EA1B3EA9C84E4295D /* Pods-VBBNow-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B7BF347308AF7376AE5628738E029F34 /* Pods-VBBNow-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9EDE4C7FAB98E4748EC4F2A61C142F9 /* object_store.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1B96ECB64F7E33324B8EAFB4DC94F87 /* object_store.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - DDA39F3D8B58BC5C706974126968A29E /* RLMProperty_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C103E061A2B83B5131E18C9F68D1358 /* RLMProperty_Private.h */; }; - DDC791C84F0B3333332678E5A3B0E0A6 /* Realm-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 60CD2CA9A20CBD33026F7468BF866A42 /* Realm-dummy.m */; }; - DE0FCBF63D8647EA663F75079D1DE669 /* placeholder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D99D3E5BF4737F66FAEB2A939631017D /* placeholder.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - DE11B44683D024231348D5F2195950A7 /* RLMRealmConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C3C1F04C74D30BB29D88383FA57C0A3 /* RLMRealmConfiguration.h */; }; - DE90A3EC92681878243EF2BC7B85D233 /* Pods-VBB-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B929A0156BDC12308858E5593B17C8A8 /* Pods-VBB-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DF87DF84166C434562FDB6D4ABE889B8 /* RLMCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FF63F74A7ADF71500412C2F86F7597C /* RLMCollection.h */; }; - E04BC099AA88190010881F6916D2E64C /* list_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3954CF0D591CFD23F9D44FC4E7F8E2BE /* list_notifier.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - E130D71C0BF3F55BE4DDB9B4C09942A4 /* RLMListBase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 398E60EFE10734F5170C88A8018F4F8D /* RLMListBase.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - E15690DF46217ABA61459C79CB8CF2DA /* RLMSyncUtil.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = FB5F122BB22DF7FECCC98129F7626EC2 /* RLMSyncUtil.h */; }; - E62B6FA973D52D2D041CB23701C92E7E /* RLMArray.h in Headers */ = {isa = PBXBuildFile; fileRef = DB875141CED28FC407D7A4738BA2DE05 /* RLMArray.h */; }; - E74813D5F09AB418E5B4F080A8F3B227 /* RLMObjectStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = DBDA483D331CC99EF81F98B144715EAE /* RLMObjectStore.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - E76D31AD3C9E0A43F80836E98322C222 /* RLMSyncUtil_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 9F7FD2D8A72BC62BAC9A5931BB8C3464 /* RLMSyncUtil_Private.h */; }; - E826E09AD10DBCD600CECF5E8C80CCE2 /* RLMArrayLinkView.mm in Sources */ = {isa = PBXBuildFile; fileRef = C5A151B1BBB1D2C9B2BE3FCCA114A573 /* RLMArrayLinkView.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - EAD97A68A613DD4F207299CB0B036977 /* RLMArray_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 424EA9C5FF9E322C559BD3FD10F9092B /* RLMArray_Private.h */; }; - EC55CE2A747B9BFD497E58F8F0120438 /* RLMAccessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 54B811089E20717FBE565C7DFF8959E0 /* RLMAccessor.h */; }; - ECADB9F2D979BFE218CE73DEA261B947 /* RLMSyncSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 5138207173D645AD7161144B667D1D88 /* RLMSyncSession.h */; }; - F1893A4FB1BC0BE070CE1BCFE9641AFC /* RLMSchema_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 38141611BE7DF729928941BA5ED8BC49 /* RLMSchema_Private.h */; }; - F270F70C1CC1F8D9BEAC0D4700BC0F4F /* RLMAnalytics.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7EC6087687F7A71A96DD7662570C4077 /* RLMAnalytics.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - F471118B12C5193A90A3283314A34C15 /* realm_coordinator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37D49A8BFA46FD198F9029FF866B84D7 /* realm_coordinator.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - F4E71F4EBC55B769AD296B6AC5109AB6 /* RLMObjectBase.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 4FDFF56DA8141886E5E4CCD082498AE9 /* RLMObjectBase.h */; }; - F7B284A01CA0D53C6AA567B45DB6A334 /* format.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CBEFAEC42322EE588C4CE1BF939C4C72 /* format.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - FB0237CD7B7ED219C343DC27A6644BBA /* RLMPredicateUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = 766345985B39340DCF40D53045539AC0 /* RLMPredicateUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - FB7C24C7506A303C5AF86D52B632F206 /* Realm.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 09147D24067FA3848A918BAAEE2C07EB /* Realm.h */; }; - FC99FFCB75E617388EFED2A9CA768766 /* list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18130AD268176A0279E97E442ABFEDCD /* list.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.0.1\"' -D__ASSERTMACROS__ -w -Xanalyzer -analyzer-disable-all-checks"; }; }; - FD7A325EB0D58CA698E083C9E3775C7C /* RLMConstants.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 46D5B0F38D1D1335A0F0C64CB1924BB5 /* RLMConstants.h */; }; - FF7E1F9AE17C7BB6B70C4C7C7102E75F /* RLMMigration_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7097776D326A5C6920C043CB3E32C28E /* RLMMigration_Private.h */; }; + 05DBD8D125C3F768A8E594A393E68CDB /* sync_metadata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B801378173B9D2B9C19028FC7C5F825 /* sync_metadata.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 05F3C48F7872D18B1ED02E13B97BEAEE /* RLMResults.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1751EACA219057FB7456621679BA2401 /* RLMResults.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 06A6E1CC2F9240806864B0908625E553 /* RLMSyncUser.h in Headers */ = {isa = PBXBuildFile; fileRef = A2EE6A9E046640D359CAB73B80320FFE /* RLMSyncUser.h */; }; + 0727EDE23165B49DE1249DED8150CA8F /* RLMListBase.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = C55FE2C555506A88D4BAF650C12867E3 /* RLMListBase.h */; }; + 08DB46DBBF8CAE627E31C2AE31CB01B2 /* RLMSyncUser.mm in Sources */ = {isa = PBXBuildFile; fileRef = CE9EF36DD57A76D33FD75564FA8B60BE /* RLMSyncUser.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 09DED5644A2DE5C7E7C261B6DB24EEF1 /* RLMSchema.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AE1CC3B0C54E737FF56A252B579D2E0 /* RLMSchema.h */; }; + 0C8EA8830DAF786E3513F4F2FB65E5FA /* RLMMigration_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = A5D4607B3A4E52359D0E8B8692E423DA /* RLMMigration_Private.h */; }; + 0CBA9D1D9C5BFFDC693497798E35E7C0 /* RLMPlatform.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 1AE1D644DD3862A7E16768BAFEAAD709 /* RLMPlatform.h */; }; + 0D61589C725AB01DA048B01D3C7E6650 /* RLMRealmConfiguration_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 4A006CFD858DDF1A94AE5E734BD7764E /* RLMRealmConfiguration_Private.h */; }; + 0D69439A117F6936F8493B07647AB2BB /* RLMProperty.mm in Sources */ = {isa = PBXBuildFile; fileRef = 30E336A7C1EA27F5B451FBE3DBC36A07 /* RLMProperty.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 0E4C4128B27BB582A0DEAF0A8C5633A2 /* RLMSyncPermissionChange.m in Sources */ = {isa = PBXBuildFile; fileRef = C682053DECAE69B034815B792F03D620 /* RLMSyncPermissionChange.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 109EC6BE3A54A077687E86D1713ECFFE /* RLMRealmConfiguration+Sync.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 2F913857B663FFCD78EA3272B4D9ECFC /* RLMRealmConfiguration+Sync.h */; }; + 14B2E954E29084BEC30479DCFE45AF87 /* RLMOptionalBase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7210F2C38964418F7E3BD25871BE64C1 /* RLMOptionalBase.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 15D9B86B6C80959B8BF1B90F5DC97FAD /* RLMObjectBase_Dynamic.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AAC83F418897D2B121C709B49F4412F /* RLMObjectBase_Dynamic.h */; }; + 16A20B38AFF37E6B9B8D4098EABAA6A2 /* RLMSyncManager.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = B877F67F7BF62A61B88198D6AAB4D7FB /* RLMSyncManager.h */; }; + 16F482E8DCC7E38178A6F9B3A1F419BA /* RLMRealm_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = F0D10F3D0EABFF6ABCAFFA14B9AD02B6 /* RLMRealm_Private.h */; }; + 182178BB78B5C1D12A667DFB637FA9E4 /* RLMObjectSchema.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = AB025FABAAF248803A252D707FAC5B62 /* RLMObjectSchema.h */; }; + 1BDA95A0FA259BD85F14D8DEA042FFB6 /* RLMPredicateUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = FAFA814BB88EF5FD337338A2F0FF51D4 /* RLMPredicateUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1C0504D90972BFB606BB4D7F16F7CE10 /* RLMRealmConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 81833731DAFA92A367A5A877335815F2 /* RLMRealmConfiguration.h */; }; + 1C32C382875D46E34D31E7BE55A8809A /* RLMConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A629EBBD35DCEB4AF7041A55938591A /* RLMConstants.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1DE96EC791D4A098A779265D9EC20112 /* RLMQueryUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = D7CF164EEEFE85102FFE630F0E85AD80 /* RLMQueryUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 1E63E40043AD28B4ABDEEAEB7509E68F /* RLMResults_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = F137EBA0B76C022AABCD8E7768C72514 /* RLMResults_Private.h */; }; + 21DEE65195D52FEE3C6C0538CDD631C4 /* RLMSyncUtil_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 607539AC413FBCD9851327FA3F2BAA6D /* RLMSyncUtil_Private.h */; }; + 25C20A5AB004124FE9D44207BD18FED3 /* RLMObjectSchema_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 9662DF7C5E53A767E7A8010F23F00AC4 /* RLMObjectSchema_Private.h */; }; + 264B1E953276612B1A04FA1B27C7D036 /* RLMRealmConfiguration.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 81833731DAFA92A367A5A877335815F2 /* RLMRealmConfiguration.h */; }; + 29D1AC5689D0E7855816E9AD5DEE02F9 /* RLMObjectBase.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = EA984350FB2017E9FB4E0BB349AF4709 /* RLMObjectBase.h */; }; + 2E1DC3DFD53D75FD37BF66B5A9BF8CB8 /* RLMCollection.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 97304DB97C36ED573506661757DCF909 /* RLMCollection.h */; }; + 2F91B6A0AC5472FD723716C077D2073E /* RLMSyncManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 42E896057D80950C8B0D9B7877BB6326 /* RLMSyncManager.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2FCA79E919981FD899ACC4FA58BC0BAF /* RLMRealm.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 43662C66460EFC7D9E291F9B9086B694 /* RLMRealm.h */; }; + 30AE92785A431280401D7A979C26DEC2 /* RLMArray_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = F0B3A8ED49858453B76D3400A624A15B /* RLMArray_Private.h */; }; + 3278C5E9E7CC1A63A491108E87DCD648 /* RLMRealmConfiguration_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A006CFD858DDF1A94AE5E734BD7764E /* RLMRealmConfiguration_Private.h */; }; + 3474F310D512FFEEAA3A5F47D83CD0C6 /* realm_coordinator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A5FDB219098757033113A20F42EC7EC /* realm_coordinator.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 34E4C87866115998CE469D0E6F9C4E03 /* RLMObject.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = E85B45CF5840DFB28ED7AD863CED703D /* RLMObject.h */; }; + 385CF3E76D20DBF3516F54C9C4E00460 /* Realm.h in Headers */ = {isa = PBXBuildFile; fileRef = BC72C77F253149E7F9F4B3B344566EB2 /* Realm.h */; }; + 3A68C58E4FCA79C3C9AFD139E08C559C /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 270DD1219F1E6CF00379D39F252D87C6 /* Cocoa.framework */; }; + 3BCA4F0CEC1ADDD2B8346F86BB5C4702 /* RLMSyncPermissionChange.h in Headers */ = {isa = PBXBuildFile; fileRef = 962A7019E7948A80AB45F39A7DFE01BD /* RLMSyncPermissionChange.h */; }; + 3CA5935115C2D6E2F349E428194B424A /* RLMListBase.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = C55FE2C555506A88D4BAF650C12867E3 /* RLMListBase.h */; }; + 3FDB4B70D55AB8E010B7C2077AA9C38F /* RLMSyncConfiguration_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = AA362F932DF0854B4BA5C5C5CBCECF79 /* RLMSyncConfiguration_Private.h */; }; + 4227BEC869C4159105EA17006E6E9FEA /* RLMAccessor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 842819BB0817F06B3BE15E916433226E /* RLMAccessor.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 429E1E3DD42BE99C4FC9037437D5031C /* object_schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E41BCB4E534CB8835740B939DC23FFC1 /* object_schema.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 42A0D568C983936DB0660E998E63E466 /* sync_session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C49E14BC92FDFBDBD3704FDE565C169 /* sync_session.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 43F6CFB800CB881BCB56A999ED0001AD /* RLMProperty_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = C1CE85299CE26714C404B4986AE03A1D /* RLMProperty_Private.h */; }; + 441E2DF52C983BD5A3756294A1CD7396 /* RLMObjectSchema.h in Headers */ = {isa = PBXBuildFile; fileRef = AB025FABAAF248803A252D707FAC5B62 /* RLMObjectSchema.h */; }; + 44BA672A2D5B10B36C8DA3B9B74A51E7 /* RLMAuthResponseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 9879E438CC8862D98C6A1D413281B540 /* RLMAuthResponseModel.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 46FC1435E3972C39787E6EC0B97A5493 /* Realm-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 396431AE286E1938A480C6B7F5BA86A5 /* Realm-dummy.m */; }; + 477EBEC0444079C11199C41378513829 /* format.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E177B0177B0A05503FEE813634035AC2 /* format.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 47C415354DB093EAD0CD47C693C4066F /* RLMSchema.mm in Sources */ = {isa = PBXBuildFile; fileRef = 19568FA5741E7C17F8CA64CF5C25A676 /* RLMSchema.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 49BB799A5AA054ED13B0E8B6EE3F38E5 /* collection_change_builder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6C46D6C0783F61C6E1D253660E472622 /* collection_change_builder.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 500338D2146D76BAB72F9A9C843AA682 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 270DD1219F1E6CF00379D39F252D87C6 /* Cocoa.framework */; }; + 500DBB9902058720722E16E6C40FF495 /* RLMConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = A46E0C3460F4755D41E89231F71F52D3 /* RLMConstants.h */; }; + 505FD3AFEB77D52890E0E00B7FC34276 /* results.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCDC499822E9ACD5E24C9AB0CD479F84 /* results.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 5347FB095831DAD9A7DCBD457BA2FCD9 /* thread_confined.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F1C8328614183AFAEC5511A660E8162D /* thread_confined.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 59EBC6E1FC13E47F7420EB9639AE8369 /* collection_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8745208AEDA874159FEEAC2FA2DDB148 /* collection_notifier.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 5AF9149DE122F5511B88F615536F3A74 /* RLMSyncPermissionChange_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 406F84DAC28B85067F1FDE8F2159D1B3 /* RLMSyncPermissionChange_Private.h */; }; + 5BF6EF17288A787E9F648C7003741977 /* RLMOptionalBase.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = BFA3C0619720C825FFD969A8694D6459 /* RLMOptionalBase.h */; }; + 5C61BB64B116F23C0C57A1EA43BE42EA /* RLMAccessor.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = A57CD6C47A80BC1DD1C7135012261456 /* RLMAccessor.h */; }; + 5E229AE338922099B3877043DCF20410 /* RLMSyncManager_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 31DAABC9CC6C6DA17482CF2698838940 /* RLMSyncManager_Private.h */; }; + 5E84340694A9E67EB8D3CE69F7926C7C /* RLMObjectSchema.mm in Sources */ = {isa = PBXBuildFile; fileRef = 18AE4F83A475D08286BE890E54DAEC63 /* RLMObjectSchema.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 5EB973A865695E65B90665CC3B564E68 /* RLMSyncConfiguration_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = AA362F932DF0854B4BA5C5C5CBCECF79 /* RLMSyncConfiguration_Private.h */; }; + 622896028277741362B6CACBDB7282AB /* RLMProperty_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = C1CE85299CE26714C404B4986AE03A1D /* RLMProperty_Private.h */; }; + 632EF17C5D99597469184E7270B73916 /* RLMSyncCredentials.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D94346D87FDA36DEB8D1163228477 /* RLMSyncCredentials.h */; }; + 63C3177DFA084E5CB80B88682DA82991 /* RLMSyncUtil.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = D536E13D0B52FC8D5B1282CB79A9F1B3 /* RLMSyncUtil.h */; }; + 64D24812223C912FF5B106905363973E /* RLMRealmConfiguration+Sync.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F913857B663FFCD78EA3272B4D9ECFC /* RLMRealmConfiguration+Sync.h */; }; + 67BE493B54641A55CD8072710FDE9CC8 /* RLMMigration.h in Headers */ = {isa = PBXBuildFile; fileRef = 7123AFF085B35CDFF3D705B06AB75638 /* RLMMigration.h */; }; + 68399A7792E12B13032570F22B6E2EA4 /* RLMSyncCredentials.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 173D94346D87FDA36DEB8D1163228477 /* RLMSyncCredentials.h */; }; + 6A710329D4DD487A170CF3F3DBEA5FD7 /* RLMArrayLinkView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5CC5E03DF0C0E51B12CCC635C1F0B105 /* RLMArrayLinkView.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6A7281BA44249E241901FA077EE82242 /* RLMRealm.mm in Sources */ = {isa = PBXBuildFile; fileRef = FB3E640EA7BD2B8D315F453E29E1537E /* RLMRealm.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 71322DEB42B90731861F2B09F6736254 /* RLMSchema_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DF7706F095459FD4971E5CFD187AED6 /* RLMSchema_Private.h */; }; + 739C359E5373B8F29716D3A1DA5D5DBE /* RLMResults.h in Headers */ = {isa = PBXBuildFile; fileRef = A41691C4302FAC7629802089876E8848 /* RLMResults.h */; }; + 74F26456BE08FF60524635AFDE452A41 /* RLMSyncUtil_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 607539AC413FBCD9851327FA3F2BAA6D /* RLMSyncUtil_Private.h */; }; + 7833FE6ACE50F62478F10E58D7546076 /* RLMSyncPermissionChange_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 406F84DAC28B85067F1FDE8F2159D1B3 /* RLMSyncPermissionChange_Private.h */; }; + 7A13A77BBD5BB889E338FD425C7A7659 /* list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FF26C210A745CF572D4577E4676CCD4C /* list.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 7B6FCE53992B4357291D552613C06A79 /* RLMSyncConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 6358FFFE171233AE4F917C29DE8E817F /* RLMSyncConfiguration.h */; }; + 8162CD7C7344CDE6DD4B4C0A585B450C /* RLMSyncSession.mm in Sources */ = {isa = PBXBuildFile; fileRef = BD17FF5BBECD1015FC9988031ED4384D /* RLMSyncSession.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 83A60CAD9E8F19D398F8E3DC1F07C705 /* RLMListBase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 27FF71D843775C57E7B8AAA4979F4A86 /* RLMListBase.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 846D2144F53FB461D2AEFA1201BF1738 /* RLMSyncManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B877F67F7BF62A61B88198D6AAB4D7FB /* RLMSyncManager.h */; }; + 85DCA8034220ABF3A07E830147843F85 /* shared_realm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AD292E35AB2D656F1CD2B974E3A63B /* shared_realm.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 878F789CE2EF674C6DCCD53D3B792BAD /* RLMObjectBase.h in Headers */ = {isa = PBXBuildFile; fileRef = EA984350FB2017E9FB4E0BB349AF4709 /* RLMObjectBase.h */; }; + 87D584752B968A6FDA9D7E03E15FE7EF /* schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93B4F8BAA6A5D122AF94E4E017B223A6 /* schema.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 89512A53E3563F67296869C895F72643 /* RLMSyncSessionRefreshHandle.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8A1BCE9F0706933B9C52B3F71A6CB35C /* RLMSyncSessionRefreshHandle.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 89B0D6E308FDEA7BCC9595FA86A5CCA5 /* RLMListBase.h in Headers */ = {isa = PBXBuildFile; fileRef = C55FE2C555506A88D4BAF650C12867E3 /* RLMListBase.h */; }; + 8A1AFDB383AB1D2478D593940716C77F /* RLMObjectBase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6CA7A5BB864ADDEDE2B7D29EA2C83418 /* RLMObjectBase.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8AAF77B36EC9EBBF8C71016CC0B0477C /* RLMObject_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = C36347AE80C13783C1D80ED4DAE84C86 /* RLMObject_Private.h */; }; + 8ADE9886BC266D00B2ACAF5E6AA7EF5A /* RLMSyncCredentials.m in Sources */ = {isa = PBXBuildFile; fileRef = B711C581A88BD9FE0DDD4F9141EFE382 /* RLMSyncCredentials.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8C6D2F00EA4311CC4FCE75B4253C2B43 /* handover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C3AE2CBBB9AEF2E0AA421B3316B3B983 /* handover.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8CB71DAA0A649F89022686F28F17DD09 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 270DD1219F1E6CF00379D39F252D87C6 /* Cocoa.framework */; }; + 8F198282A52C6329CFCAADFAD16CA425 /* results_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 589E794D261E19A6638A2A2285F592D0 /* results_notifier.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8FB5D05A734415B912C2EAB2C74F4053 /* Pods-VBBNow-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B7BF347308AF7376AE5628738E029F34 /* Pods-VBBNow-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9001A69BC9D7D22C7A87055FB41B856A /* RLMArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 595CD5E05996D9C6E812BCAD75B77CC4 /* RLMArray.h */; }; + 941C9CC87387BCB9ACF6E4633D7BE11F /* RLMProperty.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 9AB1D76D5F4D78EB58442B1D5A0E227C /* RLMProperty.h */; }; + 97EF980147B739EF1964165D3A09FED1 /* keychain_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDBAE440891841D85B8B304695888694 /* keychain_helper.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9C52AD2FF9F68A2B50869CCD1DA1484E /* RLMNetworkClient.m in Sources */ = {isa = PBXBuildFile; fileRef = EED4293C58AA5A0D21213F39C12BEFA7 /* RLMNetworkClient.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9DEB1A9675C6DC24A2FE779538CF4B0A /* RLMSyncUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5C3196F97E003804B9BDD075494F299E /* RLMSyncUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9F9349A0B552A9A47CC73A5406092FF0 /* RLMMigration_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = A5D4607B3A4E52359D0E8B8692E423DA /* RLMMigration_Private.h */; }; + A294A1A3CB8FE80AA36F2567C36087F1 /* RLMPlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AE1D644DD3862A7E16768BAFEAAD709 /* RLMPlatform.h */; }; + A2F8A6E34A8BD7DD26B9B79F7F4BBD22 /* RLMProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AB1D76D5F4D78EB58442B1D5A0E227C /* RLMProperty.h */; }; + A47F5B74E9FA3C32F6F8192F1C12579C /* Pods-VBB-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B929A0156BDC12308858E5593B17C8A8 /* Pods-VBB-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A64FB462F2F55FE4D36E95F4DB46DCDE /* RLMRealm.h in Headers */ = {isa = PBXBuildFile; fileRef = 43662C66460EFC7D9E291F9B9086B694 /* RLMRealm.h */; }; + A80FCF8588238A5669071A51E8F01F30 /* RLMRealm_Dynamic.h in Headers */ = {isa = PBXBuildFile; fileRef = BF1F05958D394CC73FAD54C74857DFB7 /* RLMRealm_Dynamic.h */; }; + A97EA07AEE0202EFEFA5E43FDB28CC5A /* sync_file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 54899CE56D9776FA8B5DE8FA2A773BEB /* sync_file.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A98F81B68B736D3F55D163A8CF24C9A5 /* RLMObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = AC3C1FCD80BB317610A445C2D61A6447 /* RLMObject.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A9B59E01A7526997D7F2BF8EDC3EA168 /* RLMRealmConfiguration+Sync.mm in Sources */ = {isa = PBXBuildFile; fileRef = 328DEE271B3CD7A53BADCA85C261B7C4 /* RLMRealmConfiguration+Sync.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AB3BD7540E6E68710609A40565307246 /* RLMRealmConfiguration.mm in Sources */ = {isa = PBXBuildFile; fileRef = 75899BEC4655592543A2EC218AC1ACE3 /* RLMRealmConfiguration.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AD1D8D08CFD525D51361BF3955A882B5 /* sync_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C030C57D7F1395F1350BFEFC7EF37EF8 /* sync_manager.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AF6AEF120785DD0FFC80F9DDCD16D5D2 /* RLMObjectStore.h in Headers */ = {isa = PBXBuildFile; fileRef = B7A22640019BF322FD69A3FC75662C87 /* RLMObjectStore.h */; }; + B1479361D3076C0F766531DAEE3460A8 /* RLMObjectSchema_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9662DF7C5E53A767E7A8010F23F00AC4 /* RLMObjectSchema_Private.h */; }; + B37AA799915AE03EE849805F6C782C45 /* RLMAccessor.h in Headers */ = {isa = PBXBuildFile; fileRef = A57CD6C47A80BC1DD1C7135012261456 /* RLMAccessor.h */; }; + B41C5EFFD4DC9139F3F05E8ACFBE3FAB /* RLMOptionalBase.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = BFA3C0619720C825FFD969A8694D6459 /* RLMOptionalBase.h */; }; + B4B71FE8662DAB1124359B4A4BCEF80D /* RLMSyncSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 50F59561979D2AFC6D63C18BEA53EE69 /* RLMSyncSession.h */; }; + BA61D4C8C784F7786D671CB2D04CBFA8 /* RLMObjectStore.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = B7A22640019BF322FD69A3FC75662C87 /* RLMObjectStore.h */; }; + BE36CC148B32FA43571C217DABB7B9C8 /* RLMSyncSession.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 50F59561979D2AFC6D63C18BEA53EE69 /* RLMSyncSession.h */; }; + BEBBA4400C87D961413FFA0DC7E931F1 /* RLMResults_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = F137EBA0B76C022AABCD8E7768C72514 /* RLMResults_Private.h */; }; + BFAC8FA7FF03E61641773CCD2D780940 /* RLMSyncUser.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = A2EE6A9E046640D359CAB73B80320FFE /* RLMSyncUser.h */; }; + C1C2377BCCF027C11682082030921F3F /* external_commit_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2308EC716DAE5A031F0561FE45BE112B /* external_commit_helper.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C37BE1A79E6595D677BD3FF11208704E /* RLMRealmUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = BBC3565C3A2FCE6639D20C68353E504E /* RLMRealmUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C47AEBAE5768043D7145C86F9442E206 /* RLMSchema_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 2DF7706F095459FD4971E5CFD187AED6 /* RLMSchema_Private.h */; }; + C5A96DC6F9C3DDAD9482F18CC9AF1486 /* RLMArray.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1B29797E7F996208B3F56B01C8068CC /* RLMArray.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C67CBD9B466D24F30E05E1E1185F88B7 /* weak_realm_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0605B3919063758184EDE3E40A9AB8C6 /* weak_realm_notifier.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C70C353F2DAB85D06CE3FF0C283EEBD5 /* RLMRealm_Dynamic.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = BF1F05958D394CC73FAD54C74857DFB7 /* RLMRealm_Dynamic.h */; }; + C84817A7CD1004E0E2D8084579C06D77 /* RLMConstants.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = A46E0C3460F4755D41E89231F71F52D3 /* RLMConstants.h */; }; + CA47DE883C5D5664489656A034BF4ADF /* RLMObjectStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = E5A5BD2F46C4BF5023EFC4E3278F70DC /* RLMObjectStore.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + CAEE7253E91FB51DA2906B5D8F2F2BEF /* Realm.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = BC72C77F253149E7F9F4B3B344566EB2 /* Realm.h */; }; + CE4A935512F17BFB39C87819174C0FCF /* RLMObjectBase_Dynamic.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 3AAC83F418897D2B121C709B49F4412F /* RLMObjectBase_Dynamic.h */; }; + D04F905FB9234868A99258983E565481 /* RLMCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 97304DB97C36ED573506661757DCF909 /* RLMCollection.h */; }; + D1FAB3EB37197E12A3601E1AAAFD6B3D /* RLMResults.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = A41691C4302FAC7629802089876E8848 /* RLMResults.h */; }; + D2142F672ED7250A562047FE46524C38 /* RLMOptionalBase.h in Headers */ = {isa = PBXBuildFile; fileRef = BFA3C0619720C825FFD969A8694D6459 /* RLMOptionalBase.h */; }; + D35F5E9BD02ECB3F0F6B6F8B79BFA63F /* object_store.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E847382C16A12FB27419671BE87CBF48 /* object_store.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D4C7BBE293B075535AFA737C878D7D02 /* RLMMigration.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1930B09148A313A9BC9B4B7A8177E1B4 /* RLMMigration.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + D6BADCA8931FB6B904B60ECCDAD723B4 /* Pods-VBB-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 670BBB97DAC0DF3030CDC5E2D40B5024 /* Pods-VBB-dummy.m */; }; + D9DCC94D29A0408E394074988BE47133 /* transact_log_handler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C1D6BDAF543593F2F7C2073804F277C /* transact_log_handler.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DB59DC2450130901D111B0DF5671F552 /* RLMObservation.mm in Sources */ = {isa = PBXBuildFile; fileRef = BF0F199551C99F2AF39C52369269BC6A /* RLMObservation.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + DC526F8CAD4D0C0C874A6574AF8125FC /* RLMClassInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = 00256CADEDF0A4449FB3C7808A0A76C8 /* RLMClassInfo.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E0063353A50BF81430DE33A115D09284 /* RLMRealm_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = F0D10F3D0EABFF6ABCAFFA14B9AD02B6 /* RLMRealm_Private.h */; }; + E1CD95813DB6A31BF8BB2BCE67D617C8 /* RLMSyncPermissionChange.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 962A7019E7948A80AB45F39A7DFE01BD /* RLMSyncPermissionChange.h */; }; + E25675D107032EC0BD4932F1D2082908 /* RLMObject_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = C36347AE80C13783C1D80ED4DAE84C86 /* RLMObject_Private.h */; }; + E37B338D5550987BDC4AF5534DAD7515 /* RLMObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E85B45CF5840DFB28ED7AD863CED703D /* RLMObject.h */; }; + E3963E66B3C28B0C48D704B3E46023E7 /* Pods-VBBNow-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 442FF1F0DFB50397039D6B4A956361AA /* Pods-VBBNow-dummy.m */; }; + E5CBF99119746C04F2BFC1A1D5CA22D1 /* RLMSyncManager_Private.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 31DAABC9CC6C6DA17482CF2698838940 /* RLMSyncManager_Private.h */; }; + E8B57737686524010B0E97495370C61A /* RLMSyncConfiguration.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 6358FFFE171233AE4F917C29DE8E817F /* RLMSyncConfiguration.h */; }; + E91364FEBEBD7DE01B34E7BB08678F8D /* placeholder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0CF987B74A9228808D79F2728CCA910 /* placeholder.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E992BF718E58B53660588898BC09216F /* RLMSchema.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 1AE1CC3B0C54E737FF56A252B579D2E0 /* RLMSchema.h */; }; + E9C18EF87FEA05164AC706B936C2E3F9 /* list_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A22E12264A783E6AC7BB0831C3CAFA0A /* list_notifier.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E9E1AEDF2C30282A3F82D1C6A5248493 /* RLMSwiftSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C16C4A846BCBF9E4D13D3FC8A9FF4D /* RLMSwiftSupport.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F1963CC84D3C9E92441FB5868361CD9B /* RLMTokenModels.m in Sources */ = {isa = PBXBuildFile; fileRef = 403E12E002FB0D181261C590B7B14BD4 /* RLMTokenModels.m */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F2751B5F0355B8FB31E4504853686066 /* RLMAnalytics.mm in Sources */ = {isa = PBXBuildFile; fileRef = 817D8B62EE7BAB27C2D7AC377912262D /* RLMAnalytics.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F27ACDCFA1305AED15000A6E169A09F2 /* RLMMigration.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 7123AFF085B35CDFF3D705B06AB75638 /* RLMMigration.h */; }; + F5A24CF92B643E0CB22BC70D6EF4B755 /* RLMUpdateChecker.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1D47B5C027BBF9EFE751A390BDBEF096 /* RLMUpdateChecker.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F600C0EA3461CC3550342BAF36F1D8AB /* RLMCollection.mm in Sources */ = {isa = PBXBuildFile; fileRef = F87B39E953F550932766A60E627858E5 /* RLMCollection.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F6CA4527F3E65BD332E0EFCCC4265121 /* sync_user.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14A60E08812158EE860006A89CC29F09 /* sync_user.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + F7202CDF8CDE913D4ABD17DD6819E9A7 /* RLMSyncUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = D536E13D0B52FC8D5B1282CB79A9F1B3 /* RLMSyncUtil.h */; }; + F914CA252023D3BEA41D090F0EE481A7 /* RLMArray.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 595CD5E05996D9C6E812BCAD75B77CC4 /* RLMArray.h */; }; + F928E16E2B2FFB5E53D9D155D2C6EFA5 /* RLMArray_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = F0B3A8ED49858453B76D3400A624A15B /* RLMArray_Private.h */; }; + FC31C9E08F4FB2665B721C99EFB2C6F7 /* RLMUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57AA417A0A637C8877C7338959DA5380 /* RLMUtil.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + FC4980676574C10ED6F181FECB3B9EBA /* RLMSyncConfiguration.mm in Sources */ = {isa = PBXBuildFile; fileRef = 86A5FE684DBA2A9BA18F97C555BF7EA2 /* RLMSyncConfiguration.mm */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + FCF10E56DC800578258374E69657C75A /* collection_notifications.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EDE5687A305C57C985AB9A665B77C53C /* collection_notifications.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; + FFF5BD906CBC4FF7A08896F5139E85D4 /* index_set.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE619E8BF823EDFA0B94672B12630032 /* index_set.cpp */; settings = {COMPILER_FLAGS = "-DREALM_HAVE_CONFIG -DREALM_COCOA_VERSION='@\"2.1.1\"' -D__ASSERTMACROS__ -DREALM_ENABLE_SYNC -w -Xanalyzer -analyzer-disable-all-checks"; }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 450E9CDC72DCD25DC23494BF4A427D81 /* PBXContainerItemProxy */ = { + 23A0E0DCCCB9375813C9BB753AE5BAF9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; - remoteGlobalIDString = 4DDB663ABA2FF8128D066C4CD1A0F7F0; + remoteGlobalIDString = 6C31A1283F4FB329C26860F6277C6F90; remoteInfo = Realm; }; - 4FA23BEBDF90894A985DBB2C8C784EDE /* PBXContainerItemProxy */ = { + F31F63D41F116CA578B3F01FD5EC18BD /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; - remoteGlobalIDString = 4DDB663ABA2FF8128D066C4CD1A0F7F0; + remoteGlobalIDString = 6C31A1283F4FB329C26860F6277C6F90; remoteInfo = Realm; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - 7AF2A1A857C7DF989801F87CE3B495D0 /* Copy . Private Headers */ = { + 5281406C0A3757FF864A6DE0E5E374ED /* Copy . Private Headers */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = "$(PRIVATE_HEADERS_FOLDER_PATH)/."; dstSubfolderSpec = 16; files = ( - 556DD7E6D4603C0618602FBFB8AFD4D3 /* RLMAccessor.h in Copy . Private Headers */, - EAD97A68A613DD4F207299CB0B036977 /* RLMArray_Private.h in Copy . Private Headers */, - 4E0DBF31B59294CCA9D351A1000BE61D /* RLMListBase.h in Copy . Private Headers */, - 4F58746405636E81D1B74BB856FB8D2E /* RLMMigration_Private.h in Copy . Private Headers */, - 5D4F419CA7D2F68938A37D3CE9A94B91 /* RLMObject_Private.h in Copy . Private Headers */, - 1C7CF7709F1068C2E9A1FEA600F71D9D /* RLMObjectSchema_Private.h in Copy . Private Headers */, - B3EECF59B103F937622383FFFE23EACE /* RLMObjectStore.h in Copy . Private Headers */, - 9794EB916D24DC476025DDC90BBCBE2C /* RLMOptionalBase.h in Copy . Private Headers */, - C6C1EA7EE3EAA37FF202B12CBEE33441 /* RLMProperty_Private.h in Copy . Private Headers */, - 4D8709EF2534A594EEB8A79139AE7E77 /* RLMRealm_Private.h in Copy . Private Headers */, - 6C798E731BDA3F1C6032AA476CBD1808 /* RLMRealmConfiguration_Private.h in Copy . Private Headers */, - 45079426CDE485F7432B315D39E64F2E /* RLMResults_Private.h in Copy . Private Headers */, - 33AD3184091299FAABDBC4E578E877E9 /* RLMSchema_Private.h in Copy . Private Headers */, - 4ED964D1A0592AC145D6C14072868365 /* RLMSyncConfiguration_Private.h in Copy . Private Headers */, - 1740CA8FB9F7912BD75D644C0F4F2831 /* RLMSyncSession_Private.h in Copy . Private Headers */, - E76D31AD3C9E0A43F80836E98322C222 /* RLMSyncUtil_Private.h in Copy . Private Headers */, + 5C61BB64B116F23C0C57A1EA43BE42EA /* RLMAccessor.h in Copy . Private Headers */, + 30AE92785A431280401D7A979C26DEC2 /* RLMArray_Private.h in Copy . Private Headers */, + 3CA5935115C2D6E2F349E428194B424A /* RLMListBase.h in Copy . Private Headers */, + 9F9349A0B552A9A47CC73A5406092FF0 /* RLMMigration_Private.h in Copy . Private Headers */, + E25675D107032EC0BD4932F1D2082908 /* RLMObject_Private.h in Copy . Private Headers */, + 25C20A5AB004124FE9D44207BD18FED3 /* RLMObjectSchema_Private.h in Copy . Private Headers */, + BA61D4C8C784F7786D671CB2D04CBFA8 /* RLMObjectStore.h in Copy . Private Headers */, + B41C5EFFD4DC9139F3F05E8ACFBE3FAB /* RLMOptionalBase.h in Copy . Private Headers */, + 622896028277741362B6CACBDB7282AB /* RLMProperty_Private.h in Copy . Private Headers */, + E0063353A50BF81430DE33A115D09284 /* RLMRealm_Private.h in Copy . Private Headers */, + 0D61589C725AB01DA048B01D3C7E6650 /* RLMRealmConfiguration_Private.h in Copy . Private Headers */, + BEBBA4400C87D961413FFA0DC7E931F1 /* RLMResults_Private.h in Copy . Private Headers */, + C47AEBAE5768043D7145C86F9442E206 /* RLMSchema_Private.h in Copy . Private Headers */, + 5EB973A865695E65B90665CC3B564E68 /* RLMSyncConfiguration_Private.h in Copy . Private Headers */, + E5CBF99119746C04F2BFC1A1D5CA22D1 /* RLMSyncManager_Private.h in Copy . Private Headers */, + 5AF9149DE122F5511B88F615536F3A74 /* RLMSyncPermissionChange_Private.h in Copy . Private Headers */, + 74F26456BE08FF60524635AFDE452A41 /* RLMSyncUtil_Private.h in Copy . Private Headers */, ); name = "Copy . Private Headers"; runOnlyForDeploymentPostprocessing = 0; }; - 8236059238F994036E3DCE3894F0E392 /* Copy . Public Headers */ = { + 77445E2DE8BCF757895E86746E1F3471 /* Copy . Public Headers */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = "$(PUBLIC_HEADERS_FOLDER_PATH)/."; dstSubfolderSpec = 16; files = ( - FB7C24C7506A303C5AF86D52B632F206 /* Realm.h in Copy . Public Headers */, - 048760C43D03E08874506B06B7EF2BA7 /* RLMArray.h in Copy . Public Headers */, - 776B59705B4986805823CA7037A1790F /* RLMCollection.h in Copy . Public Headers */, - FD7A325EB0D58CA698E083C9E3775C7C /* RLMConstants.h in Copy . Public Headers */, - 7044BD9D2B94ED1CDB75B51982EC275B /* RLMListBase.h in Copy . Public Headers */, - 2D85820D45177CDAC8A822E42CA82F33 /* RLMMigration.h in Copy . Public Headers */, - 6532C6D910E007016F49C20188190D96 /* RLMObject.h in Copy . Public Headers */, - F4E71F4EBC55B769AD296B6AC5109AB6 /* RLMObjectBase.h in Copy . Public Headers */, - 466957D8B94A58B9E077CB545AC0A373 /* RLMObjectBase_Dynamic.h in Copy . Public Headers */, - 405F3DCBE38B3B64FBBBB71433C42D64 /* RLMObjectSchema.h in Copy . Public Headers */, - 9D53CA24F9378C6431F0EA43559D1A8A /* RLMOptionalBase.h in Copy . Public Headers */, - 5C757868E35D76F281F86DF6A3EB9248 /* RLMPlatform.h in Copy . Public Headers */, - BA8584CB008ED552E19C02C0F1C1FF8A /* RLMProperty.h in Copy . Public Headers */, - 5624B9E2392C7880697781A194D60B0A /* RLMRealm.h in Copy . Public Headers */, - C8DAAFDDA76EED996EABF4FF5D45E645 /* RLMRealm_Dynamic.h in Copy . Public Headers */, - 4CA65141256920C526B050589363C51C /* RLMRealmConfiguration+Sync.h in Copy . Public Headers */, - D00D1CCB10A1022CFAA608EF5839E01F /* RLMRealmConfiguration.h in Copy . Public Headers */, - 3704706A1290A0D59582E382EE80A274 /* RLMResults.h in Copy . Public Headers */, - 4595A4681680F91FB676D959ABD80443 /* RLMSchema.h in Copy . Public Headers */, - 9F0C6E80C8B828501B3A98BFCCB52BC3 /* RLMSyncConfiguration.h in Copy . Public Headers */, - C25EA19DAE982AB53978A64880299AD6 /* RLMSyncCredential.h in Copy . Public Headers */, - 210D77853ABBF30D95E6DC29660090FB /* RLMSyncManager.h in Copy . Public Headers */, - 94EB706F84F12D62896A687E5247A449 /* RLMSyncSession.h in Copy . Public Headers */, - CE4031C6487FB4DBFF2040D587D40BB2 /* RLMSyncUser.h in Copy . Public Headers */, - E15690DF46217ABA61459C79CB8CF2DA /* RLMSyncUtil.h in Copy . Public Headers */, + CAEE7253E91FB51DA2906B5D8F2F2BEF /* Realm.h in Copy . Public Headers */, + F914CA252023D3BEA41D090F0EE481A7 /* RLMArray.h in Copy . Public Headers */, + 2E1DC3DFD53D75FD37BF66B5A9BF8CB8 /* RLMCollection.h in Copy . Public Headers */, + C84817A7CD1004E0E2D8084579C06D77 /* RLMConstants.h in Copy . Public Headers */, + 0727EDE23165B49DE1249DED8150CA8F /* RLMListBase.h in Copy . Public Headers */, + F27ACDCFA1305AED15000A6E169A09F2 /* RLMMigration.h in Copy . Public Headers */, + 34E4C87866115998CE469D0E6F9C4E03 /* RLMObject.h in Copy . Public Headers */, + 29D1AC5689D0E7855816E9AD5DEE02F9 /* RLMObjectBase.h in Copy . Public Headers */, + CE4A935512F17BFB39C87819174C0FCF /* RLMObjectBase_Dynamic.h in Copy . Public Headers */, + 182178BB78B5C1D12A667DFB637FA9E4 /* RLMObjectSchema.h in Copy . Public Headers */, + 5BF6EF17288A787E9F648C7003741977 /* RLMOptionalBase.h in Copy . Public Headers */, + 0CBA9D1D9C5BFFDC693497798E35E7C0 /* RLMPlatform.h in Copy . Public Headers */, + 941C9CC87387BCB9ACF6E4633D7BE11F /* RLMProperty.h in Copy . Public Headers */, + 2FCA79E919981FD899ACC4FA58BC0BAF /* RLMRealm.h in Copy . Public Headers */, + C70C353F2DAB85D06CE3FF0C283EEBD5 /* RLMRealm_Dynamic.h in Copy . Public Headers */, + 109EC6BE3A54A077687E86D1713ECFFE /* RLMRealmConfiguration+Sync.h in Copy . Public Headers */, + 264B1E953276612B1A04FA1B27C7D036 /* RLMRealmConfiguration.h in Copy . Public Headers */, + D1FAB3EB37197E12A3601E1AAAFD6B3D /* RLMResults.h in Copy . Public Headers */, + E992BF718E58B53660588898BC09216F /* RLMSchema.h in Copy . Public Headers */, + E8B57737686524010B0E97495370C61A /* RLMSyncConfiguration.h in Copy . Public Headers */, + 68399A7792E12B13032570F22B6E2EA4 /* RLMSyncCredentials.h in Copy . Public Headers */, + 16A20B38AFF37E6B9B8D4098EABAA6A2 /* RLMSyncManager.h in Copy . Public Headers */, + E1CD95813DB6A31BF8BB2BCE67D617C8 /* RLMSyncPermissionChange.h in Copy . Public Headers */, + BE36CC148B32FA43571C217DABB7B9C8 /* RLMSyncSession.h in Copy . Public Headers */, + BFAC8FA7FF03E61641773CCD2D780940 /* RLMSyncUser.h in Copy . Public Headers */, + 63C3177DFA084E5CB80B88682DA82991 /* RLMSyncUtil.h in Copy . Public Headers */, ); name = "Copy . Public Headers"; runOnlyForDeploymentPostprocessing = 0; @@ -241,167 +249,192 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 00A6AC0F9C79B0C691DDB361F7ED9E76 /* RLMRealm_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealm_Private.h; path = include/RLMRealm_Private.h; sourceTree = ""; }; - 014469716A1D2CD0219B1E692FFCEE88 /* RLMRealmConfiguration+Sync.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RLMRealmConfiguration+Sync.h"; path = "include/RLMRealmConfiguration+Sync.h"; sourceTree = ""; }; - 034990FBBE926C95450017780DDE2549 /* RLMTokenModels.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMTokenModels.m; path = Realm/RLMTokenModels.m; sourceTree = ""; }; - 0485EC23C75C4004E94E2EABA6BE7C59 /* transact_log_handler.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = transact_log_handler.cpp; path = Realm/ObjectStore/src/impl/transact_log_handler.cpp; sourceTree = ""; }; - 05A7114F8F766A04D201539C57F60258 /* sync_manager.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = sync_manager.cpp; path = Realm/ObjectStore/src/sync_manager.cpp; sourceTree = ""; }; - 09147D24067FA3848A918BAAEE2C07EB /* Realm.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Realm.h; path = include/Realm.h; sourceTree = ""; }; - 0B805AA31413DCF2DEBFE6409971B700 /* RLMAccessor.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMAccessor.mm; path = Realm/RLMAccessor.mm; sourceTree = ""; }; - 0C103E061A2B83B5131E18C9F68D1358 /* RLMProperty_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMProperty_Private.h; path = include/RLMProperty_Private.h; sourceTree = ""; }; - 104BA96F47D6DBBD513718328A0F1D37 /* RLMUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMUtil.mm; path = Realm/RLMUtil.mm; sourceTree = ""; }; - 12C058B644388DD29B690D5B6D256A3E /* RLMConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMConstants.m; path = Realm/RLMConstants.m; sourceTree = ""; }; - 15B2F0FB2718B1150B4B97C2E1D1CA0F /* sync_session.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = sync_session.cpp; path = Realm/ObjectStore/src/sync_session.cpp; sourceTree = ""; }; - 18130AD268176A0279E97E442ABFEDCD /* list.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = list.cpp; path = Realm/ObjectStore/src/list.cpp; sourceTree = ""; }; - 1B10AD3AF9E9007B1ADA4C52747C4719 /* keychain_helper.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = keychain_helper.cpp; path = Realm/ObjectStore/src/impl/apple/keychain_helper.cpp; sourceTree = ""; }; - 1C59229F270BCA843F3B9FFBDA06657F /* Pods_VBB.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_VBB.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 1CA6EBC2E57D96052268211209D6AA52 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; }; - 207655DE5C14B2A57A94D5C954011DDE /* RLMSwiftSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMSwiftSupport.m; path = Realm/RLMSwiftSupport.m; sourceTree = ""; }; - 2290AC1CA7EB105C6C316E1CCBCB7092 /* RLMObject.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMObject.mm; path = Realm/RLMObject.mm; sourceTree = ""; }; - 25ABD97B85A0A4EFCD3DB372EF367A42 /* RLMOptionalBase.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMOptionalBase.mm; path = Realm/RLMOptionalBase.mm; sourceTree = ""; }; - 289AFBB1A2545E0525C8783CB4430B64 /* RLMRealmConfiguration.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMRealmConfiguration.mm; path = Realm/RLMRealmConfiguration.mm; sourceTree = ""; }; - 2C8E33FA00AB7C9EFC177ECB50B14A90 /* RLMRealmConfiguration+Sync.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = "RLMRealmConfiguration+Sync.mm"; path = "Realm/RLMRealmConfiguration+Sync.mm"; sourceTree = ""; }; - 2ED1C41AF7A34E5092BAC9E583ADA1AE /* RLMSyncConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncConfiguration.h; path = include/RLMSyncConfiguration.h; sourceTree = ""; }; - 32363ABF33F1D25013C61D5678A7CD4F /* librealm-macosx.a */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = archive.ar; name = "librealm-macosx.a"; path = "core/librealm-macosx.a"; sourceTree = ""; }; - 32829B880D0B8DD45E1D882459CF2D88 /* RLMRealm.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMRealm.mm; path = Realm/RLMRealm.mm; sourceTree = ""; }; - 32E60FAC5AA32DB30476E57D759ABE49 /* RLMUpdateChecker.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMUpdateChecker.mm; path = Realm/RLMUpdateChecker.mm; sourceTree = ""; }; + 00256CADEDF0A4449FB3C7808A0A76C8 /* RLMClassInfo.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMClassInfo.mm; path = Realm/RLMClassInfo.mm; sourceTree = ""; }; + 0605B3919063758184EDE3E40A9AB8C6 /* weak_realm_notifier.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = weak_realm_notifier.cpp; path = Realm/ObjectStore/src/impl/weak_realm_notifier.cpp; sourceTree = ""; }; + 0C49E14BC92FDFBDBD3704FDE565C169 /* sync_session.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = sync_session.cpp; path = Realm/ObjectStore/src/sync/sync_session.cpp; sourceTree = ""; }; + 14A60E08812158EE860006A89CC29F09 /* sync_user.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = sync_user.cpp; path = Realm/ObjectStore/src/sync/sync_user.cpp; sourceTree = ""; }; + 173D94346D87FDA36DEB8D1163228477 /* RLMSyncCredentials.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncCredentials.h; path = include/RLMSyncCredentials.h; sourceTree = ""; }; + 1751EACA219057FB7456621679BA2401 /* RLMResults.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMResults.mm; path = Realm/RLMResults.mm; sourceTree = ""; }; + 18AE4F83A475D08286BE890E54DAEC63 /* RLMObjectSchema.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMObjectSchema.mm; path = Realm/RLMObjectSchema.mm; sourceTree = ""; }; + 1930B09148A313A9BC9B4B7A8177E1B4 /* RLMMigration.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMMigration.mm; path = Realm/RLMMigration.mm; sourceTree = ""; }; + 19568FA5741E7C17F8CA64CF5C25A676 /* RLMSchema.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMSchema.mm; path = Realm/RLMSchema.mm; sourceTree = ""; }; + 1AE1CC3B0C54E737FF56A252B579D2E0 /* RLMSchema.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSchema.h; path = include/RLMSchema.h; sourceTree = ""; }; + 1AE1D644DD3862A7E16768BAFEAAD709 /* RLMPlatform.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMPlatform.h; path = include/RLMPlatform.h; sourceTree = ""; }; + 1C59229F270BCA843F3B9FFBDA06657F /* Pods_VBB.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_VBB.framework; path = "Pods-VBB.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1D47B5C027BBF9EFE751A390BDBEF096 /* RLMUpdateChecker.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMUpdateChecker.mm; path = Realm/RLMUpdateChecker.mm; sourceTree = ""; }; + 21AD292E35AB2D656F1CD2B974E3A63B /* shared_realm.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = shared_realm.cpp; path = Realm/ObjectStore/src/shared_realm.cpp; sourceTree = ""; }; + 2308EC716DAE5A031F0561FE45BE112B /* external_commit_helper.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = external_commit_helper.cpp; path = Realm/ObjectStore/src/impl/apple/external_commit_helper.cpp; sourceTree = ""; }; + 270DD1219F1E6CF00379D39F252D87C6 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; }; + 27FF71D843775C57E7B8AAA4979F4A86 /* RLMListBase.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMListBase.mm; path = Realm/RLMListBase.mm; sourceTree = ""; }; + 29DD04BC47E51FC330A2884282773F8A /* librealm-macosx.a */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = archive.ar; name = "librealm-macosx.a"; path = "core/librealm-macosx.a"; sourceTree = ""; }; + 2A629EBBD35DCEB4AF7041A55938591A /* RLMConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMConstants.m; path = Realm/RLMConstants.m; sourceTree = ""; }; + 2DF7706F095459FD4971E5CFD187AED6 /* RLMSchema_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSchema_Private.h; path = include/RLMSchema_Private.h; sourceTree = ""; }; + 2F4DB766E5986241F1DA71EFA552DF04 /* Realm.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = Realm.modulemap; sourceTree = ""; }; + 2F913857B663FFCD78EA3272B4D9ECFC /* RLMRealmConfiguration+Sync.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RLMRealmConfiguration+Sync.h"; path = "include/RLMRealmConfiguration+Sync.h"; sourceTree = ""; }; + 30E336A7C1EA27F5B451FBE3DBC36A07 /* RLMProperty.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMProperty.mm; path = Realm/RLMProperty.mm; sourceTree = ""; }; + 31BCA3693B5FC383E0019D858E3961F4 /* Realm.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Realm.xcconfig; sourceTree = ""; }; + 31DAABC9CC6C6DA17482CF2698838940 /* RLMSyncManager_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncManager_Private.h; path = include/RLMSyncManager_Private.h; sourceTree = ""; }; + 328DEE271B3CD7A53BADCA85C261B7C4 /* RLMRealmConfiguration+Sync.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = "RLMRealmConfiguration+Sync.mm"; path = "Realm/RLMRealmConfiguration+Sync.mm"; sourceTree = ""; }; 330F67DBC229E210EAC8B3BA0A6DFDB4 /* Pods-VBB.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-VBB.release.xcconfig"; sourceTree = ""; }; - 3660CB7CF901F80EE595D72D9307E3C9 /* RLMSyncCredential.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMSyncCredential.m; path = Realm/RLMSyncCredential.m; sourceTree = ""; }; - 37D49A8BFA46FD198F9029FF866B84D7 /* realm_coordinator.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = realm_coordinator.cpp; path = Realm/ObjectStore/src/impl/realm_coordinator.cpp; sourceTree = ""; }; - 38141611BE7DF729928941BA5ED8BC49 /* RLMSchema_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSchema_Private.h; path = include/RLMSchema_Private.h; sourceTree = ""; }; - 38874DFF13042D1E43548BCEDE87D229 /* Pods-VBB.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-VBB.modulemap"; sourceTree = ""; }; + 38874DFF13042D1E43548BCEDE87D229 /* Pods-VBB.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-VBB.modulemap"; sourceTree = ""; }; 394B944878C86F46D573132FE44ED791 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 3954CF0D591CFD23F9D44FC4E7F8E2BE /* list_notifier.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = list_notifier.cpp; path = Realm/ObjectStore/src/impl/list_notifier.cpp; sourceTree = ""; }; - 398E60EFE10734F5170C88A8018F4F8D /* RLMListBase.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMListBase.mm; path = Realm/RLMListBase.mm; sourceTree = ""; }; - 39F8AFBC85C45F619757B8863AAF76EA /* RLMRealmUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMRealmUtil.mm; path = Realm/RLMRealmUtil.mm; sourceTree = ""; }; + 396431AE286E1938A480C6B7F5BA86A5 /* Realm-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Realm-dummy.m"; sourceTree = ""; }; 3A21E5B003B9FD93E48310A07C98D1B9 /* Pods-VBB-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-VBB-acknowledgements.plist"; sourceTree = ""; }; - 3B955FE3E7BE7FEFE6EF9AE9E6190ECD /* RLMObjectSchema_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectSchema_Private.h; path = include/RLMObjectSchema_Private.h; sourceTree = ""; }; - 3C61306AB8513B6408B637E5C032E042 /* thread_confined.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = thread_confined.cpp; path = Realm/ObjectStore/src/thread_confined.cpp; sourceTree = ""; }; + 3AAC83F418897D2B121C709B49F4412F /* RLMObjectBase_Dynamic.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectBase_Dynamic.h; path = include/RLMObjectBase_Dynamic.h; sourceTree = ""; }; 3C98F107634FE7071CFCC4EF946889A9 /* Pods-VBB.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-VBB.debug.xcconfig"; sourceTree = ""; }; - 3D61ECDE4E4EA174F578A3DEF987C17C /* RLMSyncSession_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncSession_Private.h; path = include/RLMSyncSession_Private.h; sourceTree = ""; }; - 424EA9C5FF9E322C559BD3FD10F9092B /* RLMArray_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMArray_Private.h; path = include/RLMArray_Private.h; sourceTree = ""; }; + 403E12E002FB0D181261C590B7B14BD4 /* RLMTokenModels.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMTokenModels.m; path = Realm/RLMTokenModels.m; sourceTree = ""; }; + 406F84DAC28B85067F1FDE8F2159D1B3 /* RLMSyncPermissionChange_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncPermissionChange_Private.h; path = include/RLMSyncPermissionChange_Private.h; sourceTree = ""; }; + 42E896057D80950C8B0D9B7877BB6326 /* RLMSyncManager.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMSyncManager.mm; path = Realm/RLMSyncManager.mm; sourceTree = ""; }; + 43662C66460EFC7D9E291F9B9086B694 /* RLMRealm.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealm.h; path = include/RLMRealm.h; sourceTree = ""; }; 442FF1F0DFB50397039D6B4A956361AA /* Pods-VBBNow-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-VBBNow-dummy.m"; sourceTree = ""; }; - 45FAA23D2B88ACEAE13C5819F1F20A54 /* RLMSyncUser.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMSyncUser.mm; path = Realm/RLMSyncUser.mm; sourceTree = ""; }; - 46D5B0F38D1D1335A0F0C64CB1924BB5 /* RLMConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMConstants.h; path = include/RLMConstants.h; sourceTree = ""; }; - 48441474D1D8C3B66F967B0E76837062 /* RLMRealmConfiguration_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealmConfiguration_Private.h; path = include/RLMRealmConfiguration_Private.h; sourceTree = ""; }; - 4FDFF56DA8141886E5E4CCD082498AE9 /* RLMObjectBase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectBase.h; path = include/RLMObjectBase.h; sourceTree = ""; }; - 5138207173D645AD7161144B667D1D88 /* RLMSyncSession.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncSession.h; path = include/RLMSyncSession.h; sourceTree = ""; }; - 5164B39A8F60C42A1AFF04B540316B7A /* collection_notifier.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = collection_notifier.cpp; path = Realm/ObjectStore/src/impl/collection_notifier.cpp; sourceTree = ""; }; - 519044AC217178621FF363269D6344C2 /* RLMListBase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMListBase.h; path = include/RLMListBase.h; sourceTree = ""; }; - 52201054DED1B93163C58A80BB2DC94F /* RLMSyncManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncManager.h; path = include/RLMSyncManager.h; sourceTree = ""; }; - 52CDE0006AE03361D1D46D446377C3EE /* sync_metadata.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = sync_metadata.cpp; path = Realm/ObjectStore/src/sync_metadata.cpp; sourceTree = ""; }; - 54B811089E20717FBE565C7DFF8959E0 /* RLMAccessor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMAccessor.h; path = include/RLMAccessor.h; sourceTree = ""; }; - 5D81C9A7ACBF3EF1D8CFC6F10B626EE6 /* RLMRealm.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealm.h; path = include/RLMRealm.h; sourceTree = ""; }; + 4A006CFD858DDF1A94AE5E734BD7764E /* RLMRealmConfiguration_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealmConfiguration_Private.h; path = include/RLMRealmConfiguration_Private.h; sourceTree = ""; }; + 50F59561979D2AFC6D63C18BEA53EE69 /* RLMSyncSession.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncSession.h; path = include/RLMSyncSession.h; sourceTree = ""; }; + 54899CE56D9776FA8B5DE8FA2A773BEB /* sync_file.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = sync_file.cpp; path = Realm/ObjectStore/src/sync/impl/sync_file.cpp; sourceTree = ""; }; + 57AA417A0A637C8877C7338959DA5380 /* RLMUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMUtil.mm; path = Realm/RLMUtil.mm; sourceTree = ""; }; + 589E794D261E19A6638A2A2285F592D0 /* results_notifier.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = results_notifier.cpp; path = Realm/ObjectStore/src/impl/results_notifier.cpp; sourceTree = ""; }; + 595CD5E05996D9C6E812BCAD75B77CC4 /* RLMArray.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMArray.h; path = include/RLMArray.h; sourceTree = ""; }; + 5C1D6BDAF543593F2F7C2073804F277C /* transact_log_handler.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = transact_log_handler.cpp; path = Realm/ObjectStore/src/impl/transact_log_handler.cpp; sourceTree = ""; }; + 5C3196F97E003804B9BDD075494F299E /* RLMSyncUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMSyncUtil.mm; path = Realm/RLMSyncUtil.mm; sourceTree = ""; }; + 5CC5E03DF0C0E51B12CCC635C1F0B105 /* RLMArrayLinkView.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMArrayLinkView.mm; path = Realm/RLMArrayLinkView.mm; sourceTree = ""; }; 5DDC869D8CF0A1276BA751B04130E10D /* Pods-VBB-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-VBB-acknowledgements.markdown"; sourceTree = ""; }; - 60CD2CA9A20CBD33026F7468BF866A42 /* Realm-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Realm-dummy.m"; sourceTree = ""; }; + 607539AC413FBCD9851327FA3F2BAA6D /* RLMSyncUtil_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncUtil_Private.h; path = include/RLMSyncUtil_Private.h; sourceTree = ""; }; 62924E0FC106DDBF9F530EB048E4E825 /* Pods-VBBNow.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-VBBNow.debug.xcconfig"; sourceTree = ""; }; - 63A49ECE34E65AAE2B43BB73B2737794 /* RLMSyncSessionHandle.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMSyncSessionHandle.mm; path = Realm/RLMSyncSessionHandle.mm; sourceTree = ""; }; - 661739F0FBDC9E8CBC03C9699EB38E89 /* RLMSyncConfiguration.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMSyncConfiguration.mm; path = Realm/RLMSyncConfiguration.mm; sourceTree = ""; }; + 6358FFFE171233AE4F917C29DE8E817F /* RLMSyncConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncConfiguration.h; path = include/RLMSyncConfiguration.h; sourceTree = ""; }; 670BBB97DAC0DF3030CDC5E2D40B5024 /* Pods-VBB-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-VBB-dummy.m"; sourceTree = ""; }; - 6944B6C86719E86FC72FC6723D02E65C /* RLMProperty.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMProperty.h; path = include/RLMProperty.h; sourceTree = ""; }; - 6D337A9C1F193E27D99C6EB31B18C6F7 /* RLMSyncCredential.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncCredential.h; path = include/RLMSyncCredential.h; sourceTree = ""; }; - 6FF63F74A7ADF71500412C2F86F7597C /* RLMCollection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMCollection.h; path = include/RLMCollection.h; sourceTree = ""; }; - 7097776D326A5C6920C043CB3E32C28E /* RLMMigration_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMMigration_Private.h; path = include/RLMMigration_Private.h; sourceTree = ""; }; - 766345985B39340DCF40D53045539AC0 /* RLMPredicateUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMPredicateUtil.mm; path = Realm/RLMPredicateUtil.mm; sourceTree = ""; }; - 78B8C8451B740B8F2441708DB434479E /* RLMSchema.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMSchema.mm; path = Realm/RLMSchema.mm; sourceTree = ""; }; - 7A310DA12B3F4F661AB508E5E4705E2E /* RLMObservation.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMObservation.mm; path = Realm/RLMObservation.mm; sourceTree = ""; }; - 7CA1A05864AF04C106ACCBFD60852BD6 /* results_notifier.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = results_notifier.cpp; path = Realm/ObjectStore/src/impl/results_notifier.cpp; sourceTree = ""; }; - 7E10BDDCD1452430D956D7D35FB82770 /* RLMProperty.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMProperty.mm; path = Realm/RLMProperty.mm; sourceTree = ""; }; - 7E1BF4F4217B5993AFF70FC53C787628 /* RLMSyncManager.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMSyncManager.mm; path = Realm/RLMSyncManager.mm; sourceTree = ""; }; - 7EC6087687F7A71A96DD7662570C4077 /* RLMAnalytics.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMAnalytics.mm; path = Realm/RLMAnalytics.mm; sourceTree = ""; }; - 8022D1416A1403F2AF801D90045A5452 /* index_set.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = index_set.cpp; path = Realm/ObjectStore/src/index_set.cpp; sourceTree = ""; }; - 8864E15D52FC228189BA78CA478D44E8 /* weak_realm_notifier.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = weak_realm_notifier.cpp; path = Realm/ObjectStore/src/impl/weak_realm_notifier.cpp; sourceTree = ""; }; - 8A2F88B75421BB1BAA51BC6DAA226894 /* results.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = results.cpp; path = Realm/ObjectStore/src/results.cpp; sourceTree = ""; }; - 8D8428B5625A18C92C90C87BE598C76E /* RLMNetworkClient.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMNetworkClient.m; path = Realm/RLMNetworkClient.m; sourceTree = ""; }; + 6C46D6C0783F61C6E1D253660E472622 /* collection_change_builder.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = collection_change_builder.cpp; path = Realm/ObjectStore/src/impl/collection_change_builder.cpp; sourceTree = ""; }; + 6CA7A5BB864ADDEDE2B7D29EA2C83418 /* RLMObjectBase.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMObjectBase.mm; path = Realm/RLMObjectBase.mm; sourceTree = ""; }; + 7123AFF085B35CDFF3D705B06AB75638 /* RLMMigration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMMigration.h; path = include/RLMMigration.h; sourceTree = ""; }; + 7210F2C38964418F7E3BD25871BE64C1 /* RLMOptionalBase.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMOptionalBase.mm; path = Realm/RLMOptionalBase.mm; sourceTree = ""; }; + 75899BEC4655592543A2EC218AC1ACE3 /* RLMRealmConfiguration.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMRealmConfiguration.mm; path = Realm/RLMRealmConfiguration.mm; sourceTree = ""; }; + 7A5FDB219098757033113A20F42EC7EC /* realm_coordinator.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = realm_coordinator.cpp; path = Realm/ObjectStore/src/impl/realm_coordinator.cpp; sourceTree = ""; }; + 817D8B62EE7BAB27C2D7AC377912262D /* RLMAnalytics.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMAnalytics.mm; path = Realm/RLMAnalytics.mm; sourceTree = ""; }; + 81833731DAFA92A367A5A877335815F2 /* RLMRealmConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealmConfiguration.h; path = include/RLMRealmConfiguration.h; sourceTree = ""; }; + 842819BB0817F06B3BE15E916433226E /* RLMAccessor.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMAccessor.mm; path = Realm/RLMAccessor.mm; sourceTree = ""; }; + 86A5FE684DBA2A9BA18F97C555BF7EA2 /* RLMSyncConfiguration.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMSyncConfiguration.mm; path = Realm/RLMSyncConfiguration.mm; sourceTree = ""; }; + 8745208AEDA874159FEEAC2FA2DDB148 /* collection_notifier.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = collection_notifier.cpp; path = Realm/ObjectStore/src/impl/collection_notifier.cpp; sourceTree = ""; }; + 8A1BCE9F0706933B9C52B3F71A6CB35C /* RLMSyncSessionRefreshHandle.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMSyncSessionRefreshHandle.mm; path = Realm/RLMSyncSessionRefreshHandle.mm; sourceTree = ""; }; 90959EED2820C6F4FBCBF8FB14908AA9 /* Pods-VBBNow-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-VBBNow-acknowledgements.markdown"; sourceTree = ""; }; - 92DF303C97DC5989901A786C31C35C80 /* Realm.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Realm.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 91C16C4A846BCBF9E4D13D3FC8A9FF4D /* RLMSwiftSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMSwiftSupport.m; path = Realm/RLMSwiftSupport.m; sourceTree = ""; }; + 92DF303C97DC5989901A786C31C35C80 /* Realm.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Realm.framework; path = Realm.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9381C08AED2AEB137C5BF8B828AB54E2 /* Pods-VBBNow.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-VBBNow.release.xcconfig"; sourceTree = ""; }; - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 943D843F536640EE12B8EAFA1A038957 /* RLMArray.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMArray.mm; path = Realm/RLMArray.mm; sourceTree = ""; }; - 9A6F512185B5D12F73C4295DCA121267 /* RLMAuthResponseModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMAuthResponseModel.m; path = Realm/RLMAuthResponseModel.m; sourceTree = ""; }; - 9B98E7E083A4E91CD57D92F3B66BC0F9 /* handover.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = handover.cpp; path = Realm/ObjectStore/src/impl/handover.cpp; sourceTree = ""; }; - 9C3C1F04C74D30BB29D88383FA57C0A3 /* RLMRealmConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealmConfiguration.h; path = include/RLMRealmConfiguration.h; sourceTree = ""; }; - 9F7FD2D8A72BC62BAC9A5931BB8C3464 /* RLMSyncUtil_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncUtil_Private.h; path = include/RLMSyncUtil_Private.h; sourceTree = ""; }; - 9F872DC760E3A7A913501CDD0E49688B /* collection_notifications.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = collection_notifications.cpp; path = Realm/ObjectStore/src/collection_notifications.cpp; sourceTree = ""; }; - 9FAB115944EF40EC1215F52BB37E4EA6 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - A27ADBC6D0F1A0029C22B746260CD620 /* RLMObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObject.h; path = include/RLMObject.h; sourceTree = ""; }; - A5CCD9825C816504EEF6840EAEA70F72 /* RLMPlatform.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMPlatform.h; path = include/RLMPlatform.h; sourceTree = ""; }; - AA012AC6A1901FE6B7EA71FFA5BF29B4 /* external_commit_helper.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = external_commit_helper.cpp; path = Realm/ObjectStore/src/impl/apple/external_commit_helper.cpp; sourceTree = ""; }; - AA736B703E62FCEA7CE8123CCAEB360F /* Pods-VBBNow.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-VBBNow.modulemap"; sourceTree = ""; }; - AF507FA42053E9B8A381F25EC487F49A /* Realm.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Realm.xcconfig; sourceTree = ""; }; - B0B4CBC2DBA8C64954C17C9B1712ABD3 /* RLMRealm_Dynamic.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealm_Dynamic.h; path = include/RLMRealm_Dynamic.h; sourceTree = ""; }; - B1431EDD4F50DF5FC020C0A75FB4F9DD /* object_schema.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = object_schema.cpp; path = Realm/ObjectStore/src/object_schema.cpp; sourceTree = ""; }; - B1B96ECB64F7E33324B8EAFB4DC94F87 /* object_store.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = object_store.cpp; path = Realm/ObjectStore/src/object_store.cpp; sourceTree = ""; }; - B32F919064BB5621A476FEC9A530668C /* RLMObjectBase.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMObjectBase.mm; path = Realm/RLMObjectBase.mm; sourceTree = ""; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 93B4F8BAA6A5D122AF94E4E017B223A6 /* schema.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = schema.cpp; path = Realm/ObjectStore/src/schema.cpp; sourceTree = ""; }; + 962A7019E7948A80AB45F39A7DFE01BD /* RLMSyncPermissionChange.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncPermissionChange.h; path = include/RLMSyncPermissionChange.h; sourceTree = ""; }; + 9662DF7C5E53A767E7A8010F23F00AC4 /* RLMObjectSchema_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectSchema_Private.h; path = include/RLMObjectSchema_Private.h; sourceTree = ""; }; + 97304DB97C36ED573506661757DCF909 /* RLMCollection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMCollection.h; path = include/RLMCollection.h; sourceTree = ""; }; + 9879E438CC8862D98C6A1D413281B540 /* RLMAuthResponseModel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMAuthResponseModel.m; path = Realm/RLMAuthResponseModel.m; sourceTree = ""; }; + 9AB1D76D5F4D78EB58442B1D5A0E227C /* RLMProperty.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMProperty.h; path = include/RLMProperty.h; sourceTree = ""; }; + 9B801378173B9D2B9C19028FC7C5F825 /* sync_metadata.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = sync_metadata.cpp; path = Realm/ObjectStore/src/sync/impl/sync_metadata.cpp; sourceTree = ""; }; + A1B29797E7F996208B3F56B01C8068CC /* RLMArray.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMArray.mm; path = Realm/RLMArray.mm; sourceTree = ""; }; + A22E12264A783E6AC7BB0831C3CAFA0A /* list_notifier.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = list_notifier.cpp; path = Realm/ObjectStore/src/impl/list_notifier.cpp; sourceTree = ""; }; + A2EE6A9E046640D359CAB73B80320FFE /* RLMSyncUser.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncUser.h; path = include/RLMSyncUser.h; sourceTree = ""; }; + A41691C4302FAC7629802089876E8848 /* RLMResults.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMResults.h; path = include/RLMResults.h; sourceTree = ""; }; + A46E0C3460F4755D41E89231F71F52D3 /* RLMConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMConstants.h; path = include/RLMConstants.h; sourceTree = ""; }; + A57CD6C47A80BC1DD1C7135012261456 /* RLMAccessor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMAccessor.h; path = include/RLMAccessor.h; sourceTree = ""; }; + A5D4607B3A4E52359D0E8B8692E423DA /* RLMMigration_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMMigration_Private.h; path = include/RLMMigration_Private.h; sourceTree = ""; }; + AA362F932DF0854B4BA5C5C5CBCECF79 /* RLMSyncConfiguration_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncConfiguration_Private.h; path = include/RLMSyncConfiguration_Private.h; sourceTree = ""; }; + AA736B703E62FCEA7CE8123CCAEB360F /* Pods-VBBNow.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-VBBNow.modulemap"; sourceTree = ""; }; + AB025FABAAF248803A252D707FAC5B62 /* RLMObjectSchema.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectSchema.h; path = include/RLMObjectSchema.h; sourceTree = ""; }; + AC3C1FCD80BB317610A445C2D61A6447 /* RLMObject.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMObject.mm; path = Realm/RLMObject.mm; sourceTree = ""; }; + B711C581A88BD9FE0DDD4F9141EFE382 /* RLMSyncCredentials.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMSyncCredentials.m; path = Realm/RLMSyncCredentials.m; sourceTree = ""; }; + B7A22640019BF322FD69A3FC75662C87 /* RLMObjectStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectStore.h; path = include/RLMObjectStore.h; sourceTree = ""; }; B7BF347308AF7376AE5628738E029F34 /* Pods-VBBNow-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-VBBNow-umbrella.h"; sourceTree = ""; }; + B877F67F7BF62A61B88198D6AAB4D7FB /* RLMSyncManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncManager.h; path = include/RLMSyncManager.h; sourceTree = ""; }; B929A0156BDC12308858E5593B17C8A8 /* Pods-VBB-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-VBB-umbrella.h"; sourceTree = ""; }; - B9DB85E07728315E010FEC792388CE57 /* RLMSyncFileManager.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMSyncFileManager.mm; path = Realm/RLMSyncFileManager.mm; sourceTree = ""; }; BA610EF38FB9571842F3AFC7E25FD5DD /* Pods-VBB-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-VBB-resources.sh"; sourceTree = ""; }; - C261C8CF818E53F2D3EB0F29DB59877D /* RLMClassInfo.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMClassInfo.mm; path = Realm/RLMClassInfo.mm; sourceTree = ""; }; - C5A151B1BBB1D2C9B2BE3FCCA114A573 /* RLMArrayLinkView.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMArrayLinkView.mm; path = Realm/RLMArrayLinkView.mm; sourceTree = ""; }; - C64F45A2EE41F6AF3CD60EAB4F47F8C3 /* RLMObjectSchema.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMObjectSchema.mm; path = Realm/RLMObjectSchema.mm; sourceTree = ""; }; + BBC3565C3A2FCE6639D20C68353E504E /* RLMRealmUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMRealmUtil.mm; path = Realm/RLMRealmUtil.mm; sourceTree = ""; }; + BC72C77F253149E7F9F4B3B344566EB2 /* Realm.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Realm.h; path = include/Realm.h; sourceTree = ""; }; + BCDC499822E9ACD5E24C9AB0CD479F84 /* results.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = results.cpp; path = Realm/ObjectStore/src/results.cpp; sourceTree = ""; }; + BD17FF5BBECD1015FC9988031ED4384D /* RLMSyncSession.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMSyncSession.mm; path = Realm/RLMSyncSession.mm; sourceTree = ""; }; + BF0F199551C99F2AF39C52369269BC6A /* RLMObservation.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMObservation.mm; path = Realm/RLMObservation.mm; sourceTree = ""; }; + BF1F05958D394CC73FAD54C74857DFB7 /* RLMRealm_Dynamic.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealm_Dynamic.h; path = include/RLMRealm_Dynamic.h; sourceTree = ""; }; + BFA3C0619720C825FFD969A8694D6459 /* RLMOptionalBase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMOptionalBase.h; path = include/RLMOptionalBase.h; sourceTree = ""; }; + C030C57D7F1395F1350BFEFC7EF37EF8 /* sync_manager.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = sync_manager.cpp; path = Realm/ObjectStore/src/sync/sync_manager.cpp; sourceTree = ""; }; + C1CE85299CE26714C404B4986AE03A1D /* RLMProperty_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMProperty_Private.h; path = include/RLMProperty_Private.h; sourceTree = ""; }; + C36347AE80C13783C1D80ED4DAE84C86 /* RLMObject_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObject_Private.h; path = include/RLMObject_Private.h; sourceTree = ""; }; + C3AE2CBBB9AEF2E0AA421B3316B3B983 /* handover.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = handover.cpp; path = Realm/ObjectStore/src/impl/handover.cpp; sourceTree = ""; }; + C55FE2C555506A88D4BAF650C12867E3 /* RLMListBase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMListBase.h; path = include/RLMListBase.h; sourceTree = ""; }; + C682053DECAE69B034815B792F03D620 /* RLMSyncPermissionChange.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMSyncPermissionChange.m; path = Realm/RLMSyncPermissionChange.m; sourceTree = ""; }; C73379CF391D190F89A32CDA0D713807 /* Pods-VBB-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-VBB-frameworks.sh"; sourceTree = ""; }; - C92029B18F453CA95D99A21A7DBA7C65 /* RLMObjectStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectStore.h; path = include/RLMObjectStore.h; sourceTree = ""; }; - CBEFAEC42322EE588C4CE1BF939C4C72 /* format.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = format.cpp; path = Realm/ObjectStore/src/util/format.cpp; sourceTree = ""; }; - CC3074D458C8E4B7B88B55DE244480FB /* RLMResults_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMResults_Private.h; path = include/RLMResults_Private.h; sourceTree = ""; }; - D071D5BA8565046C01C9ACED4E7A6D84 /* RLMCollection.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMCollection.mm; path = Realm/RLMCollection.mm; sourceTree = ""; }; - D1963CF370AD94FF8542B49818029E44 /* RLMResults.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMResults.mm; path = Realm/RLMResults.mm; sourceTree = ""; }; - D51047ABC2AFEE69E43D15A318848A24 /* RLMObject_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObject_Private.h; path = include/RLMObject_Private.h; sourceTree = ""; }; - D81269265A61E7F096BAAE0F9ECBC16A /* RLMMigration.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMMigration.mm; path = Realm/RLMMigration.mm; sourceTree = ""; }; - D84036052E8CB24CB40E17886144B336 /* shared_realm.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = shared_realm.cpp; path = Realm/ObjectStore/src/shared_realm.cpp; sourceTree = ""; }; - D8C27F6A06FBD7BC9D2CAA007D33BF65 /* RLMSyncConfiguration_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncConfiguration_Private.h; path = include/RLMSyncConfiguration_Private.h; sourceTree = ""; }; - D99D3E5BF4737F66FAEB2A939631017D /* placeholder.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = placeholder.cpp; path = Realm/ObjectStore/src/placeholder.cpp; sourceTree = ""; }; - DB875141CED28FC407D7A4738BA2DE05 /* RLMArray.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMArray.h; path = include/RLMArray.h; sourceTree = ""; }; - DBDA483D331CC99EF81F98B144715EAE /* RLMObjectStore.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMObjectStore.mm; path = Realm/RLMObjectStore.mm; sourceTree = ""; }; - DC686D6D9603864D29EA0F2058FAB2CE /* RLMSyncSession.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMSyncSession.mm; path = Realm/RLMSyncSession.mm; sourceTree = ""; }; - DCB7F8D3C434001DEC287625F5FAE924 /* RLMResults.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMResults.h; path = include/RLMResults.h; sourceTree = ""; }; - DFF3E07B87AF9496BD5E82F5039E99F8 /* RLMOptionalBase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMOptionalBase.h; path = include/RLMOptionalBase.h; sourceTree = ""; }; + CE9EF36DD57A76D33FD75564FA8B60BE /* RLMSyncUser.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMSyncUser.mm; path = Realm/RLMSyncUser.mm; sourceTree = ""; }; + D0CF987B74A9228808D79F2728CCA910 /* placeholder.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = placeholder.cpp; path = Realm/ObjectStore/src/placeholder.cpp; sourceTree = ""; }; + D536E13D0B52FC8D5B1282CB79A9F1B3 /* RLMSyncUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncUtil.h; path = include/RLMSyncUtil.h; sourceTree = ""; }; + D7CF164EEEFE85102FFE630F0E85AD80 /* RLMQueryUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMQueryUtil.mm; path = Realm/RLMQueryUtil.mm; sourceTree = ""; }; + D8F402A7612BD54527423CF61EAA67A5 /* Realm-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Realm-prefix.pch"; sourceTree = ""; }; + DD399C7A7419295C8F0A275CBAB4EA10 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DE619E8BF823EDFA0B94672B12630032 /* index_set.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = index_set.cpp; path = Realm/ObjectStore/src/index_set.cpp; sourceTree = ""; }; E0BE04002EC3932C452FE3F6DAB17643 /* Pods-VBBNow-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-VBBNow-acknowledgements.plist"; sourceTree = ""; }; - E0FAFDE4566B1CC34938EFDB139DE1A5 /* RLMObjectBase_Dynamic.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectBase_Dynamic.h; path = include/RLMObjectBase_Dynamic.h; sourceTree = ""; }; + E177B0177B0A05503FEE813634035AC2 /* format.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = format.cpp; path = Realm/ObjectStore/src/util/format.cpp; sourceTree = ""; }; E18AA64DEC92C945AFC32C2EA7BBC6D6 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - E350FAEE1CE28DF3F5C95D54F76A8663 /* RLMSyncUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMSyncUtil.mm; path = Realm/RLMSyncUtil.mm; sourceTree = ""; }; E3E8F0B49D4E4A2F591E9CBE57E04D24 /* Pods-VBBNow-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-VBBNow-resources.sh"; sourceTree = ""; }; - EBDFC5BC545FCBE6B4AF71FE2818ED90 /* RLMQueryUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; name = RLMQueryUtil.mm; path = Realm/RLMQueryUtil.mm; sourceTree = ""; }; - ED16BE6C29090CAE7F32B9D757075674 /* Realm-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Realm-prefix.pch"; sourceTree = ""; }; - EEAAE9E613DFE79610E529C04D19FD93 /* RLMObjectSchema.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectSchema.h; path = include/RLMObjectSchema.h; sourceTree = ""; }; - F1B403F1D525866885F27E2B0A5C2F95 /* Pods_VBBNow.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_VBBNow.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - F499BD65626016E373C109D2EE8194B2 /* collection_change_builder.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = collection_change_builder.cpp; path = Realm/ObjectStore/src/impl/collection_change_builder.cpp; sourceTree = ""; }; - F823B85F973EDBE4F46962194D9C003B /* Realm.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = Realm.modulemap; sourceTree = ""; }; - F83DF66FA251959174CB98F3E41DF215 /* RLMSchema.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSchema.h; path = include/RLMSchema.h; sourceTree = ""; }; - FB5F122BB22DF7FECCC98129F7626EC2 /* RLMSyncUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncUtil.h; path = include/RLMSyncUtil.h; sourceTree = ""; }; - FB5F8F3612C08944A9FBF99D92590975 /* schema.cpp */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = schema.cpp; path = Realm/ObjectStore/src/schema.cpp; sourceTree = ""; }; - FE6BD60C5945F58879F5FB4465F9CA95 /* RLMSyncUser.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMSyncUser.h; path = include/RLMSyncUser.h; sourceTree = ""; }; - FE8BE2362C2F5AB54077FB69FC5D2239 /* RLMMigration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMMigration.h; path = include/RLMMigration.h; sourceTree = ""; }; + E41BCB4E534CB8835740B939DC23FFC1 /* object_schema.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = object_schema.cpp; path = Realm/ObjectStore/src/object_schema.cpp; sourceTree = ""; }; + E5A5BD2F46C4BF5023EFC4E3278F70DC /* RLMObjectStore.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMObjectStore.mm; path = Realm/RLMObjectStore.mm; sourceTree = ""; }; + E847382C16A12FB27419671BE87CBF48 /* object_store.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = object_store.cpp; path = Realm/ObjectStore/src/object_store.cpp; sourceTree = ""; }; + E85B45CF5840DFB28ED7AD863CED703D /* RLMObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObject.h; path = include/RLMObject.h; sourceTree = ""; }; + EA984350FB2017E9FB4E0BB349AF4709 /* RLMObjectBase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMObjectBase.h; path = include/RLMObjectBase.h; sourceTree = ""; }; + EDBAE440891841D85B8B304695888694 /* keychain_helper.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = keychain_helper.cpp; path = Realm/ObjectStore/src/impl/apple/keychain_helper.cpp; sourceTree = ""; }; + EDE5687A305C57C985AB9A665B77C53C /* collection_notifications.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = collection_notifications.cpp; path = Realm/ObjectStore/src/collection_notifications.cpp; sourceTree = ""; }; + EED4293C58AA5A0D21213F39C12BEFA7 /* RLMNetworkClient.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RLMNetworkClient.m; path = Realm/RLMNetworkClient.m; sourceTree = ""; }; + F0B3A8ED49858453B76D3400A624A15B /* RLMArray_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMArray_Private.h; path = include/RLMArray_Private.h; sourceTree = ""; }; + F0D10F3D0EABFF6ABCAFFA14B9AD02B6 /* RLMRealm_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMRealm_Private.h; path = include/RLMRealm_Private.h; sourceTree = ""; }; + F137EBA0B76C022AABCD8E7768C72514 /* RLMResults_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RLMResults_Private.h; path = include/RLMResults_Private.h; sourceTree = ""; }; + F1B403F1D525866885F27E2B0A5C2F95 /* Pods_VBBNow.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_VBBNow.framework; path = "Pods-VBBNow.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + F1C8328614183AFAEC5511A660E8162D /* thread_confined.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = thread_confined.cpp; path = Realm/ObjectStore/src/thread_confined.cpp; sourceTree = ""; }; + F87B39E953F550932766A60E627858E5 /* RLMCollection.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMCollection.mm; path = Realm/RLMCollection.mm; sourceTree = ""; }; + FAFA814BB88EF5FD337338A2F0FF51D4 /* RLMPredicateUtil.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMPredicateUtil.mm; path = Realm/RLMPredicateUtil.mm; sourceTree = ""; }; + FB3E640EA7BD2B8D315F453E29E1537E /* RLMRealm.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = RLMRealm.mm; path = Realm/RLMRealm.mm; sourceTree = ""; }; + FF26C210A745CF572D4577E4676CCD4C /* list.cpp */ = {isa = PBXFileReference; includeInIndex = 1; name = list.cpp; path = Realm/ObjectStore/src/list.cpp; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 3E30A27A7CE930C149B2302218214B3E /* Frameworks */ = { + 866F7E304F5AB6684BCC46232557CEE3 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 756B29527A3BB0C5DDEB9FCC7DFEB4AC /* Cocoa.framework in Frameworks */, + 500338D2146D76BAB72F9A9C843AA682 /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 7090EA2307648BF3546B6F2E02C756DC /* Frameworks */ = { + D91DA68FA56B64061CBB9A00874D01FB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A6CC6C49F5B74F4B5D3E42A2E02AD1B6 /* Cocoa.framework in Frameworks */, + 8CB71DAA0A649F89022686F28F17DD09 /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 84CA489DCD5FDE74063A6DE20ACAEE9D /* Frameworks */ = { + FF4F90A1FAF08B898113CF20A8DBE20E /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - CCD9217B7FEE3DCBEF777D5DDCAD7C40 /* Cocoa.framework in Frameworks */, + 3A68C58E4FCA79C3C9AFD139E08C559C /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 03415438DEB3F7AB04B17842F946520D /* Support Files */ = { + isa = PBXGroup; + children = ( + DD399C7A7419295C8F0A275CBAB4EA10 /* Info.plist */, + 2F4DB766E5986241F1DA71EFA552DF04 /* Realm.modulemap */, + 31BCA3693B5FC383E0019D858E3961F4 /* Realm.xcconfig */, + 396431AE286E1938A480C6B7F5BA86A5 /* Realm-dummy.m */, + D8F402A7612BD54527423CF61EAA67A5 /* Realm-prefix.pch */, + ); + name = "Support Files"; + path = "../Target Support Files/Realm"; + sourceTree = ""; + }; + 04C068A18C5413F804A2959126093416 /* OS X */ = { + isa = PBXGroup; + children = ( + 270DD1219F1E6CF00379D39F252D87C6 /* Cocoa.framework */, + ); + name = "OS X"; + sourceTree = ""; + }; 14E2F46C34F067132A6C8FD30E0ACFF9 /* Pods-VBBNow */ = { isa = PBXGroup; children = ( @@ -419,14 +452,6 @@ path = "Target Support Files/Pods-VBBNow"; sourceTree = ""; }; - 28C17CEF104526ACA07B6EEE217EC43E /* OS X */ = { - isa = PBXGroup; - children = ( - 1CA6EBC2E57D96052268211209D6AA52 /* Cocoa.framework */, - ); - name = "OS X"; - sourceTree = ""; - }; 29C50C9930EDDD02D6D4066519270ABB /* Products */ = { isa = PBXGroup; children = ( @@ -440,11 +465,19 @@ 39E9EE8210D861DFD82346C1F5EB7218 /* Frameworks */ = { isa = PBXGroup; children = ( - 28C17CEF104526ACA07B6EEE217EC43E /* OS X */, + 04C068A18C5413F804A2959126093416 /* OS X */, ); name = Frameworks; sourceTree = ""; }; + 49B5263DC936247EF1096A815B127C71 /* Pods */ = { + isa = PBXGroup; + children = ( + 6BB6315E6BF7B1A0AE784D460DF89AF5 /* Realm */, + ); + name = Pods; + sourceTree = ""; + }; 52D0E813A82F71B454579218FACB5E41 /* Pods-VBB */ = { isa = PBXGroup; children = ( @@ -463,91 +496,95 @@ path = "Target Support Files/Pods-VBB"; sourceTree = ""; }; - 7465DE7B6FDF991C92DA0CB5C9F63BED /* Realm */ = { + 6BB6315E6BF7B1A0AE784D460DF89AF5 /* Realm */ = { isa = PBXGroup; children = ( - F499BD65626016E373C109D2EE8194B2 /* collection_change_builder.cpp */, - 9F872DC760E3A7A913501CDD0E49688B /* collection_notifications.cpp */, - 5164B39A8F60C42A1AFF04B540316B7A /* collection_notifier.cpp */, - AA012AC6A1901FE6B7EA71FFA5BF29B4 /* external_commit_helper.cpp */, - CBEFAEC42322EE588C4CE1BF939C4C72 /* format.cpp */, - 9B98E7E083A4E91CD57D92F3B66BC0F9 /* handover.cpp */, - 8022D1416A1403F2AF801D90045A5452 /* index_set.cpp */, - 1B10AD3AF9E9007B1ADA4C52747C4719 /* keychain_helper.cpp */, - 18130AD268176A0279E97E442ABFEDCD /* list.cpp */, - 3954CF0D591CFD23F9D44FC4E7F8E2BE /* list_notifier.cpp */, - B1431EDD4F50DF5FC020C0A75FB4F9DD /* object_schema.cpp */, - B1B96ECB64F7E33324B8EAFB4DC94F87 /* object_store.cpp */, - D99D3E5BF4737F66FAEB2A939631017D /* placeholder.cpp */, - 37D49A8BFA46FD198F9029FF866B84D7 /* realm_coordinator.cpp */, - 8A2F88B75421BB1BAA51BC6DAA226894 /* results.cpp */, - 7CA1A05864AF04C106ACCBFD60852BD6 /* results_notifier.cpp */, - 54B811089E20717FBE565C7DFF8959E0 /* RLMAccessor.h */, - 0B805AA31413DCF2DEBFE6409971B700 /* RLMAccessor.mm */, - 7EC6087687F7A71A96DD7662570C4077 /* RLMAnalytics.mm */, - 943D843F536640EE12B8EAFA1A038957 /* RLMArray.mm */, - 424EA9C5FF9E322C559BD3FD10F9092B /* RLMArray_Private.h */, - C5A151B1BBB1D2C9B2BE3FCCA114A573 /* RLMArrayLinkView.mm */, - 9A6F512185B5D12F73C4295DCA121267 /* RLMAuthResponseModel.m */, - C261C8CF818E53F2D3EB0F29DB59877D /* RLMClassInfo.mm */, - D071D5BA8565046C01C9ACED4E7A6D84 /* RLMCollection.mm */, - 12C058B644388DD29B690D5B6D256A3E /* RLMConstants.m */, - 519044AC217178621FF363269D6344C2 /* RLMListBase.h */, - 398E60EFE10734F5170C88A8018F4F8D /* RLMListBase.mm */, - D81269265A61E7F096BAAE0F9ECBC16A /* RLMMigration.mm */, - 7097776D326A5C6920C043CB3E32C28E /* RLMMigration_Private.h */, - 8D8428B5625A18C92C90C87BE598C76E /* RLMNetworkClient.m */, - 2290AC1CA7EB105C6C316E1CCBCB7092 /* RLMObject.mm */, - D51047ABC2AFEE69E43D15A318848A24 /* RLMObject_Private.h */, - B32F919064BB5621A476FEC9A530668C /* RLMObjectBase.mm */, - C64F45A2EE41F6AF3CD60EAB4F47F8C3 /* RLMObjectSchema.mm */, - 3B955FE3E7BE7FEFE6EF9AE9E6190ECD /* RLMObjectSchema_Private.h */, - C92029B18F453CA95D99A21A7DBA7C65 /* RLMObjectStore.h */, - DBDA483D331CC99EF81F98B144715EAE /* RLMObjectStore.mm */, - 7A310DA12B3F4F661AB508E5E4705E2E /* RLMObservation.mm */, - DFF3E07B87AF9496BD5E82F5039E99F8 /* RLMOptionalBase.h */, - 25ABD97B85A0A4EFCD3DB372EF367A42 /* RLMOptionalBase.mm */, - 766345985B39340DCF40D53045539AC0 /* RLMPredicateUtil.mm */, - 7E10BDDCD1452430D956D7D35FB82770 /* RLMProperty.mm */, - 0C103E061A2B83B5131E18C9F68D1358 /* RLMProperty_Private.h */, - EBDFC5BC545FCBE6B4AF71FE2818ED90 /* RLMQueryUtil.mm */, - 32829B880D0B8DD45E1D882459CF2D88 /* RLMRealm.mm */, - 00A6AC0F9C79B0C691DDB361F7ED9E76 /* RLMRealm_Private.h */, - 289AFBB1A2545E0525C8783CB4430B64 /* RLMRealmConfiguration.mm */, - 2C8E33FA00AB7C9EFC177ECB50B14A90 /* RLMRealmConfiguration+Sync.mm */, - 48441474D1D8C3B66F967B0E76837062 /* RLMRealmConfiguration_Private.h */, - 39F8AFBC85C45F619757B8863AAF76EA /* RLMRealmUtil.mm */, - D1963CF370AD94FF8542B49818029E44 /* RLMResults.mm */, - CC3074D458C8E4B7B88B55DE244480FB /* RLMResults_Private.h */, - 78B8C8451B740B8F2441708DB434479E /* RLMSchema.mm */, - 38141611BE7DF729928941BA5ED8BC49 /* RLMSchema_Private.h */, - 207655DE5C14B2A57A94D5C954011DDE /* RLMSwiftSupport.m */, - 661739F0FBDC9E8CBC03C9699EB38E89 /* RLMSyncConfiguration.mm */, - D8C27F6A06FBD7BC9D2CAA007D33BF65 /* RLMSyncConfiguration_Private.h */, - 3660CB7CF901F80EE595D72D9307E3C9 /* RLMSyncCredential.m */, - B9DB85E07728315E010FEC792388CE57 /* RLMSyncFileManager.mm */, - 7E1BF4F4217B5993AFF70FC53C787628 /* RLMSyncManager.mm */, - DC686D6D9603864D29EA0F2058FAB2CE /* RLMSyncSession.mm */, - 3D61ECDE4E4EA174F578A3DEF987C17C /* RLMSyncSession_Private.h */, - 63A49ECE34E65AAE2B43BB73B2737794 /* RLMSyncSessionHandle.mm */, - 45FAA23D2B88ACEAE13C5819F1F20A54 /* RLMSyncUser.mm */, - E350FAEE1CE28DF3F5C95D54F76A8663 /* RLMSyncUtil.mm */, - 9F7FD2D8A72BC62BAC9A5931BB8C3464 /* RLMSyncUtil_Private.h */, - 034990FBBE926C95450017780DDE2549 /* RLMTokenModels.m */, - 32E60FAC5AA32DB30476E57D759ABE49 /* RLMUpdateChecker.mm */, - 104BA96F47D6DBBD513718328A0F1D37 /* RLMUtil.mm */, - FB5F8F3612C08944A9FBF99D92590975 /* schema.cpp */, - D84036052E8CB24CB40E17886144B336 /* shared_realm.cpp */, - 05A7114F8F766A04D201539C57F60258 /* sync_manager.cpp */, - 52CDE0006AE03361D1D46D446377C3EE /* sync_metadata.cpp */, - 15B2F0FB2718B1150B4B97C2E1D1CA0F /* sync_session.cpp */, - 3C61306AB8513B6408B637E5C032E042 /* thread_confined.cpp */, - 0485EC23C75C4004E94E2EABA6BE7C59 /* transact_log_handler.cpp */, - 8864E15D52FC228189BA78CA478D44E8 /* weak_realm_notifier.cpp */, - 97CBE39052582F4C96A5D4032D17561E /* Frameworks */, - 9B3FD849DD2A6B44272B0603C173CCC3 /* Headers */, - 91083658C9CA99E22B2E03E5EEDF7D8B /* Support Files */, + 6C46D6C0783F61C6E1D253660E472622 /* collection_change_builder.cpp */, + EDE5687A305C57C985AB9A665B77C53C /* collection_notifications.cpp */, + 8745208AEDA874159FEEAC2FA2DDB148 /* collection_notifier.cpp */, + 2308EC716DAE5A031F0561FE45BE112B /* external_commit_helper.cpp */, + E177B0177B0A05503FEE813634035AC2 /* format.cpp */, + C3AE2CBBB9AEF2E0AA421B3316B3B983 /* handover.cpp */, + DE619E8BF823EDFA0B94672B12630032 /* index_set.cpp */, + EDBAE440891841D85B8B304695888694 /* keychain_helper.cpp */, + FF26C210A745CF572D4577E4676CCD4C /* list.cpp */, + A22E12264A783E6AC7BB0831C3CAFA0A /* list_notifier.cpp */, + E41BCB4E534CB8835740B939DC23FFC1 /* object_schema.cpp */, + E847382C16A12FB27419671BE87CBF48 /* object_store.cpp */, + D0CF987B74A9228808D79F2728CCA910 /* placeholder.cpp */, + 7A5FDB219098757033113A20F42EC7EC /* realm_coordinator.cpp */, + BCDC499822E9ACD5E24C9AB0CD479F84 /* results.cpp */, + 589E794D261E19A6638A2A2285F592D0 /* results_notifier.cpp */, + A57CD6C47A80BC1DD1C7135012261456 /* RLMAccessor.h */, + 842819BB0817F06B3BE15E916433226E /* RLMAccessor.mm */, + 817D8B62EE7BAB27C2D7AC377912262D /* RLMAnalytics.mm */, + A1B29797E7F996208B3F56B01C8068CC /* RLMArray.mm */, + F0B3A8ED49858453B76D3400A624A15B /* RLMArray_Private.h */, + 5CC5E03DF0C0E51B12CCC635C1F0B105 /* RLMArrayLinkView.mm */, + 9879E438CC8862D98C6A1D413281B540 /* RLMAuthResponseModel.m */, + 00256CADEDF0A4449FB3C7808A0A76C8 /* RLMClassInfo.mm */, + F87B39E953F550932766A60E627858E5 /* RLMCollection.mm */, + 2A629EBBD35DCEB4AF7041A55938591A /* RLMConstants.m */, + C55FE2C555506A88D4BAF650C12867E3 /* RLMListBase.h */, + 27FF71D843775C57E7B8AAA4979F4A86 /* RLMListBase.mm */, + 1930B09148A313A9BC9B4B7A8177E1B4 /* RLMMigration.mm */, + A5D4607B3A4E52359D0E8B8692E423DA /* RLMMigration_Private.h */, + EED4293C58AA5A0D21213F39C12BEFA7 /* RLMNetworkClient.m */, + AC3C1FCD80BB317610A445C2D61A6447 /* RLMObject.mm */, + C36347AE80C13783C1D80ED4DAE84C86 /* RLMObject_Private.h */, + 6CA7A5BB864ADDEDE2B7D29EA2C83418 /* RLMObjectBase.mm */, + 18AE4F83A475D08286BE890E54DAEC63 /* RLMObjectSchema.mm */, + 9662DF7C5E53A767E7A8010F23F00AC4 /* RLMObjectSchema_Private.h */, + B7A22640019BF322FD69A3FC75662C87 /* RLMObjectStore.h */, + E5A5BD2F46C4BF5023EFC4E3278F70DC /* RLMObjectStore.mm */, + BF0F199551C99F2AF39C52369269BC6A /* RLMObservation.mm */, + BFA3C0619720C825FFD969A8694D6459 /* RLMOptionalBase.h */, + 7210F2C38964418F7E3BD25871BE64C1 /* RLMOptionalBase.mm */, + FAFA814BB88EF5FD337338A2F0FF51D4 /* RLMPredicateUtil.mm */, + 30E336A7C1EA27F5B451FBE3DBC36A07 /* RLMProperty.mm */, + C1CE85299CE26714C404B4986AE03A1D /* RLMProperty_Private.h */, + D7CF164EEEFE85102FFE630F0E85AD80 /* RLMQueryUtil.mm */, + FB3E640EA7BD2B8D315F453E29E1537E /* RLMRealm.mm */, + F0D10F3D0EABFF6ABCAFFA14B9AD02B6 /* RLMRealm_Private.h */, + 75899BEC4655592543A2EC218AC1ACE3 /* RLMRealmConfiguration.mm */, + 328DEE271B3CD7A53BADCA85C261B7C4 /* RLMRealmConfiguration+Sync.mm */, + 4A006CFD858DDF1A94AE5E734BD7764E /* RLMRealmConfiguration_Private.h */, + BBC3565C3A2FCE6639D20C68353E504E /* RLMRealmUtil.mm */, + 1751EACA219057FB7456621679BA2401 /* RLMResults.mm */, + F137EBA0B76C022AABCD8E7768C72514 /* RLMResults_Private.h */, + 19568FA5741E7C17F8CA64CF5C25A676 /* RLMSchema.mm */, + 2DF7706F095459FD4971E5CFD187AED6 /* RLMSchema_Private.h */, + 91C16C4A846BCBF9E4D13D3FC8A9FF4D /* RLMSwiftSupport.m */, + 86A5FE684DBA2A9BA18F97C555BF7EA2 /* RLMSyncConfiguration.mm */, + AA362F932DF0854B4BA5C5C5CBCECF79 /* RLMSyncConfiguration_Private.h */, + B711C581A88BD9FE0DDD4F9141EFE382 /* RLMSyncCredentials.m */, + 42E896057D80950C8B0D9B7877BB6326 /* RLMSyncManager.mm */, + 31DAABC9CC6C6DA17482CF2698838940 /* RLMSyncManager_Private.h */, + C682053DECAE69B034815B792F03D620 /* RLMSyncPermissionChange.m */, + 406F84DAC28B85067F1FDE8F2159D1B3 /* RLMSyncPermissionChange_Private.h */, + BD17FF5BBECD1015FC9988031ED4384D /* RLMSyncSession.mm */, + 8A1BCE9F0706933B9C52B3F71A6CB35C /* RLMSyncSessionRefreshHandle.mm */, + CE9EF36DD57A76D33FD75564FA8B60BE /* RLMSyncUser.mm */, + 5C3196F97E003804B9BDD075494F299E /* RLMSyncUtil.mm */, + 607539AC413FBCD9851327FA3F2BAA6D /* RLMSyncUtil_Private.h */, + 403E12E002FB0D181261C590B7B14BD4 /* RLMTokenModels.m */, + 1D47B5C027BBF9EFE751A390BDBEF096 /* RLMUpdateChecker.mm */, + 57AA417A0A637C8877C7338959DA5380 /* RLMUtil.mm */, + 93B4F8BAA6A5D122AF94E4E017B223A6 /* schema.cpp */, + 21AD292E35AB2D656F1CD2B974E3A63B /* shared_realm.cpp */, + 54899CE56D9776FA8B5DE8FA2A773BEB /* sync_file.cpp */, + C030C57D7F1395F1350BFEFC7EF37EF8 /* sync_manager.cpp */, + 9B801378173B9D2B9C19028FC7C5F825 /* sync_metadata.cpp */, + 0C49E14BC92FDFBDBD3704FDE565C169 /* sync_session.cpp */, + 14A60E08812158EE860006A89CC29F09 /* sync_user.cpp */, + F1C8328614183AFAEC5511A660E8162D /* thread_confined.cpp */, + 5C1D6BDAF543593F2F7C2073804F277C /* transact_log_handler.cpp */, + 0605B3919063758184EDE3E40A9AB8C6 /* weak_realm_notifier.cpp */, + A4DF9AF09261D86B68840AEB9C7FE9C3 /* Frameworks */, + FAECABDEBA60C864C0A3BA4903216E08 /* Headers */, + 03415438DEB3F7AB04B17842F946520D /* Support Files */, ); + name = Realm; path = Realm; sourceTree = ""; }; @@ -556,158 +593,140 @@ children = ( 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, 39E9EE8210D861DFD82346C1F5EB7218 /* Frameworks */, - E348CC1D429CE7CD4D4C97A8665B0FE8 /* Pods */, + 49B5263DC936247EF1096A815B127C71 /* Pods */, 29C50C9930EDDD02D6D4066519270ABB /* Products */, F12906208EFEBB9AE6FCB20361697CF4 /* Targets Support Files */, ); sourceTree = ""; }; - 91083658C9CA99E22B2E03E5EEDF7D8B /* Support Files */ = { + A4DF9AF09261D86B68840AEB9C7FE9C3 /* Frameworks */ = { isa = PBXGroup; children = ( - 9FAB115944EF40EC1215F52BB37E4EA6 /* Info.plist */, - F823B85F973EDBE4F46962194D9C003B /* Realm.modulemap */, - AF507FA42053E9B8A381F25EC487F49A /* Realm.xcconfig */, - 60CD2CA9A20CBD33026F7468BF866A42 /* Realm-dummy.m */, - ED16BE6C29090CAE7F32B9D757075674 /* Realm-prefix.pch */, - ); - name = "Support Files"; - path = "../Target Support Files/Realm"; - sourceTree = ""; - }; - 97CBE39052582F4C96A5D4032D17561E /* Frameworks */ = { - isa = PBXGroup; - children = ( - 32363ABF33F1D25013C61D5678A7CD4F /* librealm-macosx.a */, + 29DD04BC47E51FC330A2884282773F8A /* librealm-macosx.a */, ); name = Frameworks; sourceTree = ""; }; - 9B3FD849DD2A6B44272B0603C173CCC3 /* Headers */ = { - isa = PBXGroup; - children = ( - 09147D24067FA3848A918BAAEE2C07EB /* Realm.h */, - DB875141CED28FC407D7A4738BA2DE05 /* RLMArray.h */, - 6FF63F74A7ADF71500412C2F86F7597C /* RLMCollection.h */, - 46D5B0F38D1D1335A0F0C64CB1924BB5 /* RLMConstants.h */, - FE8BE2362C2F5AB54077FB69FC5D2239 /* RLMMigration.h */, - A27ADBC6D0F1A0029C22B746260CD620 /* RLMObject.h */, - 4FDFF56DA8141886E5E4CCD082498AE9 /* RLMObjectBase.h */, - E0FAFDE4566B1CC34938EFDB139DE1A5 /* RLMObjectBase_Dynamic.h */, - EEAAE9E613DFE79610E529C04D19FD93 /* RLMObjectSchema.h */, - A5CCD9825C816504EEF6840EAEA70F72 /* RLMPlatform.h */, - 6944B6C86719E86FC72FC6723D02E65C /* RLMProperty.h */, - 5D81C9A7ACBF3EF1D8CFC6F10B626EE6 /* RLMRealm.h */, - B0B4CBC2DBA8C64954C17C9B1712ABD3 /* RLMRealm_Dynamic.h */, - 9C3C1F04C74D30BB29D88383FA57C0A3 /* RLMRealmConfiguration.h */, - 014469716A1D2CD0219B1E692FFCEE88 /* RLMRealmConfiguration+Sync.h */, - DCB7F8D3C434001DEC287625F5FAE924 /* RLMResults.h */, - F83DF66FA251959174CB98F3E41DF215 /* RLMSchema.h */, - 2ED1C41AF7A34E5092BAC9E583ADA1AE /* RLMSyncConfiguration.h */, - 6D337A9C1F193E27D99C6EB31B18C6F7 /* RLMSyncCredential.h */, - 52201054DED1B93163C58A80BB2DC94F /* RLMSyncManager.h */, - 5138207173D645AD7161144B667D1D88 /* RLMSyncSession.h */, - FE6BD60C5945F58879F5FB4465F9CA95 /* RLMSyncUser.h */, - FB5F122BB22DF7FECCC98129F7626EC2 /* RLMSyncUtil.h */, - ); - name = Headers; - sourceTree = ""; - }; - E348CC1D429CE7CD4D4C97A8665B0FE8 /* Pods */ = { + F12906208EFEBB9AE6FCB20361697CF4 /* Targets Support Files */ = { isa = PBXGroup; children = ( - 7465DE7B6FDF991C92DA0CB5C9F63BED /* Realm */, + 52D0E813A82F71B454579218FACB5E41 /* Pods-VBB */, + 14E2F46C34F067132A6C8FD30E0ACFF9 /* Pods-VBBNow */, ); - name = Pods; + name = "Targets Support Files"; sourceTree = ""; }; - F12906208EFEBB9AE6FCB20361697CF4 /* Targets Support Files */ = { + FAECABDEBA60C864C0A3BA4903216E08 /* Headers */ = { isa = PBXGroup; children = ( - 52D0E813A82F71B454579218FACB5E41 /* Pods-VBB */, - 14E2F46C34F067132A6C8FD30E0ACFF9 /* Pods-VBBNow */, + BC72C77F253149E7F9F4B3B344566EB2 /* Realm.h */, + 595CD5E05996D9C6E812BCAD75B77CC4 /* RLMArray.h */, + 97304DB97C36ED573506661757DCF909 /* RLMCollection.h */, + A46E0C3460F4755D41E89231F71F52D3 /* RLMConstants.h */, + 7123AFF085B35CDFF3D705B06AB75638 /* RLMMigration.h */, + E85B45CF5840DFB28ED7AD863CED703D /* RLMObject.h */, + EA984350FB2017E9FB4E0BB349AF4709 /* RLMObjectBase.h */, + 3AAC83F418897D2B121C709B49F4412F /* RLMObjectBase_Dynamic.h */, + AB025FABAAF248803A252D707FAC5B62 /* RLMObjectSchema.h */, + 1AE1D644DD3862A7E16768BAFEAAD709 /* RLMPlatform.h */, + 9AB1D76D5F4D78EB58442B1D5A0E227C /* RLMProperty.h */, + 43662C66460EFC7D9E291F9B9086B694 /* RLMRealm.h */, + BF1F05958D394CC73FAD54C74857DFB7 /* RLMRealm_Dynamic.h */, + 81833731DAFA92A367A5A877335815F2 /* RLMRealmConfiguration.h */, + 2F913857B663FFCD78EA3272B4D9ECFC /* RLMRealmConfiguration+Sync.h */, + A41691C4302FAC7629802089876E8848 /* RLMResults.h */, + 1AE1CC3B0C54E737FF56A252B579D2E0 /* RLMSchema.h */, + 6358FFFE171233AE4F917C29DE8E817F /* RLMSyncConfiguration.h */, + 173D94346D87FDA36DEB8D1163228477 /* RLMSyncCredentials.h */, + B877F67F7BF62A61B88198D6AAB4D7FB /* RLMSyncManager.h */, + 962A7019E7948A80AB45F39A7DFE01BD /* RLMSyncPermissionChange.h */, + 50F59561979D2AFC6D63C18BEA53EE69 /* RLMSyncSession.h */, + A2EE6A9E046640D359CAB73B80320FFE /* RLMSyncUser.h */, + D536E13D0B52FC8D5B1282CB79A9F1B3 /* RLMSyncUtil.h */, ); - name = "Targets Support Files"; + name = Headers; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 26634FB7A0D6975432F075C4B4628B20 /* Headers */ = { + 1FB1763E9B2508E2B2F26678688CA63D /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 5CC058E066760D6A15E0E197BD320202 /* Realm.h in Headers */, - EC55CE2A747B9BFD497E58F8F0120438 /* RLMAccessor.h in Headers */, - E62B6FA973D52D2D041CB23701C92E7E /* RLMArray.h in Headers */, - B1EEE31F9BB07356685B2A7D049EF1BF /* RLMArray_Private.h in Headers */, - DF87DF84166C434562FDB6D4ABE889B8 /* RLMCollection.h in Headers */, - 9A653104F0A4F059CC2A17A02597F30B /* RLMConstants.h in Headers */, - 7E52912667F1F270927C06D44678D852 /* RLMListBase.h in Headers */, - 30F7AA5E6EBA415049E49E38EB6BEB81 /* RLMMigration.h in Headers */, - FF7E1F9AE17C7BB6B70C4C7C7102E75F /* RLMMigration_Private.h in Headers */, - 7A984943AF0AA3B7C2EE09B62273CC36 /* RLMObject.h in Headers */, - 55051F3ABB7B00D559C626C144CFB875 /* RLMObject_Private.h in Headers */, - CEACC6846D2E72FA5A53D9C5FAB05373 /* RLMObjectBase.h in Headers */, - BDB7A9F7B1CA3A7FB83484EEE6F056D2 /* RLMObjectBase_Dynamic.h in Headers */, - 8608363EC049C080F037F7227DC19B58 /* RLMObjectSchema.h in Headers */, - 332351CAE765FE4545CF1AF5154D49AC /* RLMObjectSchema_Private.h in Headers */, - 96EAD28BC5B0C6B9FA0A4BA2D224A2A8 /* RLMObjectStore.h in Headers */, - CD465BC37CA2FF8BE789E39975E35E5D /* RLMOptionalBase.h in Headers */, - 1609307D58BBF0643A35CFE4ADAB7934 /* RLMPlatform.h in Headers */, - BE4CF1EB91E38AAD2E3F626074FA3B7B /* RLMProperty.h in Headers */, - DDA39F3D8B58BC5C706974126968A29E /* RLMProperty_Private.h in Headers */, - 72AF75A275A6EBBAB857FFF63D9BD2DD /* RLMRealm.h in Headers */, - 0DF357FF69DEAC1D3FED3B923140FD42 /* RLMRealm_Dynamic.h in Headers */, - 4C54B6964DA593918F03D6F8BA3AE0D8 /* RLMRealm_Private.h in Headers */, - 694864831D91F1D033FA1FA724094728 /* RLMRealmConfiguration+Sync.h in Headers */, - DE11B44683D024231348D5F2195950A7 /* RLMRealmConfiguration.h in Headers */, - D1B464A7B701D06CE68EA1E4D16AE82B /* RLMRealmConfiguration_Private.h in Headers */, - 043D48C377905C6B5D57758B1D37C45E /* RLMResults.h in Headers */, - 2B426F9C527CE73A594851504F7F9EDD /* RLMResults_Private.h in Headers */, - 4A66E5B8EADEFF2B42B66CBA146D079D /* RLMSchema.h in Headers */, - F1893A4FB1BC0BE070CE1BCFE9641AFC /* RLMSchema_Private.h in Headers */, - 63ABD9F092F88AB6A497EFF2684EE16F /* RLMSyncConfiguration.h in Headers */, - 70DBB7C7EA6ABB6ABE1286EA7BD582A5 /* RLMSyncConfiguration_Private.h in Headers */, - A0E8EA415E181D84DD9E5D1A427244DE /* RLMSyncCredential.h in Headers */, - 10C39B5D46E881F79013177C9DEB072A /* RLMSyncManager.h in Headers */, - ECADB9F2D979BFE218CE73DEA261B947 /* RLMSyncSession.h in Headers */, - 4B74B7597C3AD5226CEDFC34D253A5E5 /* RLMSyncSession_Private.h in Headers */, - 295900CF8636E9FE9A480D1837CF5139 /* RLMSyncUser.h in Headers */, - A0207C417267F8D80608CD347AE74431 /* RLMSyncUtil.h in Headers */, - 1ED10BC5C59606ED64540A1874C43A27 /* RLMSyncUtil_Private.h in Headers */, + 385CF3E76D20DBF3516F54C9C4E00460 /* Realm.h in Headers */, + B37AA799915AE03EE849805F6C782C45 /* RLMAccessor.h in Headers */, + 9001A69BC9D7D22C7A87055FB41B856A /* RLMArray.h in Headers */, + F928E16E2B2FFB5E53D9D155D2C6EFA5 /* RLMArray_Private.h in Headers */, + D04F905FB9234868A99258983E565481 /* RLMCollection.h in Headers */, + 500DBB9902058720722E16E6C40FF495 /* RLMConstants.h in Headers */, + 89B0D6E308FDEA7BCC9595FA86A5CCA5 /* RLMListBase.h in Headers */, + 67BE493B54641A55CD8072710FDE9CC8 /* RLMMigration.h in Headers */, + 0C8EA8830DAF786E3513F4F2FB65E5FA /* RLMMigration_Private.h in Headers */, + E37B338D5550987BDC4AF5534DAD7515 /* RLMObject.h in Headers */, + 8AAF77B36EC9EBBF8C71016CC0B0477C /* RLMObject_Private.h in Headers */, + 878F789CE2EF674C6DCCD53D3B792BAD /* RLMObjectBase.h in Headers */, + 15D9B86B6C80959B8BF1B90F5DC97FAD /* RLMObjectBase_Dynamic.h in Headers */, + 441E2DF52C983BD5A3756294A1CD7396 /* RLMObjectSchema.h in Headers */, + B1479361D3076C0F766531DAEE3460A8 /* RLMObjectSchema_Private.h in Headers */, + AF6AEF120785DD0FFC80F9DDCD16D5D2 /* RLMObjectStore.h in Headers */, + D2142F672ED7250A562047FE46524C38 /* RLMOptionalBase.h in Headers */, + A294A1A3CB8FE80AA36F2567C36087F1 /* RLMPlatform.h in Headers */, + A2F8A6E34A8BD7DD26B9B79F7F4BBD22 /* RLMProperty.h in Headers */, + 43F6CFB800CB881BCB56A999ED0001AD /* RLMProperty_Private.h in Headers */, + A64FB462F2F55FE4D36E95F4DB46DCDE /* RLMRealm.h in Headers */, + A80FCF8588238A5669071A51E8F01F30 /* RLMRealm_Dynamic.h in Headers */, + 16F482E8DCC7E38178A6F9B3A1F419BA /* RLMRealm_Private.h in Headers */, + 64D24812223C912FF5B106905363973E /* RLMRealmConfiguration+Sync.h in Headers */, + 1C0504D90972BFB606BB4D7F16F7CE10 /* RLMRealmConfiguration.h in Headers */, + 3278C5E9E7CC1A63A491108E87DCD648 /* RLMRealmConfiguration_Private.h in Headers */, + 739C359E5373B8F29716D3A1DA5D5DBE /* RLMResults.h in Headers */, + 1E63E40043AD28B4ABDEEAEB7509E68F /* RLMResults_Private.h in Headers */, + 09DED5644A2DE5C7E7C261B6DB24EEF1 /* RLMSchema.h in Headers */, + 71322DEB42B90731861F2B09F6736254 /* RLMSchema_Private.h in Headers */, + 7B6FCE53992B4357291D552613C06A79 /* RLMSyncConfiguration.h in Headers */, + 3FDB4B70D55AB8E010B7C2077AA9C38F /* RLMSyncConfiguration_Private.h in Headers */, + 632EF17C5D99597469184E7270B73916 /* RLMSyncCredentials.h in Headers */, + 846D2144F53FB461D2AEFA1201BF1738 /* RLMSyncManager.h in Headers */, + 5E229AE338922099B3877043DCF20410 /* RLMSyncManager_Private.h in Headers */, + 3BCA4F0CEC1ADDD2B8346F86BB5C4702 /* RLMSyncPermissionChange.h in Headers */, + 7833FE6ACE50F62478F10E58D7546076 /* RLMSyncPermissionChange_Private.h in Headers */, + B4B71FE8662DAB1124359B4A4BCEF80D /* RLMSyncSession.h in Headers */, + 06A6E1CC2F9240806864B0908625E553 /* RLMSyncUser.h in Headers */, + F7202CDF8CDE913D4ABD17DD6819E9A7 /* RLMSyncUtil.h in Headers */, + 21DEE65195D52FEE3C6C0538CDD631C4 /* RLMSyncUtil_Private.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 5E52E7739A82171EE48386003E7D9342 /* Headers */ = { + 4B53E9F243846F6D9B3DBDDB4C309205 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - DE90A3EC92681878243EF2BC7B85D233 /* Pods-VBB-umbrella.h in Headers */, + A47F5B74E9FA3C32F6F8192F1C12579C /* Pods-VBB-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - EB4652058DC941581F81546A3ECC1A8F /* Headers */ = { + 72805D93F01A7C7DE19FD994333A8E1C /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - D4D62CCD84EFE66EA1B3EA9C84E4295D /* Pods-VBBNow-umbrella.h in Headers */, + 8FB5D05A734415B912C2EAB2C74F4053 /* Pods-VBBNow-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 4DDB663ABA2FF8128D066C4CD1A0F7F0 /* Realm */ = { + 6C31A1283F4FB329C26860F6277C6F90 /* Realm */ = { isa = PBXNativeTarget; - buildConfigurationList = 5D0AEAB9127B2F4798AC0F12742EC6A6 /* Build configuration list for PBXNativeTarget "Realm" */; + buildConfigurationList = B6034D2FF0A9434A6F0E4ABBD75E6C28 /* Build configuration list for PBXNativeTarget "Realm" */; buildPhases = ( - 4CE72E5466991395EE6615752CB42025 /* Sources */, - 84CA489DCD5FDE74063A6DE20ACAEE9D /* Frameworks */, - 26634FB7A0D6975432F075C4B4628B20 /* Headers */, - 7AF2A1A857C7DF989801F87CE3B495D0 /* Copy . Private Headers */, - 8236059238F994036E3DCE3894F0E392 /* Copy . Public Headers */, - 43E3C523FAB396DEBC74D3209F9559A5 /* Create Symlinks to Header Folders */, + 1B36FDEAF423BB25552DA023B884EA8B /* Sources */, + FF4F90A1FAF08B898113CF20A8DBE20E /* Frameworks */, + 1FB1763E9B2508E2B2F26678688CA63D /* Headers */, + 5281406C0A3757FF864A6DE0E5E374ED /* Copy . Private Headers */, + 77445E2DE8BCF757895E86746E1F3471 /* Copy . Public Headers */, + 9F240E564C4D403659FAB4B9C19EA696 /* Create Symlinks to Header Folders */, ); buildRules = ( ); @@ -718,36 +737,36 @@ productReference = 92DF303C97DC5989901A786C31C35C80 /* Realm.framework */; productType = "com.apple.product-type.framework"; }; - F96210CB4524D4536E88D6D89C562567 /* Pods-VBB */ = { + D688801B55CE2B3547BBBF538E4D75C0 /* Pods-VBB */ = { isa = PBXNativeTarget; - buildConfigurationList = A0A734C5869452619F8C56CA65AAEF50 /* Build configuration list for PBXNativeTarget "Pods-VBB" */; + buildConfigurationList = 86E6976635D1C495B907BE6192424639 /* Build configuration list for PBXNativeTarget "Pods-VBB" */; buildPhases = ( - F1D716FC4EC8417DA84FEDD8AF0FC47D /* Sources */, - 3E30A27A7CE930C149B2302218214B3E /* Frameworks */, - 5E52E7739A82171EE48386003E7D9342 /* Headers */, + A369A3527EFEB3107B8C2BA278334930 /* Sources */, + D91DA68FA56B64061CBB9A00874D01FB /* Frameworks */, + 4B53E9F243846F6D9B3DBDDB4C309205 /* Headers */, ); buildRules = ( ); dependencies = ( - 369D847F407830EBB392A9E1A16EE38E /* PBXTargetDependency */, + 2F41894AE3A4E5D9FEF34F11E04932F2 /* PBXTargetDependency */, ); name = "Pods-VBB"; productName = "Pods-VBB"; productReference = 1C59229F270BCA843F3B9FFBDA06657F /* Pods_VBB.framework */; productType = "com.apple.product-type.framework"; }; - FA83DE490C0F28B293DD6BC1A1C1D637 /* Pods-VBBNow */ = { + FFFE57F7B7262CA710D999C1351D9F66 /* Pods-VBBNow */ = { isa = PBXNativeTarget; - buildConfigurationList = 6A78E25377BE109E8238CFC63BBC800F /* Build configuration list for PBXNativeTarget "Pods-VBBNow" */; + buildConfigurationList = F1935D90197D7F0E0E4601E2F53EF895 /* Build configuration list for PBXNativeTarget "Pods-VBBNow" */; buildPhases = ( - ADD0EC4339B0A399D04C7A6B05D0C130 /* Sources */, - 7090EA2307648BF3546B6F2E02C756DC /* Frameworks */, - EB4652058DC941581F81546A3ECC1A8F /* Headers */, + 7DEF3AE82FACD78B50835D3EF2C1D345 /* Sources */, + 866F7E304F5AB6684BCC46232557CEE3 /* Frameworks */, + 72805D93F01A7C7DE19FD994333A8E1C /* Headers */, ); buildRules = ( ); dependencies = ( - 533E62B43CA06328F8B87669B43498FE /* PBXTargetDependency */, + 3E9B274693E5B8F1CACFC2EBED789914 /* PBXTargetDependency */, ); name = "Pods-VBBNow"; productName = "Pods-VBBNow"; @@ -775,15 +794,15 @@ projectDirPath = ""; projectRoot = ""; targets = ( - F96210CB4524D4536E88D6D89C562567 /* Pods-VBB */, - FA83DE490C0F28B293DD6BC1A1C1D637 /* Pods-VBBNow */, - 4DDB663ABA2FF8128D066C4CD1A0F7F0 /* Realm */, + D688801B55CE2B3547BBBF538E4D75C0 /* Pods-VBB */, + FFFE57F7B7262CA710D999C1351D9F66 /* Pods-VBBNow */, + 6C31A1283F4FB329C26860F6277C6F90 /* Realm */, ); }; /* End PBXProject section */ /* Begin PBXShellScriptBuildPhase section */ - 43E3C523FAB396DEBC74D3209F9559A5 /* Create Symlinks to Header Folders */ = { + 9F240E564C4D403659FAB4B9C19EA696 /* Create Symlinks to Header Folders */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -795,118 +814,121 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "cd \"$CONFIGURATION_BUILD_DIR/$WRAPPER_NAME\"\nln -fs ${PUBLIC_HEADERS_FOLDER_PATH#$WRAPPER_NAME/} ${PUBLIC_HEADERS_FOLDER_PATH#$CONTENTS_FOLDER_PATH/}\nln -fs ${PRIVATE_HEADERS_FOLDER_PATH#$WRAPPER_NAME/} ${PRIVATE_HEADERS_FOLDER_PATH#$CONTENTS_FOLDER_PATH/}\n"; + shellScript = "base=\"$CONFIGURATION_BUILD_DIR/$WRAPPER_NAME\"\nln -fs $base/${PUBLIC_HEADERS_FOLDER_PATH#$WRAPPER_NAME/} $base/${PUBLIC_HEADERS_FOLDER_PATH#$CONTENTS_FOLDER_PATH/}\nln -fs $base/${PRIVATE_HEADERS_FOLDER_PATH#$WRAPPER_NAME/} $base/${PRIVATE_HEADERS_FOLDER_PATH#$CONTENTS_FOLDER_PATH/}\n"; + showEnvVarsInLog = 1; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 4CE72E5466991395EE6615752CB42025 /* Sources */ = { + 1B36FDEAF423BB25552DA023B884EA8B /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1194C66B5AE3A2589CC280DFE085BF8D /* collection_change_builder.cpp in Sources */, - 5072AD824D6AD7E3B30F5F5FAA325BA2 /* collection_notifications.cpp in Sources */, - B265C4151D9E434737B48FB2C145C90F /* collection_notifier.cpp in Sources */, - 5302DED431FC5C0BA69580C4DA6522AC /* external_commit_helper.cpp in Sources */, - F7B284A01CA0D53C6AA567B45DB6A334 /* format.cpp in Sources */, - 4F57AF131D77079DBA7D86AC1D5DB8E2 /* handover.cpp in Sources */, - 168BEA544B848C406D3FC9FB3882E0EE /* index_set.cpp in Sources */, - D08E697963D472D7C74AA1B4E3EAA154 /* keychain_helper.cpp in Sources */, - FC99FFCB75E617388EFED2A9CA768766 /* list.cpp in Sources */, - E04BC099AA88190010881F6916D2E64C /* list_notifier.cpp in Sources */, - 9343F0F000A235F81FF81DF56912557D /* object_schema.cpp in Sources */, - D9EDE4C7FAB98E4748EC4F2A61C142F9 /* object_store.cpp in Sources */, - DE0FCBF63D8647EA663F75079D1DE669 /* placeholder.cpp in Sources */, - DDC791C84F0B3333332678E5A3B0E0A6 /* Realm-dummy.m in Sources */, - F471118B12C5193A90A3283314A34C15 /* realm_coordinator.cpp in Sources */, - 9C90474C7943EDC97CCFFF54F5BB606D /* results.cpp in Sources */, - 0F287993F131D182BA941A85C7769922 /* results_notifier.cpp in Sources */, - 63D654B4A872CD960AC8F7910EC8DF44 /* RLMAccessor.mm in Sources */, - F270F70C1CC1F8D9BEAC0D4700BC0F4F /* RLMAnalytics.mm in Sources */, - 12717CA85FC64D692BE5F9FF2F56AE7C /* RLMArray.mm in Sources */, - E826E09AD10DBCD600CECF5E8C80CCE2 /* RLMArrayLinkView.mm in Sources */, - 1647B820844411D553027E67869AE43A /* RLMAuthResponseModel.m in Sources */, - 9465C567C5FACA5BA780EE38C29C0FC0 /* RLMClassInfo.mm in Sources */, - 55AEF02F4B0D88FBCB7DEBC249E7C8A0 /* RLMCollection.mm in Sources */, - C078D7B810C111EA51CD5A3111D9CCA6 /* RLMConstants.m in Sources */, - E130D71C0BF3F55BE4DDB9B4C09942A4 /* RLMListBase.mm in Sources */, - B2EC9D8EDD7510EA39E3FEF2901F4EAB /* RLMMigration.mm in Sources */, - B0AC441B01D8DB5DCCA426E5651AC66E /* RLMNetworkClient.m in Sources */, - 9E52C55923C95D151F8CDC2319A014AF /* RLMObject.mm in Sources */, - B8B3850B8A144C9AE501DF24DCBFDB72 /* RLMObjectBase.mm in Sources */, - 2916E4339CC6FDEC475AD05ED221C857 /* RLMObjectSchema.mm in Sources */, - E74813D5F09AB418E5B4F080A8F3B227 /* RLMObjectStore.mm in Sources */, - C7641E5193DBB4DC8023B532B5515C68 /* RLMObservation.mm in Sources */, - 009FFC9303097703F79B61193B66BAD2 /* RLMOptionalBase.mm in Sources */, - FB0237CD7B7ED219C343DC27A6644BBA /* RLMPredicateUtil.mm in Sources */, - 10C47D71057411A27C638DE2D0C4D22A /* RLMProperty.mm in Sources */, - 09D0DFDF8347435BE95D56AE6FDADBCB /* RLMQueryUtil.mm in Sources */, - 71CE0EBA96635BA51BF115FC1BE82011 /* RLMRealm.mm in Sources */, - D04FDB724FCB57B56451FDA378B3DF81 /* RLMRealmConfiguration+Sync.mm in Sources */, - 81A1870BCEA631B08938069F94C923F8 /* RLMRealmConfiguration.mm in Sources */, - 10E133170F959FEF9913AE3DFAD42C41 /* RLMRealmUtil.mm in Sources */, - 4FAEEB41872BFE1F0224F1A0D29453A1 /* RLMResults.mm in Sources */, - 4F1BFB974BB09F1E3A341EA52008CD50 /* RLMSchema.mm in Sources */, - 1AB09F890CF130E17580119B4199F848 /* RLMSwiftSupport.m in Sources */, - 56643A709064D5CD283BB1FA211AB84A /* RLMSyncConfiguration.mm in Sources */, - 26CD1EEB82053E536F0FE241492EF6F2 /* RLMSyncCredential.m in Sources */, - 65D870331F885960B0FA671466EEB029 /* RLMSyncFileManager.mm in Sources */, - 1A18CE94FCB350DD61C4E225CAFB66A6 /* RLMSyncManager.mm in Sources */, - 7C063E56F503B745AE3866FDCEDAAB05 /* RLMSyncSession.mm in Sources */, - 9A9436B44D911373AB9AF405B5A470F8 /* RLMSyncSessionHandle.mm in Sources */, - 4436ABEDE05178987318AF722C7D78B3 /* RLMSyncUser.mm in Sources */, - 15672E6EBBB60FD33C720758B6C061D6 /* RLMSyncUtil.mm in Sources */, - 09F6233ECAEA6D5E768B65EEEB194438 /* RLMTokenModels.m in Sources */, - 4A814DC9D9E3C919EB0B6440ECC79F76 /* RLMUpdateChecker.mm in Sources */, - B5AC18C25F8FC499143A741BF616D4E4 /* RLMUtil.mm in Sources */, - AC70C6FE3341A86A863E5BF70FA52101 /* schema.cpp in Sources */, - 48E83195D65F8079ECF08232996463C6 /* shared_realm.cpp in Sources */, - 544E1BACAA0914CEDEB101DB6E9726A9 /* sync_manager.cpp in Sources */, - 4F0D281550F043A72D2510A7306FE36A /* sync_metadata.cpp in Sources */, - AADB69710892C7587FE5D6A902763897 /* sync_session.cpp in Sources */, - 14AFB23EC73BC008065D06D3778D69B2 /* thread_confined.cpp in Sources */, - 74C34BE2B46DC63D1DB1ECACB071FC84 /* transact_log_handler.cpp in Sources */, - 046FAC0DCEA4E3B42A5E5C28DE94F50D /* weak_realm_notifier.cpp in Sources */, + 49BB799A5AA054ED13B0E8B6EE3F38E5 /* collection_change_builder.cpp in Sources */, + FCF10E56DC800578258374E69657C75A /* collection_notifications.cpp in Sources */, + 59EBC6E1FC13E47F7420EB9639AE8369 /* collection_notifier.cpp in Sources */, + C1C2377BCCF027C11682082030921F3F /* external_commit_helper.cpp in Sources */, + 477EBEC0444079C11199C41378513829 /* format.cpp in Sources */, + 8C6D2F00EA4311CC4FCE75B4253C2B43 /* handover.cpp in Sources */, + FFF5BD906CBC4FF7A08896F5139E85D4 /* index_set.cpp in Sources */, + 97EF980147B739EF1964165D3A09FED1 /* keychain_helper.cpp in Sources */, + 7A13A77BBD5BB889E338FD425C7A7659 /* list.cpp in Sources */, + E9C18EF87FEA05164AC706B936C2E3F9 /* list_notifier.cpp in Sources */, + 429E1E3DD42BE99C4FC9037437D5031C /* object_schema.cpp in Sources */, + D35F5E9BD02ECB3F0F6B6F8B79BFA63F /* object_store.cpp in Sources */, + E91364FEBEBD7DE01B34E7BB08678F8D /* placeholder.cpp in Sources */, + 46FC1435E3972C39787E6EC0B97A5493 /* Realm-dummy.m in Sources */, + 3474F310D512FFEEAA3A5F47D83CD0C6 /* realm_coordinator.cpp in Sources */, + 505FD3AFEB77D52890E0E00B7FC34276 /* results.cpp in Sources */, + 8F198282A52C6329CFCAADFAD16CA425 /* results_notifier.cpp in Sources */, + 4227BEC869C4159105EA17006E6E9FEA /* RLMAccessor.mm in Sources */, + F2751B5F0355B8FB31E4504853686066 /* RLMAnalytics.mm in Sources */, + C5A96DC6F9C3DDAD9482F18CC9AF1486 /* RLMArray.mm in Sources */, + 6A710329D4DD487A170CF3F3DBEA5FD7 /* RLMArrayLinkView.mm in Sources */, + 44BA672A2D5B10B36C8DA3B9B74A51E7 /* RLMAuthResponseModel.m in Sources */, + DC526F8CAD4D0C0C874A6574AF8125FC /* RLMClassInfo.mm in Sources */, + F600C0EA3461CC3550342BAF36F1D8AB /* RLMCollection.mm in Sources */, + 1C32C382875D46E34D31E7BE55A8809A /* RLMConstants.m in Sources */, + 83A60CAD9E8F19D398F8E3DC1F07C705 /* RLMListBase.mm in Sources */, + D4C7BBE293B075535AFA737C878D7D02 /* RLMMigration.mm in Sources */, + 9C52AD2FF9F68A2B50869CCD1DA1484E /* RLMNetworkClient.m in Sources */, + A98F81B68B736D3F55D163A8CF24C9A5 /* RLMObject.mm in Sources */, + 8A1AFDB383AB1D2478D593940716C77F /* RLMObjectBase.mm in Sources */, + 5E84340694A9E67EB8D3CE69F7926C7C /* RLMObjectSchema.mm in Sources */, + CA47DE883C5D5664489656A034BF4ADF /* RLMObjectStore.mm in Sources */, + DB59DC2450130901D111B0DF5671F552 /* RLMObservation.mm in Sources */, + 14B2E954E29084BEC30479DCFE45AF87 /* RLMOptionalBase.mm in Sources */, + 1BDA95A0FA259BD85F14D8DEA042FFB6 /* RLMPredicateUtil.mm in Sources */, + 0D69439A117F6936F8493B07647AB2BB /* RLMProperty.mm in Sources */, + 1DE96EC791D4A098A779265D9EC20112 /* RLMQueryUtil.mm in Sources */, + 6A7281BA44249E241901FA077EE82242 /* RLMRealm.mm in Sources */, + A9B59E01A7526997D7F2BF8EDC3EA168 /* RLMRealmConfiguration+Sync.mm in Sources */, + AB3BD7540E6E68710609A40565307246 /* RLMRealmConfiguration.mm in Sources */, + C37BE1A79E6595D677BD3FF11208704E /* RLMRealmUtil.mm in Sources */, + 05F3C48F7872D18B1ED02E13B97BEAEE /* RLMResults.mm in Sources */, + 47C415354DB093EAD0CD47C693C4066F /* RLMSchema.mm in Sources */, + E9E1AEDF2C30282A3F82D1C6A5248493 /* RLMSwiftSupport.m in Sources */, + FC4980676574C10ED6F181FECB3B9EBA /* RLMSyncConfiguration.mm in Sources */, + 8ADE9886BC266D00B2ACAF5E6AA7EF5A /* RLMSyncCredentials.m in Sources */, + 2F91B6A0AC5472FD723716C077D2073E /* RLMSyncManager.mm in Sources */, + 0E4C4128B27BB582A0DEAF0A8C5633A2 /* RLMSyncPermissionChange.m in Sources */, + 8162CD7C7344CDE6DD4B4C0A585B450C /* RLMSyncSession.mm in Sources */, + 89512A53E3563F67296869C895F72643 /* RLMSyncSessionRefreshHandle.mm in Sources */, + 08DB46DBBF8CAE627E31C2AE31CB01B2 /* RLMSyncUser.mm in Sources */, + 9DEB1A9675C6DC24A2FE779538CF4B0A /* RLMSyncUtil.mm in Sources */, + F1963CC84D3C9E92441FB5868361CD9B /* RLMTokenModels.m in Sources */, + F5A24CF92B643E0CB22BC70D6EF4B755 /* RLMUpdateChecker.mm in Sources */, + FC31C9E08F4FB2665B721C99EFB2C6F7 /* RLMUtil.mm in Sources */, + 87D584752B968A6FDA9D7E03E15FE7EF /* schema.cpp in Sources */, + 85DCA8034220ABF3A07E830147843F85 /* shared_realm.cpp in Sources */, + A97EA07AEE0202EFEFA5E43FDB28CC5A /* sync_file.cpp in Sources */, + AD1D8D08CFD525D51361BF3955A882B5 /* sync_manager.cpp in Sources */, + 05DBD8D125C3F768A8E594A393E68CDB /* sync_metadata.cpp in Sources */, + 42A0D568C983936DB0660E998E63E466 /* sync_session.cpp in Sources */, + F6CA4527F3E65BD332E0EFCCC4265121 /* sync_user.cpp in Sources */, + 5347FB095831DAD9A7DCBD457BA2FCD9 /* thread_confined.cpp in Sources */, + D9DCC94D29A0408E394074988BE47133 /* transact_log_handler.cpp in Sources */, + C67CBD9B466D24F30E05E1E1185F88B7 /* weak_realm_notifier.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - ADD0EC4339B0A399D04C7A6B05D0C130 /* Sources */ = { + 7DEF3AE82FACD78B50835D3EF2C1D345 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 7C296329738864259BE74A954327C920 /* Pods-VBBNow-dummy.m in Sources */, + E3963E66B3C28B0C48D704B3E46023E7 /* Pods-VBBNow-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - F1D716FC4EC8417DA84FEDD8AF0FC47D /* Sources */ = { + A369A3527EFEB3107B8C2BA278334930 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2A47E33C5048CDDAC2DEBEE6417ED315 /* Pods-VBB-dummy.m in Sources */, + D6BADCA8931FB6B904B60ECCDAD723B4 /* Pods-VBB-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 369D847F407830EBB392A9E1A16EE38E /* PBXTargetDependency */ = { + 2F41894AE3A4E5D9FEF34F11E04932F2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Realm; - target = 4DDB663ABA2FF8128D066C4CD1A0F7F0 /* Realm */; - targetProxy = 4FA23BEBDF90894A985DBB2C8C784EDE /* PBXContainerItemProxy */; + target = 6C31A1283F4FB329C26860F6277C6F90 /* Realm */; + targetProxy = F31F63D41F116CA578B3F01FD5EC18BD /* PBXContainerItemProxy */; }; - 533E62B43CA06328F8B87669B43498FE /* PBXTargetDependency */ = { + 3E9B274693E5B8F1CACFC2EBED789914 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Realm; - target = 4DDB663ABA2FF8128D066C4CD1A0F7F0 /* Realm */; - targetProxy = 450E9CDC72DCD25DC23494BF4A427D81 /* PBXContainerItemProxy */; + target = 6C31A1283F4FB329C26860F6277C6F90 /* Realm */; + targetProxy = 23A0E0DCCCB9375813C9BB753AE5BAF9 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 1C4BB2D9278DA2774672E0E9857A26B2 /* Release */ = { + 26A531BF57553981EC3197213EDA6742 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9381C08AED2AEB137C5BF8B828AB54E2 /* Pods-VBBNow.release.xcconfig */; + baseConfigurationReference = 62924E0FC106DDBF9F530EB048E4E825 /* Pods-VBBNow.debug.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_IDENTITY = "-"; @@ -915,7 +937,7 @@ "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -929,7 +951,7 @@ MACH_O_TYPE = staticlib; MACOSX_DEPLOYMENT_TARGET = 10.10; MODULEMAP_FILE = "Target Support Files/Pods-VBBNow/Pods-VBBNow.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; + MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -940,6 +962,40 @@ VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; + name = Debug; + }; + 68DB3EBF3C72CA446FD67DD83C98AC5A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 31BCA3693B5FC383E0019D858E3961F4 /* Realm.xcconfig */; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = "-"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_VERSION = A; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREFIX_HEADER = "Target Support Files/Realm/Realm-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Realm/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MODULEMAP_FILE = "Target Support Files/Realm/Realm.modulemap"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = Realm; + SDKROOT = macosx; + SKIP_INSTALL = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; name = Release; }; 9420A7205B8F85520AF134F4EE25F7CC /* Release */ = { @@ -982,9 +1038,9 @@ }; name = Release; }; - A97A4B7EF0BBFAC8F18754D44C220D5E /* Release */ = { + BA8D3B6E8B3813905605B8B4A327C64D /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = AF507FA42053E9B8A381F25EC487F49A /* Realm.xcconfig */; + baseConfigurationReference = 31BCA3693B5FC383E0019D858E3961F4 /* Realm.xcconfig */; buildSettings = { APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_IDENTITY = "-"; @@ -993,7 +1049,7 @@ "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -1007,19 +1063,20 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; MODULEMAP_FILE = "Target Support Files/Realm/Realm.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; + MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_NAME = Realm; SDKROOT = macosx; SKIP_INSTALL = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; - AAD3E6F79B3C3F9C66A7EB9F8F5DB6AF /* Release */ = { + BE8EA0CEE443E145D4F665F8B4C11B4B /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 330F67DBC229E210EAC8B3BA0A6DFDB4 /* Pods-VBB.release.xcconfig */; + baseConfigurationReference = 9381C08AED2AEB137C5BF8B828AB54E2 /* Pods-VBBNow.release.xcconfig */; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_IDENTITY = "-"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -1034,18 +1091,18 @@ ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_VERSION = A; GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Target Support Files/Pods-VBB/Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-VBBNow/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MACOSX_DEPLOYMENT_TARGET = 10.10; - MODULEMAP_FILE = "Target Support Files/Pods-VBB/Pods-VBB.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-VBBNow/Pods-VBBNow.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = Pods_VBB; + PRODUCT_NAME = Pods_VBBNow; SDKROOT = macosx; SKIP_INSTALL = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -1053,52 +1110,17 @@ }; name = Release; }; - BB4340C3FD2CD3D102F7AC0B34DC1049 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = AF507FA42053E9B8A381F25EC487F49A /* Realm.xcconfig */; - buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CODE_SIGN_IDENTITY = "-"; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_VERSION = A; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Realm/Realm-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Realm/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.9; - MODULEMAP_FILE = "Target Support Files/Realm/Realm.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = Realm; - SDKROOT = macosx; - SKIP_INSTALL = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - E431DA05779CA3E2027FFA43200F6B43 /* Debug */ = { + C4EFA582DD9B20FA3D7CBD994BEBAB62 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 62924E0FC106DDBF9F530EB048E4E825 /* Pods-VBBNow.debug.xcconfig */; + baseConfigurationReference = 330F67DBC229E210EAC8B3BA0A6DFDB4 /* Pods-VBB.release.xcconfig */; buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_IDENTITY = "-"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -1106,26 +1128,26 @@ ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_VERSION = A; GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Target Support Files/Pods-VBBNow/Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-VBB/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MACOSX_DEPLOYMENT_TARGET = 10.10; - MODULEMAP_FILE = "Target Support Files/Pods-VBBNow/Pods-VBBNow.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; + MODULEMAP_FILE = "Target Support Files/Pods-VBB/Pods-VBB.modulemap"; + MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = Pods_VBBNow; + PRODUCT_NAME = Pods_VBB; SDKROOT = macosx; SKIP_INSTALL = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Release; }; - E7E81EB6E519546EB72FF1E196EEFA9B /* Debug */ = { + E305F9999899B7D112C0A794932A7569 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 3C98F107634FE7071CFCC4EF946889A9 /* Pods-VBB.debug.xcconfig */; buildSettings = { @@ -1218,29 +1240,29 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 5D0AEAB9127B2F4798AC0F12742EC6A6 /* Build configuration list for PBXNativeTarget "Realm" */ = { + 86E6976635D1C495B907BE6192424639 /* Build configuration list for PBXNativeTarget "Pods-VBB" */ = { isa = XCConfigurationList; buildConfigurations = ( - BB4340C3FD2CD3D102F7AC0B34DC1049 /* Debug */, - A97A4B7EF0BBFAC8F18754D44C220D5E /* Release */, + E305F9999899B7D112C0A794932A7569 /* Debug */, + C4EFA582DD9B20FA3D7CBD994BEBAB62 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 6A78E25377BE109E8238CFC63BBC800F /* Build configuration list for PBXNativeTarget "Pods-VBBNow" */ = { + B6034D2FF0A9434A6F0E4ABBD75E6C28 /* Build configuration list for PBXNativeTarget "Realm" */ = { isa = XCConfigurationList; buildConfigurations = ( - E431DA05779CA3E2027FFA43200F6B43 /* Debug */, - 1C4BB2D9278DA2774672E0E9857A26B2 /* Release */, + BA8D3B6E8B3813905605B8B4A327C64D /* Debug */, + 68DB3EBF3C72CA446FD67DD83C98AC5A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - A0A734C5869452619F8C56CA65AAEF50 /* Build configuration list for PBXNativeTarget "Pods-VBB" */ = { + F1935D90197D7F0E0E4601E2F53EF895 /* Build configuration list for PBXNativeTarget "Pods-VBBNow" */ = { isa = XCConfigurationList; buildConfigurations = ( - E7E81EB6E519546EB72FF1E196EEFA9B /* Debug */, - AAD3E6F79B3C3F9C66A7EB9F8F5DB6AF /* Release */, + 26A531BF57553981EC3197213EDA6742 /* Debug */, + BE8EA0CEE443E145D4F665F8B4C11B4B /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Pods/Realm/README.md b/Pods/Realm/README.md index 25fbd78..4a1d7b9 100644 --- a/Pods/Realm/README.md +++ b/Pods/Realm/README.md @@ -39,7 +39,8 @@ In case you don't want to use the precompiled version, you can build Realm yours Prerequisites: -* Building Realm requires Xcode 7.3.1 or Xcode 8.0. +* Building Realm requires Xcode 7.3.1 or Xcode 8.x. +* If cloning from git, submodules are required: `git submodule update --init --recursive`. * Building Realm documentation requires [jazzy](https://github.com/realm/jazzy) Once you have all the necessary prerequisites, building Realm.framework just takes a single command: `sh build.sh build`. You'll need an internet connection the first time you build Realm to download the core binary. diff --git a/Pods/Realm/Realm/ObjectStore/src/collection_notifications.cpp b/Pods/Realm/Realm/ObjectStore/src/collection_notifications.cpp index 12fca83..165021d 100644 --- a/Pods/Realm/Realm/ObjectStore/src/collection_notifications.cpp +++ b/Pods/Realm/Realm/ObjectStore/src/collection_notifications.cpp @@ -54,3 +54,8 @@ NotificationToken& NotificationToken::operator=(realm::NotificationToken&& rgt) } return *this; } + +void NotificationToken::suppress_next() +{ + m_notifier.load()->suppress_next_notification(m_token); +} diff --git a/Pods/Realm/Realm/ObjectStore/src/impl/apple/external_commit_helper.cpp b/Pods/Realm/Realm/ObjectStore/src/impl/apple/external_commit_helper.cpp index 5195a3e..60f7a66 100644 --- a/Pods/Realm/Realm/ObjectStore/src/impl/apple/external_commit_helper.cpp +++ b/Pods/Realm/Realm/ObjectStore/src/impl/apple/external_commit_helper.cpp @@ -158,6 +158,8 @@ ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent) try { listen(); } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" catch (std::exception const& e) { fprintf(stderr, "uncaught exception in notifier thread: %s: %s\n", typeid(e).name(), e.what()); asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "uncaught exception in notifier thread: %s: %s", typeid(e).name(), e.what()); @@ -168,6 +170,7 @@ ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent) asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "uncaught exception in notifier thread"); throw; } +#pragma clang diagnostic pop }); } diff --git a/Pods/Realm/Realm/ObjectStore/src/impl/apple/keychain_helper.cpp b/Pods/Realm/Realm/ObjectStore/src/impl/apple/keychain_helper.cpp index 2ebd991..b12128d 100644 --- a/Pods/Realm/Realm/ObjectStore/src/impl/apple/keychain_helper.cpp +++ b/Pods/Realm/Realm/ObjectStore/src/impl/apple/keychain_helper.cpp @@ -33,7 +33,7 @@ using realm::util::adoptCF; namespace realm { namespace keychain { -KeychainAccessException::KeychainAccessException(size_t error_code) +KeychainAccessException::KeychainAccessException(int32_t error_code) : std::runtime_error(util::format("Keychain returned unexpected status code: %1", error_code)) { } CFPtr convert_string(const std::string& string); diff --git a/Pods/Realm/Realm/ObjectStore/src/impl/collection_notifier.cpp b/Pods/Realm/Realm/ObjectStore/src/impl/collection_notifier.cpp index c7b76f0..f6e9184 100644 --- a/Pods/Realm/Realm/ObjectStore/src/impl/collection_notifier.cpp +++ b/Pods/Realm/Realm/ObjectStore/src/impl/collection_notifier.cpp @@ -21,6 +21,7 @@ #include "impl/realm_coordinator.hpp" #include "shared_realm.hpp" +#include #include using namespace realm; @@ -181,9 +182,9 @@ size_t CollectionNotifier::add_callback(CollectionChangeCallback callback) std::lock_guard lock(m_callback_mutex); auto token = next_token(); - m_callbacks.push_back({std::move(callback), token, false}); + m_callbacks.push_back({std::move(callback), {}, {}, token, false, false}); if (m_callback_index == npos) { // Don't need to wake up if we're already sending notifications - Realm::Internal::get_coordinator(*m_realm).send_commit_notifications(*m_realm); + Realm::Internal::get_coordinator(*m_realm).wake_up_notifier_worker(); m_have_callbacks = true; } return token; @@ -191,15 +192,12 @@ size_t CollectionNotifier::add_callback(CollectionChangeCallback callback) void CollectionNotifier::remove_callback(size_t token) { + // the callback needs to be destroyed after releasing the lock as destroying + // it could cause user code to be called Callback old; { std::lock_guard lock(m_callback_mutex); - REALM_ASSERT(m_error || m_callbacks.size() > 0); - - auto it = find_if(begin(m_callbacks), end(m_callbacks), - [=](const auto& c) { return c.token == token; }); - // We should only fail to find the callback if it was removed due to an error - REALM_ASSERT(m_error || it != end(m_callbacks)); + auto it = find_callback(token); if (it == end(m_callbacks)) { return; } @@ -216,6 +214,33 @@ void CollectionNotifier::remove_callback(size_t token) } } +void CollectionNotifier::suppress_next_notification(size_t token) +{ + { + std::lock_guard lock(m_realm_mutex); + REALM_ASSERT(m_realm); + m_realm->verify_thread(); + m_realm->verify_in_write(); + } + + std::lock_guard lock(m_callback_mutex); + auto it = find_callback(token); + if (it != end(m_callbacks)) { + it->skip_next = true; + } +} + +std::vector::iterator CollectionNotifier::find_callback(size_t token) +{ + REALM_ASSERT(m_error || m_callbacks.size() > 0); + + auto it = find_if(begin(m_callbacks), end(m_callbacks), + [=](const auto& c) { return c.token == token; }); + // We should only fail to find the callback if it was removed due to an error + REALM_ASSERT(m_error || it != end(m_callbacks)); + return it; +} + void CollectionNotifier::unregister() noexcept { std::lock_guard lock(m_realm_mutex); @@ -260,66 +285,85 @@ void CollectionNotifier::prepare_handover() REALM_ASSERT(m_sg); m_sg_version = m_sg->get_version_of_current_transaction(); do_prepare_handover(*m_sg); + m_has_run = true; } void CollectionNotifier::before_advance() { - while (auto fn = next_callback(!m_changes_to_deliver.empty(), true)) - fn.before(m_changes_to_deliver); + for_each_callback([&](auto& lock, auto& callback) { + if (callback.changes_to_deliver.empty()) { + return; + } + + auto changes = callback.changes_to_deliver; + // acquire a local reference to the callback so that removing the + // callback from within it can't result in a dangling pointer + auto cb = callback.fn; + lock.unlock(); + cb.before(changes); + }); } void CollectionNotifier::after_advance() { - while (auto fn = next_callback(!m_changes_to_deliver.empty(), false)) - fn.after(m_changes_to_deliver); - m_changes_to_deliver = {}; + for_each_callback([&](auto& lock, auto& callback) { + if (callback.initial_delivered && callback.changes_to_deliver.empty()) { + return; + } + callback.initial_delivered = true; + + auto changes = std::move(callback.changes_to_deliver); + // acquire a local reference to the callback so that removing the + // callback from within it can't result in a dangling pointer + auto cb = callback.fn; + lock.unlock(); + cb.after(changes); + }); } void CollectionNotifier::deliver_error(std::exception_ptr error) { - while (auto fn = next_callback(true, false)) { - fn.error(error); - } + for_each_callback([&](auto& lock, auto& callback) { + // acquire a local reference to the callback so that removing the + // callback from within it can't result in a dangling pointer + auto cb = callback.fn; + lock.unlock(); + cb.error(error); + }); // Remove all the callbacks as we never need to call anything ever again // after delivering an error - std::lock_guard callback_lock(m_callback_mutex); m_callbacks.clear(); m_error = true; } -SharedGroup::VersionID CollectionNotifier::package_for_delivery(Realm& realm) +bool CollectionNotifier::is_for_realm(Realm& realm) const noexcept { - { - std::lock_guard lock(m_realm_mutex); - if (m_realm.get() != &realm) { - return SharedGroup::VersionID{}; - } - } - - if (!prepare_to_deliver()) { - return SharedGroup::VersionID{}; - } - m_changes_to_deliver = std::move(m_accumulated_changes).finalize(); - return version(); + std::lock_guard lock(m_realm_mutex); + return m_realm.get() == &realm; } -CollectionChangeCallback CollectionNotifier::next_callback(bool has_changes, bool pre) +bool CollectionNotifier::package_for_delivery() { - std::lock_guard callback_lock(m_callback_mutex); + if (!prepare_to_deliver()) + return false; + std::lock_guard l(m_callback_mutex); + for (auto& callback : m_callbacks) + callback.changes_to_deliver = std::move(callback.accumulated_changes).finalize(); + return true; +} +template +void CollectionNotifier::for_each_callback(Fn&& fn) +{ + std::unique_lock callback_lock(m_callback_mutex); for (++m_callback_index; m_callback_index < m_callbacks.size(); ++m_callback_index) { - auto& callback = m_callbacks[m_callback_index]; - if (callback.initial_delivered && !has_changes) { - continue; - } - if (!pre) - callback.initial_delivered = true; - return callback.fn; + fn(callback_lock, m_callbacks[m_callback_index]); + if (!callback_lock.owns_lock()) + callback_lock.lock(); } m_callback_index = npos; - return nullptr; } void CollectionNotifier::attach_to(SharedGroup& sg) @@ -336,3 +380,90 @@ void CollectionNotifier::detach() do_detach_from(*m_sg); m_sg = nullptr; } + +void CollectionNotifier::add_changes(CollectionChangeBuilder change) +{ + std::lock_guard lock(m_callback_mutex); + for (auto& callback : m_callbacks) { + if (callback.skip_next) { + REALM_ASSERT_DEBUG(callback.accumulated_changes.empty()); + callback.skip_next = false; + } + else { + if (&callback == &m_callbacks.back()) + callback.accumulated_changes.merge(std::move(change)); + else + callback.accumulated_changes.merge(CollectionChangeBuilder(change)); + } + } +} + +NotifierPackage::NotifierPackage(std::exception_ptr error, + std::vector> notifiers, + RealmCoordinator* coordinator) +: m_notifiers(std::move(notifiers)) +, m_coordinator(coordinator) +, m_error(std::move(error)) +{ +} + +void NotifierPackage::package_and_wait(util::Optional target_version) +{ + if (!m_coordinator || m_error || !*this) + return; + + auto lock = m_coordinator->wait_for_notifiers([&] { + if (!target_version) + return true; + return std::all_of(begin(m_notifiers), end(m_notifiers), [&](auto const& n) { + return !n->have_callbacks() || (n->has_run() && n->version().version >= *target_version); + }); + }); + + // Package the notifiers for delivery and remove any which don't have anything to deliver + auto package = [&](auto& notifier) { + if (notifier->has_run() && notifier->package_for_delivery()) { + m_version = notifier->version(); + return false; + } + return true; + }; + m_notifiers.erase(std::remove_if(begin(m_notifiers), end(m_notifiers), package), end(m_notifiers)); + if (m_version && target_version && m_version->version < *target_version) { + m_notifiers.clear(); + m_version = util::none; + } + REALM_ASSERT(m_version || m_notifiers.empty()); + + m_coordinator = nullptr; +} + +void NotifierPackage::before_advance() +{ + if (m_error) + return; + for (auto& notifier : m_notifiers) + notifier->before_advance(); +} + +void NotifierPackage::deliver(SharedGroup& sg) +{ + if (m_error) { + for (auto& notifier : m_notifiers) + notifier->deliver_error(m_error); + return; + } + // Can't deliver while in a write transaction + if (sg.get_transact_stage() != SharedGroup::transact_Reading) + return; + for (auto& notifier : m_notifiers) + notifier->deliver(sg); +} + +void NotifierPackage::after_advance() +{ + if (m_error) + return; + for (auto& notifier : m_notifiers) + notifier->after_advance(); +} diff --git a/Pods/Realm/Realm/ObjectStore/src/impl/realm_coordinator.cpp b/Pods/Realm/Realm/ObjectStore/src/impl/realm_coordinator.cpp index 6ddebdc..ebb2772 100644 --- a/Pods/Realm/Realm/ObjectStore/src/impl/realm_coordinator.cpp +++ b/Pods/Realm/Realm/ObjectStore/src/impl/realm_coordinator.cpp @@ -22,20 +22,23 @@ #include "impl/external_commit_helper.hpp" #include "impl/transact_log_handler.hpp" #include "impl/weak_realm_notifier.hpp" +#include "binding_context.hpp" #include "object_schema.hpp" #include "object_store.hpp" #include "schema.hpp" -#include "sync_config.hpp" -#include "sync_manager.hpp" -#include "sync_session.hpp" +#if REALM_ENABLE_SYNC +#include "sync/sync_config.hpp" +#include "sync/sync_manager.hpp" +#include "sync/sync_session.hpp" +#endif #include #include #include -#include #include +#include using namespace realm; using namespace realm::_impl; @@ -57,6 +60,14 @@ std::shared_ptr RealmCoordinator::get_coordinator(StringData p return coordinator; } +std::shared_ptr RealmCoordinator::get_coordinator(const Realm::Config& config) +{ + auto coordinator = get_coordinator(config.path); + std::lock_guard lock(coordinator->m_realm_mutex); + coordinator->set_config(config); + return coordinator; +} + std::shared_ptr RealmCoordinator::get_existing_coordinator(StringData path) { std::lock_guard lock(s_coordinator_mutex); @@ -64,9 +75,32 @@ std::shared_ptr RealmCoordinator::get_existing_coordinator(Str return it == s_coordinators_per_path.end() ? nullptr : it->second.lock(); } -std::shared_ptr RealmCoordinator::get_realm(Realm::Config config) +void RealmCoordinator::create_sync_session() +{ +#if REALM_ENABLE_SYNC + if (m_sync_session) + return; + + m_sync_session = SyncManager::shared().get_session(m_config.path, *m_config.sync_config); + + std::weak_ptr weak_self = shared_from_this(); + SyncSession::Internal::set_sync_transact_callback(*m_sync_session, + [weak_self](VersionID old_version, VersionID new_version) { + if (auto self = weak_self.lock()) { + if (self->m_transaction_callback) + self->m_transaction_callback(old_version, new_version); + if (self->m_notifier) + self->m_notifier->notify_others(); + } + }); + if (m_config.sync_config->error_handler) { + SyncSession::Internal::set_error_handler(*m_sync_session, m_config.sync_config->error_handler); + } +#endif +} + +void RealmCoordinator::set_config(const Realm::Config& config) { - std::lock_guard lock(m_realm_mutex); if ((!m_config.read_only() && !m_notifier) || (m_config.read_only() && m_weak_realm_notifiers.empty())) { m_config = config; } @@ -86,9 +120,38 @@ std::shared_ptr RealmCoordinator::get_realm(Realm::Config config) if (m_config.schema_version != config.schema_version && config.schema_version != ObjectStore::NotVersioned) { throw MismatchedConfigException("Realm at path '%1' already opened with different schema version.", config.path); } + +#if REALM_ENABLE_SYNC + if (bool(m_config.sync_config) != bool(config.sync_config)) { + throw MismatchedConfigException("Realm at path '%1' already opened with different sync configurations.", config.path); + } + + if (config.sync_config) { + if (m_config.sync_config->user != config.sync_config->user) { + throw MismatchedConfigException("Realm at path '%1' already opened with different sync user.", config.path); + } + if (m_config.sync_config->realm_url != config.sync_config->realm_url) { + throw MismatchedConfigException("Realm at path '%1' already opened with different sync server URL.", config.path); + } + } +#endif + // Realm::update_schema() handles complaining about schema mismatches } +#if REALM_ENABLE_SYNC + if (config.sync_config) { + create_sync_session(); + } +#endif +} + +std::shared_ptr RealmCoordinator::get_realm(Realm::Config config) +{ + std::lock_guard lock(m_realm_mutex); + + set_config(config); + if (config.cache) { for (auto& cached_realm : m_weak_realm_notifiers) { if (cached_realm.is_cached_for_current_thread()) { @@ -101,17 +164,6 @@ std::shared_ptr RealmCoordinator::get_realm(Realm::Config config) } } - if (config.sync_config && !m_sync_session) { - m_sync_session = SyncManager::shared().get_session(config.path, *config.sync_config); - SyncSession::Internal::set_sync_transact_callback(*m_sync_session, [this](VersionID, VersionID) { - if (m_notifier) - m_notifier->notify_others(); - }); - if (config.sync_config->error_handler) { - SyncSession::Internal::set_error_handler(*m_sync_session, config.sync_config->error_handler); - } - } - auto realm = Realm::make_shared_realm(std::move(config)); if (!config.read_only() && !m_notifier && config.automatic_change_notifications) { try { @@ -222,26 +274,59 @@ void RealmCoordinator::clear_all_caches() } } -void RealmCoordinator::send_commit_notifications(Realm& source_realm) +void RealmCoordinator::wake_up_notifier_worker() +{ + if (m_notifier) { + // FIXME: this wakes up the notification workers for all processes and + // not just us. This might be worth optimizing in the future. + m_notifier->notify_others(); + } +} + +void RealmCoordinator::commit_write(Realm& realm) { REALM_ASSERT(!m_config.read_only()); + REALM_ASSERT(realm.is_in_transaction()); + + { + // Need to acquire this lock before committing or another process could + // perform a write and notify us before we get the chance to set the + // skip version + std::lock_guard l(m_notifier_mutex); + + transaction::commit(Realm::Internal::get_shared_group(realm)); + + // Don't need to check m_new_notifiers because those don't skip versions + bool have_notifiers = std::any_of(m_notifiers.begin(), m_notifiers.end(), + [&](auto&& notifier) { return notifier->is_for_realm(realm); }); + if (have_notifiers) { + m_notifier_skip_version = Realm::Internal::get_shared_group(realm).get_version_of_current_transaction(); + } + } + + if (realm.m_binding_context) { + realm.m_binding_context->did_change({}, {}); + } + if (m_notifier) { m_notifier->notify_others(); } +#if REALM_ENABLE_SYNC if (m_sync_session) { - auto& sg = Realm::Internal::get_shared_group(source_realm); + auto& sg = Realm::Internal::get_shared_group(realm); auto version = LangBindHelper::get_version_of_latest_snapshot(sg); SyncSession::Internal::nonsync_transact_notify(*m_sync_session, version); } +#endif } -void RealmCoordinator::pin_version(uint_fast64_t version, uint_fast32_t index) +void RealmCoordinator::pin_version(VersionID versionid) { + REALM_ASSERT_DEBUG(!m_notifier_mutex.try_lock()); if (m_async_error) { return; } - SharedGroup::VersionID versionid(version, index); if (!m_advancer_sg) { try { std::unique_ptr read_only_group; @@ -277,7 +362,7 @@ void RealmCoordinator::register_notifier(std::shared_ptr not auto& self = Realm::Internal::get_coordinator(*notifier->get_realm()); { std::lock_guard lock(self.m_notifier_mutex); - self.pin_version(version.version, version.index); + self.pin_version(version); self.m_new_notifiers.push_back(std::move(notifier)); } } @@ -312,9 +397,9 @@ void RealmCoordinator::clean_up_dead_notifiers() m_notifier_sg->end_read(); } } - if (swap_remove(m_new_notifiers)) { + if (swap_remove(m_new_notifiers) && m_advancer_sg) { REALM_ASSERT_3(m_advancer_sg->get_transact_stage(), ==, SharedGroup::transact_Reading); - if (m_new_notifiers.empty() && m_advancer_sg) { + if (m_new_notifiers.empty()) { m_advancer_sg->end_read(); } } @@ -363,7 +448,7 @@ class IncrementalChangeInfo { TransactionChangeInfo& current() const { return *m_current; } - bool advance_incremental(SharedGroup::VersionID version) + bool advance_incremental(VersionID version) { if (version != m_sg.get_version_of_current_transaction()) { transaction::advance(m_sg, *m_current, version); @@ -377,7 +462,7 @@ class IncrementalChangeInfo { return false; } - void advance_to_final(SharedGroup::VersionID version) + void advance_to_final(VersionID version) { if (!m_current) { transaction::advance(m_sg, nullptr, m_schema_mode, version); @@ -447,7 +532,7 @@ void RealmCoordinator::run_async_notifiers() return; } - SharedGroup::VersionID version; + VersionID version; // Advance all of the new notifiers to the most recent version, if any auto new_notifiers = std::move(m_new_notifiers); @@ -475,7 +560,7 @@ void RealmCoordinator::run_async_notifiers() notifier->attach_to(*m_advancer_sg); notifier->add_required_change_info(new_notifier_change_info.current()); } - new_notifier_change_info.advance_to_final(SharedGroup::VersionID{}); + new_notifier_change_info.advance_to_final(VersionID{}); for (auto& notifier : new_notifiers) { notifier->detach(); @@ -485,11 +570,31 @@ void RealmCoordinator::run_async_notifiers() } REALM_ASSERT_3(m_advancer_sg->get_transact_stage(), ==, SharedGroup::transact_Ready); + auto skip_version = m_notifier_skip_version; + m_notifier_skip_version = {0, 0}; + // Make a copy of the notifiers vector and then release the lock to avoid // blocking other threads trying to register or unregister notifiers while we run them auto notifiers = m_notifiers; + m_notifiers.insert(m_notifiers.end(), new_notifiers.begin(), new_notifiers.end()); lock.unlock(); + if (skip_version.version) { + REALM_ASSERT(version >= skip_version); + IncrementalChangeInfo change_info(*m_notifier_sg, m_config.schema_mode, notifiers); + for (auto& notifier : notifiers) + notifier->add_required_change_info(change_info.current()); + change_info.advance_to_final(skip_version); + + for (auto& notifier : notifiers) + notifier->run(); + + lock.lock(); + for (auto& notifier : notifiers) + notifier->prepare_handover(); + lock.unlock(); + } + // Advance the non-new notifiers to the same version as we advanced the new // ones to (or the latest if there were no new ones) IncrementalChangeInfo change_info(*m_notifier_sg, m_config.schema_mode, notifiers); @@ -501,8 +606,8 @@ void RealmCoordinator::run_async_notifiers() // Attach the new notifiers to the main SG and move them to the main list for (auto& notifier : new_notifiers) { notifier->attach_to(*m_notifier_sg); + notifier->run(); } - std::move(new_notifiers.begin(), new_notifiers.end(), std::back_inserter(notifiers)); // Change info is now all ready, so the notifiers can now perform their // background work @@ -513,11 +618,14 @@ void RealmCoordinator::run_async_notifiers() // Reacquire the lock while updating the fields that are actually read on // other threads lock.lock(); + for (auto& notifier : new_notifiers) { + notifier->prepare_handover(); + } for (auto& notifier : notifiers) { notifier->prepare_handover(); } - m_notifiers = std::move(notifiers); clean_up_dead_notifiers(); + m_notifier_cv.notify_all(); } void RealmCoordinator::open_helper_shared_group() @@ -541,70 +649,108 @@ void RealmCoordinator::open_helper_shared_group() } } - -std::vector> RealmCoordinator::notifiers_to_deliver(Realm& realm) +void RealmCoordinator::advance_to_ready(Realm& realm) { std::unique_lock lock(m_notifier_mutex); - decltype(m_notifiers) notifiers; - if (m_async_error) { - auto error = m_async_error; - notifiers = m_notifiers; - lock.unlock(); - for (auto& notifier : notifiers) - notifier->deliver_error(error); - return {}; + _impl::NotifierPackage notifiers(m_async_error, notifiers_for_realm(realm), this); + lock.unlock(); + notifiers.package_and_wait(util::none); + + auto& sg = Realm::Internal::get_shared_group(realm); + if (!notifiers) { + transaction::advance(sg, realm.m_binding_context.get(), m_config.schema_mode, VersionID{}); + return; } + auto version = notifiers.version(); + if (version && *version <= sg.get_version_of_current_transaction()) + return; + + transaction::advance(sg, realm.m_binding_context.get(), m_config.schema_mode, notifiers); +} + +std::vector> RealmCoordinator::notifiers_for_realm(Realm& realm) +{ + std::vector> ret; + for (auto& notifier : m_new_notifiers) { + if (notifier->is_for_realm(realm)) + ret.push_back(notifier); + } for (auto& notifier : m_notifiers) { - auto notifier_version = notifier->package_for_delivery(realm); - if (notifier_version == SharedGroup::VersionID{}) - continue; - notifiers.push_back(notifier); + if (notifier->is_for_realm(realm)) + ret.push_back(notifier); } - - return notifiers; + return ret; } -void RealmCoordinator::advance_to_ready(Realm& realm) +bool RealmCoordinator::advance_to_latest(Realm& realm) { + using sgf = SharedGroupFriend; + auto& sg = Realm::Internal::get_shared_group(realm); - auto notifiers = notifiers_to_deliver(realm); - if (notifiers.empty()) { - transaction::advance(sg, realm.m_binding_context.get(), m_config.schema_mode); - return; - } + std::unique_lock lock(m_notifier_mutex); + _impl::NotifierPackage notifiers(m_async_error, notifiers_for_realm(realm), this); + lock.unlock(); + notifiers.package_and_wait(sgf::get_version_of_latest_snapshot(sg)); - auto version = notifiers[0]->version(); - if (version <= sg.get_version_of_current_transaction()) - return; + auto version = sg.get_version_of_current_transaction(); + transaction::advance(sg, realm.m_binding_context.get(), m_config.schema_mode, notifiers); + return version != sg.get_version_of_current_transaction(); +} - for (auto& notifier : notifiers) - notifier->before_advance(); - transaction::advance(sg, realm.m_binding_context.get(), m_config.schema_mode, version); - for (auto& notifier : notifiers) - notifier->deliver(sg); - for (auto& notifier : notifiers) - notifier->after_advance(); +void RealmCoordinator::promote_to_write(Realm& realm) +{ + REALM_ASSERT(!realm.is_in_transaction()); + + std::unique_lock lock(m_notifier_mutex); + _impl::NotifierPackage notifiers(m_async_error, notifiers_for_realm(realm), this); + lock.unlock(); + + auto& sg = Realm::Internal::get_shared_group(realm); + transaction::begin(sg, realm.m_binding_context.get(), m_config.schema_mode, notifiers); } void RealmCoordinator::process_available_async(Realm& realm) { - auto notifiers = notifiers_to_deliver(realm); + REALM_ASSERT(!realm.is_in_transaction()); + + std::unique_lock lock(m_notifier_mutex); + auto notifiers = notifiers_for_realm(realm); if (notifiers.empty()) return; - auto& sg = Realm::Internal::get_shared_group(realm); - auto version = notifiers[0]->version(); - if (version != sg.get_version_of_current_transaction()) + if (auto error = m_async_error) { + lock.unlock(); + for (auto& notifier : notifiers) + notifier->deliver_error(m_async_error); return; + } - for (auto& notifier : notifiers) - notifier->deliver(sg); + bool in_read = realm.is_in_read_transaction(); + auto& sg = Realm::Internal::get_shared_group(realm); + auto version = sg.get_version_of_current_transaction(); + auto package = [&](auto& notifier) { + return !(notifier->has_run() && (!in_read || notifier->version() == version) && notifier->package_for_delivery()); + }; + notifiers.erase(std::remove_if(begin(notifiers), end(notifiers), package), end(notifiers)); + lock.unlock(); + + // no before advance because the Realm is already at the given version, + // because we're either sending initial notifications or the write was + // done on this Realm instance + + // Skip delivering if the Realm isn't in a read transaction + if (in_read) { + for (auto& notifier : notifiers) + notifier->deliver(sg); + } + + // but still call the change callbacks for (auto& notifier : notifiers) notifier->after_advance(); } -void RealmCoordinator::notify_others() +void RealmCoordinator::set_transaction_callback(std::function fn) { - m_notifier->notify_others(); + m_transaction_callback = std::move(fn); } diff --git a/Pods/Realm/Realm/ObjectStore/src/impl/results_notifier.cpp b/Pods/Realm/Realm/ObjectStore/src/impl/results_notifier.cpp index 3f6c65f..28ab8d6 100644 --- a/Pods/Realm/Realm/ObjectStore/src/impl/results_notifier.cpp +++ b/Pods/Realm/Realm/ObjectStore/src/impl/results_notifier.cpp @@ -76,7 +76,7 @@ bool ResultsNotifier::do_add_required_change_info(TransactionChangeInfo& info) info.table_moves_needed.resize(table_ndx + 1); info.table_moves_needed[table_ndx] = true; - return m_initial_run_complete && have_callbacks(); + return has_run() && have_callbacks(); } bool ResultsNotifier::need_to_run() @@ -93,7 +93,7 @@ bool ResultsNotifier::need_to_run() } // If we've run previously, check if we need to rerun - if (m_initial_run_complete && m_query->sync_view_if_needed() == m_last_seen_version) { + if (has_run() && m_query->sync_view_if_needed() == m_last_seen_version) { return false; } @@ -103,7 +103,7 @@ bool ResultsNotifier::need_to_run() void ResultsNotifier::calculate_changes() { size_t table_ndx = m_query->get_table()->get_index_in_group(); - if (m_initial_run_complete) { + if (has_run()) { auto changes = table_ndx < m_info->tables.size() ? &m_info->tables[table_ndx] : nullptr; std::vector next_rows; @@ -159,12 +159,15 @@ void ResultsNotifier::run() void ResultsNotifier::do_prepare_handover(SharedGroup& sg) { if (!m_tv.is_attached()) { + // if the table version didn't change we can just reuse the same handover + // object and bump its version to the current SG version + if (m_tv_handover) + m_tv_handover->version = sg.get_version_of_current_transaction(); return; } REALM_ASSERT(m_tv.is_in_sync()); - m_initial_run_complete = true; m_tv_handover = sg.export_for_handover(m_tv, MutableSourcePayload::Move); add_changes(std::move(m_changes)); @@ -188,7 +191,6 @@ void ResultsNotifier::deliver(SharedGroup& sg) REALM_ASSERT(!m_query_handover); if (m_tv_to_deliver) { - m_tv_to_deliver->version = version(); Results::Internal::set_table_view(*m_target_results, std::move(*sg.import_from_handover(std::move(m_tv_to_deliver)))); } @@ -198,10 +200,7 @@ void ResultsNotifier::deliver(SharedGroup& sg) bool ResultsNotifier::prepare_to_deliver() { auto lock = lock_target(); - // We can get called before the query has actually had the chance to run if - // we're added immediately before a different set of async results are - // delivered - if (!get_realm() || !m_initial_run_complete) + if (!get_realm()) return false; m_tv_to_deliver = std::move(m_tv_handover); return true; diff --git a/Pods/Realm/Realm/ObjectStore/src/impl/transact_log_handler.cpp b/Pods/Realm/Realm/ObjectStore/src/impl/transact_log_handler.cpp index d0e40da..759b019 100644 --- a/Pods/Realm/Realm/ObjectStore/src/impl/transact_log_handler.cpp +++ b/Pods/Realm/Realm/ObjectStore/src/impl/transact_log_handler.cpp @@ -25,6 +25,7 @@ #include #include + #include using namespace realm; @@ -32,7 +33,6 @@ using namespace realm; namespace { template struct MarkDirtyMixin { -#if REALM_VER_MAJOR >= 2 bool mark_dirty(size_t row, size_t col, _impl::Instruction instr=_impl::instr_Set) { // Ignore SetDefault and SetUnique as those conceptually cannot be @@ -54,28 +54,8 @@ struct MarkDirtyMixin { bool set_mixed(size_t c, size_t r, const Mixed&, _impl::Instruction i) { return mark_dirty(r, c, i); } bool set_link(size_t c, size_t r, size_t, size_t, _impl::Instruction i) { return mark_dirty(r, c, i); } bool set_null(size_t c, size_t r, _impl::Instruction i, size_t) { return mark_dirty(r, c, i); } -#else - bool mark_dirty(size_t row, size_t col) - { - static_cast(this)->mark_dirty(row, col); - return true; - } - bool set_int(size_t col, size_t row, int_fast64_t) { return mark_dirty(row, col); } - bool set_bool(size_t col, size_t row, bool) { return mark_dirty(row, col); } - bool set_float(size_t col, size_t row, float) { return mark_dirty(row, col); } - bool set_double(size_t col, size_t row, double) { return mark_dirty(row, col); } - bool set_string(size_t col, size_t row, StringData) { return mark_dirty(row, col); } - bool set_binary(size_t col, size_t row, BinaryData) { return mark_dirty(row, col); } - bool set_olddatetime(size_t col, size_t row, OldDateTime) { return mark_dirty(row, col); } - bool set_timestamp(size_t col, size_t row, Timestamp) { return mark_dirty(row, col); } - bool set_table(size_t col, size_t row) { return mark_dirty(row, col); } - bool set_mixed(size_t col, size_t row, const Mixed&) { return mark_dirty(row, col); } - bool set_link(size_t col, size_t row, size_t, size_t) { return mark_dirty(row, col); } - bool set_null(size_t col, size_t row) { return mark_dirty(row, col); } -#endif - - bool add_int(size_t col, size_t row, size_t) { return mark_dirty(row, col); } + bool add_int(size_t col, size_t row, int_fast64_t) { return mark_dirty(row, col); } bool nullify_link(size_t col, size_t row, size_t) { return mark_dirty(row, col); } bool insert_substring(size_t col, size_t row, size_t, StringData) { return mark_dirty(row, col); } bool erase_substring(size_t col, size_t row, size_t, size_t) { return mark_dirty(row, col); } @@ -177,17 +157,9 @@ class TransactLogValidationMixin { bool link_list_clear(size_t) { return true; } bool link_list_move(size_t, size_t) { return true; } bool link_list_swap(size_t, size_t) { return true; } - bool change_link_targets(size_t, size_t) { return true; } + bool merge_rows(size_t, size_t) { return true; } bool optimize_table() { return true; } -#if REALM_VER_MAJOR < 2 - // Translate calls into their modern equivalents, relying on the fact that we do not - // care about the value of the new `prior_size` argument. - bool link_list_set(size_t index, size_t value) { return link_list_set(index, value, npos); } - bool link_list_insert(size_t index, size_t value) { return link_list_insert(index, value, npos); } - bool link_list_erase(size_t index) { return link_list_erase(index, npos); } - bool link_list_nullify(size_t index) { return link_list_nullify(index, npos); } -#endif }; @@ -249,6 +221,9 @@ class TransactLogObserver : public TransactLogValidationMixin, public MarkDirtyM // Change information for the currently selected LinkList, if any ColumnInfo* m_active_linklist = nullptr; + _impl::NotifierPackage& m_notifiers; + SharedGroup& m_sg; + // Get the change info for the given column, creating it if needed static ColumnInfo& get_change(ObserverState& state, size_t i) { @@ -278,14 +253,23 @@ class TransactLogObserver : public TransactLogValidationMixin, public MarkDirtyM public: template - TransactLogObserver(BindingContext* context, SharedGroup& sg, Func&& func, util::Optional schema_mode) + TransactLogObserver(BindingContext* context, SharedGroup& sg, Func&& func, + util::Optional schema_mode, + _impl::NotifierPackage& notifiers) : m_context(context) + , m_notifiers(notifiers) + , m_sg(sg) { auto old_version = sg.get_version_of_current_transaction(); if (context) { m_observers = context->get_observed_rows(); } - if (m_observers.empty()) { + + // If we have collection notifiers we have to use the transaction log + // observer to send will_change notifications once we know what the + // target version is, despite not otherwise needing to observe anything + if (m_observers.empty() && (!m_notifiers || m_notifiers.version())) { + m_notifiers.before_advance(); if (schema_mode) { func(TransactLogValidator(*schema_mode)); } @@ -295,12 +279,18 @@ class TransactLogObserver : public TransactLogValidationMixin, public MarkDirtyM if (context && old_version != sg.get_version_of_current_transaction()) { context->did_change({}, {}); } + m_notifiers.deliver(sg); + m_notifiers.after_advance(); return; } std::sort(begin(m_observers), end(m_observers)); func(*this); - context->did_change(m_observers, invalidated); + if (context) + context->did_change(m_observers, invalidated, old_version != sg.get_version_of_current_transaction()); + m_notifiers.package_and_wait(sg.get_version_of_current_transaction().version); // is a no-op if parse_complete() was called + m_notifiers.deliver(sg); // only will ever deliver errors + m_notifiers.after_advance(); } // Mark the given row/col as needing notifications sent @@ -316,7 +306,11 @@ class TransactLogObserver : public TransactLogValidationMixin, public MarkDirtyM // is advanced void parse_complete() { - m_context->will_change(m_observers, invalidated); + if (m_context) + m_context->will_change(m_observers, invalidated); + using sgf = _impl::SharedGroupFriend; + m_notifiers.package_and_wait(sgf::get_version_of_latest_snapshot(m_sg)); + m_notifiers.before_advance(); } bool insert_group_level_table(size_t table_ndx, size_t prior_size, StringData name) @@ -409,7 +403,7 @@ class TransactLogObserver : public TransactLogValidationMixin, public MarkDirtyM return true; } - bool change_link_targets(size_t from, size_t to) + bool merge_rows(size_t from, size_t to) { REALM_ASSERT(from != to); @@ -592,14 +586,6 @@ class TransactLogObserver : public TransactLogValidationMixin, public MarkDirtyM bool insert_link_column(size_t ndx, DataType type, StringData name, size_t, size_t) { return insert_column(ndx, type, name, false); } -#if REALM_VER_MAJOR < 2 - // Translate calls into their modern equivalents, relying on the fact that we do not - // care about the value of the new `prior_size` argument. - bool link_list_set(size_t index, size_t value) { return link_list_set(index, value, npos); } - bool link_list_insert(size_t index, size_t value) { return link_list_insert(index, value, npos); } - bool link_list_erase(size_t index) { return link_list_erase(index, npos); } - bool link_list_nullify(size_t index) { return link_list_nullify(index, npos); } -#endif }; // Extends TransactLogValidator to track changes made to LinkViews @@ -610,7 +596,7 @@ class LinkViewObserver : public TransactLogValidationMixin, public MarkDirtyMixi _impl::CollectionChangeBuilder* get_change() { auto tbl_ndx = current_table(); - if (tbl_ndx >= m_info.table_modifications_needed.size() || !m_info.table_modifications_needed[tbl_ndx]) + if (!m_info.track_all && (tbl_ndx >= m_info.table_modifications_needed.size() || !m_info.table_modifications_needed[tbl_ndx])) return nullptr; if (m_info.tables.size() <= tbl_ndx) { m_info.tables.resize(std::max(m_info.tables.size() * 2, tbl_ndx + 1)); @@ -621,7 +607,7 @@ class LinkViewObserver : public TransactLogValidationMixin, public MarkDirtyMixi bool need_move_info() const { auto tbl_ndx = current_table(); - return tbl_ndx < m_info.table_moves_needed.size() && m_info.table_moves_needed[tbl_ndx]; + return m_info.track_all || (tbl_ndx < m_info.table_moves_needed.size() && m_info.table_moves_needed[tbl_ndx]); } public: @@ -759,7 +745,7 @@ class LinkViewObserver : public TransactLogValidationMixin, public MarkDirtyMixi return true; } - bool change_link_targets(size_t from, size_t to) + bool merge_rows(size_t from, size_t to) { for (auto& list : m_info.lists) { if (list.table_ndx == current_table() && list.row_ndx == from) @@ -823,25 +809,26 @@ class LinkViewObserver : public TransactLogValidationMixin, public MarkDirtyMixi bool insert_link_column(size_t ndx, DataType type, StringData name, size_t, size_t) { return insert_column(ndx, type, name, false); } -#if REALM_VER_MAJOR < 2 - // Translate calls into their modern equivalents, relying on the fact that we do not - // care about the value of the new `prior_size` argument. - bool link_list_set(size_t index, size_t value) { return link_list_set(index, value, npos); } - bool link_list_insert(size_t index, size_t value) { return link_list_insert(index, value, npos); } - bool link_list_erase(size_t index) { return link_list_erase(index, npos); } - bool link_list_nullify(size_t index) { return link_list_nullify(index, npos); } -#endif }; } // anonymous namespace namespace realm { namespace _impl { + namespace transaction { -void advance(SharedGroup& sg, BindingContext* context, SchemaMode schema_mode, SharedGroup::VersionID version) +void advance(SharedGroup& sg, BindingContext* context, SchemaMode schema_mode, VersionID version) { + _impl::NotifierPackage notifiers; TransactLogObserver(context, sg, [&](auto&&... args) { LangBindHelper::advance_read(sg, std::move(args)..., version); - }, schema_mode); + }, schema_mode, notifiers); +} + +void advance(SharedGroup& sg, BindingContext* context, SchemaMode schema_mode, NotifierPackage& notifiers) +{ + TransactLogObserver(context, sg, [&](auto&&... args) { + LangBindHelper::advance_read(sg, std::move(args)..., notifiers.version().value_or(VersionID{})); + }, schema_mode, notifiers); } void begin_without_validation(SharedGroup& sg) @@ -849,34 +836,32 @@ void begin_without_validation(SharedGroup& sg) LangBindHelper::promote_to_write(sg); } -void begin(SharedGroup& sg, BindingContext* context, SchemaMode schema_mode) +void begin(SharedGroup& sg, BindingContext* context, SchemaMode schema_mode, + NotifierPackage& notifiers) { TransactLogObserver(context, sg, [&](auto&&... args) { LangBindHelper::promote_to_write(sg, std::move(args)...); - }, schema_mode); + }, schema_mode, notifiers); } -void commit(SharedGroup& sg, BindingContext* context) +void commit(SharedGroup& sg) { LangBindHelper::commit_and_continue_as_read(sg); - - if (context) { - context->did_change({}, {}); - } } void cancel(SharedGroup& sg, BindingContext* context) { + _impl::NotifierPackage notifiers; TransactLogObserver(context, sg, [&](auto&&... args) { LangBindHelper::rollback_and_continue_as_read(sg, std::move(args)...); - }, util::none); + }, util::none, notifiers); } void advance(SharedGroup& sg, TransactionChangeInfo& info, - SharedGroup::VersionID version) + VersionID version) { - if (info.table_modifications_needed.empty() && info.lists.empty()) { + if (!info.track_all && info.table_modifications_needed.empty() && info.lists.empty()) { LangBindHelper::advance_read(sg, version); } else { diff --git a/Pods/Realm/Realm/ObjectStore/src/object_schema.cpp b/Pods/Realm/Realm/ObjectStore/src/object_schema.cpp index dee4f44..269dd5b 100644 --- a/Pods/Realm/Realm/ObjectStore/src/object_schema.cpp +++ b/Pods/Realm/Realm/ObjectStore/src/object_schema.cpp @@ -106,6 +106,11 @@ const Property *ObjectSchema::property_for_name(StringData name) const { return const_cast(this)->property_for_name(name); } +bool ObjectSchema::property_is_computed(Property const& property) const { + auto end = computed_properties.end(); + return std::find(computed_properties.begin(), end, property) != end; +} + void ObjectSchema::set_primary_key_property() { if (primary_key.length()) { diff --git a/Pods/Realm/Realm/ObjectStore/src/object_store.cpp b/Pods/Realm/Realm/ObjectStore/src/object_store.cpp index 1b24a3d..e9fe1cb 100644 --- a/Pods/Realm/Realm/ObjectStore/src/object_store.cpp +++ b/Pods/Realm/Realm/ObjectStore/src/object_store.cpp @@ -93,6 +93,10 @@ void add_index(Table& table, size_t col) void insert_column(Group& group, Table& table, Property const& property, size_t col_ndx) { + // Cannot directly insert a LinkingObjects column (a computed property). + // LinkingObjects must be an artifact of an existing link column. + REALM_ASSERT(property.type != PropertyType::LinkingObjects); + if (property.type == PropertyType::Object || property.type == PropertyType::Array) { auto target_name = ObjectStore::table_name_for_object_type(property.object_type); TableRef link_table = group.get_or_add_table(target_name); @@ -137,13 +141,9 @@ void copy_property_values(Property const& prop, Table& table) { auto copy_property_values = [&](auto getter, auto setter) { for (size_t i = 0, count = table.size(); i < count; i++) { -#if REALM_VER_MAJOR >= 2 bool is_default = false; (table.*setter)(prop.table_column, i, (table.*getter)(prop.table_column + 1, i), is_default); -#else - (table.*setter)(prop.table_column, i, (table.*getter)(prop.table_column + 1, i)); -#endif } }; @@ -235,11 +235,7 @@ void ObjectStore::set_primary_key_for_object(Group& group, StringData object_typ size_t row = table->find_first_string(c_primaryKeyObjectClassColumnIndex, object_type); if (row == not_found && primary_key.size()) { row = table->add_empty_row(); -#if REALM_VER_MAJOR >= 2 row = table->set_string_unique(c_primaryKeyObjectClassColumnIndex, row, object_type); -#else - table->set_string(c_primaryKeyObjectClassColumnIndex, row, object_type); -#endif } // set if changing, or remove if setting to nil @@ -468,8 +464,7 @@ static void create_initial_tables(Group& group, std::vector const& void operator()(ChangePropertyType op) { - insert_column(group, table(op.object), *op.new_property, op.old_property->table_column); - table(op.object).remove_column(op.old_property->table_column + 1); + replace_column(group, table(op.object), *op.old_property, *op.new_property); } } applier{group}; diff --git a/Pods/Realm/Realm/ObjectStore/src/results.cpp b/Pods/Realm/Realm/ObjectStore/src/results.cpp index 5585f32..51451a8 100644 --- a/Pods/Realm/Realm/ObjectStore/src/results.cpp +++ b/Pods/Realm/Realm/ObjectStore/src/results.cpp @@ -33,11 +33,12 @@ using namespace realm; Results::Results() = default; Results::~Results() = default; -Results::Results(SharedRealm r, Query q, SortDescriptor s) +Results::Results(SharedRealm r, Query q, SortDescriptor s, SortDescriptor d) : m_realm(std::move(r)) , m_query(std::move(q)) , m_table(m_query.get_table().get()) , m_sort(std::move(s)) +, m_distinct(std::move(d)) , m_mode(Mode::Query) { } @@ -62,11 +63,12 @@ Results::Results(SharedRealm r, LinkViewRef lv, util::Optional q, SortDes } } -Results::Results(SharedRealm r, TableView tv, SortDescriptor s) +Results::Results(SharedRealm r, TableView tv, SortDescriptor s, SortDescriptor d) : m_realm(std::move(r)) , m_table_view(std::move(tv)) , m_table(&m_table_view.get_parent()) , m_sort(std::move(s)) +, m_distinct(std::move(d)) , m_mode(Mode::TableView) { } @@ -82,6 +84,7 @@ Results::Results(Results&& other) , m_link_view(std::move(other.m_link_view)) , m_table(other.m_table) , m_sort(std::move(other.m_sort)) +, m_distinct(std::move(other.m_distinct)) , m_notifier(std::move(other.m_notifier)) , m_mode(other.m_mode) , m_update_policy(other.m_update_policy) @@ -134,7 +137,9 @@ size_t Results::size() case Mode::LinkView: return m_link_view->size(); case Mode::Query: m_query.sync_view_if_needed(); - return m_query.count(); + if (!m_distinct) + return m_query.count(); + REALM_FALLTHROUGH; case Mode::TableView: update_tableview(); return m_table_view.size(); @@ -239,7 +244,7 @@ bool Results::update_linkview() { REALM_ASSERT(m_update_policy == UpdatePolicy::Auto); - if (m_sort) { + if (m_sort || m_distinct) { m_query = get_query(); m_mode = Mode::Query; update_tableview(); @@ -266,6 +271,9 @@ void Results::update_tableview(bool wants_notifications) if (m_sort) { m_table_view.sort(m_sort); } + if (m_distinct) { + m_table_view.distinct(m_distinct); + } m_mode = Mode::TableView; REALM_FALLTHROUGH; case Mode::TableView: @@ -483,12 +491,24 @@ TableView Results::get_tableview() Results Results::sort(realm::SortDescriptor&& sort) const { - return Results(m_realm, get_query(), std::move(sort)); + return Results(m_realm, get_query(), std::move(sort), m_distinct); } Results Results::filter(Query&& q) const { - return Results(m_realm, get_query().and_query(std::move(q)), m_sort); + return Results(m_realm, get_query().and_query(std::move(q)), m_sort, m_distinct); +} + + +// FIXME: The current implementation of distinct() breaks the Results API. +// This is tracked by the following issues: +// - https://github.com/realm/realm-object-store/issues/266 +// - https://github.com/realm/realm-core/issues/2332 +Results Results::distinct(realm::SortDescriptor&& uniqueness) +{ + auto tv = get_tableview(); + tv.distinct(uniqueness); + return Results(m_realm, std::move(tv), m_sort, std::move(uniqueness)); } Results Results::snapshot() const & @@ -524,6 +544,9 @@ Results Results::snapshot() && void Results::prepare_async() { + if (m_notifier) { + return; + } if (m_realm->config().read_only()) { throw InvalidTransactionException("Cannot create asynchronous query for read-only Realms"); } @@ -534,11 +557,9 @@ void Results::prepare_async() throw std::logic_error("Cannot create asynchronous query for snapshotted Results."); } - if (!m_notifier) { - m_wants_background_updates = true; - m_notifier = std::make_shared<_impl::ResultsNotifier>(*this); - _impl::RealmCoordinator::register_notifier(m_notifier); - } + m_wants_background_updates = true; + m_notifier = std::make_shared<_impl::ResultsNotifier>(*this); + _impl::RealmCoordinator::register_notifier(m_notifier); } NotificationToken Results::async(std::function target) diff --git a/Pods/Realm/Realm/ObjectStore/src/schema.cpp b/Pods/Realm/Realm/ObjectStore/src/schema.cpp index f45dd13..0908866 100644 --- a/Pods/Realm/Realm/ObjectStore/src/schema.cpp +++ b/Pods/Realm/Realm/ObjectStore/src/schema.cpp @@ -112,6 +112,10 @@ static void compare(ObjectSchema const& existing_schema, changes.emplace_back(schema_change::RemoveProperty{&existing_schema, ¤t_prop}); continue; } + if (target_schema.property_is_computed(*target_prop)) { + changes.emplace_back(schema_change::RemoveProperty{&existing_schema, ¤t_prop}); + continue; + } if (current_prop.type != target_prop->type || current_prop.object_type != target_prop->object_type) { changes.emplace_back(schema_change::ChangePropertyType{&existing_schema, ¤t_prop, target_prop}); continue; diff --git a/Pods/Realm/Realm/ObjectStore/src/shared_realm.cpp b/Pods/Realm/Realm/ObjectStore/src/shared_realm.cpp index a6cf089..977328a 100644 --- a/Pods/Realm/Realm/ObjectStore/src/shared_realm.cpp +++ b/Pods/Realm/Realm/ObjectStore/src/shared_realm.cpp @@ -30,18 +30,47 @@ #include "util/format.hpp" -#if REALM_VER_MAJOR >= 2 #include -#else -#include -#endif +#include +#if REALM_ENABLE_SYNC #include -#include +#endif using namespace realm; using namespace realm::_impl; +static std::string get_initial_temporary_directory() +{ + auto tmp_dir = getenv("TMPDIR"); + if (!tmp_dir) { + return std::string(); + } + std::string tmp_dir_str(tmp_dir); + if (!tmp_dir_str.empty() && tmp_dir_str.back() != '/') { + tmp_dir_str += '/'; + } + return tmp_dir_str; +} + +static std::string temporary_directory = get_initial_temporary_directory(); + +void realm::set_temporary_directory(std::string directory_path) +{ + if (directory_path.empty()) { + throw std::invalid_argument("'directory_path` is empty."); + } + if (directory_path.back() != '/') { + throw std::invalid_argument("'directory_path` must ends with '/'."); + } + temporary_directory = std::move(directory_path); +} + +const std::string& realm::get_temporary_directory() noexcept +{ + return temporary_directory; +} + Realm::Realm(Config config) : m_config(std::move(config)) { @@ -113,12 +142,16 @@ REALM_NOINLINE static void translate_file_exception(StringData path, bool read_o // don't want two copies of the path in the error, so strip it out if it // appears, and then include it in our prefix. std::string underlying = ex.what(); + RealmFileException::Kind error_kind = RealmFileException::Kind::AccessError; + // FIXME: Replace this with a proper specific exception type once Core adds support for it. + if (underlying == "Bad or incompatible history type") + error_kind = RealmFileException::Kind::BadHistoryError; auto pos = underlying.find(ex.get_path()); if (pos != std::string::npos && pos > 0) { // One extra char at each end for the quotes underlying.replace(pos - 1, ex.get_path().size() + 2, ""); } - throw RealmFileException(RealmFileException::Kind::AccessError, ex.get_path(), + throw RealmFileException(error_kind, ex.get_path(), util::format("Unable to open a realm at path '%1': %2.", ex.get_path(), underlying), ex.what()); } catch (IncompatibleLockFile const& ex) { @@ -142,30 +175,36 @@ void Realm::open_with_config(const Config& config, std::unique_ptr& read_only_group, Realm* realm) { - if (config.encryption_key.data() && config.encryption_key.size() != 64) { + if (config.encryption_key.data() && config.encryption_key.size() != 64) throw InvalidEncryptionKeyException(); - } + if (config.schema && config.schema_version == ObjectStore::NotVersioned) + throw std::logic_error("A schema version must be specified when the schema is specified"); + if (config.schema_mode == SchemaMode::ReadOnly && config.sync_config) + throw std::logic_error("Synchronized Realms cannot be opened in read-only mode"); + if (config.schema_mode == SchemaMode::Additive && config.migration_function) + throw std::logic_error("Realms opened in Additive-only schema mode do not use a migration function"); + if (config.schema_mode == SchemaMode::ReadOnly && config.migration_function) + throw std::logic_error("Realms opened in read-only mode do not use a migration function"); + // ResetFile also won't use the migration function, but specifying one is + // allowed to simplify temporarily switching modes during development + try { if (config.read_only()) { read_only_group = std::make_unique(config.path, config.encryption_key.data(), Group::mode_ReadOnly); } else { - // FIXME: The SharedGroup constructor, when called below, will - // throw a C++ exception if server_synchronization_mode is - // inconsistent with the accessed Realm file. This exception - // probably has to be transmuted to an NSError. bool server_synchronization_mode = bool(config.sync_config); if (server_synchronization_mode) { +#if REALM_ENABLE_SYNC history = realm::sync::make_sync_history(config.path); +#else + REALM_TERMINATE("Realm was not built with sync enabled"); +#endif } else { -#if REALM_VER_MAJOR >= 2 history = realm::make_in_realm_history(config.path); -#else - history = realm::make_client_history(config.path, config.encryption_key.data()); -#endif } -#ifdef REALM_GROUP_SHARED_OPTIONS_HPP + SharedGroupOptions options; options.durability = config.in_memory ? SharedGroupOptions::Durability::MemOnly : SharedGroupOptions::Durability::Full; @@ -177,18 +216,8 @@ void Realm::open_with_config(const Config& config, realm->upgrade_final_version = to_version; } }; + options.temp_dir = get_temporary_directory(); shared_group = std::make_unique(*history, options); -#else - SharedGroup::DurabilityLevel durability = config.in_memory ? SharedGroup::durability_MemOnly : - SharedGroup::durability_Full; - shared_group = std::make_unique(*history, durability, config.encryption_key.data(), !config.disable_format_upgrade, - [&](int from_version, int to_version) { - if (realm) { - realm->upgrade_initial_version = from_version; - realm->upgrade_final_version = to_version; - } - }); -#endif } } catch (...) { @@ -212,6 +241,13 @@ Group& Realm::read_group() return *m_group; } +void Realm::Internal::begin_read(Realm& realm, VersionID version_id) +{ + REALM_ASSERT(!realm.m_group); + realm.m_group = &const_cast(realm.m_shared_group->begin_read(version_id)); + realm.add_schema_change_handler(); +} + SharedRealm Realm::get_shared_realm(Config config) { auto coordinator = RealmCoordinator::get_coordinator(config.path); @@ -242,12 +278,18 @@ bool Realm::read_schema_from_group_if_needed() return true; } -void Realm::reset_file_if_needed(Schema const& schema, uint64_t version, std::vector& required_changes) +bool Realm::reset_file_if_needed(Schema& schema, uint64_t version, std::vector& required_changes) { if (m_schema_version == ObjectStore::NotVersioned) - return; - if (m_schema_version == version && !ObjectStore::needs_migration(required_changes)) - return; + return false; + if (m_schema_version == version) { + if (required_changes.empty()) { + set_schema(std::move(schema), version); + return true; + } + if (!ObjectStore::needs_migration(required_changes)) + return false; + } // FIXME: this does not work if multiple processes try to open the file at // the same time, or even multiple threads if there is not any external @@ -262,6 +304,7 @@ void Realm::reset_file_if_needed(Schema const& schema, uint64_t version, std::ve m_schema = ObjectStore::schema_from_group(read_group()); m_schema_version = ObjectStore::get_schema_version(read_group()); required_changes = m_schema.compare(schema); + return false; } void Realm::update_schema(Schema schema, uint64_t version, MigrationFunction migration_function) @@ -293,8 +336,7 @@ void Realm::update_schema(Schema schema, uint64_t version, MigrationFunction mig return true; case SchemaMode::ResetFile: - reset_file_if_needed(schema, version, required_changes); - return required_changes.empty(); + return reset_file_if_needed(schema, version, required_changes); case SchemaMode::Additive: if (required_changes.empty()) { @@ -416,10 +458,23 @@ void Realm::begin_transaction() throw InvalidTransactionException("The Realm is already in a write transaction"); } + // If we're already in the middle of sending notifications, just begin the + // write transaction without sending more notifications. If this actually + // advances the read version this could leave the user in an inconsistent + // state, but that's unavoidable. + if (m_is_sending_notifications) { + _impl::NotifierPackage notifiers; + transaction::begin(*m_shared_group, m_binding_context.get(), m_config.schema_mode, notifiers); + return; + } + // make sure we have a read transaction read_group(); - transaction::begin(*m_shared_group, m_binding_context.get(), m_config.schema_mode); + m_is_sending_notifications = true; + auto cleanup = util::make_scope_exit([this]() noexcept { m_is_sending_notifications = false; }); + + m_coordinator->promote_to_write(*this); } void Realm::commit_transaction() @@ -431,8 +486,7 @@ void Realm::commit_transaction() throw InvalidTransactionException("Can't commit a non-existing write transaction"); } - transaction::commit(*m_shared_group, m_binding_context.get()); - m_coordinator->send_commit_notifications(*this); + m_coordinator->commit_write(*this); } void Realm::cancel_transaction() @@ -500,12 +554,15 @@ void Realm::write_copy(StringData path, BinaryData key) void Realm::notify() { - if (is_closed()) { + if (is_closed() || is_in_transaction()) { return; } verify_thread(); + m_is_sending_notifications = true; + auto cleanup = util::make_scope_exit([this]() noexcept { m_is_sending_notifications = false; }); + if (m_shared_group->has_changed()) { // Throws if (m_binding_context) { m_binding_context->changes_available(); @@ -514,8 +571,11 @@ void Realm::notify() if (m_group) { m_coordinator->advance_to_ready(*this); } - else if (m_binding_context) { - m_binding_context->did_change({}, {}); + else { + if (m_binding_context) { + m_binding_context->did_change({}, {}); + } + m_coordinator->process_available_async(*this); } } } @@ -533,21 +593,22 @@ bool Realm::refresh() if (is_in_transaction()) { return false; } - - // advance transaction if database has changed - if (!m_shared_group->has_changed()) { // Throws + // don't advance if we're already in the process of advancing as that just + // makes things needlessly complicated + if (m_is_sending_notifications) { return false; } + m_is_sending_notifications = true; + auto cleanup = util::make_scope_exit([this]() noexcept { m_is_sending_notifications = false; }); + if (m_group) { - transaction::advance(*m_shared_group, m_binding_context.get(), m_config.schema_mode); - m_coordinator->process_available_async(*this); - } - else { - // Create the read transaction - read_group(); + return m_coordinator->advance_to_latest(*this); } + // No current read transaction, so just create a new one + read_group(); + m_coordinator->process_available_async(*this); return true; } @@ -598,16 +659,15 @@ util::Optional Realm::file_format_upgraded_from_version() const Realm::HandoverPackage::HandoverPackage(HandoverPackage&&) = default; Realm::HandoverPackage& Realm::HandoverPackage::operator=(HandoverPackage&&) = default; -Realm::HandoverPackage::VersionID::VersionID() : VersionID(SharedGroup::VersionID()) { } // Precondition: `m_version` is not greater than `new_version` // Postcondition: `m_version` is equal to `new_version` void Realm::HandoverPackage::advance_to_version(VersionID new_version) { - if (SharedGroup::VersionID(new_version) == SharedGroup::VersionID(m_version_id)) { + if (new_version == m_version_id) { return; } - REALM_ASSERT_DEBUG((SharedGroup::VersionID(new_version) > SharedGroup::VersionID(m_version_id))); + REALM_ASSERT_DEBUG(new_version > m_version_id); // Open `Realm` at handover version _impl::RealmCoordinator& coordinator = get_coordinator(); @@ -681,7 +741,7 @@ std::vector Realm::accept_handover(Realm::HandoverPackage han else { auto current_version = m_shared_group->get_version_of_current_transaction(); - if (SharedGroup::VersionID(handover.m_version_id) <= current_version) { + if (handover.m_version_id <= current_version) { // The handover is behind, so advance it to our version handover.advance_to_version(current_version); } else { diff --git a/Pods/Realm/Realm/ObjectStore/src/sync/impl/sync_file.cpp b/Pods/Realm/Realm/ObjectStore/src/sync/impl/sync_file.cpp new file mode 100644 index 0000000..4bc0c73 --- /dev/null +++ b/Pods/Realm/Realm/ObjectStore/src/sync/impl/sync_file.cpp @@ -0,0 +1,296 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// 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 "sync/impl/sync_file.hpp" + +#include +#include + +using File = realm::util::File; + +namespace realm { + +namespace { + +uint8_t value_of_hex_digit(char hex_digit) +{ + if (hex_digit >= '0' && hex_digit <= '9') { + return hex_digit - '0'; + } else if (hex_digit >= 'A' && hex_digit <= 'F') { + return 10 + hex_digit - 'A'; + } else if (hex_digit >= 'a' && hex_digit <= 'f') { + return 10 + hex_digit - 'a'; + } else { + throw std::invalid_argument("Cannot get the value of a character that isn't a hex digit."); + } +} + +bool filename_is_reserved(const std::string& filename) { + return (filename == "." || filename == ".."); +} + +bool character_is_unreserved(char character) +{ + bool is_capital_letter = (character >= 'A' && character <= 'Z'); + bool is_lowercase_letter = (character >= 'a' && character <= 'z'); + bool is_number = (character >= '0' && character <= '9'); + bool is_allowed_symbol = (character == '-' || character == '_' || character == '.'); + return is_capital_letter || is_lowercase_letter || is_number || is_allowed_symbol; +} + +char decoded_char_for(const std::string& percent_encoding, size_t index) +{ + if (index+2 >= percent_encoding.length()) { + throw std::invalid_argument("Malformed string: not enough characters after '%' before end of string."); + } + REALM_ASSERT(percent_encoding[index] == '%'); + return (16*value_of_hex_digit(percent_encoding[index + 1])) + value_of_hex_digit(percent_encoding[index + 2]); +} + +} // (anonymous namespace) + +namespace util { + +void remove_nonempty_dir(const std::string& path) +{ + // Open the directory and list all the files. + DIR *dir_listing = opendir(path.c_str()); + if (!dir_listing) { + return; + } + auto cleanup = util::make_scope_exit([=]() noexcept { closedir(dir_listing); }); + while (struct dirent *file = readdir(dir_listing)) { + auto file_type = file->d_type; + std::string file_name = file->d_name; + if (file_name == "." || file_name == "..") { + continue; + } + if (file_type == DT_REG || file_type == DT_FIFO) { + File::try_remove(file_path_by_appending_component(path, file_name)); + } else if (file_type == DT_DIR) { + // Directory, recurse + remove_nonempty_dir(file_path_by_appending_component(path, file_name, FilePathType::Directory)); + } + } + // Delete the directory itself + try { + util::remove_dir(path); + } + catch (File::NotFound const&) { + } +} + +std::string make_percent_encoded_string(const std::string& raw_string) +{ + std::string buffer; + buffer.reserve(raw_string.size()); + for (size_t i=0; i 0); + if (filename_is_reserved(user_identity)) { + throw std::invalid_argument("A user can't have an identifier reserved by the filesystem."); + } + auto user_path = file_path_by_appending_component(get_base_sync_directory(), + user_identity, + util::FilePathType::Directory); + util::try_make_dir(user_path); + return user_path; +} + +void SyncFileManager::remove_user_directory(const std::string& user_identity) const +{ + REALM_ASSERT(user_identity.length() > 0); + if (filename_is_reserved(user_identity)) { + throw std::invalid_argument("A user can't have an identifier reserved by the filesystem."); + } + auto user_path = file_path_by_appending_component(get_base_sync_directory(), + user_identity, + util::FilePathType::Directory); + util::remove_nonempty_dir(user_path); +} + +bool SyncFileManager::remove_realm(const std::string& user_identity, const std::string& raw_realm_path) const +{ + REALM_ASSERT(user_identity.length() > 0); + REALM_ASSERT(raw_realm_path.length() > 0); + if (filename_is_reserved(user_identity) || filename_is_reserved(raw_realm_path)) { + throw std::invalid_argument("A user or Realm can't have an identifier reserved by the filesystem."); + } + auto escaped = util::make_percent_encoded_string(raw_realm_path); + auto realm_path = util::file_path_by_appending_component(user_directory(user_identity), escaped); + bool success = true; + // Remove the base Realm file (e.g. "example.realm"). + success = File::try_remove(realm_path); + // Remove the lock file (e.g. "example.realm.lock"). + auto lock_path = util::file_path_by_appending_extension(realm_path, "lock"); + success = File::try_remove(lock_path); + // Remove the management directory (e.g. "example.realm.management"). + auto management_path = util::file_path_by_appending_extension(realm_path, "management"); + try { + util::remove_nonempty_dir(management_path); + } + catch (File::NotFound const&) { + } + catch (File::AccessError const&) { + success = false; + } + return success; +} + +std::string SyncFileManager::path(const std::string& user_identity, const std::string& raw_realm_path) const +{ + REALM_ASSERT(user_identity.length() > 0); + REALM_ASSERT(raw_realm_path.length() > 0); + if (filename_is_reserved(user_identity) || filename_is_reserved(raw_realm_path)) { + throw std::invalid_argument("A user or Realm can't have an identifier reserved by the filesystem."); + } + auto escaped = util::make_percent_encoded_string(raw_realm_path); + auto realm_path = util::file_path_by_appending_component(user_directory(user_identity), escaped); + return realm_path; +} + +std::string SyncFileManager::metadata_path() const +{ + auto dir_path = file_path_by_appending_component(get_utility_directory(), + c_metadata_directory, + util::FilePathType::Directory); + util::try_make_dir(dir_path); + return util::file_path_by_appending_component(dir_path, c_metadata_realm); +} + +bool SyncFileManager::remove_metadata_realm() const +{ + auto dir_path = file_path_by_appending_component(get_utility_directory(), + c_metadata_directory, + util::FilePathType::Directory); + try { + util::remove_nonempty_dir(dir_path); + return true; + } + catch (File::AccessError const&) { + return false; + } +} + +} // realm diff --git a/Pods/Realm/Realm/ObjectStore/src/sync_metadata.cpp b/Pods/Realm/Realm/ObjectStore/src/sync/impl/sync_metadata.cpp similarity index 91% rename from Pods/Realm/Realm/ObjectStore/src/sync_metadata.cpp rename to Pods/Realm/Realm/ObjectStore/src/sync/impl/sync_metadata.cpp index 7ba3c03..56c9104 100644 --- a/Pods/Realm/Realm/ObjectStore/src/sync_metadata.cpp +++ b/Pods/Realm/Realm/ObjectStore/src/sync/impl/sync_metadata.cpp @@ -16,7 +16,7 @@ // //////////////////////////////////////////////////////////////////////////// -#include "sync_metadata.hpp" +#include "sync/impl/sync_metadata.hpp" #include "object_schema.hpp" #include "object_store.hpp" @@ -44,30 +44,28 @@ SyncMetadataManager::SyncMetadataManager(std::string path, { std::lock_guard lock(m_metadata_lock); - auto nullable_string_property = [](std::string name)->Property { - Property p = { name, PropertyType::String }; + auto nullable_string_property = [](const char *name) -> Property { + Property p = {name, PropertyType::String}; p.is_nullable = true; return p; }; - Property primary_key = { c_sync_identity, PropertyType::String }; + Property primary_key = {c_sync_identity, PropertyType::String}; primary_key.is_indexed = true; primary_key.is_primary = true; Realm::Config config; config.path = std::move(path); - Schema schema = { - { c_sync_userMetadata, - { - primary_key, - { c_sync_marked_for_removal, PropertyType::Bool }, - nullable_string_property(c_sync_auth_server_url), - nullable_string_property(c_sync_user_token), - } - } + config.schema = Schema{ + {c_sync_userMetadata, { + primary_key, + {c_sync_marked_for_removal, PropertyType::Bool}, + nullable_string_property(c_sync_auth_server_url), + nullable_string_property(c_sync_user_token), + }} }; - config.schema = std::move(schema); config.schema_mode = SchemaMode::Additive; + config.schema_version = 0; #if REALM_PLATFORM_APPLE if (should_encrypt && !encryption_key) { encryption_key = keychain::metadata_realm_encryption_key(); @@ -131,7 +129,7 @@ SyncUserMetadata::SyncUserMetadata(Schema schema, SharedRealm realm, RowExpr row , m_row(row) { } -SyncUserMetadata::SyncUserMetadata(SyncMetadataManager& manager, std::string identity, bool make_if_absent) +SyncUserMetadata::SyncUserMetadata(const SyncMetadataManager& manager, std::string identity, bool make_if_absent) : m_schema(manager.m_schema) { // Open the Realm. diff --git a/Pods/Realm/Realm/ObjectStore/src/sync/sync_manager.cpp b/Pods/Realm/Realm/ObjectStore/src/sync/sync_manager.cpp new file mode 100644 index 0000000..7c265e3 --- /dev/null +++ b/Pods/Realm/Realm/ObjectStore/src/sync/sync_manager.cpp @@ -0,0 +1,400 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// 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 "sync/sync_manager.hpp" + +#include "sync/impl/sync_client.hpp" +#include "sync/impl/sync_file.hpp" +#include "sync/impl/sync_metadata.hpp" +#include "sync/sync_session.hpp" +#include "sync/sync_user.hpp" + +#include + +using namespace realm; +using namespace realm::_impl; + +SyncManager& SyncManager::shared() +{ + // The singleton is heap-allocated in order to fix an issue when running unit tests where tests would crash after + // they were done running because the manager was destroyed too early. + static SyncManager& manager = *new SyncManager; + return manager; +} + +void SyncManager::configure_file_system(const std::string& base_file_path, + MetadataMode metadata_mode, + util::Optional> custom_encryption_key, + bool reset_metadata_on_error) +{ + struct UserCreationData { + std::string identity; + std::string user_token; + util::Optional server_url; + }; + + std::vector users_to_add; + { + std::lock_guard lock(m_file_system_mutex); + + // Set up the file manager. + if (m_file_manager) { + REALM_ASSERT(m_file_manager->base_path() == base_file_path); + } else { + m_file_manager = std::make_unique(base_file_path); + } + + // Set up the metadata manager, and perform initial loading/purging work. + if (m_metadata_manager) { + return; + } + switch (metadata_mode) { + case MetadataMode::NoEncryption: + m_metadata_manager = std::make_unique(m_file_manager->metadata_path(), + false); + break; + case MetadataMode::Encryption: + try { + m_metadata_manager = std::make_unique(m_file_manager->metadata_path(), + true, + std::move(custom_encryption_key)); + } catch (RealmFileException const& ex) { + if (reset_metadata_on_error && m_file_manager->remove_metadata_realm()) { + m_metadata_manager = std::make_unique(m_file_manager->metadata_path(), + true, + std::move(custom_encryption_key)); + } else { + throw; + } + } + break; + case MetadataMode::NoMetadata: + return; + } + + REALM_ASSERT(m_metadata_manager); + // Load persisted users into the users map. + SyncUserMetadataResults users = m_metadata_manager->all_unmarked_users(); + for (size_t i = 0; i < users.size(); i++) { + // Note that 'admin' style users are not persisted. + auto user_data = users.get(i); + auto user_token = user_data.user_token(); + auto identity = user_data.identity(); + auto server_url = user_data.server_url(); + if (user_token) { + UserCreationData data = { std::move(identity), std::move(*user_token), std::move(server_url) }; + users_to_add.emplace_back(std::move(data)); + } + } + // Delete any users marked for death. + std::vector dead_users; + SyncUserMetadataResults users_to_remove = m_metadata_manager->all_users_marked_for_removal(); + dead_users.reserve(users_to_remove.size()); + for (size_t i = 0; i < users_to_remove.size(); i++) { + auto user = users_to_remove.get(i); + // FIXME: delete user data in a different way? (This deletes a logged-out user's data as soon as the app + // launches again, which might not be how some apps want to treat their data.) + try { + m_file_manager->remove_user_directory(user.identity()); + dead_users.emplace_back(std::move(user)); + } catch (util::File::AccessError const&) { + continue; + } + } + for (auto& user : dead_users) { + user.remove(); + } + } + { + std::lock_guard lock(m_user_mutex); + for (auto& user_data : users_to_add) { + m_users.insert({ user_data.identity, std::make_shared(user_data.user_token, + user_data.identity, + user_data.server_url) }); + } + } +} + +void SyncManager::reset_for_testing() +{ + std::lock_guard lock(m_file_system_mutex); + m_file_manager = nullptr; + m_metadata_manager = nullptr; + { + // Destroy all the users. + std::lock_guard lock(m_user_mutex); + m_users.clear(); + } + { + // Assert there are no active sessions remaining. + REALM_ASSERT(std::all_of(m_active_sessions.begin(), m_active_sessions.end(), [](auto& element){ return element.second.expired(); })); + // Destroy the client. + std::lock_guard lock(m_mutex); + m_sync_client = nullptr; + m_inactive_sessions.clear(); + // Reset even more state. + // NOTE: these should always match the defaults. + m_log_level = util::Logger::Level::info; + m_logger_factory = nullptr; + m_client_reconnect_mode = sync::Client::Reconnect::normal; + m_client_validate_ssl = true; + } +} + +void SyncManager::set_log_level(util::Logger::Level level) noexcept +{ + std::lock_guard lock(m_mutex); + m_log_level = level; +} + +void SyncManager::set_logger_factory(SyncLoggerFactory& factory) noexcept +{ + std::lock_guard lock(m_mutex); + m_logger_factory = &factory; +} + +void SyncManager::set_error_handler(std::function handler) +{ + std::lock_guard lock(m_mutex); + auto wrapped_handler = [=](int error_code, std::string message) { + // FIXME: If the sync team decides to route all errors through the session-level error handler, the client-level + // error handler might go away altogether. + switch (error_code) { + case 100: // Connection closed (no error) + case 101: // Unspecified non-critical error + return; + default: + handler(error_code, message); + } + }; + m_error_handler = std::move(wrapped_handler); +} + +void SyncManager::set_client_should_reconnect_immediately(bool reconnect_immediately) +{ + std::lock_guard lock(m_mutex); + using Reconnect = sync::Client::Reconnect; + m_client_reconnect_mode = reconnect_immediately ? Reconnect::immediately : Reconnect::normal; +} + +bool SyncManager::client_should_reconnect_immediately() const noexcept +{ + std::lock_guard lock(m_mutex); + using Reconnect = sync::Client::Reconnect; + return m_client_reconnect_mode == Reconnect::immediately; +} + +void SyncManager::set_client_should_validate_ssl(bool validate_ssl) +{ + std::lock_guard lock(m_mutex); + m_client_validate_ssl = validate_ssl; +} + +bool SyncManager::client_should_validate_ssl() const noexcept +{ + std::lock_guard lock(m_mutex); + return m_client_validate_ssl; +} + +util::Logger::Level SyncManager::log_level() const noexcept +{ + std::lock_guard lock(m_mutex); + return m_log_level; +} + +bool SyncManager::perform_metadata_update(std::function update_function) const +{ + std::lock_guard lock(m_file_system_mutex); + if (!m_metadata_manager) { + return false; + } + update_function(*m_metadata_manager); + return true; +} + +std::shared_ptr SyncManager::get_user(const std::string& identity, + std::string refresh_token, + util::Optional auth_server_url, + bool is_admin) +{ + std::lock_guard lock(m_user_mutex); + auto it = m_users.find(identity); + if (it == m_users.end()) { + // No existing user. + auto new_user = std::make_shared(std::move(refresh_token), identity, auth_server_url, is_admin); + m_users.insert({ identity, new_user }); + return new_user; + } else { + auto user = it->second; + if (auth_server_url && *auth_server_url != user->server_url()) { + throw std::invalid_argument("Cannot retrieve an existing user specifying a different auth server."); + } + if (is_admin != user->is_admin()) { + throw std::invalid_argument("Cannot retrieve an existing user with a different admin status."); + } + if (user->state() == SyncUser::State::Error) { + return nullptr; + } + user->update_refresh_token(std::move(refresh_token)); + return user; + } +} + +std::shared_ptr SyncManager::get_existing_logged_in_user(const std::string& identity) const +{ + std::lock_guard lock(m_user_mutex); + auto it = m_users.find(identity); + if (it == m_users.end()) { + return nullptr; + } + auto ptr = it->second; + return (ptr->state() == SyncUser::State::Active ? ptr : nullptr); +} + +std::vector> SyncManager::all_logged_in_users() const +{ + std::lock_guard lock(m_user_mutex); + std::vector> users; + users.reserve(m_users.size()); + for (auto& it : m_users) { + auto user = it.second; + if (user->state() == SyncUser::State::Active) { + users.emplace_back(std::move(user)); + } + } + return users; +} + +std::string SyncManager::path_for_realm(const std::string& user_identity, const std::string& raw_realm_url) const +{ + std::lock_guard lock(m_file_system_mutex); + REALM_ASSERT(m_file_manager); + return m_file_manager->path(user_identity, raw_realm_url); +} + +std::shared_ptr SyncManager::get_existing_active_session(const std::string& path) const +{ + std::lock_guard lock(m_session_mutex); + return get_existing_active_session_locked(path); +} + +std::shared_ptr SyncManager::get_existing_active_session_locked(const std::string& path) const +{ + REALM_ASSERT(!m_session_mutex.try_lock()); + auto it = m_active_sessions.find(path); + if (it == m_active_sessions.end()) { + return nullptr; + } + if (auto session = it->second.lock()) { + return session; + } + return nullptr; +} + +std::unique_ptr SyncManager::get_existing_inactive_session_locked(const std::string& path) +{ + REALM_ASSERT(!m_session_mutex.try_lock()); + auto it = m_inactive_sessions.find(path); + if (it == m_inactive_sessions.end()) { + return nullptr; + } + auto ret = std::move(it->second); + m_inactive_sessions.erase(it); + return ret; +} + +std::shared_ptr SyncManager::get_session(const std::string& path, const SyncConfig& sync_config) +{ + auto client = get_sync_client(); // Throws + + // The session is declared outside the scope of the lock so that if an exception is thrown + // it'll be destroyed after the lock has been dropped. This avoids deadlocking when + // dropped_last_reference_to_session attempts to lock the mutex. + std::shared_ptr shared_session; + + std::lock_guard lock(m_session_mutex); + if (auto session = get_existing_active_session_locked(path)) { + return session; + } + + std::unique_ptr session = get_existing_inactive_session_locked(path); + bool session_is_new = false; + if (!session) { + session_is_new = true; + session.reset(new SyncSession(std::move(client), path, sync_config)); + } + + auto session_deleter = [this](SyncSession *session) { dropped_last_reference_to_session(session); }; + shared_session = std::shared_ptr(session.release(), std::move(session_deleter)); + m_active_sessions[path] = shared_session; + if (session_is_new) { + sync_config.user->register_session(shared_session); + } else { + SyncSession::revive_if_needed(shared_session); + } + return shared_session; +} + +void SyncManager::dropped_last_reference_to_session(SyncSession* session) +{ + { + std::lock_guard lock(m_session_mutex); + auto path = session->path(); + REALM_ASSERT_DEBUG(m_active_sessions.count(path)); + m_active_sessions.erase(path); + m_inactive_sessions[path].reset(session); + } + session->close(); +} + +void SyncManager::unregister_session(const std::string& path) +{ + std::lock_guard lock(m_session_mutex); + if (m_active_sessions.count(path)) + return; + auto it = m_inactive_sessions.find(path); + REALM_ASSERT(it != m_inactive_sessions.end()); + m_inactive_sessions.erase(path); +} + +std::shared_ptr SyncManager::get_sync_client() const +{ + std::lock_guard lock(m_mutex); + if (!m_sync_client) + m_sync_client = create_sync_client(); // Throws + return m_sync_client; +} + +std::shared_ptr SyncManager::create_sync_client() const +{ + REALM_ASSERT(!m_mutex.try_lock()); + + std::unique_ptr logger; + if (m_logger_factory) { + logger = m_logger_factory->make_logger(m_log_level); // Throws + } + else { + auto stderr_logger = std::make_unique(); // Throws + stderr_logger->set_level_threshold(m_log_level); + logger = std::move(stderr_logger); + } + return std::make_shared(std::move(logger), + std::move(m_error_handler), + m_client_reconnect_mode, + m_client_validate_ssl); +} diff --git a/Pods/Realm/Realm/ObjectStore/src/sync_session.cpp b/Pods/Realm/Realm/ObjectStore/src/sync/sync_session.cpp similarity index 64% rename from Pods/Realm/Realm/ObjectStore/src/sync_session.cpp rename to Pods/Realm/Realm/ObjectStore/src/sync/sync_session.cpp index a666bc5..9fa747f 100644 --- a/Pods/Realm/Realm/ObjectStore/src/sync_session.cpp +++ b/Pods/Realm/Realm/ObjectStore/src/sync/sync_session.cpp @@ -16,10 +16,11 @@ // //////////////////////////////////////////////////////////////////////////// -#include "sync_session.hpp" +#include "sync/sync_session.hpp" -#include "impl/sync_client.hpp" -#include "sync_manager.hpp" +#include "sync/impl/sync_client.hpp" +#include "sync/sync_manager.hpp" +#include "sync/sync_user.hpp" #include @@ -35,7 +36,7 @@ using namespace realm::_impl::sync_session_states; /// WAITING_FOR_ACCESS_TOKEN: upon entering this state, the binding is informed /// that the session wants an access token. The session is now waiting for the /// binding to provide the token. -/// From: initial, INACTIVE +/// From: INACTIVE /// To: /// * ACTIVE: when the binding successfully refreshes the token /// * INACTIVE: if asked to log out, or if asked to close and the stop policy @@ -65,7 +66,7 @@ using namespace realm::_impl::sync_session_states; /// /// INACTIVE: the user owning this session has logged out, the `sync::Session` /// owned by this session is destroyed, and the session is quiescent. -/// From: WAITING_FOR_ACCESS_TOKEN, ACTIVE, DYING +/// From: initial, WAITING_FOR_ACCESS_TOKEN, ACTIVE, DYING /// To: /// * WAITING_FOR_ACCESS_TOKEN: if the session is revived /// * ERROR: if a fatal error occurs @@ -85,7 +86,11 @@ struct SyncSession::State { SyncSession&, const std::string&, const util::Optional&) const { } - virtual void access_token_expired(std::unique_lock&, SyncSession&) const { } + virtual void bind_with_admin_token(std::unique_lock&, + SyncSession&, const std::string&, const std::string&) const { } + + /// Returns true iff the lock is still locked when the method returns. + virtual bool access_token_expired(std::unique_lock&, SyncSession&) const { return true; } virtual void nonsync_transact_notify(std::unique_lock&, SyncSession&, sync::Session::version_type) const { } @@ -164,9 +169,13 @@ struct sync_session_states::Active : public SyncSession::State { session.m_session->refresh(std::move(access_token)); } - void access_token_expired(std::unique_lock& lock, SyncSession& session) const override + bool access_token_expired(std::unique_lock& lock, SyncSession& session) const override { session.advance_state(lock, waiting_for_access_token); + std::shared_ptr session_ptr = session.shared_from_this(); + lock.unlock(); + session.m_config.bind_session_handler(session_ptr->m_realm_path, session_ptr->m_config, std::move(session_ptr)); + return false; } void log_out(std::unique_lock& lock, SyncSession& session) const override @@ -201,24 +210,21 @@ struct sync_session_states::Active : public SyncSession::State { struct sync_session_states::Dying : public SyncSession::State { void enter_state(std::unique_lock&, SyncSession& session) const override { - ++session.m_pending_upload_threads; - std::thread([session=&session] { - std::unique_lock lock(session->m_state_mutex); - if (session->m_pending_upload_threads != 1) { - --session->m_pending_upload_threads; + size_t current_death_count = ++session.m_death_count; + session.m_session->async_wait_for_upload_completion([session=&session, current_death_count](std::error_code error_code) { + if (error_code == util::error::operation_aborted) { + // Session was killed beneath us. Don't do anything. return; } - - if (session->m_state != &State::dying) { - // The session was revived. Don't kill it. - --session->m_pending_upload_threads; - return; + // FIXME: It's possible for the session to be destroyed while the callback is running, + // which is something we should address in the future. It is only possible when + // SyncManager::reset_for_testing() is called. + // c.f. https://github.com/realm/realm-object-store/issues/269 + std::unique_lock lock(session->m_state_mutex); + if (session->m_state == &State::dying && session->m_death_count == current_death_count) { + session->advance_state(lock, inactive); } - - session->m_session->wait_for_upload_complete_or_client_stopped(); - --session->m_pending_upload_threads; - session->advance_state(lock, inactive); - }).detach(); + }); } bool revive_if_needed(std::unique_lock& lock, SyncSession& session) const override @@ -242,6 +248,15 @@ struct sync_session_states::Inactive : public SyncSession::State { session.unregister(lock); } + void bind_with_admin_token(std::unique_lock& lock, SyncSession& session, + const std::string& admin_token, + const std::string& server_url) const override + { + session.create_sync_session(); + session.advance_state(lock, waiting_for_access_token); + session.m_state->refresh_access_token(lock, session, admin_token, server_url); + } + bool revive_if_needed(std::unique_lock& lock, SyncSession& session) const override { // Revive. @@ -255,6 +270,7 @@ struct sync_session_states::Error : public SyncSession::State { void enter_state(std::unique_lock&, SyncSession& session) const override { session.m_session = nullptr; + session.m_config = { nullptr, "", SyncSessionStopPolicy::Immediately, nullptr }; } // Everything else is a no-op when in the error state. @@ -272,10 +288,7 @@ SyncSession::SyncSession(std::shared_ptr client, std::string realm_p : m_state(&State::inactive) , m_config(std::move(config)) , m_realm_path(std::move(realm_path)) -, m_client(std::move(client)) -{ - revive_if_needed(); -} +, m_client(std::move(client)) { } void SyncSession::create_sync_session() { @@ -283,74 +296,92 @@ void SyncSession::create_sync_session() m_session = std::make_unique(m_client->client, m_realm_path); // Set up the wrapped handler - auto wrapped_handler = [this](int error_code, std::string message) { - using Error = realm::sync::Error; + std::weak_ptr weak_self = shared_from_this(); + auto wrapped_handler = [this, weak_self](int error_code, std::string message) { + auto self = weak_self.lock(); + if (!self) { + // An error was delivered after the session it relates to was destroyed. There's nothing useful + // we can do with it. + return; + } + + using ProtocolError = realm::sync::ProtocolError; - SyncSessionError error_type; + SyncSessionError error_type = SyncSessionError::Debug; // Precondition: error_code is a valid realm::sync::Error raw value. - Error strong_code = static_cast(error_code); + ProtocolError strong_code = static_cast(error_code); switch (strong_code) { // Client errors; all ignored (for now) - case Error::connection_closed: - case Error::other_error: - case Error::unknown_message: - case Error::bad_syntax: - case Error::limits_exceeded: - case Error::wrong_protocol_version: - case Error::bad_session_ident: - case Error::reuse_of_session_ident: - case Error::bound_in_other_session: - case Error::bad_message_order: + case ProtocolError::invalid_error: + case ProtocolError::connection_closed: + case ProtocolError::other_error: + case ProtocolError::unknown_message: + case ProtocolError::bad_syntax: + case ProtocolError::limits_exceeded: + case ProtocolError::wrong_protocol_version: + case ProtocolError::bad_session_ident: + case ProtocolError::reuse_of_session_ident: + case ProtocolError::bound_in_other_session: + case ProtocolError::bad_message_order: return; // Session errors - case Error::session_closed: - case Error::other_session_error: + case ProtocolError::disabled_session: + case ProtocolError::session_closed: + case ProtocolError::other_session_error: // The binding doesn't need to be aware of these because they are strictly informational, and do not // represent actual errors. return; - case Error::token_expired: { + case ProtocolError::token_expired: { std::unique_lock lock(m_state_mutex); // This isn't an error from the binding's point of view. If we're connected we'll // simply ask the binding to log in again. m_state->access_token_expired(lock, *this); return; } - case Error::bad_authentication: { - std::unique_lock lock(m_state_mutex); - error_type = SyncSessionError::UserFatal; - advance_state(lock, State::error); + case ProtocolError::bad_authentication: { + std::shared_ptr user_to_invalidate; + { + std::unique_lock lock(m_state_mutex); + error_type = SyncSessionError::UserFatal; + user_to_invalidate = user(); + advance_state(lock, State::error); + } + if (user_to_invalidate) + user_to_invalidate->invalidate(); break; } - case Error::illegal_realm_path: - case Error::no_such_realm: - case Error::bad_server_file_ident: - case Error::diverging_histories: - case Error::bad_changeset: { + case ProtocolError::illegal_realm_path: + case ProtocolError::no_such_realm: + case ProtocolError::bad_server_file_ident: + case ProtocolError::diverging_histories: + case ProtocolError::bad_changeset: { std::unique_lock lock(m_state_mutex); error_type = SyncSessionError::SessionFatal; advance_state(lock, State::error); break; } - case Error::permission_denied: + case ProtocolError::permission_denied: error_type = SyncSessionError::AccessDenied; break; - case Error::bad_client_file_ident: - case Error::bad_server_version: - case Error::bad_client_version: + case ProtocolError::bad_client_file_ident: + case ProtocolError::bad_server_version: + case ProtocolError::bad_client_version: error_type = SyncSessionError::Debug; break; } if (m_error_handler) { - m_error_handler(error_code, message, error_type); + m_error_handler(std::move(self), error_code, message, error_type); } }; m_session->set_error_handler(std::move(wrapped_handler)); // Set up the wrapped sync transact callback - auto wrapped_callback = [this](VersionID old_version, VersionID new_version) { - if (m_sync_transact_callback) { - m_sync_transact_callback(old_version, new_version); + auto wrapped_callback = [this, weak_self](VersionID old_version, VersionID new_version) { + if (auto self = weak_self.lock()) { + if (m_sync_transact_callback) { + m_sync_transact_callback(old_version, new_version); + } } }; m_session->set_sync_transact_callback(std::move(wrapped_callback)); @@ -380,15 +411,19 @@ void SyncSession::nonsync_transact_notify(sync::Session::version_type version) m_state->nonsync_transact_notify(lock, *this, version); } -void SyncSession::revive_if_needed() +void SyncSession::revive_if_needed(std::shared_ptr session) { - bool need_login; + REALM_ASSERT(session); + util::Optional&> handler; { - std::unique_lock lock(m_state_mutex); - need_login = m_state->revive_if_needed(lock, *this); + std::unique_lock lock(session->m_state_mutex); + if (session->m_state->revive_if_needed(lock, *session)) { + handler = session->m_config.bind_session_handler; + } + } + if (handler) { + handler.value()(session->m_realm_path, session->m_config, session); } - if (need_login) - SyncManager::shared().get_sync_login_function()(m_realm_path, m_config); } void SyncSession::log_out() @@ -418,57 +453,77 @@ void SyncSession::unregister(std::unique_lock& lock) SyncManager::shared().unregister_session(m_realm_path); } -void SyncSession::wait_for_upload_completion(std::function callback) +bool SyncSession::can_wait_for_network_completion() const { - REALM_ASSERT(shared_from_this()); - auto thread = std::thread([this, callback=std::move(callback), self=shared_from_this()]() { - { - std::unique_lock lock(m_state_mutex); - if (m_session) { - m_session->wait_for_upload_complete_or_client_stopped(); - } - } + return m_state == &State::active || m_state == &State::dying; +} - callback(); - }); - thread.detach(); +bool SyncSession::wait_for_upload_completion(std::function callback) +{ + std::unique_lock lock(m_state_mutex); + // FIXME: instead of dropping the callback if we haven't yet `bind()`ed, + // save it and register it when the session `bind()`s. + if (can_wait_for_network_completion()) { + REALM_ASSERT(m_session); + m_session->async_wait_for_upload_completion(std::move(callback)); + return true; + } + return false; } -void SyncSession::wait_for_download_completion(std::function callback) +bool SyncSession::wait_for_download_completion(std::function callback) { - REALM_ASSERT(shared_from_this()); - auto thread = std::thread([this, callback=std::move(callback), self=shared_from_this()]() { - { - std::unique_lock lock(m_state_mutex); - if (m_session) { - m_session->wait_for_download_complete_or_client_stopped(); - } - } + std::unique_lock lock(m_state_mutex); + // FIXME: instead of dropping the callback if we haven't yet `bind()`ed, + // save it and register it when the session `bind()`s. + if (can_wait_for_network_completion()) { + REALM_ASSERT(m_session); + m_session->async_wait_for_download_completion(std::move(callback)); + return true; + } + return false; +} - callback(); - }); - thread.detach(); +bool SyncSession::wait_for_upload_completion_blocking() +{ + std::unique_lock lock(m_state_mutex); + if (can_wait_for_network_completion()) { + REALM_ASSERT(m_session); + m_session->wait_for_upload_complete_or_client_stopped(); + return true; + } + return false; } void SyncSession::refresh_access_token(std::string access_token, util::Optional server_url) { + std::unique_lock lock(m_state_mutex); if (!m_server_url && !server_url) { // The first time this method is called, the server URL must be provided. return; } - - std::unique_lock lock(m_state_mutex); m_state->refresh_access_token(lock, *this, access_token, server_url); } -bool SyncSession::is_valid() const +void SyncSession::bind_with_admin_token(std::string admin_token, std::string server_url) { std::unique_lock lock(m_state_mutex); - return m_state != &State::error; + m_state->bind_with_admin_token(lock, *this, admin_token, server_url); } -bool SyncSession::is_inactive() const +SyncSession::PublicState SyncSession::state() const { std::unique_lock lock(m_state_mutex); - return m_state == &State::inactive && m_pending_upload_threads == 0; + if (m_state == &State::waiting_for_access_token) { + return PublicState::WaitingForAccessToken; + } else if (m_state == &State::active) { + return PublicState::Active; + } else if (m_state == &State::dying) { + return PublicState::Dying; + } else if (m_state == &State::inactive) { + return PublicState::Inactive; + } else if (m_state == &State::error) { + return PublicState::Error; + } + REALM_UNREACHABLE(); } diff --git a/Pods/Realm/Realm/ObjectStore/src/sync/sync_user.cpp b/Pods/Realm/Realm/ObjectStore/src/sync/sync_user.cpp new file mode 100644 index 0000000..d2e3a26 --- /dev/null +++ b/Pods/Realm/Realm/ObjectStore/src/sync/sync_user.cpp @@ -0,0 +1,202 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// 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 "sync/sync_user.hpp" + +#include "sync/impl/sync_metadata.hpp" +#include "sync/sync_manager.hpp" +#include "sync/sync_session.hpp" + +namespace realm { + +SyncUser::SyncUser(std::string refresh_token, + std::string identity, + util::Optional server_url, + bool is_admin) +: m_state(State::Active) +, m_server_url(server_url.value_or("")) +, m_is_admin(is_admin) +, m_refresh_token(std::move(refresh_token)) +, m_identity(std::move(identity)) +{ + if (!is_admin) { + SyncManager::shared().perform_metadata_update([this, server_url=std::move(server_url)](const auto& manager) { + auto metadata = SyncUserMetadata(manager, m_identity); + metadata.set_state(server_url, m_refresh_token); + }); + } +} + +std::vector> SyncUser::all_sessions() +{ + std::lock_guard lock(m_mutex); + std::vector> sessions; + if (m_state == State::Error) { + return sessions; + } + for (auto it = m_sessions.begin(); it != m_sessions.end();) { + if (auto ptr_to_session = it->second.lock()) { + if (!ptr_to_session->is_in_error_state()) { + sessions.emplace_back(std::move(ptr_to_session)); + it++; + continue; + } + } + // This session is bad, destroy it. + it = m_sessions.erase(it); + } + return sessions; +} + +std::shared_ptr SyncUser::session_for_url(const std::string& url) +{ + std::lock_guard lock(m_mutex); + if (m_state == State::Error) { + return nullptr; + } + auto it = m_sessions.find(url); + if (it == m_sessions.end()) { + return nullptr; + } + auto locked = it->second.lock(); + if (!locked) { + // Remove the session from the map, because it has fatally errored out or the entry is invalid. + m_sessions.erase(it); + } + return locked; +} + +void SyncUser::update_refresh_token(std::string token) +{ + std::vector> sessions_to_revive; + { + std::unique_lock lock(m_mutex); + switch (m_state) { + case State::Error: + return; + case State::Active: + m_refresh_token = token; + break; + case State::LoggedOut: { + sessions_to_revive.reserve(m_waiting_sessions.size()); + m_refresh_token = token; + m_state = State::Active; + for (auto& pair : m_waiting_sessions) { + if (auto ptr = pair.second.lock()) { + m_sessions[pair.first] = ptr; + sessions_to_revive.emplace_back(std::move(ptr)); + } + } + m_waiting_sessions.clear(); + break; + } + } + // Update persistent user metadata. + if (!m_is_admin) { + SyncManager::shared().perform_metadata_update([=](const auto& manager) { + auto metadata = SyncUserMetadata(manager, m_identity); + metadata.set_state(m_server_url, token); + }); + } + } + // (Re)activate all pending sessions. + // Note that we do this after releasing the lock, since the session may + // need to access protected User state in the process of binding itself. + for (auto& session : sessions_to_revive) { + SyncSession::revive_if_needed(session); + } +} + +void SyncUser::log_out() +{ + if (m_is_admin) { + // Admin users cannot be logged out. + return; + } + std::lock_guard lock(m_mutex); + if (m_state == State::LoggedOut) { + return; + } + m_state = State::LoggedOut; + // Move all active sessions into the waiting sessions pool. If the user is + // logged back in, they will automatically be reactivated. + for (auto& pair : m_sessions) { + if (auto ptr = pair.second.lock()) { + ptr->log_out(); + m_waiting_sessions[pair.first] = ptr; + } + } + m_sessions.clear(); + // Mark the user as 'dead' in the persisted metadata Realm. + if (!m_is_admin) { + SyncManager::shared().perform_metadata_update([=](const auto& manager) { + auto metadata = SyncUserMetadata(manager, m_identity, false); + metadata.mark_for_removal(); + }); + } +} + +void SyncUser::invalidate() +{ + std::lock_guard lock(m_mutex); + m_state = State::Error; +} + +std::string SyncUser::refresh_token() const +{ + std::lock_guard lock(m_mutex); + return m_refresh_token; +} + +SyncUser::State SyncUser::state() const +{ + std::lock_guard lock(m_mutex); + return m_state; +} + +void SyncUser::register_session(std::shared_ptr session) +{ + const std::string& url = session->config().realm_url; + std::unique_lock lock(m_mutex); + auto has_session = [&] (const auto& sessions) { + auto it = sessions.find(url); + return it != sessions.end() && !it->second.expired(); + }; + if (has_session(m_sessions) || has_session(m_waiting_sessions)) { + throw std::invalid_argument("Can only register sessions that haven't previously been registered."); + } + switch (m_state) { + case State::Active: + // Immediately ask the session to come online. + m_sessions[url] = session; + if (m_is_admin) { + session->bind_with_admin_token(m_refresh_token, session->config().realm_url); + } else { + lock.unlock(); + SyncSession::revive_if_needed(std::move(session)); + } + break; + case State::LoggedOut: + m_waiting_sessions[url] = session; + break; + case State::Error: + break; + } +} + +} diff --git a/Pods/Realm/Realm/ObjectStore/src/sync_manager.cpp b/Pods/Realm/Realm/ObjectStore/src/sync_manager.cpp deleted file mode 100644 index b9bdc0b..0000000 --- a/Pods/Realm/Realm/ObjectStore/src/sync_manager.cpp +++ /dev/null @@ -1,190 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 Realm Inc. -// -// 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 "sync_manager.hpp" - -#include "impl/sync_client.hpp" -#include "sync_session.hpp" - -#include - -using namespace realm; -using namespace realm::_impl; - -SyncManager& SyncManager::shared() -{ - static SyncManager& manager = *new SyncManager; - return manager; -} - -void SyncManager::set_log_level(util::Logger::Level level) noexcept -{ - std::lock_guard lock(m_mutex); - m_log_level = level; -} - -void SyncManager::set_logger_factory(SyncLoggerFactory& factory) noexcept -{ - std::lock_guard lock(m_mutex); - m_logger_factory = &factory; -} - -void SyncManager::set_error_handler(std::function handler) -{ - std::lock_guard lock(m_mutex); - auto wrapped_handler = [=](int error_code, std::string message) { - // FIXME: If the sync team decides to route all errors through the session-level error handler, the client-level - // error handler might go away altogether. - switch (error_code) { - case 100: // Connection closed (no error) - case 101: // Unspecified non-critical error - return; - default: - handler(error_code, message); - } - }; - m_error_handler = std::move(wrapped_handler); -} - -void SyncManager::set_login_function(SyncLoginFunction login_function) -{ - std::lock_guard lock(m_mutex); - m_login_function = std::move(login_function); -} - -SyncLoginFunction& SyncManager::get_sync_login_function() -{ - std::lock_guard lock(m_mutex); - // Precondition: binding must set a login callback before connecting any synced Realms. - REALM_ASSERT(m_login_function); - return m_login_function; -} - -void SyncManager::set_client_should_reconnect_immediately(bool reconnect_immediately) -{ - std::lock_guard lock(m_mutex); - using Reconnect = sync::Client::Reconnect; - m_client_reconnect_mode = reconnect_immediately ? Reconnect::immediately : Reconnect::normal; -} - -void SyncManager::set_client_should_validate_ssl(bool validate_ssl) -{ - std::lock_guard lock(m_mutex); - m_client_validate_ssl = validate_ssl; -} - -std::shared_ptr SyncManager::get_existing_active_session(const std::string& path) const -{ - std::lock_guard lock(m_session_mutex); - return get_existing_active_session_locked(path); -} - -std::shared_ptr SyncManager::get_existing_active_session_locked(const std::string& path) const -{ - REALM_ASSERT(!m_session_mutex.try_lock()); - auto it = m_active_sessions.find(path); - if (it == m_active_sessions.end()) { - return nullptr; - } - if (auto session = it->second.lock()) { - return session; - } - return nullptr; -} - -std::unique_ptr SyncManager::get_existing_inactive_session_locked(const std::string& path) -{ - REALM_ASSERT(!m_session_mutex.try_lock()); - auto it = m_inactive_sessions.find(path); - if (it == m_inactive_sessions.end()) { - return nullptr; - } - auto ret = std::move(it->second); - m_inactive_sessions.erase(it); - return ret; -} - -std::shared_ptr SyncManager::get_session(const std::string& path, const SyncConfig& sync_config) -{ - auto client = get_sync_client(); // Throws - - std::lock_guard lock(m_session_mutex); - if (auto session = get_existing_active_session_locked(path)) { - return session; - } - - std::unique_ptr session = get_existing_inactive_session_locked(path); - if (!session) - session.reset(new SyncSession(std::move(client), path, sync_config)); - session->revive_if_needed(); - - auto session_deleter = [this](SyncSession *session) { dropped_last_reference_to_session(session); }; - auto shared_session = std::shared_ptr(session.release(), std::move(session_deleter)); - m_active_sessions[path] = shared_session; - return shared_session; -} - -void SyncManager::dropped_last_reference_to_session(SyncSession* session) -{ - { - std::lock_guard lock(m_session_mutex); - auto path = session->path(); - REALM_ASSERT_DEBUG(m_active_sessions.count(path)); - m_active_sessions.erase(path); - m_inactive_sessions[path].reset(session); - } - session->close(); -} - -void SyncManager::unregister_session(const std::string& path) -{ - std::lock_guard lock(m_session_mutex); - if (m_active_sessions.count(path)) - return; - auto it = m_inactive_sessions.find(path); - REALM_ASSERT(it != m_inactive_sessions.end()); - if (it->second->is_inactive()) - m_inactive_sessions.erase(path); -} - -std::shared_ptr SyncManager::get_sync_client() const -{ - std::lock_guard lock(m_mutex); - if (!m_sync_client) - m_sync_client = create_sync_client(); // Throws - return m_sync_client; -} - -std::shared_ptr SyncManager::create_sync_client() const -{ - REALM_ASSERT(!m_mutex.try_lock()); - - std::unique_ptr logger; - if (m_logger_factory) { - logger = m_logger_factory->make_logger(m_log_level); // Throws - } - else { - auto stderr_logger = std::make_unique(); // Throws - stderr_logger->set_level_threshold(m_log_level); - logger = std::move(stderr_logger); - } - return std::make_shared(std::move(logger), - std::move(m_error_handler), - m_client_reconnect_mode, - m_client_validate_ssl); -} diff --git a/Pods/Realm/Realm/RLMArray.mm b/Pods/Realm/Realm/RLMArray.mm index 2cfccf9..051267f 100644 --- a/Pods/Realm/Realm/RLMArray.mm +++ b/Pods/Realm/Realm/RLMArray.mm @@ -378,7 +378,7 @@ - (RLMResults *)sortedResultsUsingProperty:(NSString *)property ascending:(BOOL) return [self sortedResultsUsingDescriptors:@[[RLMSortDescriptor sortDescriptorWithProperty:property ascending:ascending]]]; } -- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties +- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties { @throw RLMException(@"This method may only be called on RLMArray instances retrieved from an RLMRealm"); } diff --git a/Pods/Realm/Realm/RLMArrayLinkView.mm b/Pods/Realm/Realm/RLMArrayLinkView.mm index af62781..c045627 100644 --- a/Pods/Realm/Realm/RLMArrayLinkView.mm +++ b/Pods/Realm/Realm/RLMArrayLinkView.mm @@ -360,7 +360,7 @@ - (void)deleteObjectsFromRealm { }); } -- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties { +- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties { if (properties.count == 0) { auto results = translateErrors([&] { return _backingList.filter({}); }); return [RLMResults resultsWithObjectInfo:*_objectInfo results:std::move(results)]; diff --git a/Pods/Realm/Realm/RLMClassInfo.mm b/Pods/Realm/Realm/RLMClassInfo.mm index 09ad9d5..b0ff82b 100644 --- a/Pods/Realm/Realm/RLMClassInfo.mm +++ b/Pods/Realm/Realm/RLMClassInfo.mm @@ -19,7 +19,7 @@ #import "RLMClassInfo.hpp" #import "RLMRealm_Private.hpp" -#import "RLMObjectSchema.h" +#import "RLMObjectSchema_Private.h" #import "RLMSchema.h" #import "RLMProperty_Private.h" #import "RLMQueryUtil.hpp" @@ -102,6 +102,6 @@ m_objects.emplace(std::piecewise_construct, std::forward_as_tuple(rlmObjectSchema.className), std::forward_as_tuple(realm, rlmObjectSchema, - &*schema.find(rlmObjectSchema.className.UTF8String))); + &*schema.find(rlmObjectSchema.objectName.UTF8String))); } } diff --git a/Pods/Realm/Realm/RLMCollection.mm b/Pods/Realm/Realm/RLMCollection.mm index 8b1bfe1..b039d99 100644 --- a/Pods/Realm/Realm/RLMCollection.mm +++ b/Pods/Realm/Realm/RLMCollection.mm @@ -219,15 +219,25 @@ void RLMCollectionSetValueForKey(id collection, NSString *key @implementation RLMCancellationToken { realm::NotificationToken _token; + __unsafe_unretained RLMRealm *_realm; } -- (instancetype)initWithToken:(realm::NotificationToken)token { +- (instancetype)initWithToken:(realm::NotificationToken)token realm:(RLMRealm *)realm { self = [super init]; if (self) { _token = std::move(token); + _realm = realm; } return self; } +- (RLMRealm *)realm { + return _realm; +} + +- (void)suppressNextNotification { + _token.suppress_next(); +} + - (void)stop { _token = {}; } @@ -336,7 +346,8 @@ static bool call(realm::Results const&) { } }; - return [[RLMCancellationToken alloc] initWithToken:collection.add_notification_callback(cb)]; + return [[RLMCancellationToken alloc] initWithToken:collection.add_notification_callback(cb) + realm:(RLMRealm *)[objcCollection realm]]; } // Explicitly instantiate the templated function for the two types we'll use it on diff --git a/Pods/Realm/Realm/RLMNetworkClient.m b/Pods/Realm/Realm/RLMNetworkClient.m index f6cd317..2adcdf2 100644 --- a/Pods/Realm/Realm/RLMNetworkClient.m +++ b/Pods/Realm/Realm/RLMNetworkClient.m @@ -54,15 +54,15 @@ + (NSURL *)urlForServer:(NSURL *)serverURL endpoint:(RLMServerEndpoint)endpoint pathComponent = @"logout"; NSAssert(NO, @"logout endpoint isn't implemented yet, don't use it"); break; - case RLMServerEndpointAddCredential: + case RLMServerEndpointAddCredentials: // TODO: fix this - pathComponent = @"addCredential"; - NSAssert(NO, @"add credential endpoint isn't implemented yet, don't use it"); + pathComponent = @"addCredentials"; + NSAssert(NO, @"add credentials endpoint isn't implemented yet, don't use it"); break; - case RLMServerEndpointRemoveCredential: + case RLMServerEndpointRemoveCredentials: // TODO: fix this - pathComponent = @"removeCredential"; - NSAssert(NO, @"remove credential endpoint isn't implemented yet, don't use it"); + pathComponent = @"removeCredentials"; + NSAssert(NO, @"remove credentials endpoint isn't implemented yet, don't use it"); break; } NSAssert(pathComponent != nil, @"Unrecognized value for RLMServerEndpoint enum"); diff --git a/Pods/Realm/Realm/RLMObjectBase.mm b/Pods/Realm/Realm/RLMObjectBase.mm index 80e5205..c3e23c8 100644 --- a/Pods/Realm/Realm/RLMObjectBase.mm +++ b/Pods/Realm/Realm/RLMObjectBase.mm @@ -293,6 +293,10 @@ + (BOOL)shouldIncludeInDefaultSchema { return RLMIsObjectSubclass(self); } ++ (NSString *)_realmObjectName { + return nil; +} + - (id)mutableArrayValueForKey:(NSString *)key { id obj = [self valueForKey:key]; if ([obj isKindOfClass:[RLMArray class]]) { diff --git a/Pods/Realm/Realm/RLMObjectSchema.mm b/Pods/Realm/Realm/RLMObjectSchema.mm index 8762dae..fb19575 100644 --- a/Pods/Realm/Realm/RLMObjectSchema.mm +++ b/Pods/Realm/Realm/RLMObjectSchema.mm @@ -53,12 +53,12 @@ - (instancetype)initWithClassName:(NSString *)objectClassName objectClass:(Class } // return properties by name --(RLMProperty *)objectForKeyedSubscript:(__unsafe_unretained NSString *const)key { +- (RLMProperty *)objectForKeyedSubscript:(__unsafe_unretained NSString *const)key { return _allPropertiesByName[key]; } // create property map when setting property array --(void)setProperties:(NSArray *)properties { +- (void)setProperties:(NSArray *)properties { _properties = properties; [self _propertiesDidChange]; } @@ -357,9 +357,13 @@ - (NSString *)description { return [NSString stringWithFormat:@"%@ {\n%@}", self.className, propertiesString]; } +- (NSString *)objectName { + return [self.objectClass _realmObjectName] ?: _className; +} + - (realm::ObjectSchema)objectStoreCopy { ObjectSchema objectSchema; - objectSchema.name = _className.UTF8String; + objectSchema.name = self.objectName.UTF8String; objectSchema.primary_key = _primaryKeyProperty ? _primaryKeyProperty.name.UTF8String : ""; for (RLMProperty *prop in _properties) { Property p = [prop objectStoreCopy]; diff --git a/Pods/Realm/Realm/RLMObjectStore.mm b/Pods/Realm/Realm/RLMObjectStore.mm index 4654100..144748c 100644 --- a/Pods/Realm/Realm/RLMObjectStore.mm +++ b/Pods/Realm/Realm/RLMObjectStore.mm @@ -301,6 +301,10 @@ void RLMAddObjectToRealm(__unsafe_unretained RLMObjectBase *const object, // populate all properties for (RLMProperty *prop in info.rlmObjectSchema.properties) { + // skip primary key when updating since it doesn't change + if (prop.isPrimary) + continue; + // get object from ivar using key value coding id value = nil; if (prop.swiftIvar) { @@ -331,10 +335,6 @@ void RLMAddObjectToRealm(__unsafe_unretained RLMObjectBase *const object, } } - // skip primary key when updating since it doesn't change - if (prop.isPrimary) - continue; - // set in table with out validation RLMDynamicSet(object, prop, RLMCoerceToNil(value), creationOptions); } diff --git a/Pods/Realm/Realm/RLMQueryUtil.mm b/Pods/Realm/Realm/RLMQueryUtil.mm index cf861e8..c1af2a3 100644 --- a/Pods/Realm/Realm/RLMQueryUtil.mm +++ b/Pods/Realm/Realm/RLMQueryUtil.mm @@ -19,7 +19,7 @@ #import "RLMQueryUtil.hpp" #import "RLMArray.h" -#import "RLMObjectSchema.h" +#import "RLMObjectSchema_Private.h" #import "RLMObject_Private.hpp" #import "RLMPredicateUtil.hpp" #import "RLMProperty.h" @@ -151,7 +151,7 @@ void set_base_table(const Table*) override {} Table& get_table(Group& group, RLMObjectSchema *objectSchema) { - return *ObjectStore::table_for_object_type(group, objectSchema.className.UTF8String); + return *ObjectStore::table_for_object_type(group, objectSchema.objectName.UTF8String); } // A reference to a column within a query. Can be resolved to a Columns for use in query expressions. diff --git a/Pods/Realm/Realm/RLMRealm.mm b/Pods/Realm/Realm/RLMRealm.mm index d5a7a76..4f440fe 100644 --- a/Pods/Realm/Realm/RLMRealm.mm +++ b/Pods/Realm/Realm/RLMRealm.mm @@ -32,7 +32,7 @@ #import "RLMQueryUtil.hpp" #import "RLMRealmUtil.hpp" #import "RLMSchema_Private.hpp" -#import "RLMSyncManager_Private.hpp" +#import "RLMSyncManager_Private.h" #import "RLMUpdateChecker.hpp" #import "RLMUtil.hpp" @@ -42,13 +42,19 @@ #include "shared_realm.hpp" #include +#include #include using namespace realm; using util::File; +@interface RLMRealmNotificationToken : RLMNotificationToken +@property (nonatomic, strong) RLMRealm *realm; +@property (nonatomic, copy) RLMNotificationBlock block; +@end + @interface RLMRealm () -@property (nonatomic, strong) NSHashTable *notificationHandlers; +@property (nonatomic, strong) NSHashTable *notificationHandlers; - (void)sendNotifications:(RLMNotification)notification; @end @@ -56,12 +62,6 @@ void RLMDisableSyncToDisk() { realm::disable_sync_to_disk(); } -// Notification Token -@interface RLMRealmNotificationToken : RLMNotificationToken -@property (nonatomic, strong) RLMRealm *realm; -@property (nonatomic, copy) RLMNotificationBlock block; -@end - @implementation RLMRealmNotificationToken - (void)stop { [_realm verifyThread]; @@ -70,6 +70,21 @@ - (void)stop { _block = nil; } +- (void)suppressNextNotification { + // Temporarily replace the block with one which restores the old block + // rather than producing a notification. + + // This briefly creates a retain cycle but it's fine because the block will + // be synchronously called shortly after this method is called. Unlike with + // collection notifications, this does not have to go through the object + // store or do fancy things to handle transaction coalescing because it's + // called synchronously by the obj-c code and not by the object store. + auto notificationBlock = _block; + _block = ^(RLMNotification, RLMRealm *) { + _block = notificationBlock; + }; +} + - (void)dealloc { if (_realm || _block) { NSLog(@"RLMNotificationToken released without unregistering a notification. You must hold " @@ -102,7 +117,8 @@ static bool shouldForciblyDisableEncryption() { } @implementation RLMRealm { - NSHashTable *_collectionEnumerators; + NSHashTable *_collectionEnumerators; + bool _sendingNotifications; } + (BOOL)isCoreDebug { @@ -144,10 +160,6 @@ - (void)setAutorefresh:(BOOL)autorefresh { _realm->set_auto_refresh(autorefresh); } -+ (NSString *)writeableTemporaryPathForFile:(NSString *)fileName { - return [NSTemporaryDirectory() stringByAppendingPathComponent:fileName]; -} - + (instancetype)defaultRealm { return [RLMRealm realmWithConfiguration:[RLMRealmConfiguration rawDefaultConfiguration] error:nil]; } @@ -204,6 +216,16 @@ REALM_NOINLINE void RLMRealmTranslateException(NSError **error) { case RealmFileException::Kind::Exists: RLMSetErrorOrThrow(RLMMakeError(RLMErrorFileExists, ex), error); break; + case RealmFileException::Kind::BadHistoryError: { + NSString *err = @"Realm file's history format is incompatible with the " + "settings in the configuration object being used to open " + "the Realm. Note that Realms configured for sync cannot be " + "opened as non-synced Realms, and vice versa. Otherwise, the " + "file may be corrupt."; + RLMSetErrorOrThrow(RLMMakeError(RLMErrorFileAccess, + File::AccessError(err.UTF8String, ex.path())), error); + break; + } case RealmFileException::Kind::AccessError: RLMSetErrorOrThrow(RLMMakeError(RLMErrorFileAccess, ex), error); break; @@ -336,7 +358,6 @@ + (instancetype)realmWithConfiguration:(RLMRealmConfiguration *)configuration er } + (void)resetRealmState { - [RLMSyncManager _resetStateForTesting]; RLMClearRealmCache(); realm::_impl::RealmCoordinator::clear_cache(); [RLMRealmConfiguration resetRealmConfigurationState]; @@ -373,12 +394,20 @@ - (RLMNotificationToken *)addNotificationBlock:(RLMNotificationBlock)block { - (void)sendNotifications:(RLMNotification)notification { NSAssert(!_realm->config().read_only(), @"Read-only realms do not have notifications"); - + if (_sendingNotifications) { + return; + } NSUInteger count = _notificationHandlers.count; if (count == 0) { return; } - // call this realms notification blocks + + _sendingNotifications = true; + auto cleanup = realm::util::make_scope_exit([&]() noexcept { + _sendingNotifications = false; + }); + + // call this realm's notification blocks if (count == 1) { if (auto block = [_notificationHandlers.anyObject block]) { block(notification, self); @@ -425,6 +454,24 @@ - (BOOL)commitWriteTransaction:(NSError **)outError { } } +- (BOOL)commitWriteTransactionWithoutNotifying:(NSArray *)tokens error:(NSError **)error { + for (RLMNotificationToken *token in tokens) { + if (token.realm != self) { + @throw RLMException(@"Incorrect Realm: only notifications for the Realm being modified can be skipped."); + } + [token suppressNextNotification]; + } + + try { + _realm->commit_transaction(); + return YES; + } + catch (...) { + RLMRealmTranslateException(error); + return NO; + } +} + - (void)transactionWithBlock:(void(^)(void))block { [self transactionWithBlock:block error:nil]; } @@ -474,17 +521,17 @@ - (void)invalidate { /** Replaces all string columns in this Realm with a string enumeration column and compacts the database file. - + Cannot be called from a write transaction. Compaction will not occur if other `RLMRealm` instances exist. - + While compaction is in progress, attempts by other threads or processes to open the database will wait. - + Be warned that resource requirements for compaction is proportional to the amount of live data in the database. - + Compaction works by writing the database contents to a temporary database file and then replacing the database with the temporary one. The name of the temporary file is formed by appending `.tmp_compaction_space` to the name of the database. diff --git a/Pods/Realm/Realm/RLMRealmConfiguration+Sync.mm b/Pods/Realm/Realm/RLMRealmConfiguration+Sync.mm index c5f5e34..528d732 100644 --- a/Pods/Realm/Realm/RLMRealmConfiguration+Sync.mm +++ b/Pods/Realm/Realm/RLMRealmConfiguration+Sync.mm @@ -21,13 +21,12 @@ #import "RLMRealmConfiguration_Private.hpp" #import "RLMSyncConfiguration_Private.hpp" #import "RLMSyncUser_Private.hpp" -#import "RLMSyncFileManager.h" -#import "RLMSyncManager_Private.hpp" +#import "RLMSyncManager_Private.h" #import "RLMSyncUtil_Private.hpp" #import "RLMUtil.hpp" -#import "sync_config.hpp" -#import "sync_manager.hpp" +#import "sync/sync_config.hpp" +#import "sync/sync_manager.hpp" @implementation RLMRealmConfiguration (Sync) @@ -43,11 +42,12 @@ - (void)setSyncConfiguration:(RLMSyncConfiguration *)syncConfiguration { // Ensure sync manager is initialized, if it hasn't already been. [RLMSyncManager sharedManager]; NSAssert(user.identity, @"Cannot call this method on a user that doesn't have an identity."); - NSURL *localFileURL = [RLMSyncFileManager fileURLForRawRealmURL:realmURL user:user]; if (syncConfiguration.customFileURL) { - localFileURL = syncConfiguration.customFileURL; + self.config.path = syncConfiguration.customFileURL.path.UTF8String; + } else { + self.config.path = SyncManager::shared().path_for_realm([user.identity UTF8String], + [realmURL.absoluteString UTF8String]); } - self.config.path = [[localFileURL path] UTF8String]; self.config.in_memory = false; self.config.sync_config = std::make_shared([syncConfiguration rawConfiguration]); self.config.schema_mode = realm::SchemaMode::Additive; @@ -58,16 +58,7 @@ - (RLMSyncConfiguration *)syncConfiguration { return nil; } realm::SyncConfig& sync_config = *self.config.sync_config; - // Try to get the user - RLMSyncUser *thisUser = [[RLMSyncManager sharedManager] _userForIdentity:@(sync_config.user_tag.c_str())]; - if (!thisUser) { - @throw RLMException(@"Could not find the user this configuration refers to."); - } - NSURL *realmURL = [NSURL URLWithString:@(sync_config.realm_url.c_str())]; - RLMSyncConfiguration *c = [[RLMSyncConfiguration alloc] initWithUser:thisUser - realmURL:realmURL]; - c.stopPolicy = realm::translateStopPolicy(sync_config.stop_policy); - return c; + return [[RLMSyncConfiguration alloc] initWithRawConfig:sync_config]; } @end diff --git a/Pods/Realm/Realm/RLMRealmUtil.mm b/Pods/Realm/Realm/RLMRealmUtil.mm index 72d1051..41c0b51 100644 --- a/Pods/Realm/Realm/RLMRealmUtil.mm +++ b/Pods/Realm/Realm/RLMRealmUtil.mm @@ -111,11 +111,13 @@ void will_change(std::vector const& observed, std::vector } } - void did_change(std::vector const& observed, std::vector const& invalidated) override { + void did_change(std::vector const& observed, std::vector const& invalidated, bool version_changed) override { try { @autoreleasepool { RLMDidChange(observed, invalidated); - [_realm sendNotifications:RLMRealmDidChangeNotification]; + if (version_changed) { + [_realm sendNotifications:RLMRealmDidChangeNotification]; + } } } catch (...) { diff --git a/Pods/Realm/Realm/RLMResults.mm b/Pods/Realm/Realm/RLMResults.mm index 3b4fc64..40420f7 100644 --- a/Pods/Realm/Realm/RLMResults.mm +++ b/Pods/Realm/Realm/RLMResults.mm @@ -138,10 +138,6 @@ - (NSString *)objectClassName { return RLMStringDataToNSString(_results.get_object_type()); } -- (RLMObjectSchema *)objectSchema { - return _info->rlmObjectSchema; -} - - (RLMClassInfo *)objectInfo { return _info; } @@ -149,6 +145,10 @@ - (RLMClassInfo *)objectInfo { - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unused __unsafe_unretained id [])buffer count:(NSUInteger)len { + if (!_info) { + return 0; + } + __autoreleasing RLMFastEnumerator *enumerator; if (state->state == 0) { enumerator = [[RLMFastEnumerator alloc] initWithCollection:self objectSchema:*_info]; @@ -279,25 +279,26 @@ - (void)setValue:(id)value forKey:(NSString *)key { RLMCollectionSetValueForKey(self, key, value); } -- (NSNumber *)_aggregateForKeyPath:(NSString *)keyPath method:(util::Optional (Results::*)(size_t))method methodName:(NSString *)methodName { +- (NSNumber *)_aggregateForKeyPath:(NSString *)keyPath method:(util::Optional (Results::*)(size_t))method + methodName:(NSString *)methodName returnNilForEmpty:(BOOL)returnNilForEmpty { assertKeyPathIsNotNested(keyPath); - return [self aggregate:keyPath method:method methodName:methodName]; + return [self aggregate:keyPath method:method methodName:methodName returnNilForEmpty:returnNilForEmpty]; } - (NSNumber *)_minForKeyPath:(NSString *)keyPath { - return [self _aggregateForKeyPath:keyPath method:&Results::min methodName:@"@min"]; + return [self _aggregateForKeyPath:keyPath method:&Results::min methodName:@"@min" returnNilForEmpty:YES]; } - (NSNumber *)_maxForKeyPath:(NSString *)keyPath { - return [self _aggregateForKeyPath:keyPath method:&Results::max methodName:@"@max"]; + return [self _aggregateForKeyPath:keyPath method:&Results::max methodName:@"@max" returnNilForEmpty:YES]; } - (NSNumber *)_sumForKeyPath:(NSString *)keyPath { - return [self _aggregateForKeyPath:keyPath method:&Results::sum methodName:@"@sum"]; + return [self _aggregateForKeyPath:keyPath method:&Results::sum methodName:@"@sum" returnNilForEmpty:NO]; } - (NSNumber *)_avgForKeyPath:(NSString *)keyPath { - return [self _aggregateForKeyPath:keyPath method:&Results::average methodName:@"@avg"]; + return [self _aggregateForKeyPath:keyPath method:&Results::average methodName:@"@avg" returnNilForEmpty:YES]; } - (NSArray *)_unionOfObjectsForKeyPath:(NSString *)keyPath { @@ -358,7 +359,7 @@ - (RLMResults *)sortedResultsUsingProperty:(NSString *)property ascending:(BOOL) return [self sortedResultsUsingDescriptors:@[[RLMSortDescriptor sortDescriptorWithProperty:property ascending:ascending]]]; } -- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties { +- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties { if (properties.count == 0) { return self; } @@ -375,7 +376,11 @@ - (id)objectAtIndexedSubscript:(NSUInteger)index { return [self objectAtIndex:index]; } -- (id)aggregate:(NSString *)property method:(util::Optional (Results::*)(size_t))method methodName:(NSString *)methodName { +- (id)aggregate:(NSString *)property method:(util::Optional (Results::*)(size_t))method + methodName:(NSString *)methodName returnNilForEmpty:(BOOL)returnNilForEmpty { + if (_results.get_mode() == Results::Mode::Empty) { + return returnNilForEmpty ? nil : @0; + } size_t column = _info->tableColumn(property); auto value = translateErrors([&] { return (_results.*method)(column); }, methodName); if (!value) { @@ -385,26 +390,26 @@ - (id)aggregate:(NSString *)property method:(util::Optional (Results::*)( } - (id)minOfProperty:(NSString *)property { - return [self aggregate:property method:&Results::min methodName:@"minOfProperty"]; + return [self aggregate:property method:&Results::min methodName:@"minOfProperty" returnNilForEmpty:YES]; } - (id)maxOfProperty:(NSString *)property { - return [self aggregate:property method:&Results::max methodName:@"maxOfProperty"]; + return [self aggregate:property method:&Results::max methodName:@"maxOfProperty" returnNilForEmpty:YES]; } - (id)sumOfProperty:(NSString *)property { - return [self aggregate:property method:&Results::sum methodName:@"sumOfProperty"]; + return [self aggregate:property method:&Results::sum methodName:@"sumOfProperty" returnNilForEmpty:NO]; } - (id)averageOfProperty:(NSString *)property { - return [self aggregate:property method:&Results::average methodName:@"averageOfProperty"]; + return [self aggregate:property method:&Results::average methodName:@"averageOfProperty" returnNilForEmpty:YES]; } - (void)deleteObjectsFromRealm { return translateErrors([&] { if (_results.get_mode() == Results::Mode::Table) { RLMResultsValidateInWriteTransaction(self); - RLMClearTable(*self.objectInfo); + RLMClearTable(*_info); } else { RLMTrackDeletions(_realm, ^{ _results.clear(); }); diff --git a/Pods/Realm/Realm/RLMSyncConfiguration.mm b/Pods/Realm/Realm/RLMSyncConfiguration.mm index d42b09c..3ea2409 100644 --- a/Pods/Realm/Realm/RLMSyncConfiguration.mm +++ b/Pods/Realm/Realm/RLMSyncConfiguration.mm @@ -18,13 +18,28 @@ #import "RLMSyncConfiguration_Private.hpp" -#import "RLMSyncManager_Private.hpp" -#import "RLMSyncUser.h" +#import "RLMSyncManager_Private.h" +#import "RLMSyncSession_Private.hpp" +#import "RLMSyncUser_Private.hpp" #import "RLMSyncUtil_Private.hpp" #import "RLMUtil.hpp" -#import "sync_manager.hpp" -#import "sync_config.hpp" +#import "sync/sync_manager.hpp" +#import "sync/sync_config.hpp" + +using namespace realm; + +namespace { +RLMSyncSessionErrorKind errorKindForSessionError(SyncSessionError error) { + switch (error) { + case SyncSessionError::AccessDenied: return RLMSyncSessionErrorKindAccessDenied; + case SyncSessionError::Debug: return RLMSyncSessionErrorKindDebug; + case SyncSessionError::SessionFatal: return RLMSyncSessionErrorKindSessionFatal; + case SyncSessionError::UserFatal: return RLMSyncSessionErrorKindUserFatal; + } + REALM_UNREACHABLE(); +} +} static BOOL isValidRealmURL(NSURL *url) { NSString *scheme = [url scheme]; @@ -35,42 +50,50 @@ static BOOL isValidRealmURL(NSURL *url) { } @interface RLMSyncConfiguration () { - std::function _error_handler; + std::unique_ptr _config; } - (instancetype)initWithUser:(RLMSyncUser *)user realmURL:(NSURL *)url customFileURL:(nullable NSURL *)customFileURL stopPolicy:(RLMSyncStopPolicy)stopPolicy - errorHandler:(std::function)errorHandler NS_DESIGNATED_INITIALIZER; - -@property (nonatomic, readwrite) RLMSyncUser *user; -@property (nonatomic, readwrite) NSURL *realmURL; - + errorHandler:(std::function)errorHandler; @end @implementation RLMSyncConfiguration - (instancetype)initWithRawConfig:(realm::SyncConfig)config { - RLMSyncUser *user = [[RLMSyncManager sharedManager] _userForIdentity:@(config.user_tag.c_str())]; - // Note that `user` is allowed to be nil. Any code which uses this private API must ensure that a sync configuration - // with a nil user is destroyed or gets a valid user before the configuration is exposed to application code. - NSURL *realmURL = [NSURL URLWithString:@(config.realm_url.c_str())]; - RLMSyncStopPolicy stopPolicy = realm::translateStopPolicy(config.stop_policy); - self = [self initWithUser:user - realmURL:realmURL - customFileURL:nil - stopPolicy:stopPolicy - errorHandler:config.error_handler]; + if (self = [super init]) { + _config = std::make_unique(config); + } return self; } +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[RLMSyncConfiguration class]]) { + return NO; + } + RLMSyncConfiguration *that = (RLMSyncConfiguration *)object; + return [self.realmURL isEqual:that.realmURL] + && [self.user isEqual:that.user] + && self.stopPolicy == that.stopPolicy; +} + - (realm::SyncConfig)rawConfiguration { - std::string user_tag = [self.user.identity UTF8String]; - std::string realm_url = [[self.realmURL absoluteString] UTF8String]; - auto stop_policy = realm::translateStopPolicy(self.stopPolicy); + return *_config; +} + +- (RLMSyncUser *)user { + return [[RLMSyncUser alloc] initWithSyncUser:_config->user]; +} + +- (RLMSyncStopPolicy)stopPolicy { + return translateStopPolicy(_config->stop_policy); +} - return realm::SyncConfig(std::move(user_tag), std::move(realm_url), _error_handler, std::move(stop_policy)); +- (NSURL *)realmURL { + NSString *rawStringURL = @(_config->realm_url.c_str()); + return [NSURL URLWithString:rawStringURL]; } - (instancetype)initWithUser:(RLMSyncUser *)user realmURL:(NSURL *)url { @@ -87,27 +110,39 @@ - (instancetype)initWithUser:(RLMSyncUser *)user stopPolicy:(RLMSyncStopPolicy)stopPolicy errorHandler:(std::function)errorHandler { if (self = [super init]) { - self.user = user; if (!isValidRealmURL(url)) { @throw RLMException(@"The provided URL (%@) was not a valid Realm URL.", [url absoluteString]); } - self.customFileURL = customFileURL; - self.stopPolicy = stopPolicy; - self.realmURL = url; - - if (errorHandler) { - _error_handler = std::move(errorHandler); - } else { - // Automatically configure the per-Realm error handler. - _error_handler = [=](int error_code, std::string message, realm::SyncSessionError error_type) { - RLMSyncSession *session = [user sessionForURL:url]; + auto bindHandler = [=](const std::string& path, + const SyncConfig& config, + const std::shared_ptr& session) { + [user _bindSessionWithPath:path + config:config + session:session + completion:[RLMSyncManager sharedManager].sessionCompletionNotifier + isStandalone:NO]; + }; + if (!errorHandler) { + errorHandler = [=](std::shared_ptr errored_session, + int error_code, + std::string message, + realm::SyncSessionError error_type) { + RLMSyncSession *session = [[RLMSyncSession alloc] initWithSyncSession:errored_session]; [[RLMSyncManager sharedManager] _fireErrorWithCode:error_code message:@(message.c_str()) session:session - errorClass:error_type]; + errorClass:errorKindForSessionError(error_type)]; }; } + _config = std::make_unique(SyncConfig{ + [user _syncUser], + [[url absoluteString] UTF8String], + translateStopPolicy(stopPolicy), + std::move(bindHandler), + std::move(errorHandler) + }); + self.customFileURL = customFileURL; return self; } return nil; diff --git a/Pods/Realm/Realm/RLMSyncCredential.m b/Pods/Realm/Realm/RLMSyncCredentials.m similarity index 69% rename from Pods/Realm/Realm/RLMSyncCredential.m rename to Pods/Realm/Realm/RLMSyncCredentials.m index 15e87c7..77587ab 100644 --- a/Pods/Realm/Realm/RLMSyncCredential.m +++ b/Pods/Realm/Realm/RLMSyncCredentials.m @@ -16,7 +16,7 @@ // //////////////////////////////////////////////////////////////////////////// -#import "RLMSyncCredential.h" +#import "RLMSyncCredentials.h" #import "RLMSyncUtil_Private.h" /// A Twitter account as an identity provider. @@ -30,48 +30,58 @@ RLMIdentityProvider const RLMIdentityProviderGoogle = @"google"; RLMIdentityProvider const RLMIdentityProviderICloud = @"icloud"; -@interface RLMSyncCredential () +@interface RLMSyncCredentials () -- (instancetype)initWithCustomToken:(RLMCredentialToken)token +- (instancetype)initWithCustomToken:(RLMSyncCredentialsToken)token provider:(RLMIdentityProvider)provider userInfo:(NSDictionary *)userInfo NS_DESIGNATED_INITIALIZER; -@property (nonatomic, readwrite) RLMCredentialToken token; +@property (nonatomic, readwrite) RLMSyncCredentialsToken token; @property (nonatomic, readwrite) RLMIdentityProvider provider; @property (nonatomic, readwrite) NSDictionary *userInfo; @end -@implementation RLMSyncCredential +@implementation RLMSyncCredentials -+ (instancetype)credentialWithFacebookToken:(RLMCredentialToken)token { ++ (instancetype)credentialsWithFacebookToken:(RLMSyncCredentialsToken)token { return [[self alloc] initWithCustomToken:token provider:RLMIdentityProviderFacebook userInfo:nil]; } -+ (instancetype)credentialWithGoogleToken:(RLMCredentialToken)token { ++ (instancetype)credentialsWithGoogleToken:(RLMSyncCredentialsToken)token { return [[self alloc] initWithCustomToken:token provider:RLMIdentityProviderGoogle userInfo:nil]; } -+ (instancetype)credentialWithICloudToken:(RLMCredentialToken)token { ++ (instancetype)credentialsWithICloudToken:(RLMSyncCredentialsToken)token { return [[self alloc] initWithCustomToken:token provider:RLMIdentityProviderICloud userInfo:nil]; } -+ (instancetype)credentialWithUsername:(NSString *)username - password:(NSString *)password - actions:(RLMAuthenticationActions)actions { ++ (instancetype)credentialsWithUsername:(NSString *)username + password:(NSString *)password + register:(BOOL)shouldRegister { return [[self alloc] initWithCustomToken:username provider:RLMIdentityProviderUsernamePassword userInfo:@{kRLMSyncPasswordKey: password, - kRLMSyncActionsKey: @(actions)}]; + kRLMSyncRegisterKey: @(shouldRegister)}]; } -+ (instancetype)credentialWithAccessToken:(RLMServerToken)accessToken identity:(NSString *)identity { ++ (instancetype)credentialsWithAccessToken:(RLMServerToken)accessToken identity:(NSString *)identity { return [[self alloc] initWithCustomToken:accessToken provider:RLMIdentityProviderAccessToken userInfo:@{kRLMSyncIdentityKey: identity}]; } -- (instancetype)initWithCustomToken:(RLMCredentialToken)token +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[RLMSyncCredentials class]]) { + return NO; + } + RLMSyncCredentials *that = (RLMSyncCredentials *)object; + return ([self.token isEqualToString:that.token] + && [self.provider isEqualToString:that.provider] + && [self.userInfo isEqual:that.userInfo]); +} + +- (instancetype)initWithCustomToken:(RLMSyncCredentialsToken)token provider:(RLMIdentityProvider)provider userInfo:(NSDictionary *)userInfo { if (self = [super init]) { diff --git a/Pods/Realm/Realm/RLMSyncFileManager.mm b/Pods/Realm/Realm/RLMSyncFileManager.mm deleted file mode 100644 index 02a6d92..0000000 --- a/Pods/Realm/Realm/RLMSyncFileManager.mm +++ /dev/null @@ -1,118 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 Realm Inc. -// -// 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 "RLMSyncFileManager.h" - -#import "RLMSyncUser.h" -#import "RLMUtil.hpp" - -static NSString *const RLMSyncUtilityFolderName = @"io.realm.object-server-metadata"; -static NSString *const RLMSyncMetadataRealmName = @"sync_metadata.realm"; - -@implementation RLMSyncFileManager - -/** - The directory within which all Realm Object Server related Realm database and support files are stored. This directory - is a subdirectory within the default directory within which normal on-disk Realms are stored. - - The directory will be created if it does not already exist, and then verified. If there was an error setting it up an - exception will be thrown. - */ -+ (NSURL *)_baseDirectory { - static NSURL *s_baseDirectory; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - // Create the path. - NSFileManager *manager = [NSFileManager defaultManager]; - NSURL *base = [NSURL fileURLWithPath:RLMDefaultDirectoryForBundleIdentifier(nil)]; - s_baseDirectory = [base URLByAppendingPathComponent:@"realm-object-server" isDirectory:YES]; - - // If the directory does not already exist, create it. - [manager createDirectoryAtURL:s_baseDirectory - withIntermediateDirectories:YES - attributes:nil - error:nil]; - BOOL isDirectory = YES; - BOOL fileExists = [manager fileExistsAtPath:[s_baseDirectory path] isDirectory:&isDirectory]; - if (!fileExists || !isDirectory) { - @throw RLMException(@"Could not prepare the directory for storing synchronized Realm files."); - } - }); - return s_baseDirectory; -} - -/** - Return the file URL for a directory contained within the sync base directory. If the diretory does not already exist, - it will automatically be created. - */ -+ (NSURL *)_folderPathForString:(nonnull NSString *)folderName { - NSFileManager *manager = [NSFileManager defaultManager]; - NSURL *userDir = [[self _baseDirectory] URLByAppendingPathComponent:folderName]; - [manager createDirectoryAtURL:userDir withIntermediateDirectories:YES attributes:nil error:nil]; - BOOL isDirectory = YES; - BOOL fileExists = [manager fileExistsAtPath:[userDir path] isDirectory:&isDirectory]; - if (!fileExists || !isDirectory) { - @throw RLMException(@"Could not make a directory; a non-directory file already exists."); - } - return userDir; -} - -/** - Return the file URL for the directory storing a given Realm Sync user's state. - */ -+ (NSURL *)_folderPathForUserIdentity:(nonnull NSString *)identity { - NSCharacterSet *alpha = [NSCharacterSet alphanumericCharacterSet]; - NSString *escapedName = [identity stringByAddingPercentEncodingWithAllowedCharacters:alpha]; - if ([escapedName isEqualToString:RLMSyncUtilityFolderName]) { - @throw RLMException(@"Invalid user identity: cannot be a reserved term."); - } - return [self _folderPathForString:escapedName]; -} - -/** - Return the file URL for the sync metadata Realm. - */ -+ (NSURL *)fileURLForMetadata { - NSURL *utilityFolder = [self _folderPathForString:RLMSyncUtilityFolderName]; - return [utilityFolder URLByAppendingPathComponent:RLMSyncMetadataRealmName]; -} - -/** - Return the file URL for a given combination of a Realm Object Server URL and Realm Sync user. - */ -+ (NSURL *)fileURLForRawRealmURL:(NSURL *)url user:(RLMSyncUser *)user { - NSAssert(user.identity, @"Cannot call this method on a user that doesn't yet have an identity..."); - - NSCharacterSet *alpha = [NSCharacterSet alphanumericCharacterSet]; - NSString *filename = [[url absoluteString] stringByAddingPercentEncodingWithAllowedCharacters:alpha]; - - // Create and validate the user directory. - NSURL *userDir = [self _folderPathForUserIdentity:user.identity]; - return [userDir URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.realm", filename]]; -} - -/** - Remove all Realm state for a user. - */ -+ (BOOL)removeFilesForUserIdentity:(NSString *)identity error:(NSError **)error { - NSURL *userDir = [self _folderPathForUserIdentity:identity]; - NSFileManager *manager = [NSFileManager defaultManager]; - return [manager removeItemAtURL:userDir error:error]; -} - -@end diff --git a/Pods/Realm/Realm/RLMSyncManager.mm b/Pods/Realm/Realm/RLMSyncManager.mm index c1cf091..a26a804 100644 --- a/Pods/Realm/Realm/RLMSyncManager.mm +++ b/Pods/Realm/Realm/RLMSyncManager.mm @@ -16,19 +16,17 @@ // //////////////////////////////////////////////////////////////////////////// -#import "RLMSyncManager_Private.hpp" +#import "RLMSyncManager_Private.h" #import "RLMRealmConfiguration+Sync.h" #import "RLMSyncConfiguration_Private.hpp" -#import "RLMSyncFileManager.h" -#import "RLMSyncSession_Private.h" +#import "RLMSyncSession_Private.hpp" #import "RLMSyncUser_Private.hpp" #import "RLMUtil.hpp" -#import "sync_config.hpp" -#import "sync_manager.hpp" -#import "sync_metadata.hpp" -#import "sync_session.hpp" +#import "sync/sync_config.hpp" +#import "sync/sync_manager.hpp" +#import "sync/sync_session.hpp" using namespace realm; using Level = realm::util::Logger::Level; @@ -50,6 +48,21 @@ Level levelForSyncLogLevel(RLMSyncLogLevel logLevel) { REALM_UNREACHABLE(); // Unrecognized log level. } +RLMSyncLogLevel logLevelForLevel(Level logLevel) { + switch (logLevel) { + case Level::off: return RLMSyncLogLevelOff; + case Level::fatal: return RLMSyncLogLevelFatal; + case Level::error: return RLMSyncLogLevelError; + case Level::warn: return RLMSyncLogLevelWarn; + case Level::info: return RLMSyncLogLevelInfo; + case Level::detail: return RLMSyncLogLevelDetail; + case Level::debug: return RLMSyncLogLevelDebug; + case Level::trace: return RLMSyncLogLevelTrace; + case Level::all: return RLMSyncLogLevelAll; + } + REALM_UNREACHABLE(); // Unrecognized log level. +} + struct CocoaSyncLogger : public realm::util::RootLogger { void do_log(Level, std::string message) override { NSLog(@"Sync: %@", RLMStringDataToNSString(message)); @@ -67,12 +80,7 @@ void do_log(Level, std::string message) override { } // anonymous namespace @interface RLMSyncManager () - -- (instancetype)initPrivate NS_DESIGNATED_INITIALIZER; - -@property (nonnull, nonatomic) NSMutableDictionary *activeUsers; -@property (nonnull, nonatomic) NSMutableDictionary *loggedOutUsers; - +- (instancetype)initWithCustomRootDirectory:(nullable NSURL *)rootDirectory NS_DESIGNATED_INITIALIZER; @end @implementation RLMSyncManager @@ -82,20 +90,12 @@ @implementation RLMSyncManager + (instancetype)sharedManager { dispatch_once(&s_onceToken, ^{ - s_sharedManager = [[RLMSyncManager alloc] initPrivate]; + s_sharedManager = [[RLMSyncManager alloc] initWithCustomRootDirectory:nil]; }); return s_sharedManager; } -- (RLMSyncSession *)sessionForSyncConfiguration:(RLMSyncConfiguration *)config { - NSURL *fileURL = [RLMSyncFileManager fileURLForRawRealmURL:config.realmURL user:config.user]; - return [config.user _registerSessionForBindingWithFileURL:fileURL - syncConfig:config - standaloneSession:YES - onCompletion:nil]; -} - -- (instancetype)initPrivate { +- (instancetype)initWithCustomRootDirectory:(NSURL *)rootDirectory { if (self = [super init]) { // Create the global error handler. auto errorLambda = [=](int error_code, std::string message) { @@ -106,40 +106,18 @@ - (instancetype)initPrivate { [self _fireError:error]; }; - // Create the static login callback. This is called whenever any Realm wishes to BIND to the Realm Object Server - // for the first time. - SyncLoginFunction loginLambda = [=](const std::string& path, const SyncConfig& config) { - NSString *localFilePath = @(path.c_str()); - RLMSyncConfiguration *syncConfig = [[RLMSyncConfiguration alloc] initWithRawConfig:config]; - [self _handleBindRequestForSyncConfig:syncConfig - localFilePath:localFilePath]; - }; - - _disableSSLValidation = NO; - self.logLevel = RLMSyncLogLevelWarn; - realm::SyncManager::shared().set_logger_factory(s_syncLoggerFactory); - - self.activeUsers = [NSMutableDictionary dictionary]; - self.loggedOutUsers = [NSMutableDictionary dictionary]; - // Initialize the sync engine. + SyncManager::shared().set_logger_factory(s_syncLoggerFactory); SyncManager::shared().set_error_handler(errorLambda); - SyncManager::shared().set_login_function(loginLambda); - NSString *metadataDirectory = [[RLMSyncFileManager fileURLForMetadata] path]; - bool should_encrypt = !getenv("REALM_DISABLE_METADATA_ENCRYPTION"); - _metadata_manager = std::make_unique([metadataDirectory UTF8String], should_encrypt); - [self _cleanUpMarkedUsers]; - [self _loadPersistedUsers]; + bool should_encrypt = !getenv("REALM_DISABLE_METADATA_ENCRYPTION") && !RLMIsRunningInPlayground(); + auto mode = should_encrypt ? SyncManager::MetadataMode::Encryption : SyncManager::MetadataMode::NoEncryption; + rootDirectory = rootDirectory ?: [NSURL fileURLWithPath:RLMDefaultDirectoryForBundleIdentifier(nil)]; + SyncManager::shared().configure_file_system(rootDirectory.path.UTF8String, mode, none, true); return self; } return nil; } -- (void)setLogLevel:(RLMSyncLogLevel)logLevel { - _logLevel = logLevel; - realm::SyncManager::shared().set_log_level(levelForSyncLogLevel(logLevel)); -} - - (NSString *)appID { if (!_appID) { _appID = [[NSBundle mainBundle] bundleIdentifier] ?: @"(none)"; @@ -147,37 +125,26 @@ - (NSString *)appID { return _appID; } -- (void)setDisableSSLValidation:(BOOL)disableSSLValidation { - _disableSSLValidation = disableSSLValidation; - realm::SyncManager::shared().set_client_should_validate_ssl(!disableSSLValidation); -} - +#pragma mark - Passthrough properties -#pragma mark - Private API +- (RLMSyncLogLevel)logLevel { + return logLevelForLevel(realm::SyncManager::shared().log_level()); +} -+ (void)_resetStateForTesting { - // Log out all the logged-in users. This will immediately kill any open sessions. - NSMutableArray *buffer = [NSMutableArray array]; - if (s_sharedManager) { - for (id key in s_sharedManager.activeUsers) { - [buffer addObject:s_sharedManager.activeUsers[key]]; - } - } - [[s_sharedManager.activeUsers allValues] makeObjectsPerformSelector:@selector(logOut)]; +- (void)setLogLevel:(RLMSyncLogLevel)logLevel { + realm::SyncManager::shared().set_log_level(levelForSyncLogLevel(logLevel)); +} - // Reset the singleton. - s_onceToken = 0; - s_sharedManager = nil; +- (BOOL)disableSSLValidation { + return realm::SyncManager::shared().client_should_validate_ssl(); +} - // Destroy the metadata Realm. - NSURL *metadataURL = [RLMSyncFileManager fileURLForMetadata]; - // FIXME: replace this with the appropriate call to `[RLMSyncFileManager deleteRealmAtPath:]` once that code is in. - NSFileManager *manager = [NSFileManager defaultManager]; - [manager removeItemAtURL:metadataURL error:nil]; - [manager removeItemAtURL:[metadataURL URLByAppendingPathExtension:@"lock"] error:nil]; - [manager removeItemAtURL:[metadataURL URLByAppendingPathExtension:@"management"] error:nil]; +- (void)setDisableSSLValidation:(BOOL)disableSSLValidation { + realm::SyncManager::shared().set_client_should_validate_ssl(!disableSSLValidation); } +#pragma mark - Private API + - (void)_fireError:(NSError *)error { dispatch_async(dispatch_get_main_queue(), ^{ if (self.errorHandler) { @@ -189,28 +156,24 @@ - (void)_fireError:(NSError *)error { - (void)_fireErrorWithCode:(int)errorCode message:(NSString *)message session:(RLMSyncSession *)session - errorClass:(realm::SyncSessionError)errorClass { + errorClass:(RLMSyncSessionErrorKind)errorClass { NSError *error; switch (errorClass) { - case realm::SyncSessionError::UserFatal: - // Kill the user. - [[session parentUser] setState:RLMSyncUserStateError]; + case RLMSyncSessionErrorKindUserFatal: error = [NSError errorWithDomain:RLMSyncErrorDomain code:RLMSyncErrorClientUserError userInfo:@{@"description": message, @"error": @(errorCode)}]; break; - case realm::SyncSessionError::SessionFatal: - // Kill the session. - [session _invalidate]; - case realm::SyncSessionError::AccessDenied: + case RLMSyncSessionErrorKindSessionFatal: + case RLMSyncSessionErrorKindAccessDenied: error = [NSError errorWithDomain:RLMSyncErrorDomain code:RLMSyncErrorClientSessionError userInfo:@{@"description": message, @"error": @(errorCode)}]; break; - case realm::SyncSessionError::Debug: + case RLMSyncSessionErrorKindDebug: // Report the error. There's nothing the user can do about it, though. error = [NSError errorWithDomain:RLMSyncErrorDomain code:RLMSyncErrorClientInternalError @@ -220,114 +183,23 @@ - (void)_fireErrorWithCode:(int)errorCode } dispatch_async(dispatch_get_main_queue(), ^{ if (!self.errorHandler - || (errorClass == realm::SyncSessionError::Debug && self.logLevel >= RLMSyncLogLevelDebug)) { + || (errorClass == RLMSyncSessionErrorKindDebug && self.logLevel >= RLMSyncLogLevelDebug)) { return; } - self.errorHandler(error, nil); + self.errorHandler(error, session); }); } -- (SyncMetadataManager&)_metadataManager { - return *_metadata_manager; -} - -/// Load persisted users from the object store, and then turn them into actual users. -- (void)_loadPersistedUsers { - @synchronized(_activeUsers) { - SyncUserMetadataResults users = _metadata_manager->all_unmarked_users(); - for (size_t i = 0; i < users.size(); i++) { - RLMSyncUser *user = [[RLMSyncUser alloc] initWithMetadata:users.get(i)]; - self.activeUsers[user.identity] = user; - } - } -} - -/// Clean up marked users and destroy them. -- (void)_cleanUpMarkedUsers { - @synchronized(_activeUsers) { - std::vector dead_users; - SyncUserMetadataResults users_to_remove = _metadata_manager->all_users_marked_for_removal(); - for (size_t i = 0; i < users_to_remove.size(); i++) { - auto user = users_to_remove.get(i); - // FIXME: delete user data in a different way? (This deletes a logged-out user's data as soon as the app - // launches again, which might not be how some apps want to treat their data.) - [RLMSyncFileManager removeFilesForUserIdentity:@(user.identity().c_str()) error:nil]; - dead_users.emplace_back(std::move(user)); - } - for (auto user : dead_users) { - user.remove(); - } - } -} - -- (void)_handleBindRequestForSyncConfig:(RLMSyncConfiguration *)syncConfig - localFilePath:(NSString *)filePathString { - @synchronized(self) { - RLMSyncUser *user = syncConfig.user; - if (!user || (user.state == RLMSyncUserStateError)) { - // Can't do anything, the configuration is malformed. - // FIXME: report an error via the global error handler. - return; - } else { - // FIXME: should the completion block actually do anything? - [user _registerSessionForBindingWithFileURL:[NSURL fileURLWithPath:filePathString] - syncConfig:syncConfig - standaloneSession:NO - onCompletion:self.sessionCompletionNotifier]; - } - } -} - -- (void)_removeInvalidUsers { - NSMutableArray *keyBuffer = [NSMutableArray array]; - for (NSString *key in self.activeUsers) { - if (self.activeUsers[key].state == RLMSyncUserStateError) { - [keyBuffer addObject:key]; - } - } - [self.activeUsers removeObjectsForKeys:keyBuffer]; -} - -- (NSArray *)_allUsers { - @synchronized(_activeUsers) { - [self _removeInvalidUsers]; - return [self.activeUsers allValues]; - } -} - -- (RLMSyncUser *)_registerUser:(RLMSyncUser *)user { - @synchronized(_activeUsers) { - [self _removeInvalidUsers]; - NSString *identity = user.identity; - if (RLMSyncUser *user = [self.activeUsers objectForKey:identity]) { - return user; - } else if (RLMSyncUser *user = [self.loggedOutUsers objectForKey:identity]) { - [user setState:RLMSyncUserStateActive]; - [self.loggedOutUsers removeObjectForKey:identity]; - [self.activeUsers setObject:user forKey:identity]; - return user; - } - [self.activeUsers setObject:user forKey:identity]; - return nil; - } -} - -- (void)_deregisterLoggedOutUser:(RLMSyncUser *)user { - @synchronized(_activeUsers) { - NSString *identity = user.identity; - RLMSyncUser *user = [self.activeUsers objectForKey:identity]; - if (!user) { - @throw RLMException(@"Cannot unregister a user that isn't registered."); - } - [self.activeUsers removeObjectForKey:identity]; - self.loggedOutUsers[identity] = user; +- (NSArray *)_allUsers { + NSMutableArray *buffer = [NSMutableArray array]; + for (auto user : SyncManager::shared().all_logged_in_users()) { + [buffer addObject:[[RLMSyncUser alloc] initWithSyncUser:std::move(user)]]; } + return buffer; } -- (RLMSyncUser *)_userForIdentity:(NSString *)identity { - @synchronized (_activeUsers) { - return [self.activeUsers objectForKey:identity] ?: [self.loggedOutUsers objectForKey:identity]; - } ++ (void)resetForTesting { + SyncManager::shared().reset_for_testing(); } @end diff --git a/Pods/Realm/Realm/RLMSyncPermissionChange.m b/Pods/Realm/Realm/RLMSyncPermissionChange.m new file mode 100644 index 0000000..36e52d5 --- /dev/null +++ b/Pods/Realm/Realm/RLMSyncPermissionChange.m @@ -0,0 +1,75 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// 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 "RLMSyncPermissionChange_Private.h" + +#import "RLMRealm.h" +#import "RLMRealmConfiguration+Sync.h" +#import "RLMSyncConfiguration.h" +#import "RLMSyncUser.h" + +@implementation RLMSyncPermissionChange + ++ (instancetype)permissionChangeWithRealmURL:(NSString *)realmURL + userID:(NSString *)userID + read:(nullable NSNumber *)mayRead + write:(nullable NSNumber *)mayWrite + manage:(nullable NSNumber *)mayManage { + RLMSyncPermissionChange *permissionChange = [RLMSyncPermissionChange new]; + permissionChange.realmUrl = realmURL; + permissionChange.userId = userID; + permissionChange.mayRead = mayRead; + permissionChange.mayWrite = mayWrite; + permissionChange.mayManage = mayManage; + return permissionChange; +} + ++ (NSArray *)requiredProperties { + return @[@"id", @"createdAt", @"updatedAt", @"realmUrl", @"userId"]; +} + ++ (NSDictionary *)defaultPropertyValues { + NSDate *now = [NSDate date]; + return @{ + @"id": [NSUUID UUID].UUIDString, + @"createdAt": now, + @"updatedAt": now, + @"realmUrl": @"*", + @"userId": @"*" + }; +} + ++ (BOOL)shouldIncludeInDefaultSchema { + return NO; +} + +- (RLMSyncManagementObjectStatus)status { + if (!self.statusCode) { + return RLMSyncManagementObjectStatusNotProcessed; + } + if (self.statusCode.integerValue == 0) { + return RLMSyncManagementObjectStatusSuccess; + } + return RLMSyncManagementObjectStatusError; +} + ++ (NSString *)_realmObjectName { + return @"PermissionChange"; +} + +@end diff --git a/Pods/Realm/Realm/RLMSyncSession.mm b/Pods/Realm/Realm/RLMSyncSession.mm index 5e03a9c..506c2cd 100644 --- a/Pods/Realm/Realm/RLMSyncSession.mm +++ b/Pods/Realm/Realm/RLMSyncSession.mm @@ -16,212 +16,95 @@ // //////////////////////////////////////////////////////////////////////////// -#import "RLMSyncSession_Private.h" +#import "RLMSyncSession_Private.hpp" -#import "RLMAuthResponseModel.h" -#import "RLMNetworkClient.h" -#import "RLMRealmConfiguration+Sync.h" -#import "RLMSyncConfiguration.h" -#import "RLMSyncManager_Private.hpp" -#import "RLMSyncSessionHandle.hpp" +#import "RLMSyncConfiguration_Private.hpp" #import "RLMSyncUser_Private.hpp" -#import "RLMSyncUtil.h" -#import "RLMTokenModels.h" -#import "RLMUtil.hpp" +#import "sync/sync_session.hpp" -#import "sync_manager.hpp" +using namespace realm; -@implementation RLMSessionBindingPackage - -- (instancetype)initWithFileURL:(NSURL *)fileURL - syncConfig:(RLMSyncConfiguration *)syncConfig - standalone:(BOOL)isStandalone - block:(RLMSyncBasicErrorReportingBlock)block { - if (self = [super init]) { - self.fileURL = fileURL; - self.syncConfig = syncConfig; - self.isStandalone = isStandalone; - self.block = block; - return self; - } - return nil; +@interface RLMSyncSession () { + std::weak_ptr _session; } @end -@interface RLMSyncSession () - -@property (nonatomic, readwrite) RLMSyncSessionState state; -@property (nonatomic, readwrite) RLMSyncUser *parentUser; -@property (nonatomic, readwrite) NSURL *realmURL; - -@property (nullable, nonatomic) RLMSyncSessionHandle *sessionHandle; - -@end - @implementation RLMSyncSession -- (instancetype)initWithFileURL:(NSURL *)fileURL realmURL:(NSURL *)realmURL { +- (instancetype)initWithSyncSession:(std::shared_ptr)session { if (self = [super init]) { - self.fileURL = fileURL; - self.realmURL = realmURL; - self.resolvedPath = nil; - self.deferredBindingPackage = nil; - _state = RLMSyncSessionStateUnbound; + _session = session; return self; } return nil; } -- (nullable RLMSyncConfiguration *)configuration { - RLMSyncUser *user = self.parentUser; - if (user && self.state != RLMSyncSessionStateInvalid) { - return [[RLMSyncConfiguration alloc] initWithUser:user realmURL:self.realmURL]; +- (RLMSyncConfiguration *)configuration { + if (auto session = _session.lock()) { + if (session->state() != SyncSession::PublicState::Error) { + return [[RLMSyncConfiguration alloc] initWithRawConfig:session->config()]; + } } return nil; } -- (void)_logOut { - [self.sessionHandle logOut]; - [self.refreshTimer invalidate]; - _state = RLMSyncSessionStateLoggedOut; -} - -- (void)_invalidate { - [self.refreshTimer invalidate]; - _state = RLMSyncSessionStateInvalid; - self.sessionHandle = nil; - [self.parentUser _deregisterSessionWithRealmURL:self.realmURL]; - self.parentUser = nil; -} - -#pragma mark - per-Realm access token API - -- (void)configureWithAccessToken:(RLMServerToken)token - expiry:(NSTimeInterval)expiry - user:(RLMSyncUser *)user - handle:(RLMSyncSessionHandle *)handle { - self.parentUser = user; - self.accessToken = token; - self.accessTokenExpiry = expiry; - self.sessionHandle = handle; - [self _scheduleRefreshTimer]; -} - -- (void)_scheduleRefreshTimer { - static NSTimeInterval const refreshBuffer = 10; - - [self.refreshTimer invalidate]; - NSTimeInterval refreshTime = self.accessTokenExpiry - refreshBuffer; - NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSince1970:refreshTime] - interval:1 - target:self - selector:@selector(_refreshForTimer:) - userInfo:nil - repeats:NO]; - [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; - self.refreshTimer = timer; -} - -- (void)_refreshForTimer:(__unused NSTimer *)timer { - [self _refresh]; +- (NSURL *)realmURL { + if (auto session = _session.lock()) { + if (auto url = session->full_realm_url()) { + return [NSURL URLWithString:@(url->c_str())]; + } + } + return nil; } -- (void)_refresh { - RLMSyncUser *user = self.parentUser; - if (!user || !self.resolvedPath) { - return; +- (RLMSyncUser *)parentUser { + if (auto session = _session.lock()) { + if (session->state() != SyncSession::PublicState::Error) { + return [[RLMSyncUser alloc] initWithSyncUser:session->user()]; + } } - RLMServerToken refreshToken = user.refreshToken; - - NSDictionary *json = @{ - kRLMSyncProviderKey: @"realm", - kRLMSyncPathKey: self.resolvedPath, - kRLMSyncDataKey: refreshToken, - kRLMSyncAppIDKey: [RLMSyncManager sharedManager].appID, - }; - - RLMSyncCompletionBlock handler = ^(NSError *error, NSDictionary *json) { - if (json && !error) { - RLMAuthResponseModel *model = [[RLMAuthResponseModel alloc] initWithDictionary:json - requireAccessToken:YES - requireRefreshToken:NO]; - if (!model) { - // Malformed JSON - error = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorBadResponse - userInfo:@{kRLMSyncErrorJSONKey: json}]; - [[RLMSyncManager sharedManager] _fireError:error]; - return; - } else { - // Success - // For now, assume just one access token. - RLMTokenModel *tokenModel = model.accessToken; - self.accessToken = model.accessToken.token; - self.accessTokenExpiry = tokenModel.tokenData.expires; - [self _scheduleRefreshTimer]; + return nil; +} - [self refreshAccessToken:tokenModel.token serverURL:nil]; - } - } else { - // Something else went wrong - NSError *syncError = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorBadResponse - userInfo:@{kRLMSyncUnderlyingErrorKey: error}]; - [[RLMSyncManager sharedManager] _fireError:syncError]; - // Certain errors should trigger a retry. - if (error.domain == NSURLErrorDomain) { - BOOL shouldRetry = NO; - switch (error.code) { - case NSURLErrorCannotConnectToHost: - shouldRetry = YES; - // FIXME: 120 seconds is an arbitrarily chosen value, consider rationalizing it. - self.accessTokenExpiry = [[NSDate dateWithTimeIntervalSinceNow:120] timeIntervalSince1970]; - break; - case NSURLErrorNotConnectedToInternet: - case NSURLErrorNetworkConnectionLost: - case NSURLErrorTimedOut: - case NSURLErrorDNSLookupFailed: - case NSURLErrorCannotFindHost: - shouldRetry = YES; - // FIXME: 30 seconds is an arbitrarily chosen value, consider rationalizing it. - self.accessTokenExpiry = [[NSDate dateWithTimeIntervalSinceNow:30] timeIntervalSince1970]; - break; - default: - break; - } - if (shouldRetry) { - [self _scheduleRefreshTimer]; - } - } +- (RLMSyncSessionState)state { + if (auto session = _session.lock()) { + if (session->state() == SyncSession::PublicState::Inactive) { + return RLMSyncSessionStateInactive; } - }; - [RLMNetworkClient postRequestToEndpoint:RLMServerEndpointAuth - server:user.authenticationServer - JSON:json - completion:handler]; + if (session->state() != SyncSession::PublicState::Error) { + return RLMSyncSessionStateActive; + } + } + return RLMSyncSessionStateInvalid; } -- (void)refreshAccessToken:(NSString *)token serverURL:(NSURL *)serverURL -{ - if ([self.sessionHandle refreshAccessToken:token serverURL:serverURL]) { - self.state = RLMSyncSessionStateActive; - } - else { - [self _invalidate]; +- (BOOL)waitForUploadCompletionOnQueue:(dispatch_queue_t)queue callback:(void(^)(void))callback { + if (auto session = _session.lock()) { + if (session->state() == SyncSession::PublicState::Error) { + return NO; + } + queue = queue ?: dispatch_get_main_queue(); + session->wait_for_upload_completion([=](std::error_code) { // FIXME: report error to user + dispatch_async(queue, callback); + }); + return YES; } + return NO; } -- (void)setState:(RLMSyncSessionState)state { - // At all state transitions, check to see if the session should be invalidated. - if ([self.sessionHandle sessionIsInErrorState]) { - [self _invalidate]; - return; - } - _state = state; - if (state == RLMSyncSessionStateActive) { - self.deferredBindingPackage = nil; +- (BOOL)waitForDownloadCompletionOnQueue:(dispatch_queue_t)queue callback:(void(^)(void))callback { + if (auto session = _session.lock()) { + if (session->state() == SyncSession::PublicState::Error) { + return NO; + } + queue = queue ?: dispatch_get_main_queue(); + session->wait_for_download_completion([=](std::error_code) { // FIXME: report error to user + dispatch_async(queue, callback); + }); + return YES; } + return NO; } @end diff --git a/Pods/Realm/Realm/RLMSyncSessionHandle.mm b/Pods/Realm/Realm/RLMSyncSessionHandle.mm deleted file mode 100644 index d301d24..0000000 --- a/Pods/Realm/Realm/RLMSyncSessionHandle.mm +++ /dev/null @@ -1,206 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 Realm Inc. -// -// 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 "RLMSyncSessionHandle.hpp" - -#import "sync_session.hpp" - -using namespace realm; - -@interface RLMSyncWeakSessionHandle : RLMSyncSessionHandle { -@public - std::weak_ptr _ptr; -} -@end - -@interface RLMSyncStrongSessionHandle : RLMSyncSessionHandle { -@public - std::shared_ptr _ptr; -} -@end - -#pragma mark - Weak session handle - -@implementation RLMSyncWeakSessionHandle - -- (BOOL)sessionIsInErrorState { - if (auto pointer = _ptr.lock()) { - return !(pointer->is_valid()); - } - return NO; -} - -- (BOOL)sessionStillExists { - return bool(_ptr.lock()) == true; -} - -- (BOOL)refreshAccessToken:(NSString *)accessToken serverURL:(NSURL *)serverURL { - if (auto pointer = _ptr.lock()) { - pointer->refresh_access_token(accessToken.UTF8String, - serverURL ? util::make_optional(serverURL.absoluteString.UTF8String) - : util::none); - return YES; - } - return NO; -} - -- (void)logOut { - if (auto pointer = _ptr.lock()) { - pointer->log_out(); - } -} - -- (void)revive { - if (auto pointer = _ptr.lock()) { - pointer->revive_if_needed(); - } -} - -- (BOOL)waitForUploadCompletionOnQueue:(dispatch_queue_t)queue - callback:(void(^)(void))callback { - if (auto pointer = _ptr.lock()) { - queue = queue ?: dispatch_get_main_queue(); - pointer->wait_for_upload_completion([=](){ - dispatch_async(queue, ^{ - callback(); - }); - }); - return YES; - } - return NO; -} - -- (BOOL)waitForDownloadCompletionOnQueue:(dispatch_queue_t)queue - callback:(void(^)(void))callback { - if (auto pointer = _ptr.lock()) { - queue = queue ?: dispatch_get_main_queue(); - pointer->wait_for_download_completion([=](){ - dispatch_async(queue, ^{ - callback(); - }); - }); - return YES; - } - return NO; -} - -@end - -#pragma mark - Strong session handle - -@implementation RLMSyncStrongSessionHandle - -- (BOOL)sessionIsInErrorState { - return !(_ptr->is_valid()); -} - -- (BOOL)sessionStillExists { - return YES; -} - -- (BOOL)refreshAccessToken:(NSString *)accessToken serverURL:(NSURL *)serverURL { - _ptr->refresh_access_token(accessToken.UTF8String, - serverURL ? util::make_optional(serverURL.absoluteString.UTF8String) - : util::none); - return YES; -} - -- (void)logOut { - _ptr->log_out(); -} - -- (void)revive { - _ptr->revive_if_needed(); -} - -- (BOOL)waitForUploadCompletionOnQueue:(dispatch_queue_t)queue - callback:(void(^)(void))callback { - queue = queue ?: dispatch_get_main_queue(); - _ptr->wait_for_upload_completion([=](){ - dispatch_async(queue, ^{ - callback(); - }); - }); - return YES; -} - -- (BOOL)waitForDownloadCompletionOnQueue:(dispatch_queue_t)queue - callback:(void(^)(void))callback { - queue = queue ?: dispatch_get_main_queue(); - _ptr->wait_for_download_completion([=](){ - dispatch_async(queue, ^{ - callback(); - }); - }); - return YES; -} - -@end - -#pragma mark - Abstract base class - -@implementation RLMSyncSessionHandle - -+ (instancetype)syncSessionHandleForWeakPointer:(std::shared_ptr)session { - RLMSyncWeakSessionHandle *h = [[RLMSyncWeakSessionHandle alloc] init]; - h->_ptr = std::move(session); - return h; -} - -+ (instancetype)syncSessionHandleForPointer:(std::shared_ptr)session { - RLMSyncStrongSessionHandle *h = [[RLMSyncStrongSessionHandle alloc] init]; - h->_ptr = std::move(session); - return h; -} - -- (void)logOut { - NSAssert(NO, @"Subclasses must override..."); -} - -- (BOOL)sessionIsInErrorState { - NSAssert(NO, @"Subclasses must override..."); - return NO; -} - -- (BOOL)sessionStillExists { - NSAssert(NO, @"Subclasses must override..."); - return NO; -} - -- (BOOL)refreshAccessToken:(__unused NSString *)accessToken serverURL:(__unused NSURL *)serverURL { - NSAssert(NO, @"Subclasses must override..."); - return NO; -} - -- (void)revive { - NSAssert(NO, @"Subclasses must override..."); -} - -- (BOOL)waitForUploadCompletionOnQueue:(__unused dispatch_queue_t)queue - callback:(__unused void(^)(void))callback { - NSAssert(NO, @"Subclasses must override..."); - return NO; -} - -- (BOOL)waitForDownloadCompletionOnQueue:(__unused dispatch_queue_t)queue - callback:(__unused void(^)(void))callback { - NSAssert(NO, @"Subclasses must override..."); - return NO; -} - -@end diff --git a/Pods/Realm/Realm/RLMSyncSessionRefreshHandle.mm b/Pods/Realm/Realm/RLMSyncSessionRefreshHandle.mm new file mode 100644 index 0000000..5112df4 --- /dev/null +++ b/Pods/Realm/Realm/RLMSyncSessionRefreshHandle.mm @@ -0,0 +1,159 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// 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 "RLMSyncSessionRefreshHandle.hpp" + +#import "RLMAuthResponseModel.h" +#import "RLMNetworkClient.h" +#import "RLMSyncManager_Private.h" +#import "RLMSyncUser_Private.hpp" +#import "RLMTokenModels.h" + +#import "sync/sync_session.hpp" + +using namespace realm; + +@interface RLMSyncSessionRefreshHandle () { + std::weak_ptr _session; +} + +@property (nonatomic, weak) RLMSyncUser *user; +@property (nonatomic, strong) NSString *fullURLPath; +@property (nonatomic) NSTimer *timer; + +@end + +@implementation RLMSyncSessionRefreshHandle + +- (instancetype)initWithFullURLPath:(NSString *)urlPath + user:(RLMSyncUser *)user + session:(std::shared_ptr)session { + if (self = [super init]) { + self.fullURLPath = urlPath; + self.user = user; + _session = session; + return self; + } + return nil; +} + +- (void)invalidate { + [self.timer invalidate]; + self.user = nil; +} + +- (void)scheduleRefreshTimer:(NSTimeInterval)fireTime { + static const NSInteger refreshBuffer = 10; + [self.timer invalidate]; + self.timer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSince1970:(fireTime - refreshBuffer)] + interval:0 + target:self + selector:@selector(timerFired:) + userInfo:nil + repeats:NO]; + [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode]; +} + +- (void)timerFired:(__unused NSTimer *)timer { + RLMSyncUser *user = self.user; + if (!user) { + return; + } + RLMServerToken refreshToken = user._refreshToken; + if (!refreshToken) { + [user _unregisterRefreshHandleForURLPath:self.fullURLPath]; + [self.timer invalidate]; + return; + } + + NSDictionary *json = @{ + kRLMSyncProviderKey: @"realm", + kRLMSyncPathKey: self.fullURLPath, + kRLMSyncDataKey: refreshToken, + kRLMSyncAppIDKey: [RLMSyncManager sharedManager].appID, + }; + + RLMSyncCompletionBlock handler = ^(NSError *error, NSDictionary *json) { + if (json && !error) { + RLMAuthResponseModel *model = [[RLMAuthResponseModel alloc] initWithDictionary:json + requireAccessToken:YES + requireRefreshToken:NO]; + if (!model) { + // Malformed JSON + error = [NSError errorWithDomain:RLMSyncErrorDomain + code:RLMSyncErrorBadResponse + userInfo:@{kRLMSyncErrorJSONKey: json}]; + [user _unregisterRefreshHandleForURLPath:self.fullURLPath]; + [self.timer invalidate]; + [[RLMSyncManager sharedManager] _fireError:error]; + return; + } + + // Success + if (auto session = _session.lock()) { + if (session->state() != SyncSession::PublicState::Error) { + session->refresh_access_token([model.accessToken.token UTF8String], none); + [self scheduleRefreshTimer:model.accessToken.tokenData.expires]; + return; + } + } + // The session is dead or in a fatal error state. + [user _unregisterRefreshHandleForURLPath:self.fullURLPath]; + [self.timer invalidate]; + return; + } + + // Something else went wrong + NSError *syncError = [NSError errorWithDomain:RLMSyncErrorDomain + code:RLMSyncErrorBadResponse + userInfo:@{kRLMSyncUnderlyingErrorKey: error}]; + [[RLMSyncManager sharedManager] _fireError:syncError]; + NSTimeInterval nextFireDate = 0; + // Certain errors should trigger a retry. + if (error.domain == NSURLErrorDomain) { + switch (error.code) { + case NSURLErrorCannotConnectToHost: + // FIXME: 120 seconds is an arbitrarily chosen value, consider rationalizing it. + nextFireDate = [[NSDate dateWithTimeIntervalSinceNow:120] timeIntervalSince1970]; + break; + case NSURLErrorNotConnectedToInternet: + case NSURLErrorNetworkConnectionLost: + case NSURLErrorTimedOut: + case NSURLErrorDNSLookupFailed: + case NSURLErrorCannotFindHost: + // FIXME: 30 seconds is an arbitrarily chosen value, consider rationalizing it. + nextFireDate = [[NSDate dateWithTimeIntervalSinceNow:30] timeIntervalSince1970]; + break; + default: + break; + } + if (nextFireDate > 0) { + [self scheduleRefreshTimer:nextFireDate]; + } else { + [user _unregisterRefreshHandleForURLPath:self.fullURLPath]; + [self.timer invalidate]; + } + } + }; + [RLMNetworkClient postRequestToEndpoint:RLMServerEndpointAuth + server:user.authenticationServer + JSON:json + completion:handler]; +} + +@end diff --git a/Pods/Realm/Realm/RLMSyncUser.mm b/Pods/Realm/Realm/RLMSyncUser.mm index 0642501..cc1b930 100644 --- a/Pods/Realm/Realm/RLMSyncUser.mm +++ b/Pods/Realm/Realm/RLMSyncUser.mm @@ -20,32 +20,26 @@ #import "RLMAuthResponseModel.h" #import "RLMNetworkClient.h" -#import "RLMSyncConfiguration_Private.hpp" -#import "RLMSyncManager_Private.hpp" -#import "RLMSyncSession_Private.h" -#import "RLMSyncSessionHandle.hpp" +#import "RLMSyncManager_Private.h" +#import "RLMSyncSession_Private.hpp" +#import "RLMSyncSessionRefreshHandle.hpp" #import "RLMTokenModels.h" #import "RLMUtil.hpp" -#import "sync_manager.hpp" -#import "sync_metadata.hpp" -#import "sync_session.hpp" +#import "sync/sync_manager.hpp" +#import "sync/sync_session.hpp" +#import "sync/sync_user.hpp" using namespace realm; -@interface RLMSyncUser () +@interface RLMSyncUser () { + std::shared_ptr _user; +} - (instancetype)initWithAuthServer:(nullable NSURL *)authServer NS_DESIGNATED_INITIALIZER; -@property (nonatomic, readwrite) RLMSyncUserState state; - -@property (nonatomic, readwrite) NSString *identity; @property (nonatomic, readwrite) NSURL *authenticationServer; - -@property (nonatomic) NSMutableDictionary *sessionsStorage; -@property (nonatomic) NSDictionary *loggedOutSessions; - -@property (nonatomic) RLMServerToken directAccessToken; +@property (nonatomic) NSMutableDictionary *refreshHandles; @end @@ -53,138 +47,217 @@ @implementation RLMSyncUser #pragma mark - static API -+ (NSArray *)all { - return [[RLMSyncManager sharedManager] _allUsers]; ++ (NSDictionary *)allUsers { + NSArray *allUsers = [[RLMSyncManager sharedManager] _allUsers]; + return [NSDictionary dictionaryWithObjects:allUsers + forKeys:[allUsers valueForKey:@"identity"]]; +} + ++ (RLMSyncUser *)currentUser { + NSArray *allUsers = [[RLMSyncManager sharedManager] _allUsers]; + if (allUsers.count > 1) { + @throw RLMException(@"+currentUser cannot be called if more that one valid, logged-in user exists."); + } + return allUsers.firstObject; } #pragma mark - API - (instancetype)initWithAuthServer:(nullable NSURL *)authServer { if (self = [super init]) { - self.state = RLMSyncUserStateLoggedOut; - self.directAccessToken = nil; self.authenticationServer = authServer; - self.sessionsStorage = [NSMutableDictionary dictionary]; - // NOTE: If we add support for anonymous users, we will need to register the user to the global user store - // when the user is first created, versus when the user logs in. return self; } return nil; } -+ (void)authenticateWithCredential:(RLMSyncCredential *)credential - authServerURL:(NSURL *)authServerURL - onCompletion:(RLMUserCompletionBlock)completion { - [self authenticateWithCredential:credential - authServerURL:authServerURL - timeout:30 - onCompletion:completion]; +- (instancetype)initWithSyncUser:(std::shared_ptr)user { + NSString *rawServerURL = @(user->server_url().c_str()); + if (self = [self initWithAuthServer:[NSURL URLWithString:rawServerURL]]) { + _user = user; + return self; + } + return nil; +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[RLMSyncUser class]]) { + return NO; + } + return _user == ((RLMSyncUser *)object)->_user; } -+ (void)authenticateWithCredential:(RLMSyncCredential *)credential - authServerURL:(NSURL *)authServerURL - timeout:(NSTimeInterval)timeout - onCompletion:(RLMUserCompletionBlock)completion { ++ (void)logInWithCredentials:(RLMSyncCredentials *)credential + authServerURL:(NSURL *)authServerURL + onCompletion:(RLMUserCompletionBlock)completion { + [self logInWithCredentials:credential + authServerURL:authServerURL + timeout:30 + onCompletion:completion]; +} + ++ (void)logInWithCredentials:(RLMSyncCredentials *)credential + authServerURL:(NSURL *)authServerURL + timeout:(NSTimeInterval)timeout + onCompletion:(RLMUserCompletionBlock)completion { RLMSyncUser *user = [[RLMSyncUser alloc] initWithAuthServer:authServerURL]; [RLMSyncUser _performLogInForUser:user - credential:credential + credentials:credential authServerURL:authServerURL timeout:timeout completionBlock:completion]; } - (void)logOut { - if (self.state != RLMSyncUserStateActive || !self.identity) { - // FIXME: report a warning to the global error handler? + if (!_user) { return; } - self.state = RLMSyncUserStateLoggedOut; - for (NSURL *url in self.sessionsStorage) { - [self.sessionsStorage[url] _logOut]; + _user->log_out(); + for (id key in self.refreshHandles) { + [self.refreshHandles[key] invalidate]; } - self.loggedOutSessions = [self.sessionsStorage copy]; - self.sessionsStorage = [NSMutableDictionary dictionary]; - [[RLMSyncManager sharedManager] _deregisterLoggedOutUser:self]; - auto metadata = SyncUserMetadata([[RLMSyncManager sharedManager] _metadataManager], - [self.identity UTF8String], - false); - metadata.mark_for_removal(); + [self.refreshHandles removeAllObjects]; } - (nullable RLMSyncSession *)sessionForURL:(NSURL *)url { - RLMSyncSession *session = [self.sessionsStorage objectForKey:url]; - RLMSyncSessionHandle *handle = [session sessionHandle]; - if (handle && ![handle sessionStillExists]) { - [self.sessionsStorage removeObjectForKey:url]; - return nil; - } else if ([handle sessionIsInErrorState]) { - [session _invalidate]; + if (!_user) { return nil; } - return session; + return [[RLMSyncSession alloc] initWithSyncSession:_user->session_for_url([[url absoluteString] UTF8String])]; } - (NSArray *)allSessions { - NSMutableArray *buffer = [NSMutableArray arrayWithCapacity:self.sessionsStorage.count]; - NSArray *allURLs = [self.sessionsStorage allKeys]; - for (NSURL *url in allURLs) { - RLMSyncSession *session = [self sessionForURL:url]; - if (session) { - [buffer addObject:session]; - } + if (!_user) { + return @[]; + } + NSMutableArray *buffer = [NSMutableArray array]; + auto sessions = _user->all_sessions(); + for (auto session : sessions) { + [buffer addObject:[[RLMSyncSession alloc] initWithSyncSession:std::move(session)]]; } return [buffer copy]; } +- (NSString *)identity { + if (!_user) { + return nil; + } + return @(_user->identity().c_str()); +} -#pragma mark - Private API - -- (void)_enterErrorState { - self.state = RLMSyncUserStateError; +- (RLMSyncUserState)state { + if (!_user) { + return RLMSyncUserStateError; + } + switch (_user->state()) { + case SyncUser::State::Active: + return RLMSyncUserStateActive; + case SyncUser::State::LoggedOut: + return RLMSyncUserStateLoggedOut; + case SyncUser::State::Error: + return RLMSyncUserStateError; + } } -- (void)_enterActiveState { - self.state = RLMSyncUserStateActive; +- (RLMRealm *)managementRealmWithError:(NSError **)error { + return [RLMRealm realmWithConfiguration:[RLMRealmConfiguration managementConfigurationForUser:self] error:error]; } -- (void)_deregisterSessionWithRealmURL:(NSURL *)realmURL { - [self.sessionsStorage removeObjectForKey:realmURL]; +#pragma mark - Private API + +- (void)_unregisterRefreshHandleForURLPath:(NSString *)path { + [self.refreshHandles removeObjectForKey:path]; } - -- (instancetype)initWithMetadata:(SyncUserMetadata)metadata { - NSURL *url = nil; - if (metadata.server_url()) { - url = [NSURL URLWithString:@(metadata.server_url()->c_str())]; - } - self = [self initWithAuthServer:url]; - self.identity = @(metadata.identity().c_str()); - if (auto user_token = metadata.user_token()) { - // FIXME: Once the new auth system is enabled, rename "refreshToken" to "userToken" to reflect its new role. - self.refreshToken = @(user_token->c_str()); - self.state = RLMSyncUserStateActive; - } else { - // For now, throw an exception. In the future we may want to allow for "anonymous" style users. - @throw RLMException(@"Invalid persisted user: there must be a valid access token."); + +- (NSString *)_refreshToken { + if (!_user) { + return nil; } - return self; + return @(_user->refresh_token().c_str()); } -- (void)_updatePersistedMetadata { - if (!self.refreshToken) { - // For now, throw an exception. In the future we may want to allow for "anonymous" style users. - @throw RLMException(@"Invalid persisted user: there must be a valid access token."); - } +- (void)_bindSessionWithPath:(__unused const std::string&)path + config:(const SyncConfig&)config + session:(std::shared_ptr)session + completion:(RLMSyncBasicErrorReportingBlock)completion + isStandalone:(__unused BOOL)standalone { + NSURL *realmURL = [NSURL URLWithString:@(config.realm_url.c_str())]; + RLMServerPath unresolvedURL = [realmURL path]; + NSDictionary *json = @{ + kRLMSyncPathKey: unresolvedURL, + kRLMSyncProviderKey: @"realm", + kRLMSyncDataKey: @(_user->refresh_token().c_str()), + kRLMSyncAppIDKey: [RLMSyncManager sharedManager].appID, + }; + + RLMSyncCompletionBlock handler = ^(NSError *error, NSDictionary *json) { + if (json && !error) { + RLMAuthResponseModel *model = [[RLMAuthResponseModel alloc] initWithDictionary:json + requireAccessToken:YES + requireRefreshToken:NO]; + if (!model) { + // Malformed JSON + error = [NSError errorWithDomain:RLMSyncErrorDomain + code:RLMSyncErrorBadResponse + userInfo:@{kRLMSyncErrorJSONKey: json}]; + if (completion) { + completion(error); + } + [[RLMSyncManager sharedManager] _fireError:error]; + return; + } + + // SUCCESS + NSString *accessToken = model.accessToken.token; + RLMServerPath resolvedPath = model.accessToken.tokenData.path; + // Munge the path onto the original URL, because reasons. + NSURLComponents *urlBuffer = [NSURLComponents componentsWithURL:realmURL resolvingAgainstBaseURL:YES]; + urlBuffer.path = resolvedPath; + NSString *resolvedURLString = [[urlBuffer URL] absoluteString]; + if (!resolvedURLString) { + @throw RLMException(@"Resolved path returned from the server was invalid (%@).", resolvedPath); + } + // Refresh the access token. + session->refresh_access_token([accessToken UTF8String], {resolvedURLString.UTF8String}); + bool success = session->state() != SyncSession::PublicState::Error; + if (success) { + // Schedule the session for automatic refreshing on a timer. + auto handle = [[RLMSyncSessionRefreshHandle alloc] initWithFullURLPath:resolvedURLString + user:self + session:session]; + [self.refreshHandles[resolvedURLString] invalidate]; + self.refreshHandles[resolvedURLString] = handle; + [handle scheduleRefreshTimer:model.accessToken.tokenData.expires]; + } + if (completion) { + completion(success ? nil : [NSError errorWithDomain:RLMSyncErrorDomain + code:RLMSyncErrorClientSessionError + userInfo:nil]); + } + return; + } + + // Something else went wrong + NSError *syncError = [NSError errorWithDomain:RLMSyncErrorDomain + code:RLMSyncErrorBadResponse + userInfo:@{kRLMSyncUnderlyingErrorKey: error}]; + if (completion) { + completion(syncError); + } + [[RLMSyncManager sharedManager] _fireError:syncError]; + }; + [RLMNetworkClient postRequestToEndpoint:RLMServerEndpointAuth + server:self.authenticationServer + JSON:json + completion:handler]; +} - NSURL *authServer = self.authenticationServer; - NSString *refreshToken = self.refreshToken; - auto server = authServer ? util::Optional([[authServer absoluteString] UTF8String]) : none; - auto token = refreshToken ? util::Optional([refreshToken UTF8String]) : none; - auto metadata = SyncUserMetadata([[RLMSyncManager sharedManager] _metadataManager], [self.identity UTF8String]); - metadata.set_state(server, token); +- (std::shared_ptr)_syncUser { + return _user; } + (void)_performLogInForUser:(RLMSyncUser *)user - credential:(RLMSyncCredential *)credential + credentials:(RLMSyncCredentials *)credentials authServerURL:(NSURL *)authServerURL timeout:(NSTimeInterval)timeout completionBlock:(RLMUserCompletionBlock)completion { @@ -197,25 +270,18 @@ + (void)_performLogInForUser:(RLMSyncUser *)user }; // Special credential login should be treated differently. - if (credential.provider == RLMIdentityProviderAccessToken) { - [self _performLoginForDirectAccessTokenCredential:credential user:user completionBlock:theBlock]; + if (credentials.provider == RLMIdentityProviderAccessToken) { + [self _performLoginForDirectAccessTokenCredentials:credentials user:user completionBlock:theBlock]; return; } // Prepare login network request NSMutableDictionary *json = [@{ - kRLMSyncProviderKey: credential.provider, - kRLMSyncDataKey: credential.token, + kRLMSyncProviderKey: credentials.provider, + kRLMSyncDataKey: credentials.token, kRLMSyncAppIDKey: [RLMSyncManager sharedManager].appID, } mutableCopy]; - NSMutableDictionary *info = [(credential.userInfo ?: @{}) mutableCopy]; - - if (credential.provider == RLMIdentityProviderUsernamePassword) { - RLMAuthenticationActions actions = [info[kRLMSyncActionsKey] integerValue]; - if (actions & RLMAuthenticationActionsCreateAccount) { - info[kRLMSyncRegisterKey] = @(YES); - } - } + NSMutableDictionary *info = [(credentials.userInfo ?: @{}) mutableCopy]; if ([info count] > 0) { // Munge user info into the JSON request. @@ -235,18 +301,18 @@ + (void)_performLogInForUser:(RLMSyncUser *)user theBlock(nil, error); return; } else { - // Success: store the tokens. - user.identity = model.refreshToken.tokenData.identity; - user.refreshToken = model.refreshToken.token; - RLMSyncUser *existingUser = [[RLMSyncManager sharedManager] _registerUser:user]; - RLMSyncUser *actualUser = existingUser ?: user; - if (existingUser) { - [actualUser _mergeDataFromDuplicateUser:user]; + std::string server_url = authServerURL.absoluteString.UTF8String; + auto sync_user = SyncManager::shared().get_user([model.refreshToken.tokenData.identity UTF8String], + [model.refreshToken.token UTF8String], + std::move(server_url)); + if (!sync_user) { + completion(nil, [NSError errorWithDomain:RLMSyncErrorDomain + code:RLMSyncErrorClientSessionError + userInfo:nil]); + return; } - actualUser.state = RLMSyncUserStateActive; - [actualUser _updatePersistedMetadata]; - [actualUser _bindAllDeferredRealms]; - theBlock(actualUser, nil); + user->_user = sync_user; + completion(user, nil); } } else { // Something else went wrong @@ -260,248 +326,20 @@ + (void)_performLogInForUser:(RLMSyncUser *)user completion:handler]; } -+ (void)_performLoginForDirectAccessTokenCredential:(RLMSyncCredential *)credential - user:(RLMSyncUser *)user - completionBlock:(nonnull RLMUserCompletionBlock)completion { - user.directAccessToken = credential.token; - NSString *identity = credential.userInfo[kRLMSyncIdentityKey]; ++ (void)_performLoginForDirectAccessTokenCredentials:(RLMSyncCredentials *)credentials + user:(RLMSyncUser *)user + completionBlock:(nonnull RLMUserCompletionBlock)completion { + NSString *identity = credentials.userInfo[kRLMSyncIdentityKey]; NSAssert(identity != nil, @"Improperly created direct access token credential."); - user.identity = identity; - RLMSyncUser *existingUser = [[RLMSyncManager sharedManager] _registerUser:user]; - RLMSyncUser *actualUser = existingUser ?: user; - if (existingUser) { - [actualUser _mergeDataFromDuplicateUser:user]; - } - actualUser.state = RLMSyncUserStateActive; - [actualUser _bindAllDeferredRealms]; - completion(actualUser, nil); -} - -/** - The argument to this method represents a duplicate, not-yet-active user; the receiver is an existing user. Merge the - state of the duplicate user into the existing user, including the most up-to-date tokens and any sessions that are - waiting to be activated. - */ -- (void)_mergeDataFromDuplicateUser:(RLMSyncUser *)user { - NSAssert(user.state != RLMSyncUserStateActive, @"Erroneous user-to-be-merged: user can't be active."); - NSAssert([self.identity isEqualToString:user.identity], @"Logic error: can only merge two equivalent users."); - - self.directAccessToken = user.directAccessToken; - self.refreshToken = user.refreshToken; - // Move over any sessions that are waiting to be started up. - for (NSURL *url in user.sessionsStorage) { - RLMSyncSession *session = [user.sessionsStorage objectForKey:url]; - NSAssert(session.state != RLMSyncSessionStateActive, - @"Logic error: a newly-created user can't have active sessions."); - if (session.state == RLMSyncSessionStateUnbound) { - [self.sessionsStorage setObject:session forKey:url]; - } - } -} - -// Upon successfully logging in, bind any Realm which was opened and registered to the user previously. -- (void)_bindAllDeferredRealms { - NSAssert(self.state == RLMSyncUserStateActive, - @"_bindAllDeferredRealms can't be called unless the user is logged in."); - for (NSURL *key in self.sessionsStorage) { - RLMSyncSession *session = self.sessionsStorage[key]; - RLMSessionBindingPackage *package = session.deferredBindingPackage; - if (session.state == RLMSyncSessionStateUnbound && package) { - [self _bindSessionWithLocalFileURL:package.fileURL - syncConfig:package.syncConfig - standalone:package.isStandalone - onCompletion:package.block]; - } - } - for (NSURL *key in self.loggedOutSessions) { - RLMSyncSession *session = self.loggedOutSessions[key]; - RLMSyncSessionHandle *handle = session.sessionHandle; - if ([handle sessionStillExists] && ![handle sessionIsInErrorState]) { - // If the session still exists, there's at least one strong reference to it somewhere. Revive it. - // This will start the login handshake if necessary. - [handle revive]; - } - self.sessionsStorage[key] = session; - } - self.loggedOutSessions = nil; -} - -- (void)_bindSessionWithDirectAccessToken:(RLMServerToken)accessToken - syncConfig:(RLMSyncConfiguration *)syncConfig - localFileURL:(NSURL *)fileURL - standalone:(BOOL)isStandalone - onCompletion:(RLMSyncBasicErrorReportingBlock)completion { - NSURL *realmURL = syncConfig.realmURL; - RLMSyncSession *session = self.sessionsStorage[realmURL]; - std::string file_path = [[fileURL path] UTF8String]; - std::string realm_url = [[realmURL absoluteString] UTF8String]; - - RLMSyncSessionHandle *sessionHandle; - auto underlyingSession = SyncManager::shared().get_session(file_path, syncConfig.rawConfiguration); - if (isStandalone) { - sessionHandle = [RLMSyncSessionHandle syncSessionHandleForPointer:underlyingSession]; - } else { - sessionHandle = [RLMSyncSessionHandle syncSessionHandleForWeakPointer:underlyingSession]; - } - [session configureWithAccessToken:accessToken - expiry:[[NSDate distantFuture] timeIntervalSince1970] - user:self - handle:sessionHandle]; - [session refreshAccessToken:accessToken serverURL:realmURL]; - - if (completion) { - bool success = session.state != RLMSyncSessionStateInvalid; - completion(success ? nil : [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorClientSessionError - userInfo:nil]); - } -} - -// Immediately begin the handshake to get the resolved remote path and the access token. -- (void)_bindSessionWithLocalFileURL:(NSURL *)fileURL - syncConfig:(RLMSyncConfiguration *)syncConfig - standalone:(BOOL)isStandalone - onCompletion:(RLMSyncBasicErrorReportingBlock)completion { - if (self.directAccessToken) { - /// Like with the normal authentication methods below, make binding asynchronous so we don't recursively - /// try to acquire the session lock. - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [self _bindSessionWithDirectAccessToken:self.directAccessToken - syncConfig:syncConfig - localFileURL:fileURL - standalone:isStandalone - onCompletion:completion]; - }); + auto sync_user = SyncManager::shared().get_user([identity UTF8String], [credentials.token UTF8String], none, true); + if (!sync_user) { + completion(nil, [NSError errorWithDomain:RLMSyncErrorDomain + code:RLMSyncErrorClientSessionError + userInfo:nil]); return; } - - NSURL *realmURL = syncConfig.realmURL; - RLMServerPath unresolvedPath = [realmURL path]; - NSDictionary *json = @{ - kRLMSyncPathKey: unresolvedPath, - kRLMSyncProviderKey: @"realm", - kRLMSyncDataKey: self.refreshToken, - kRLMSyncAppIDKey: [RLMSyncManager sharedManager].appID, - }; - - RLMSyncCompletionBlock handler = ^(NSError *error, NSDictionary *json) { - if (json && !error) { - RLMAuthResponseModel *model = [[RLMAuthResponseModel alloc] initWithDictionary:json - requireAccessToken:YES - requireRefreshToken:NO]; - if (!model) { - // Malformed JSON - error = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorBadResponse - userInfo:@{kRLMSyncErrorJSONKey: json}]; - if (completion) { - completion(error); - } - [[RLMSyncManager sharedManager] _fireError:error]; - return; - } else { - // Success - // For now, assume just one access token. - std::string file_path = [[fileURL path] UTF8String]; - RLMTokenModel *tokenModel = model.accessToken; - NSString *accessToken = tokenModel.token; - - // Register the Realm as being linked to this User. - RLMServerPath resolvedPath = tokenModel.tokenData.path; - RLMSyncSession *session = [self.sessionsStorage objectForKey:realmURL]; - session.resolvedPath = resolvedPath; - NSAssert(session, - @"Could not get a sync session object for the path '%@', this is an error", - unresolvedPath); - RLMSyncSessionHandle *sessionHandle; - auto underlyingSession = SyncManager::shared().get_session(file_path, syncConfig.rawConfiguration); - if (isStandalone) { - sessionHandle = [RLMSyncSessionHandle syncSessionHandleForPointer:underlyingSession]; - } else { - sessionHandle = [RLMSyncSessionHandle syncSessionHandleForWeakPointer:underlyingSession]; - } - [session configureWithAccessToken:accessToken - expiry:tokenModel.tokenData.expires - user:self - handle:sessionHandle]; - - // Bind the Realm - NSURLComponents *urlBuffer = [NSURLComponents componentsWithURL:realmURL resolvingAgainstBaseURL:YES]; - urlBuffer.path = resolvedPath; - NSURL *resolvedURL = [urlBuffer URL]; - if (!resolvedURL) { - @throw RLMException(@"Resolved path returned from the server was invalid (%@).", resolvedPath); - } - [session refreshAccessToken:accessToken serverURL:resolvedURL]; - - if (completion) { - bool success = session.state != RLMSyncSessionStateInvalid; - completion(success ? nil : [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorClientSessionError - userInfo:nil]); - } - } - } else { - // Something else went wrong - NSError *syncError = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorBadResponse - userInfo:@{kRLMSyncUnderlyingErrorKey: error}]; - if (completion) { - completion(syncError); - } - [[RLMSyncManager sharedManager] _fireError:syncError]; - } - }; - [RLMNetworkClient postRequestToEndpoint:RLMServerEndpointAuth - server:self.authenticationServer - JSON:json - completion:handler]; -} - -// A callback handler for a Realm, used to get an updated access token which can then be used to bind the Realm. -- (RLMSyncSession *)_registerSessionForBindingWithFileURL:(NSURL *)fileURL - syncConfig:(RLMSyncConfiguration *)syncConfig - standaloneSession:(BOOL)isStandalone - onCompletion:(nullable RLMSyncBasicErrorReportingBlock)completion { - NSURL *realmURL = syncConfig.realmURL; - if (RLMSyncSession *session = [self.sessionsStorage objectForKey:realmURL]) { - RLMSyncSessionHandle *handle = [session sessionHandle]; - // The Realm at this particular path has already been registered to this user. - if ([handle sessionStillExists]) { - [session _refresh]; - if (completion) { - completion(nil); - } - return session; - } else if ([handle sessionIsInErrorState]) { - // Prohibit registering an invalid session. - if (completion) { - NSError *error = [NSError errorWithDomain:RLMSyncErrorDomain - code:RLMSyncErrorClientSessionError - userInfo:nil]; - completion(error); - } - return nil; - } - } - - RLMSyncSession *session = [[RLMSyncSession alloc] initWithFileURL:fileURL realmURL:realmURL]; - self.sessionsStorage[realmURL] = session; - - if (self.state == RLMSyncUserStateLoggedOut) { - // We will delay the path resolution/access token handshake until the user logs in. - session.deferredBindingPackage = [[RLMSessionBindingPackage alloc] initWithFileURL:fileURL - syncConfig:syncConfig - standalone:isStandalone - block:completion]; - } else { - // User is logged in, start the handshake immediately. - [self _bindSessionWithLocalFileURL:fileURL - syncConfig:syncConfig - standalone:isStandalone - onCompletion:completion]; - } - return session; + user->_user = sync_user; + completion(user, nil); } @end diff --git a/Pods/Realm/Realm/RLMSyncUtil.mm b/Pods/Realm/Realm/RLMSyncUtil.mm index 879c9ba..e963cb4 100644 --- a/Pods/Realm/Realm/RLMSyncUtil.mm +++ b/Pods/Realm/Realm/RLMSyncUtil.mm @@ -19,6 +19,28 @@ #import #import "RLMSyncUtil_Private.hpp" +#import "RLMSyncUser_Private.hpp" +#import "RLMRealmConfiguration+Sync.h" +#import "RLMRealmConfiguration_Private.hpp" +#import "RLMSyncPermissionChange.h" + +@implementation RLMRealmConfiguration (RealmSync) ++ (instancetype)managementConfigurationForUser:(RLMSyncUser *)user { + NSURLComponents *components = [NSURLComponents componentsWithURL:user.authenticationServer resolvingAgainstBaseURL:NO]; + if ([components.scheme isEqualToString:@"https"]) { + components.scheme = @"realms"; + } else { + components.scheme = @"realm"; + } + components.path = @"/~/__management"; + NSURL *managementRealmURL = components.URL; + RLMSyncConfiguration *syncConfig = [[RLMSyncConfiguration alloc] initWithUser:user realmURL:managementRealmURL]; + RLMRealmConfiguration *config = [RLMRealmConfiguration new]; + config.syncConfiguration = syncConfig; + config.objectClasses = @[RLMSyncPermissionChange.class]; + return config; +} +@end RLMIdentityProvider const RLMIdentityProviderAccessToken = @"_access_token"; @@ -33,7 +55,6 @@ NSString *const kRLMSyncProviderKey = @"provider"; NSString *const kRLMSyncRegisterKey = @"register"; NSString *const kRLMSyncUnderlyingErrorKey = @"underlying_error"; -NSString *const kRLMSyncActionsKey = @"actions"; namespace realm { diff --git a/Pods/Realm/Realm/module.modulemap b/Pods/Realm/Realm/module.modulemap index 3d6c640..ef2d102 100644 --- a/Pods/Realm/Realm/module.modulemap +++ b/Pods/Realm/Realm/module.modulemap @@ -19,6 +19,7 @@ framework module Realm { header "RLMResults_Private.h" header "RLMSchema_Private.h" header "RLMSyncConfiguration_Private.h" + header "RLMSyncUtil_Private.h" } explicit module Dynamic { diff --git a/Pods/Realm/build.sh b/Pods/Realm/build.sh index 05704b3..5d344cd 100755 --- a/Pods/Realm/build.sh +++ b/Pods/Realm/build.sh @@ -284,14 +284,20 @@ fi # Downloading ###################################### +kill_object_server() { + (pgrep -f realm-object-server || true) | while read pid; do + kill $pid 2>/dev/null + done +} + download_object_server() { - local archive_name="realm-object-server-bundled_node_darwin-$REALM_OBJECT_SERVER_VERSION.tar.gz" - /usr/local/bin/s3cmd get --force "s3://realm-ci-artifacts/services-bundle/$REALM_OBJECT_SERVER_VERSION/$archive_name" + local archive_name="realm-object-server-bundled_node_darwin-developer-$REALM_OBJECT_SERVER_VERSION.tar.gz" + curl -L -O "https://static.realm.io/downloads/object-server/$archive_name" rm -rf sync mkdir sync - tar -C sync -xf $archive_name - rm $archive_name - echo "\nenterprise:\n skip_setup: true" >> "sync/object-server/configuration.yml" + tar xf $archive_name -C sync + rm $archive_name + cp Configuration/object-server-config.yml sync/object-server/configuration.yml touch "sync/object-server/do_not_open_browser" } @@ -394,15 +400,23 @@ case "$COMMAND" in ;; "start-object-server") - # kill any object servers that are still running - (pgrep -f realm-object-server || true) | while read pid; do - kill $pid - done + kill_object_server ./sync/start-object-server.command exit 0 ;; + "reset-object-server-between-tests") + # Leave the server files alone to avoid 'bad_server_ident' errors + rm -rf "~/Library/Application Support/xctest" + rm -rf "~/Library/Application Support/io.realm.TestHost" + rm -rf "~/Library/Application Support/xctest-child" + exit 0 + ;; + "reset-object-server") + kill_object_server + # Add a short delay, so file system doesn't complain about files in use + sleep 1 package="${source_root}/sync" for file in "$package"/realm-object-server-*; do if [ -d "$file" ]; then @@ -412,6 +426,7 @@ case "$COMMAND" in done rm -rf "$package/object-server/root_dir/" rm -rf "$package/object-server/temp_dir/" + sh build.sh reset-object-server-between-tests exit 0 ;; @@ -813,6 +828,7 @@ case "$COMMAND" in "verify-osx-object-server") sh build.sh download-object-server sh build.sh test-osx-object-server + sh build.sh reset-object-server exit 0 ;; @@ -849,6 +865,7 @@ case "$COMMAND" in xc "-workspace $workspace -scheme GroupedTableView -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" xc "-workspace $workspace -scheme RACTableView -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" xc "-workspace $workspace -scheme Encryption -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" + xc "-workspace $workspace -scheme Draw -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" if [ ! -z "${JENKINS_HOME}" ]; then xc "-workspace $workspace -scheme Extension -configuration $CONFIGURATION -destination 'name=iPhone 6' build ${CODESIGN_PARAMS}" @@ -983,10 +1000,11 @@ EOM mkdir -p include mv core/include include/core - mkdir -p include/impl/apple - mkdir -p include/util/apple + mkdir -p include/impl/apple include/util/apple include/sync/impl cp Realm/*.hpp include cp Realm/ObjectStore/src/*.hpp include + cp Realm/ObjectStore/src/sync/*.hpp include/sync + cp Realm/ObjectStore/src/sync/impl/*.hpp include/sync/impl cp Realm/ObjectStore/src/impl/*.hpp include/impl cp Realm/ObjectStore/src/impl/apple/*.hpp include/impl/apple cp Realm/ObjectStore/src/util/*.hpp include/util @@ -1030,12 +1048,13 @@ EOM export CONFIGURATION=$configuration export REALM_EXTRA_BUILD_ARGUMENTS='GCC_GENERATE_DEBUGGING_SYMBOLS=NO REALM_PREFIX_HEADER=Realm/RLMPrefix.h' sh build.sh prelaunch-simulator + rm ~/Library/Logs/CoreSimulator/CoreSimulator.log # Verify that no Realm files still exist ! find ~/Library/Developer/CoreSimulator/Devices/ -name '*.realm' | grep -q . failed=0 sh build.sh verify-$target 2>&1 | tee build/build.log | xcpretty -r junit -o build/reports/junit.xml || failed=1 - if [ "$failed" = "1" ] && cat build/build.log | grep -E 'DTXProxyChannel|DTXChannel|out of date and needs to be rebuilt'; then + if [ "$failed" = "1" ] && cat build/build.log | grep -E 'DTXProxyChannel|DTXChannel|out of date and needs to be rebuilt|operation never finished bootstrapping'; then echo "Known Xcode error detected. Running job again." failed=0 sh build.sh verify-$target | tee build/build.log | xcpretty -r junit -o build/reports/junit.xml || failed=1 @@ -1126,24 +1145,24 @@ EOM "package-ios-swift") cd tightdb_objc - for version in 2.2 2.3 3.0; do + for version in 2.2 2.3 3.0 3.0.1; do REALM_SWIFT_VERSION="$version" sh build.sh prelaunch-simulator REALM_SWIFT_VERSION="$version" sh build.sh ios-swift done cd build/ios - zip --symlinks -r realm-swift-framework-ios.zip swift-2.2 swift-2.3 swift-3.0 + zip --symlinks -r realm-swift-framework-ios.zip swift-2.2 swift-2.3 swift-3.0 swift-3.0.1 ;; "package-osx-swift") cd tightdb_objc - for version in 2.2 2.3 3.0; do + for version in 2.2 2.3 3.0 3.0.1; do REALM_SWIFT_VERSION="$version" sh build.sh prelaunch-simulator REALM_SWIFT_VERSION="$version" sh build.sh osx-swift done cd build/osx - zip --symlinks -r realm-swift-framework-osx.zip swift-2.2 swift-2.3 swift-3.0 + zip --symlinks -r realm-swift-framework-osx.zip swift-2.2 swift-2.3 swift-3.0 swift-3.0.1 ;; "package-watchos") @@ -1156,13 +1175,13 @@ EOM "package-watchos-swift") cd tightdb_objc - for version in 2.2 2.3 3.0; do + for version in 2.2 2.3 3.0 3.0.1; do REALM_SWIFT_VERSION="$version" sh build.sh prelaunch-simulator REALM_SWIFT_VERSION="$version" sh build.sh watchos-swift done cd build/watchos - zip --symlinks -r realm-swift-framework-watchos.zip swift-2.2 swift-2.3 swift-3.0 + zip --symlinks -r realm-swift-framework-watchos.zip swift-2.2 swift-2.3 swift-3.0 swift-3.0.1 ;; "package-tvos") @@ -1175,13 +1194,13 @@ EOM "package-tvos-swift") cd tightdb_objc - for version in 2.2 2.3 3.0; do + for version in 2.2 2.3 3.0 3.0.1; do REALM_SWIFT_VERSION="$version" sh build.sh prelaunch-simulator REALM_SWIFT_VERSION="$version" sh build.sh tvos-swift done cd build/tvos - zip --symlinks -r realm-swift-framework-tvos.zip swift-2.2 swift-2.3 swift-3.0 + zip --symlinks -r realm-swift-framework-tvos.zip swift-2.2 swift-2.3 swift-3.0 swift-3.0.1 ;; "package-release") @@ -1355,7 +1374,11 @@ EOF x.x.x Release notes (yyyy-MM-dd) ============================================================= -### API breaking changes +### Sync Breaking Changes (In Beta) + +* None. + +### API Breaking Changes * None. diff --git a/Pods/Realm/core/librealm-macosx.a b/Pods/Realm/core/librealm-macosx.a index e677c35..78760e9 100644 Binary files a/Pods/Realm/core/librealm-macosx.a and b/Pods/Realm/core/librealm-macosx.a differ diff --git a/Pods/Realm/include/RLMArray.h b/Pods/Realm/include/RLMArray.h index fc2ef9f..eed53cc 100644 --- a/Pods/Realm/include/RLMArray.h +++ b/Pods/Realm/include/RLMArray.h @@ -276,7 +276,7 @@ NS_ASSUME_NONNULL_BEGIN @return An `RLMResults` sorted by the specified properties. */ -- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties; +- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties; /// :nodoc: - (RLMObjectType)objectAtIndexedSubscript:(NSUInteger)index; diff --git a/Pods/Realm/include/RLMCollection_Private.hpp b/Pods/Realm/include/RLMCollection_Private.hpp index 3fd2691..9f58c97 100644 --- a/Pods/Realm/include/RLMCollection_Private.hpp +++ b/Pods/Realm/include/RLMCollection_Private.hpp @@ -53,8 +53,13 @@ class RLMClassInfo; count:(NSUInteger)len; @end +@interface RLMNotificationToken () +- (void)suppressNextNotification; +- (RLMRealm *)realm; +@end + @interface RLMCancellationToken : RLMNotificationToken -- (instancetype)initWithToken:(realm::NotificationToken)token; +- (instancetype)initWithToken:(realm::NotificationToken)token realm:(RLMRealm *)realm; @end @interface RLMCollectionChange () diff --git a/Pods/Realm/include/RLMConstants.h b/Pods/Realm/include/RLMConstants.h index a4f2693..5b7899d 100644 --- a/Pods/Realm/include/RLMConstants.h +++ b/Pods/Realm/include/RLMConstants.h @@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN #define RLM_EXTENSIBLE_STRING_ENUM_CASE_SWIFT_NAME(fully_qualified, _) NS_SWIFT_NAME(fully_qualified) #endif -#if __has_attribute(ns_error_domain) +#if __has_attribute(ns_error_domain) && (!__cplusplus || __cplusplus >= 201103L) #define RLM_ERROR_ENUM(type, name, domain) \ _Pragma("clang diagnostic push") \ _Pragma("clang diagnostic ignored \"-Wignored-attributes\"") \ diff --git a/Pods/Realm/include/RLMNetworkClient.h b/Pods/Realm/include/RLMNetworkClient.h index c72afed..bde6ecf 100644 --- a/Pods/Realm/include/RLMNetworkClient.h +++ b/Pods/Realm/include/RLMNetworkClient.h @@ -26,8 +26,8 @@ typedef NS_ENUM(NSUInteger, RLMServerEndpoint) { RLMServerEndpointAuth, RLMServerEndpointLogout, - RLMServerEndpointAddCredential, - RLMServerEndpointRemoveCredential, + RLMServerEndpointAddCredentials, + RLMServerEndpointRemoveCredentials, }; /** diff --git a/Pods/Realm/include/RLMObjectBase.h b/Pods/Realm/include/RLMObjectBase.h index 1ad1234..6b3271f 100644 --- a/Pods/Realm/include/RLMObjectBase.h +++ b/Pods/Realm/include/RLMObjectBase.h @@ -36,6 +36,8 @@ NS_ASSUME_NONNULL_BEGIN // Returns whether the class is included in the default set of classes managed by a Realm. + (BOOL)shouldIncludeInDefaultSchema; ++ (nullable NSString *)_realmObjectName; + @end NS_ASSUME_NONNULL_END diff --git a/Pods/Realm/include/RLMObjectSchema_Private.h b/Pods/Realm/include/RLMObjectSchema_Private.h index 45f3018..c2968cc 100644 --- a/Pods/Realm/include/RLMObjectSchema_Private.h +++ b/Pods/Realm/include/RLMObjectSchema_Private.h @@ -28,7 +28,10 @@ NS_ASSUME_NONNULL_BEGIN bool _isSwiftClass; } -// writable redecleration +/// The object type name reported to the object store and core. +@property (nonatomic, readonly) NSString *objectName; + +// writable redeclaration @property (nonatomic, readwrite, copy) NSArray *properties; @property (nonatomic, readwrite, assign) bool isSwiftClass; diff --git a/Pods/Realm/include/RLMRealm.h b/Pods/Realm/include/RLMRealm.h index d6fc933..b251b73 100644 --- a/Pods/Realm/include/RLMRealm.h +++ b/Pods/Realm/include/RLMRealm.h @@ -34,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN objects (for example, by using the same path or identifier) multiple times on a single thread within a single iteration of the run loop will normally return the same `RLMRealm` object. - + If you specifically want to ensure an `RLMRealm` instance is destroyed (for example, if you wish to open a Realm, check some property, and then possibly delete the Realm file and re-open it), place the code which uses @@ -61,7 +61,7 @@ NS_ASSUME_NONNULL_BEGIN default Realm is persisted as *default.realm* under the *Documents* directory of your Application on iOS, and in your application's *Application Support* directory on OS X. - + The default Realm is created using the default `RLMRealmConfiguration`, which can be changed via `+[RLMRealmConfiguration setDefaultConfiguration:]`. @@ -118,7 +118,7 @@ NS_ASSUME_NONNULL_BEGIN /** The type of a block to run whenever the data within the Realm is modified. - + @see `-[RLMRealm addNotificationBlock:]` */ typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *realm); @@ -130,10 +130,11 @@ typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *rea Notification handlers are called after each write transaction is committed, either on the current thread or other threads. - - Handler blocks are called on the same thread that they were added on, and may only be added on threads which are - currently within a run loop. Unless you are specifically creating and running a run loop on a background thread, this - will normally only be the main thread. + + Handler blocks are called on the same thread that they were added on, and may + only be added on threads which are currently within a run loop. Unless you are + specifically creating and running a run loop on a background thread, this will + normally only be the main thread. The block has the following definition: @@ -161,28 +162,40 @@ typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *rea /** Begins a write transaction on the Realm. - Only one write transaction can be open at a time. Write transactions cannot be - nested, and trying to begin a write transaction on a Realm which is - already in a write transaction will throw an exception. Calls to - `beginWriteTransaction` from `RLMRealm` instances in other threads will block - until the current write transaction completes. + Only one write transaction can be open at a time for each Realm file. Write + transactions cannot be nested, and trying to begin a write transaction on a + Realm which is already in a write transaction will throw an exception. Calls to + `beginWriteTransaction` from `RLMRealm` instances for the same Realm file in + other threads or other processes will block until the current write transaction + completes or is cancelled. Before beginning the write transaction, `beginWriteTransaction` updates the - `RLMRealm` instance to the latest Realm version, as if `refresh` had been called, and - generates notifications if applicable. This has no effect if the Realm - was already up to date. + `RLMRealm` instance to the latest Realm version, as if `refresh` had been + called, and generates notifications if applicable. This has no effect if the + Realm was already up to date. It is rarely a good idea to have write transactions span multiple cycles of the run loop, but if you do wish to do so you will need to ensure that the - Realm participating in the write transaction is kept alive until the write transaction - is committed. + Realm participating in the write transaction is kept alive until the write + transaction is committed. */ - (void)beginWriteTransaction; /** - Commits all write operations in the current write transaction, and ends the + Commits all write operations in the current write transaction, and ends the transaction. + After saving the changes, all notification blocks registered on this specific + `RLMRealm` instance are invoked synchronously. Notification blocks registered + on other threads or on collections are invoked asynchronously. If you do not + want to receive a specific notification for this write tranaction, see + `commitWriteTransactionWithoutNotifying:error:`. + + This method can fail if there is insufficient disk space available to save the + writes made, or due to unexpected i/o errors. This version of the method throws + an exception when errors occur. Use the version with a `NSError` out parameter + instead if you wish to handle errors. + @warning This method may only be called during a write transaction. */ - (void)commitWriteTransaction NS_SWIFT_UNAVAILABLE(""); @@ -191,6 +204,15 @@ typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *rea Commits all write operations in the current write transaction, and ends the transaction. + After saving the changes, all notification blocks registered on this specific + `RLMRealm` instance are invoked synchronously. Notification blocks registered + on other threads or on collections are invoked asynchronously. If you do not + want to receive a specific notification for this write tranaction, see + `commitWriteTransactionWithoutNotifying:error:`. + + This method can fail if there is insufficient disk space available to save the + writes made, or due to unexpected i/o errors. + @warning This method may only be called during a write transaction. @param error If an error occurs, upon return contains an `NSError` object @@ -201,6 +223,40 @@ typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *rea */ - (BOOL)commitWriteTransaction:(NSError **)error; +/** + Commits all write operations in the current write transaction, without + notifying specific notification blocks of the changes. + + After saving the changes, all notification blocks registered on this specific + `RLMRealm` instance are invoked synchronously. Notification blocks registered + on other threads or on collections are scheduled to be invoked asynchronously. + + You can skip notifiying specific notification blocks about the changes made + in this write transaction by passing in their associated notification tokens. + This is primarily useful when the write transaction is saving changes already + made in the UI and you do not want to have the notification block attempt to + re-apply the same changes. + + The tokens passed to this method must be for notifications for this specific + `RLMRealm` instance. Notifications for different threads cannot be skipped + using this method. + + This method can fail if there is insufficient disk space available to save the + writes made, or due to unexpected i/o errors. + + @warning This method may only be called during a write transaction. + + @param tokens An array of notification tokens which were returned from adding + callbacks which you do not want to be notified for the changes + made in this write transaction. + @param error If an error occurs, upon return contains an `NSError` object + that describes the problem. If you are not interested in + possible errors, pass in `NULL`. + + @return Whether the transaction succeeded. + */ +- (BOOL)commitWriteTransactionWithoutNotifying:(NSArray *)tokens error:(NSError **)error; + /** Reverts all writes made during the current write transaction and ends the transaction. @@ -224,23 +280,27 @@ typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *rea but re-running the query which provided `oldObject` will once again return the valid object. + KVO observers on any objects which were modified during the transaction will + be notified about the change back to their initial values, but no other + notifcations are produced by a cancelled write transaction. + @warning This method may only be called during a write transaction. */ - (void)cancelWriteTransaction; /** Performs actions contained within the given block inside a write transaction. - + @see `[RLMRealm transactionWithBlock:error:]` */ - (void)transactionWithBlock:(__attribute__((noescape)) void(^)(void))block NS_SWIFT_UNAVAILABLE(""); /** Performs actions contained within the given block inside a write transaction. - - Write transactions cannot be nested, and trying to execute a write transaction + + Write transactions cannot be nested, and trying to execute a write transaction on a Realm which is already participating in a write transaction will throw an - exception. Calls to `transactionWithBlock:` from `RLMRealm` instances in other + exception. Calls to `transactionWithBlock:` from `RLMRealm` instances in other threads will block until the current write transaction completes. Before beginning the write transaction, `transactionWithBlock:` updates the @@ -258,35 +318,42 @@ typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *rea - (BOOL)transactionWithBlock:(__attribute__((noescape)) void(^)(void))block error:(NSError **)error; /** - Updates the Realm and outstanding objects managed by the Realm to point to the most recent data. + Updates the Realm and outstanding objects managed by the Realm to point to the + most recent data. + + If the version of the Realm is actually changed, Realm and collection + notifications will be sent to reflect the changes. This may take some time, as + collection notifications are prepared on a background thread. As a result, + calling this method on the main thread is not advisable. - @return Whether there were any updates for the Realm. Note that `YES` may be returned even if no data actually - changed. + @return Whether there were any updates for the Realm. Note that `YES` may be + returned even if no data actually changed. */ - (BOOL)refresh; /** - Set this property to `YES` to automatically update this Realm when changes happen in other threads. + Set this property to `YES` to automatically update this Realm when changes + happen in other threads. If set to `YES` (the default), changes made on other threads will be reflected in this Realm on the next cycle of the run loop after the changes are committed. If set to `NO`, you must manually call `-refresh` on the Realm to update it to get the latest data. - Note that by default, background threads do not have an active run loop and you + Note that by default, background threads do not have an active run loop and you will need to manually call `-refresh` in order to update to the latest version, even if `autorefresh` is set to `YES`. - Even with this property enabled, you can still call `-refresh` at any time to update the - Realm before the automatic refresh would occur. + Even with this property enabled, you can still call `-refresh` at any time to + update the Realm before the automatic refresh would occur. - Notifications are sent when a write transaction is committed whether or not - automatic refreshing is enabled. + Write transactions will still always advance a Realm to the latest version and + produce local notifications on commit even if autorefresh is disabled. Disabling `autorefresh` on a Realm without any strong references to it will not - have any effect, and `autorefresh` will revert back to `YES` the next time the Realm is created. - This is normally irrelevant as it means that there is - nothing to refresh (as managed `RLMObject`s, `RLMArray`s, and `RLMResults` have strong + have any effect, and `autorefresh` will revert back to `YES` the next time the + Realm is created. This is normally irrelevant as it means that there is nothing + to refresh (as managed `RLMObject`s, `RLMArray`s, and `RLMResults` have strong references to the Realm that manages them), but it means that setting `RLMRealm.defaultRealm.autorefresh = NO` in `application:didFinishLaunchingWithOptions:` and only later storing Realm @@ -301,8 +368,9 @@ typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *rea The destination file cannot already exist. - Note that if this method is called from within a write transaction, the *current* data is written, not the data from - the point when the previous write transaction was committed. + Note that if this method is called from within a write transaction, the + *current* data is written, not the data from the point when the previous write + transaction was committed. @param fileURL Local URL to save the Realm to. @param key Optional 64-byte encryption key to encrypt the new file with. @@ -347,9 +415,9 @@ typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *rea Once added, this object is considered to be managed by the Realm. It can be retrieved using the `objectsWhere:` selectors on `RLMRealm` and on subclasses of `RLMObject`. - When added, all child relationships referenced by this object will also be added to + When added, all child relationships referenced by this object will also be added to the Realm if they are not already in it. - + If the object or any related objects are already being managed by a different Realm an exception will be thrown. Use `-[RLMObject createInRealm:withObject:]` to insert a copy of a managed object into a different Realm. @@ -379,8 +447,8 @@ typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *rea /** Adds or updates an existing object into the Realm. - - The object provided must have a designated primary key. If no objects exist in the Realm + + The object provided must have a designated primary key. If no objects exist in the Realm with the same primary key value, the object is inserted. Otherwise, the existing object is updated with any changed values. @@ -418,13 +486,13 @@ typedef void (^RLMNotificationBlock)(RLMNotification notification, RLMRealm *rea /** Deletes one or more objects from the Realm. - + This is the equivalent of calling `deleteObject:` for every object in a collection. @warning This method may only be called during a write transaction. @param array An `RLMArray`, `NSArray`, or `RLMResults` of `RLMObject`s (or subclasses) to be deleted. - + @see `deleteObject:` */ - (void)deleteObjects:(id)array; @@ -500,7 +568,7 @@ __deprecated_msg("Use `performMigrationForConfiguration:error:`") NS_REFINED_FOR /** A token which is returned from methods which subscribe to changes to a Realm. - Change subscriptions in Realm return an `RLMNotificationToken` instance, + Change subscriptions in Realm return an `RLMNotificationToken` instance, which can be used to unsubscribe from the changes. You must store a strong reference to the token for as long as you want to continue to receive notifications. When you wish to stop, call the `-stop` method. Notifications are also stopped if diff --git a/Pods/Realm/include/RLMRealm_Private.h b/Pods/Realm/include/RLMRealm_Private.h index dbfe320..c8ca2d2 100644 --- a/Pods/Realm/include/RLMRealm_Private.h +++ b/Pods/Realm/include/RLMRealm_Private.h @@ -47,8 +47,6 @@ void RLMRealmTranslateException(NSError **error); - (void)verifyThread; - (void)verifyNotificationsAreSupported; -+ (NSString *)writeableTemporaryPathForFile:(NSString *)fileName; - @end NS_ASSUME_NONNULL_END diff --git a/Pods/Realm/include/RLMResults.h b/Pods/Realm/include/RLMResults.h index d1226b0..82ff20c 100644 --- a/Pods/Realm/include/RLMResults.h +++ b/Pods/Realm/include/RLMResults.h @@ -174,7 +174,7 @@ NS_ASSUME_NONNULL_BEGIN @return An `RLMResults` sorted by the specified properties. */ -- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties; +- (RLMResults *)sortedResultsUsingDescriptors:(NSArray *)properties; #pragma mark - Notifications diff --git a/Pods/Realm/include/RLMSyncConfiguration.h b/Pods/Realm/include/RLMSyncConfiguration.h index 6999c2d..6181d91 100644 --- a/Pods/Realm/include/RLMSyncConfiguration.h +++ b/Pods/Realm/include/RLMSyncConfiguration.h @@ -31,16 +31,21 @@ NS_ASSUME_NONNULL_BEGIN /// The user to which the remote Realm belongs. @property (nonatomic, readonly) RLMSyncUser *user; -/// The URL of the remote Realm upon the Realm Object Server. +/** + The URL of the remote Realm upon the Realm Object Server. + + @warning The URL cannot end with `.realm`, `.realm.lock` or `.realm.management`. + */ @property (nonatomic, readonly) NSURL *realmURL; /** Create a sync configuration instance. @param user A `RLMSyncUser` that owns the Realm at the given URL. - @param url The full, unresolved URL to the Realm on the Realm Object Server. "Full" means that this URL is fully - qualified; e.g. `realm://example.org/~/path/to/my.realm`. "Unresolved" means the path should contain the - wildcard marker `~`. + @param url The unresolved absolute URL to the Realm on the Realm Object Server, e.g. + `realm://example.org/~/path/to/realm`. "Unresolved" means the path should + contain the wildcard marker `~`, which will automatically be filled in with + the user identity by the Realm Object Server. */ - (instancetype)initWithUser:(RLMSyncUser *)user realmURL:(NSURL *)url; diff --git a/Pods/Realm/include/RLMSyncConfiguration_Private.h b/Pods/Realm/include/RLMSyncConfiguration_Private.h index b55fa11..1001ae8 100644 --- a/Pods/Realm/include/RLMSyncConfiguration_Private.h +++ b/Pods/Realm/include/RLMSyncConfiguration_Private.h @@ -28,7 +28,7 @@ typedef NS_ENUM(NSUInteger, RLMSyncStopPolicy) { @interface RLMSyncConfiguration () -@property (nonatomic) RLMSyncStopPolicy stopPolicy; +@property (nonatomic, readwrite) RLMSyncStopPolicy stopPolicy; // Internal-only APIs @property (nullable, nonatomic) NSURL *customFileURL; diff --git a/Pods/Realm/include/RLMSyncCredential.h b/Pods/Realm/include/RLMSyncCredentials.h similarity index 57% rename from Pods/Realm/include/RLMSyncCredential.h rename to Pods/Realm/include/RLMSyncCredentials.h index 2537544..736429c 100644 --- a/Pods/Realm/include/RLMSyncCredential.h +++ b/Pods/Realm/include/RLMSyncCredentials.h @@ -22,16 +22,8 @@ NS_ASSUME_NONNULL_BEGIN -/// A token representing an identity provider's credential. -typedef NSString* RLMCredentialToken; - -/// An options type representing different account actions which can be associated with certain types of credentials. -typedef NS_OPTIONS(NSUInteger, RLMAuthenticationActions) { - /// Create a new Realm Object Server account. - RLMAuthenticationActionsCreateAccount = 1 << 0, - /// Use an existing Realm Object Server account. - RLMAuthenticationActionsUseExistingAccount = 1 << 1, -}; +/// A token representing an identity provider's credentials. +typedef NSString *RLMSyncCredentialsToken; /// A type representing the unique identifier of a Realm Object Server identity provider. typedef NSString *RLMIdentityProvider RLM_EXTENSIBLE_STRING_ENUM; @@ -54,60 +46,60 @@ extern RLMIdentityProvider const RLMIdentityProviderGoogle; extern RLMIdentityProvider const RLMIdentityProviderICloud; /** - An opaque credential representing a specific Realm Object Server user. + Opaque credentials representing a specific Realm Object Server user. */ -@interface RLMSyncCredential : NSObject +@interface RLMSyncCredentials : NSObject -/// An opaque credential token containing information that uniquely identifies a Realm Object Server user. -@property (nonatomic, readonly) RLMCredentialToken token; +/// An opaque credentials token containing information that uniquely identifies a Realm Object Server user. +@property (nonatomic, readonly) RLMSyncCredentialsToken token; -/// The name of the identity provider which generated the credential token. +/// The name of the identity provider which generated the credentials token. @property (nonatomic, readonly) RLMIdentityProvider provider; /// A dictionary containing additional pertinent information. In most cases this is automatically configured. @property (nonatomic, readonly) NSDictionary *userInfo; /** - Construct and return a credential from a Facebook account token. + Construct and return credentials from a Facebook account token. */ -+ (instancetype)credentialWithFacebookToken:(RLMCredentialToken)token; ++ (instancetype)credentialsWithFacebookToken:(RLMSyncCredentialsToken)token; /** - Construct and return a credential from a Google account token. + Construct and return credentials from a Google account token. */ -+ (instancetype)credentialWithGoogleToken:(RLMCredentialToken)token; ++ (instancetype)credentialsWithGoogleToken:(RLMSyncCredentialsToken)token; /** - Construct and return a credential from an iCloud account token. + Construct and return credentials from an iCloud account token. */ -+ (instancetype)credentialWithICloudToken:(RLMCredentialToken)token; ++ (instancetype)credentialsWithICloudToken:(RLMSyncCredentialsToken)token; /** - Construct and return a credential from a Realm Object Server username and password. + Construct and return credentials from a Realm Object Server username and password. */ -+ (instancetype)credentialWithUsername:(NSString *)username - password:(NSString *)password - actions:(RLMAuthenticationActions)actions; ++ (instancetype)credentialsWithUsername:(NSString *)username + password:(NSString *)password + register:(BOOL)shouldRegister; /** - Construct and return a special credential representing a token that can be directly used to open a Realm. The identity + Construct and return special credentials representing a token that can be directly used to open a Realm. The identity is used to uniquely identify the user across application launches. */ -+ (instancetype)credentialWithAccessToken:(RLMServerToken)accessToken identity:(NSString *)identity; ++ (instancetype)credentialsWithAccessToken:(RLMServerToken)accessToken identity:(NSString *)identity; /** - Construct and return a credential with a custom token string, identity provider string, and optional user info. In most + Construct and return credentials with a custom token string, identity provider string, and optional user info. In most cases, the convenience initializers should be used instead. */ -- (instancetype)initWithCustomToken:(RLMCredentialToken)token +- (instancetype)initWithCustomToken:(RLMSyncCredentialsToken)token provider:(RLMIdentityProvider)provider userInfo:(nullable NSDictionary *)userInfo NS_DESIGNATED_INITIALIZER; /// :nodoc: -- (instancetype)init __attribute__((unavailable("RLMSyncCredential cannot be created directly"))); +- (instancetype)init __attribute__((unavailable("RLMSyncCredentials cannot be created directly"))); /// :nodoc: -+ (instancetype)new __attribute__((unavailable("RLMSyncCredential cannot be created directly"))); ++ (instancetype)new __attribute__((unavailable("RLMSyncCredentials cannot be created directly"))); NS_ASSUME_NONNULL_END diff --git a/Pods/Realm/include/RLMSyncManager.h b/Pods/Realm/include/RLMSyncManager.h index a8b99a5..e2f559f 100644 --- a/Pods/Realm/include/RLMSyncManager.h +++ b/Pods/Realm/include/RLMSyncManager.h @@ -20,7 +20,7 @@ #import "RLMSyncUtil.h" -@class RLMSyncSession, RLMSyncConfiguration; +@class RLMSyncSession; /// An enum representing different levels of sync-related logging that can be configured. typedef NS_ENUM(NSUInteger, RLMSyncLogLevel) { @@ -72,12 +72,12 @@ typedef void(^RLMSyncErrorReportingBlock)(NSError *, RLMSyncSession * _Nullable) A reverse-DNS string uniquely identifying this application. In most cases this is automatically set by the SDK, and does not have to be explicitly configured. */ -@property (nonatomic) NSString *appID; +@property (nonatomic, copy) NSString *appID; /** Whether SSL certificate validation should be disabled. SSL certificate validation is ON by default. Setting this property after at least one synced Realm or standalone Session has been opened is a no-op. - + @warning NEVER disable certificate validation for clients and servers in production. */ @property (nonatomic) BOOL disableSSLValidation; @@ -89,7 +89,7 @@ typedef void(^RLMSyncErrorReportingBlock)(NSError *, RLMSyncSession * _Nullable) @property (nonatomic) RLMSyncLogLevel logLevel; /// The sole instance of the singleton. -+ (instancetype)sharedManager; ++ (instancetype)sharedManager NS_REFINED_FOR_SWIFT; /// :nodoc: - (instancetype)init __attribute__((unavailable("RLMSyncManager cannot be created directly"))); diff --git a/Pods/Realm/include/RLMSyncManager_Private.h b/Pods/Realm/include/RLMSyncManager_Private.h new file mode 100644 index 0000000..b704dab --- /dev/null +++ b/Pods/Realm/include/RLMSyncManager_Private.h @@ -0,0 +1,54 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// 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 "RLMSyncManager.h" + +#import "RLMSyncUtil_Private.h" + +typedef NS_ENUM(NSUInteger, RLMSyncSessionErrorKind) { + RLMSyncSessionErrorKindDebug, + RLMSyncSessionErrorKindSessionFatal, + RLMSyncSessionErrorKindAccessDenied, + RLMSyncSessionErrorKindUserFatal, +}; + +@class RLMSyncUser, RLMSyncConfiguration; + +// All private API methods are threadsafe and synchronized, unless denoted otherwise. Since they are expected to be +// called very infrequently, this should pose no issues. + +NS_ASSUME_NONNULL_BEGIN + +@interface RLMSyncManager () + +@property (nullable, nonatomic, copy) RLMSyncBasicErrorReportingBlock sessionCompletionNotifier; + +- (void)_fireError:(NSError *)error; + +- (void)_fireErrorWithCode:(int)errorCode + message:(NSString *)message + session:(RLMSyncSession *)session + errorClass:(RLMSyncSessionErrorKind)errorClass; + +- (NSArray *)_allUsers; + ++ (void)resetForTesting; + +NS_ASSUME_NONNULL_END + +@end diff --git a/Pods/Realm/include/RLMSyncManager_Private.hpp b/Pods/Realm/include/RLMSyncManager_Private.hpp deleted file mode 100644 index f1b6ad9..0000000 --- a/Pods/Realm/include/RLMSyncManager_Private.hpp +++ /dev/null @@ -1,76 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 Realm Inc. -// -// 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 "RLMSyncManager.h" - -#import "RLMSyncUtil_Private.h" - -#import "sync_config.hpp" -#import "sync_metadata.hpp" - -@class RLMSyncUser; - -// All private API methods are threadsafe and synchronized, unless denoted otherwise. Since they are expected to be -// called very infrequently, this should pose no issues. - -NS_ASSUME_NONNULL_BEGIN - -@interface RLMSyncManager () { - std::unique_ptr _metadata_manager; -} - -@property (nullable, nonatomic, copy) RLMSyncBasicErrorReportingBlock sessionCompletionNotifier; - -/** - Given a sync configuration, open and return a standalone session. - - If a standalone session was previously opened but encountered a fatal error, attempting to open an equivalent session - (by using the same configuration) will return `nil`. - */ -- (nullable RLMSyncSession *)sessionForSyncConfiguration:(RLMSyncConfiguration *)config NS_UNAVAILABLE; - -/// Reset the singleton instance, and any saved state. Only for use with Realm Object Store tests. -+ (void)_resetStateForTesting; - -- (void)_fireError:(NSError *)error; - -- (void)_fireErrorWithCode:(int)errorCode - message:(NSString *)message - session:(nullable RLMSyncSession *)session - errorClass:(realm::SyncSessionError)errorClass; - -// Note that this method doesn't need to be threadsafe, since all locking is coordinated internally. -- (realm::SyncMetadataManager&)_metadataManager; - -- (NSArray *)_allUsers; - -/** - Register a user. If an equivalent user has already been registered, the argument is not added to the store, and the - existing user is returned. Otherwise, the argument is added to the store and `nil` is returned. - - Precondition: registered user is in the `active` state (is valid). - */ -- (nullable RLMSyncUser *)_registerUser:(RLMSyncUser *)user; - -- (void)_deregisterLoggedOutUser:(RLMSyncUser *)user; - -- (nullable RLMSyncUser *)_userForIdentity:(NSString *)identity; - -NS_ASSUME_NONNULL_END - -@end diff --git a/Pods/Realm/include/RLMSyncPermissionChange.h b/Pods/Realm/include/RLMSyncPermissionChange.h new file mode 100644 index 0000000..9581afe --- /dev/null +++ b/Pods/Realm/include/RLMSyncPermissionChange.h @@ -0,0 +1,107 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// 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 +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@class RLMSyncUser; + +/// An enum representing the different states a sync management object can take. +typedef NS_ENUM(NSUInteger, RLMSyncManagementObjectStatus) { + /// The management object has not yet been processed by the object server. + RLMSyncManagementObjectStatusNotProcessed, + /// The operations encoded in the management object have been successfully + /// performed by the object server. + RLMSyncManagementObjectStatusSuccess, + /** + The operations encoded in the management object were not successfully + performed by the object server. + + Refer to the `statusCode` and `statusMessage` properties for more details + about the error. + */ + RLMSyncManagementObjectStatusError, +}; + +/** + This model is used for requesting changes to a Realm's permissions. + + It should be used in conjunction with an `RLMSyncUser`'s management Realm. + + See https://realm.io/docs/realm-object-server/#permissions for general + documentation. + */ +@interface RLMSyncPermissionChange : RLMObject + +/// The globally unique ID string of this permission change object. +@property (readonly) NSString *id; + +/// The date this object was initially created. +@property (readonly) NSDate *createdAt; + +/// The date this object was last modified. +@property (readonly) NSDate *updatedAt; + +/// The status code of the object that was processed by Realm Object Server. +@property (nullable, readonly) NSNumber *statusCode; + +/// An error or informational message, typically written to by the Realm Object Server. +@property (nullable, readonly) NSString *statusMessage; + +/// Sync management object status. +@property (readonly) RLMSyncManagementObjectStatus status; + +/// The remote URL to the realm. +@property (readonly) NSString *realmUrl; + +/// The identity of a user affected by this permission change. +@property (readonly) NSString *userId; + +/// Define read access. Set to `YES` or `NO` to update this value. Leave unset to preserve the existing setting. +@property (nullable, readonly) NSNumber *mayRead; +/// Define write access. Set to `YES` or `NO` to update this value. Leave unset to preserve the existing setting. +@property (nullable, readonly) NSNumber *mayWrite; +/// Define management access. Set to `YES` or `NO` to update this value. Leave unset to preserve the existing setting. +@property (nullable, readonly) NSNumber *mayManage; + +/** + Construct a permission change object used to change the access permissions for a user on a Realm. + + @param realmURL The Realm URL whose permissions settings should be changed. + Use `*` to change the permissions of all Realms managed by the management Realm's `RLMSyncUser`. + @param userID The user or users who should be granted these permission changes. + Use `*` to change the permissions for all users. + @param mayRead Define read access. Set to `YES` or `NO` to update this value. + Leave unset to preserve the existing setting. + @param mayWrite Define write access. Set to `YES` or `NO` to update this value. + Leave unset to preserve the existing setting. + @param mayManage Define management access. Set to `YES` or `NO` to update this value. + Leave unset to preserve the existing setting. + */ ++ (instancetype)permissionChangeWithRealmURL:(NSString *)realmURL + userID:(NSString *)userID + read:(nullable NSNumber *)mayRead + write:(nullable NSNumber *)mayWrite + manage:(nullable NSNumber *)mayManage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/Realm/include/RLMSyncPermissionChange_Private.h b/Pods/Realm/include/RLMSyncPermissionChange_Private.h new file mode 100644 index 0000000..df632bc --- /dev/null +++ b/Pods/Realm/include/RLMSyncPermissionChange_Private.h @@ -0,0 +1,39 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// 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 "RLMSyncPermissionChange.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface RLMSyncPermissionChange() + +@property (readwrite) NSString *id; +@property (readwrite) NSDate *createdAt; +@property (readwrite) NSDate *updatedAt; +@property (nullable, readwrite) NSNumber *statusCode; +@property (nullable, readwrite) NSString *statusMessage; +@property (readwrite) NSString *realmUrl; +@property (readwrite) NSString *userId; + +@property (nullable, readwrite) NSNumber *mayRead; +@property (nullable, readwrite) NSNumber *mayWrite; +@property (nullable, readwrite) NSNumber *mayManage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Pods/Realm/include/RLMSyncSession.h b/Pods/Realm/include/RLMSyncSession.h index 1232785..46c11e3 100644 --- a/Pods/Realm/include/RLMSyncSession.h +++ b/Pods/Realm/include/RLMSyncSession.h @@ -22,12 +22,10 @@ The current state of a sync session object. */ typedef NS_ENUM(NSUInteger, RLMSyncSessionState) { - /// The sync session is valid, but has not yet been bound to the Realm Object Server. - RLMSyncSessionStateUnbound, /// The sync session is bound to the Realm Object Server and communicating with it. RLMSyncSessionStateActive, - /// The sync session is logged out, but could be rebound to the Realm Object Server. - RLMSyncSessionStateLoggedOut, + /// The sync session is not currently communicating with the Realm Object Server. + RLMSyncSessionStateInactive, /// The sync session encountered an error and is invalid; it should be discarded. RLMSyncSessionStateInvalid }; @@ -49,11 +47,10 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) RLMSyncSessionState state; /// The Realm Object Server URL of the remote Realm this session corresponds to. -@property (nonatomic, readonly) NSURL *realmURL; +@property (nullable, nonatomic, readonly) NSURL *realmURL; -/// A reference to the user object owning the Realm this session corresponds to. If the session object is invalid, this -/// property may automatically be set to `nil`. -@property (nonatomic, weak, nullable, readonly) RLMSyncUser *parentUser; +/// The user that owns this session. +- (nullable RLMSyncUser *)parentUser; /// If the session is valid, return a sync configuration that can be used to open the Realm associated with this /// session. diff --git a/Pods/Realm/include/RLMSyncFileManager.h b/Pods/Realm/include/RLMSyncSessionRefreshHandle.hpp similarity index 59% rename from Pods/Realm/include/RLMSyncFileManager.h rename to Pods/Realm/include/RLMSyncSessionRefreshHandle.hpp index c7cba42..30be435 100644 --- a/Pods/Realm/include/RLMSyncFileManager.h +++ b/Pods/Realm/include/RLMSyncSessionRefreshHandle.hpp @@ -18,16 +18,23 @@ #import -@class RLMSyncUser; +#import + +namespace realm { +class SyncSession; +} -@interface RLMSyncFileManager : NSObject +@class RLMSyncUser; -NS_ASSUME_NONNULL_BEGIN +/// An object that handles refreshing a session's auth token periodically, as long as that session remains viable. +/// Intended for easy removal once the new auth system is in place. +@interface RLMSyncSessionRefreshHandle : NSObject -+ (NSURL *)fileURLForRawRealmURL:(NSURL *)url user:(RLMSyncUser *)user; -+ (NSURL *)fileURLForMetadata; -+ (BOOL)removeFilesForUserIdentity:(NSString *)identity error:(NSError * _Nullable* _Nullable)error; +- (instancetype)initWithFullURLPath:(NSString *)urlPath + user:(RLMSyncUser *)user + session:(std::shared_ptr)session; -NS_ASSUME_NONNULL_END +- (void)scheduleRefreshTimer:(NSTimeInterval)fireTime; +- (void)invalidate; @end diff --git a/Pods/Realm/include/RLMSyncSession_Private.h b/Pods/Realm/include/RLMSyncSession_Private.h deleted file mode 100644 index 63c1da8..0000000 --- a/Pods/Realm/include/RLMSyncSession_Private.h +++ /dev/null @@ -1,76 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2016 Realm Inc. -// -// 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 "RLMSyncSession.h" - -#import "RLMSyncConfiguration.h" -#import "RLMSyncUtil_Private.h" - -@class RLMSyncUser, RLMSyncSessionHandle; - -@interface RLMSessionBindingPackage : NSObject - -NS_ASSUME_NONNULL_BEGIN - -@property (nullable, nonatomic, copy) RLMSyncBasicErrorReportingBlock block; -@property (nonatomic) NSURL *fileURL; -@property (nonatomic) RLMSyncConfiguration *syncConfig; -@property (nonatomic) BOOL isStandalone; - -- (instancetype)initWithFileURL:(NSURL *)fileURL - syncConfig:(RLMSyncConfiguration *)syncConfig - standalone:(BOOL)isStandalone - block:(nullable RLMSyncBasicErrorReportingBlock)block; - -@end - -@interface RLMSyncSession () RLM_SYNC_UNINITIALIZABLE - -- (void)_refresh; -- (void)_logOut; -- (void)_invalidate; - -- (void)setState:(RLMSyncSessionState)state; - -/// The path on disk where the Realm file backing this synced Realm is stored. -@property (nonatomic) NSURL *fileURL; - -@property (nullable, nonatomic) RLMSessionBindingPackage *deferredBindingPackage; -@property (nullable, nonatomic) RLMServerPath resolvedPath; - -- (instancetype)initWithFileURL:(NSURL *)fileURL realmURL:(NSURL *)realmURL; - -#pragma mark - per-Realm access token API - -@property (nullable, nonatomic) RLMServerToken accessToken; -@property (nonatomic) NSTimeInterval accessTokenExpiry; - -@property (nonatomic) NSTimer *refreshTimer; - -- (nullable RLMSyncSessionHandle *)sessionHandle; - -- (void)configureWithAccessToken:(RLMServerToken)token - expiry:(NSTimeInterval)expiry - user:(RLMSyncUser *)user - handle:(RLMSyncSessionHandle *)session; - -- (void)refreshAccessToken:(NSString *)token serverURL:(nullable NSURL *)serverURL; - -NS_ASSUME_NONNULL_END - -@end diff --git a/Pods/Realm/include/RLMSyncSessionHandle.hpp b/Pods/Realm/include/RLMSyncSession_Private.hpp similarity index 63% rename from Pods/Realm/include/RLMSyncSessionHandle.hpp rename to Pods/Realm/include/RLMSyncSession_Private.hpp index 445cbae..084c7dc 100644 --- a/Pods/Realm/include/RLMSyncSessionHandle.hpp +++ b/Pods/Realm/include/RLMSyncSession_Private.hpp @@ -16,34 +16,20 @@ // //////////////////////////////////////////////////////////////////////////// -#import +#import "RLMSyncSession.h" + +#import "RLMSyncUtil_Private.h" #import namespace realm { -struct SyncSession; +class SyncSession; } NS_ASSUME_NONNULL_BEGIN -@interface RLMSyncSessionHandle : NSObject - -+ (instancetype)syncSessionHandleForWeakPointer:(std::shared_ptr)pointer; -+ (instancetype)syncSessionHandleForPointer:(std::shared_ptr)pointer; - -/// Whether the underlying session is in an unrecoverable error state. -- (BOOL)sessionIsInErrorState; - -/// Whether the underlying session still exists, if the session reference is weak. -- (BOOL)sessionStillExists; - -/// Inform the session that the user that owns it has logged out. -- (void)logOut; - -/// Refresh the access token for the session. -- (BOOL)refreshAccessToken:(NSString *)accessToken serverURL:(nullable NSURL *)serverURL; +@interface RLMSyncSession () RLM_SYNC_UNINITIALIZABLE -/// Revive the session. -- (void)revive; +- (instancetype)initWithSyncSession:(std::shared_ptr)session; /// Wait for pending uploads to complete or the session to expire, and dispatch the callback onto the specified queue. - (BOOL)waitForUploadCompletionOnQueue:(nullable dispatch_queue_t)queue callback:(void(^)(void))callback; diff --git a/Pods/Realm/include/RLMSyncUser.h b/Pods/Realm/include/RLMSyncUser.h index b9083b9..a14c043 100644 --- a/Pods/Realm/include/RLMSyncUser.h +++ b/Pods/Realm/include/RLMSyncUser.h @@ -18,13 +18,13 @@ #import -@class RLMSyncUser, RLMSyncCredential, RLMSyncSession, RLMRealm; +@class RLMSyncUser, RLMSyncCredentials, RLMSyncSession, RLMRealm; /** The state of the user object. */ typedef NS_ENUM(NSUInteger, RLMSyncUserState) { - /// The user is logged out. Call `authenticateWithCredential:...` with a valid credential to log the user back in. + /// The user is logged out. Call `logInWithCredentials:...` with valid credentials to log the user back in. RLMSyncUserStateLoggedOut, /// The user is logged in, and any Realms associated with it are syncing with the Realm Object Server. RLMSyncUserStateActive, @@ -47,15 +47,22 @@ NS_ASSUME_NONNULL_BEGIN */ @interface RLMSyncUser : NSObject -/** - An array of all valid, logged-in users. +/** + A dictionary of all valid, logged-in user identities corresponding to their `RLMSyncUser` objects. + */ ++ (NSDictionary *)allUsers NS_REFINED_FOR_SWIFT; + +/** + The logged-in user. `nil` if none exists. + + @warning Throws an exception if more than one logged-in user exists. */ -+ (NSArray *)all; ++ (nullable RLMSyncUser *)currentUser NS_REFINED_FOR_SWIFT; /** The unique Realm Object Server user ID string identifying this user. */ -@property (nonatomic, readonly) NSString *identity; +@property (nullable, nonatomic, readonly) NSString *identity; /** The URL of the authentication server this user will communicate with. @@ -68,22 +75,22 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) RLMSyncUserState state; /** - Create, log in, and asynchronously return a new user object, specifying a custom timeout for the network request. A - credential identifying the user must be passed in. The user becomes available in the completion block, at which point + Create, log in, and asynchronously return a new user object, specifying a custom timeout for the network request. + Credentials identifying the user must be passed in. The user becomes available in the completion block, at which point it is ready for use. */ -+ (void)authenticateWithCredential:(RLMSyncCredential *)credential - authServerURL:(NSURL *)authServerURL - timeout:(NSTimeInterval)timeout - onCompletion:(RLMUserCompletionBlock)completion NS_REFINED_FOR_SWIFT; ++ (void)logInWithCredentials:(RLMSyncCredentials *)credentials + authServerURL:(NSURL *)authServerURL + timeout:(NSTimeInterval)timeout + onCompletion:(RLMUserCompletionBlock)completion NS_REFINED_FOR_SWIFT; /** - Create, log in, and asynchronously return a new user object. A credential identifying the user must be passed in. The + Create, log in, and asynchronously return a new user object. Credentials identifying the user must be passed in. The user becomes available in the completion block, at which point it is ready for use. */ -+ (void)authenticateWithCredential:(RLMSyncCredential *)credential - authServerURL:(NSURL *)authServerURL - onCompletion:(RLMUserCompletionBlock)completion ++ (void)logInWithCredentials:(RLMSyncCredentials *)credentials + authServerURL:(NSURL *)authServerURL + onCompletion:(RLMUserCompletionBlock)completion NS_SWIFT_UNAVAILABLE("Use the full version of this API."); /** @@ -105,6 +112,14 @@ NS_SWIFT_UNAVAILABLE("Use the full version of this API."); */ - (NSArray *)allSessions; +/** + Returns an instance of the Management Realm owned by the user. + + This Realm can be used to control access permissions for Realms managed by the user. + This includes granting other users access to Realms. + */ +- (RLMRealm *)managementRealmWithError:(NSError **)error NS_REFINED_FOR_SWIFT; + /// :nodoc: - (instancetype)init __attribute__((unavailable("RLMSyncUser cannot be created directly"))); diff --git a/Pods/Realm/include/RLMSyncUser_Private.hpp b/Pods/Realm/include/RLMSyncUser_Private.hpp index 879e8c8..20d9f6d 100644 --- a/Pods/Realm/include/RLMSyncUser_Private.hpp +++ b/Pods/Realm/include/RLMSyncUser_Private.hpp @@ -21,37 +21,31 @@ #import "RLMSyncConfiguration.h" #import "RLMSyncUtil_Private.h" -#include "sync_config.hpp" -#include "sync_metadata.hpp" +#include "sync/sync_config.hpp" +#include "sync/impl/sync_metadata.hpp" @class RLMSyncConfiguration; +using namespace realm; + typedef void(^RLMFetchedRealmCompletionBlock)(NSError * _Nullable, RLMRealm * _Nullable, BOOL * _Nonnull); NS_ASSUME_NONNULL_BEGIN @interface RLMSyncUser () -@property (nullable, nonatomic) RLMServerToken refreshToken; +- (void)_bindSessionWithPath:(const std::string&)path + config:(const SyncConfig&)config + session:(std::shared_ptr)session + completion:(nullable RLMSyncBasicErrorReportingBlock)completion + isStandalone:(BOOL)standalone; -/// Create a user based on a `SyncUserMetadata` object. This method does NOT register the user to the sync manager's -/// user store. -- (instancetype)initWithMetadata:(realm::SyncUserMetadata)metadata; +- (instancetype)initWithSyncUser:(std::shared_ptr)user; +- (std::shared_ptr)_syncUser; +- (nullable NSString *)_refreshToken; -/** - Register a Realm to a user. - - @param fileURL The location of the file on disk where the local copy of the Realm will be saved. - @param completion An optional completion block. - */ -- (nullable RLMSyncSession *)_registerSessionForBindingWithFileURL:(NSURL *)fileURL - syncConfig:(RLMSyncConfiguration *)syncConfig - standaloneSession:(BOOL)isStandalone - onCompletion:(nullable RLMSyncBasicErrorReportingBlock)completion; +- (void)_unregisterRefreshHandleForURLPath:(NSString *)path; -- (void)setState:(RLMSyncUserState)state; -- (void)_deregisterSessionWithRealmURL:(NSURL *)realmURL; +@end NS_ASSUME_NONNULL_END - -@end diff --git a/Pods/Realm/include/RLMSyncUtil.h b/Pods/Realm/include/RLMSyncUtil.h index 080db25..62f436f 100644 --- a/Pods/Realm/include/RLMSyncUtil.h +++ b/Pods/Realm/include/RLMSyncUtil.h @@ -16,7 +16,7 @@ // //////////////////////////////////////////////////////////////////////////// -#import "RLMConstants.h" +#import /// A token originating from the Realm Object Server. typedef NSString* RLMServerToken; diff --git a/Pods/Realm/include/RLMSyncUtil_Private.h b/Pods/Realm/include/RLMSyncUtil_Private.h index 5a049c7..b85ef09 100644 --- a/Pods/Realm/include/RLMSyncUtil_Private.h +++ b/Pods/Realm/include/RLMSyncUtil_Private.h @@ -16,9 +16,12 @@ // //////////////////////////////////////////////////////////////////////////// -#import "RLMSyncUtil.h" +#import -#import "RLMSyncCredential.h" +#import +#import + +@class RLMSyncUser; typedef void(^RLMSyncCompletionBlock)(NSError * _Nullable, NSDictionary * _Nullable); typedef void(^RLMSyncBasicErrorReportingBlock)(NSError * _Nullable); @@ -27,6 +30,10 @@ typedef NSString* RLMServerPath; NS_ASSUME_NONNULL_BEGIN +@interface RLMRealmConfiguration (RealmSync) ++ (instancetype)managementConfigurationForUser:(RLMSyncUser *)user; +@end + extern RLMIdentityProvider const RLMIdentityProviderAccessToken; extern RLMIdentityProvider const RLMIdentityProviderRealm; @@ -39,7 +46,6 @@ extern NSString *const kRLMSyncPathKey; extern NSString *const kRLMSyncProviderKey; extern NSString *const kRLMSyncRegisterKey; extern NSString *const kRLMSyncUnderlyingErrorKey; -extern NSString *const kRLMSyncActionsKey; #define RLM_SYNC_UNINITIALIZABLE \ - (instancetype)init __attribute__((unavailable("This type cannot be created directly"))); \ diff --git a/Pods/Realm/include/RLMSyncUtil_Private.hpp b/Pods/Realm/include/RLMSyncUtil_Private.hpp index 3ad03f6..279207a 100644 --- a/Pods/Realm/include/RLMSyncUtil_Private.hpp +++ b/Pods/Realm/include/RLMSyncUtil_Private.hpp @@ -20,7 +20,7 @@ #import "RLMSyncConfiguration_Private.h" -#import "sync_manager.hpp" +#import "sync/sync_manager.hpp" namespace realm { diff --git a/Pods/Realm/include/Realm.h b/Pods/Realm/include/Realm.h index 9d568c2..fa299d6 100644 --- a/Pods/Realm/include/Realm.h +++ b/Pods/Realm/include/Realm.h @@ -30,8 +30,9 @@ #import #import #import -#import +#import #import +#import #import #import #import diff --git a/Pods/Realm/include/binding_context.hpp b/Pods/Realm/include/binding_context.hpp index 52985bb..be31a5c 100644 --- a/Pods/Realm/include/binding_context.hpp +++ b/Pods/Realm/include/binding_context.hpp @@ -54,7 +54,7 @@ namespace realm { // } // // // Override the did_change method to call each registered notification -// void did_change(std::vector const&, std::vector const&) override +// void did_change(std::vector const&, std::vector const&, bool) override // { // // Loop oddly so that unregistering a notification from within the // // registered function works @@ -102,7 +102,8 @@ class BindingContext { // requested or if the Realm is not actually in a read transaction, although // both vectors will be empty in that case. virtual void did_change(std::vector const& observers, - std::vector const& invalidated); + std::vector const& invalidated, + bool version_changed=true); // Change information for a single field of a row struct ColumnInfo { @@ -153,7 +154,7 @@ class BindingContext { }; inline void BindingContext::will_change(std::vector const&, std::vector const&) { } -inline void BindingContext::did_change(std::vector const&, std::vector const&) { } +inline void BindingContext::did_change(std::vector const&, std::vector const&, bool) { } } // namespace realm #endif /* BINDING_CONTEXT_HPP */ diff --git a/Pods/Realm/include/collection_notifications.hpp b/Pods/Realm/include/collection_notifications.hpp index 35515fa..06b5cae 100644 --- a/Pods/Realm/include/collection_notifications.hpp +++ b/Pods/Realm/include/collection_notifications.hpp @@ -44,6 +44,8 @@ struct NotificationToken { NotificationToken(NotificationToken const&) = delete; NotificationToken& operator=(NotificationToken const&) = delete; + void suppress_next(); + private: util::AtomicSharedPtr<_impl::CollectionNotifier> m_notifier; size_t m_token; diff --git a/Pods/Realm/include/core/realm/alloc.hpp b/Pods/Realm/include/core/realm/alloc.hpp index 95eab0e..97e4965 100644 --- a/Pods/Realm/include/core/realm/alloc.hpp +++ b/Pods/Realm/include/core/realm/alloc.hpp @@ -197,7 +197,10 @@ class Allocator { /// When opening an older database file, all DateTime columns will be /// automatically upgraded Timestamp columns. /// - /// 6 Introduced a new non-compatible structure for StringIndex + /// 6 Introduced a new structure for the StringIndex. Moved the commit + /// logs into the Realm file. Changes to the transaction log format + /// including reshuffling instructions. This is the format used in + /// milestone 2.0.0. /// /// IMPORTANT: When introducing a new file format version, be sure to review /// the file validity checks in AllocSlab::validate_buffer(), the file @@ -294,14 +297,26 @@ inline int_fast64_t from_ref(ref_type v) noexcept { // Check that v is divisible by 8 (64-bit aligned). REALM_ASSERT_DEBUG(v % 8 == 0); - return util::from_twos_compl(v); + + static_assert(std::is_same::value, + "If ref_type changes, from_ref and to_ref should probably be updated"); + + // Make sure that we preserve the bit pattern of the ref_type (without sign extension). + return util::from_twos_compl(uint_fast64_t(v)); } inline ref_type to_ref(int_fast64_t v) noexcept { - REALM_ASSERT_DEBUG(!util::int_cast_has_overflow(v)); // Check that v is divisible by 8 (64-bit aligned). REALM_ASSERT_DEBUG(v % 8 == 0); + + // C++11 standard, paragraph 4.7.2 [conv.integral]: + // If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source + // integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s + // complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is + // no truncation). — end note ] + static_assert(std::is_unsigned::value, + "If ref_type changes, from_ref and to_ref should probably be updated"); return ref_type(v); } diff --git a/Pods/Realm/include/core/realm/alloc_slab.hpp b/Pods/Realm/include/core/realm/alloc_slab.hpp index b80406d..34aa9b1 100644 --- a/Pods/Realm/include/core/realm/alloc_slab.hpp +++ b/Pods/Realm/include/core/realm/alloc_slab.hpp @@ -430,6 +430,8 @@ class SlabAlloc : public Allocator { mutable hash_entry cache[256]; mutable size_t version = 1; + /// Throws if free-lists are no longer valid. + void consolidate_free_read_only(); /// Throws if free-lists are no longer valid. const chunks& get_free_read_only() const; diff --git a/Pods/Realm/include/core/realm/array.hpp b/Pods/Realm/include/core/realm/array.hpp index 364446e..fdad46e 100644 --- a/Pods/Realm/include/core/realm/array.hpp +++ b/Pods/Realm/include/core/realm/array.hpp @@ -55,6 +55,7 @@ Searching: The main finding function is: #include #include #include +#include /* MMX: mmintrin.h @@ -105,65 +106,6 @@ const size_t max_array_payload = 0x00ffffffL; /// Alias for realm::npos. const size_t not_found = npos; -// clang-format off -/* wid == 16/32 likely when accessing offsets in B tree */ -#define REALM_TEMPEX(fun, wid, arg) \ - if (wid == 16) {fun<16> arg;} \ - else if (wid == 32) {fun<32> arg;} \ - else if (wid == 0) {fun<0> arg;} \ - else if (wid == 1) {fun<1> arg;} \ - else if (wid == 2) {fun<2> arg;} \ - else if (wid == 4) {fun<4> arg;} \ - else if (wid == 8) {fun<8> arg;} \ - else if (wid == 64) {fun<64> arg;} \ - else {REALM_ASSERT_DEBUG(false); fun<0> arg;} - -#define REALM_TEMPEX2(fun, targ, wid, arg) \ - if (wid == 16) {fun arg;} \ - else if (wid == 32) {fun arg;} \ - else if (wid == 0) {fun arg;} \ - else if (wid == 1) {fun arg;} \ - else if (wid == 2) {fun arg;} \ - else if (wid == 4) {fun arg;} \ - else if (wid == 8) {fun arg;} \ - else if (wid == 64) {fun arg;} \ - else {REALM_ASSERT_DEBUG(false); fun arg;} - -#define REALM_TEMPEX3(fun, targ1, targ2, wid, arg) \ - if (wid == 16) {fun arg;} \ - else if (wid == 32) {fun arg;} \ - else if (wid == 0) {fun arg;} \ - else if (wid == 1) {fun arg;} \ - else if (wid == 2) {fun arg;} \ - else if (wid == 4) {fun arg;} \ - else if (wid == 8) {fun arg;} \ - else if (wid == 64) {fun arg;} \ - else {REALM_ASSERT_DEBUG(false); fun arg;} - -#define REALM_TEMPEX4(fun, targ1, targ2, wid, targ3, arg) \ - if (wid == 16) {fun arg;} \ - else if (wid == 32) {fun arg;} \ - else if (wid == 0) {fun arg;} \ - else if (wid == 1) {fun arg;} \ - else if (wid == 2) {fun arg;} \ - else if (wid == 4) {fun arg;} \ - else if (wid == 8) {fun arg;} \ - else if (wid == 64) {fun arg;} \ - else {REALM_ASSERT_DEBUG(false); fun arg;} - -#define REALM_TEMPEX5(fun, targ1, targ2, targ3, targ4, wid, arg) \ - if (wid == 16) {fun arg;} \ - else if (wid == 32) {fun arg;} \ - else if (wid == 0) {fun arg;} \ - else if (wid == 1) {fun arg;} \ - else if (wid == 2) {fun arg;} \ - else if (wid == 4) {fun arg;} \ - else if (wid == 8) {fun arg;} \ - else if (wid == 64) {fun arg;} \ - else {REALM_ASSERT_DEBUG(false); fun arg;} -// clang-format on - - // Pre-definitions class Array; class StringColumn; @@ -226,6 +168,10 @@ class ArrayParent { friend class Array; }; +struct TreeInsertBase { + size_t m_split_offset; + size_t m_split_size; +}; /// Provides access to individual array nodes of the database. /// @@ -501,12 +447,6 @@ class Array : public ArrayParent { /// specified value. void ensure_minimum_width(int_fast64_t value); - typedef StringData (*StringGetter)(void*, size_t, char*); // Pre-declare getter function from string index - size_t index_string_find_first(StringData value, ColumnBase* column) const; - void index_string_find_all(IntegerColumn& result, StringData value, ColumnBase* column) const; - FindRes index_string_find_all_no_copy(StringData value, ColumnBase* column, InternalFindResult& result) const; - size_t index_string_count(StringData value, ColumnBase* column) const; - /// This one may change the represenation of the array, so be carefull if /// you call it after ensure_minimum_width(). void set_all_to_zero(); @@ -600,6 +540,7 @@ class Array : public ArrayParent { /// this \c Array, sorted in ascending order /// \return the index of the value if found, or realm::not_found otherwise size_t find_gte(const int64_t target, size_t start, size_t end = size_t(-1)) const; + void preset(int64_t min, int64_t max, size_t num_items); void preset(size_t bitwidth, size_t num_items); @@ -845,138 +786,6 @@ class Array : public ArrayParent { template bool find_gtlt(int64_t v, uint64_t chunk, QueryState* state, size_t baseindex, Callback callback) const; - - /// Get the number of elements in the B+-tree rooted at this array - /// node. The root must not be a leaf. - /// - /// Please avoid using this function (consider it deprecated). It - /// will have to be removed if we choose to get rid of the last - /// element of the main array of an inner B+-tree node that stores - /// the total number of elements in the subtree. The motivation - /// for removing it, is that it will significantly improve the - /// efficiency when inserting after, and erasing the last element. - size_t get_bptree_size() const noexcept; - - /// The root must not be a leaf. - static size_t get_bptree_size_from_header(const char* root_header) noexcept; - - - /// Find the leaf node corresponding to the specified element - /// index index. The specified element index must refer to an - /// element that exists in the tree. This function must be called - /// on an inner B+-tree node, never a leaf. Note that according to - /// invar:bptree-nonempty-inner and invar:bptree-nonempty-leaf, an - /// inner B+-tree node can never be empty. - /// - /// This function is not obliged to instantiate intermediate array - /// accessors. For this reason, this function cannot be used for - /// operations that modify the tree, as that requires an unbroken - /// chain of parent array accessors between the root and the - /// leaf. Thus, despite the fact that the returned MemRef object - /// appears to allow modification of the referenced memory, the - /// caller must handle the memory reference as if it was - /// const-qualified. - /// - /// \return (`leaf_header`, `ndx_in_leaf`) where `leaf_header` - /// points to the the header of the located leaf, and - /// `ndx_in_leaf` is the local index within that leaf - /// corresponding to the specified element index. - std::pair get_bptree_leaf(size_t elem_ndx) const noexcept; - - - class NodeInfo; - class VisitHandler; - - /// Visit leaves of the B+-tree rooted at this inner node, - /// starting with the leaf that contains the element at the - /// specified element index start offset, and ending when the - /// handler returns false. The specified element index offset must - /// refer to an element that exists in the tree. This function - /// must be called on an inner B+-tree node, never a leaf. Note - /// that according to invar:bptree-nonempty-inner and - /// invar:bptree-nonempty-leaf, an inner B+-tree node can never be - /// empty. - /// - /// \param elem_ndx_offset The start position (must be valid). - /// - /// \param elems_in_tree The total number of elements in the tree. - /// - /// \param handler The callback which will get called for each leaf. - /// - /// \return True if, and only if the handler has returned true for - /// all visited leafs. - bool visit_bptree_leaves(size_t elem_ndx_offset, size_t elems_in_tree, VisitHandler& handler); - - - class UpdateHandler; - - /// Call the handler for every leaf. This function must be called - /// on an inner B+-tree node, never a leaf. - void update_bptree_leaves(UpdateHandler&); - - /// Call the handler for the leaf that contains the element at the - /// specified index. This function must be called on an inner - /// B+-tree node, never a leaf. - void update_bptree_elem(size_t elem_ndx, UpdateHandler&); - - - class EraseHandler; - - /// Erase the element at the specified index in the B+-tree with - /// the specified root. When erasing the last element, you must - /// pass npos in place of the index. This function must be called - /// with a root that is an inner B+-tree node, never a leaf. - /// - /// This function is guaranteed to succeed (not throw) if the - /// specified element was inserted during the current transaction, - /// and no other modifying operation has been carried out since - /// then (noexcept:bptree-erase-alt). - /// - /// FIXME: ExceptionSafety: The exception guarantee explained - /// above is not as powerfull as we would like it to be. Here is - /// what we would like: This function is guaranteed to succeed - /// (not throw) if the specified element was inserted during the - /// current transaction (noexcept:bptree-erase). This must be true - /// even if the element is modified after insertion, and/or if - /// other elements are inserted or erased around it. There are two - /// aspects of the current design that stand in the way of this - /// guarantee: (A) The fact that the node accessor, that is cached - /// in the column accessor, has to be reallocated/reinstantiated - /// when the root switches between being a leaf and an inner - /// node. This problem would go away if we always cached the last - /// used leaf accessor in the column accessor instead. (B) The - /// fact that replacing one child ref with another can fail, - /// because it may require reallocation of memory to expand the - /// bit-width. This can be fixed in two ways: Either have the - /// inner B+-tree nodes always have a bit-width of 64, or allow - /// the root node to be discarded and the column ref to be set to - /// zero in Table::m_columns. - static void erase_bptree_elem(Array* root, size_t elem_ndx, EraseHandler&); - - - struct TreeInsertBase { - size_t m_split_offset; - size_t m_split_size; - }; - - template - struct TreeInsert : TreeInsertBase { - typename TreeTraits::value_type m_value; - bool m_nullable; - }; - - /// Same as bptree_insert() but insert after the last element. - template - ref_type bptree_append(TreeInsert& state); - - /// Insert an element into the B+-subtree rooted at this array - /// node. The element is inserted before the specified element - /// index. This function must be called on an inner B+-tree node, - /// never a leaf. If this inner node had to be split, this - /// function returns the `ref` of the new sibling. - template - ref_type bptree_insert(size_t elem_ndx, TreeInsert& state); - ref_type bptree_leaf_insert(size_t ndx, int64_t, TreeInsertBase& state); /// Get the specified element without the cost of constructing an @@ -1070,24 +879,6 @@ class Array : public ArrayParent { protected: typedef bool (*CallbackDummy)(int64_t); - /// Insert a new child after original. If the parent has to be - /// split, this function returns the `ref` of the new parent node. - ref_type insert_bptree_child(Array& offsets, size_t orig_child_ndx, ref_type new_sibling_ref, - TreeInsertBase& state); - - void ensure_bptree_offsets(Array& offsets); - void create_bptree_offsets(Array& offsets, int_fast64_t first_value); - - bool do_erase_bptree_elem(size_t elem_ndx, EraseHandler&); - - template - size_t from_list(StringData value, IntegerColumn& result, InternalFindResult& result_ref, - const IntegerColumn& rows, ColumnBase* column) const; - - template - size_t index_string(StringData value, IntegerColumn& result, - InternalFindResult& result_ref, ColumnBase* column) const; - protected: // Includes array header. Not necessarily 8-byte aligned. virtual size_t calc_byte_len(size_t num_items, size_t width) const; @@ -1260,65 +1051,6 @@ class Array : public ArrayParent { }; -class Array::NodeInfo { -public: - MemRef m_mem; - Array* m_parent; - size_t m_ndx_in_parent; - size_t m_offset, m_size; -}; - -class Array::VisitHandler { -public: - virtual bool visit(const NodeInfo& leaf_info) = 0; - virtual ~VisitHandler() noexcept - { - } -}; - - -class Array::UpdateHandler { -public: - virtual void update(MemRef, ArrayParent*, size_t leaf_ndx_in_parent, size_t elem_ndx_in_leaf) = 0; - virtual ~UpdateHandler() noexcept - { - } -}; - - -class Array::EraseHandler { -public: - /// If the specified leaf has more than one element, this function - /// must erase the specified element from the leaf and return - /// false. Otherwise, when the leaf has a single element, this - /// function must return true without modifying the leaf. If \a - /// elem_ndx_in_leaf is `npos`, it refers to the last element in - /// the leaf. The implementation of this function must be - /// exception safe. This function is guaranteed to be called at - /// most once during each execution of Array::erase_bptree_elem(), - /// and *exactly* once during each *successful* execution of - /// Array::erase_bptree_elem(). - virtual bool erase_leaf_elem(MemRef, ArrayParent*, size_t leaf_ndx_in_parent, size_t elem_ndx_in_leaf) = 0; - - virtual void destroy_leaf(MemRef leaf_mem) noexcept = 0; - - /// Must replace the current root with the specified leaf. The - /// implementation of this function must not destroy the - /// underlying root node, or any of its children, as that will be - /// done by Array::erase_bptree_elem(). The implementation of this - /// function must be exception safe. - virtual void replace_root_by_leaf(MemRef leaf_mem) = 0; - - /// Same as replace_root_by_leaf(), but must replace the root with - /// an empty leaf. Also, if this function is called during an - /// execution of Array::erase_bptree_elem(), it is guaranteed that - /// it will be preceeded by a call to erase_leaf_elem(). - virtual void replace_root_by_empty_leaf() = 0; - - virtual ~EraseHandler() noexcept - { - } -}; // Implementation: @@ -1819,17 +1551,21 @@ inline void Array::destroy_deep(MemRef mem, Allocator& alloc) noexcept inline void Array::adjust(size_t ndx, int_fast64_t diff) { - // FIXME: Should be optimized REALM_ASSERT_3(ndx, <=, m_size); - int_fast64_t v = get(ndx); - set(ndx, int64_t(v + diff)); // Throws + if (diff != 0) { + // FIXME: Should be optimized + int_fast64_t v = get(ndx); + set(ndx, int64_t(v + diff)); // Throws + } } inline void Array::adjust(size_t begin, size_t end, int_fast64_t diff) { - // FIXME: Should be optimized - for (size_t i = begin; i != end; ++i) - adjust(i, diff); // Throws + if (diff != 0) { + // FIXME: Should be optimized + for (size_t i = begin; i != end; ++i) + adjust(i, diff); // Throws + } } @@ -2210,159 +1946,6 @@ inline ref_type Array::get_child_ref(size_t child_ndx) const noexcept return get_as_ref(child_ndx); } -inline size_t Array::get_bptree_size() const noexcept -{ - REALM_ASSERT_DEBUG(is_inner_bptree_node()); - int_fast64_t v = back(); - return size_t(v / 2); // v = 1 + 2*total_elems_in_tree -} - -inline size_t Array::get_bptree_size_from_header(const char* root_header) noexcept -{ - REALM_ASSERT_DEBUG(get_is_inner_bptree_node_from_header(root_header)); - size_t root_size = get_size_from_header(root_header); - int_fast64_t v = get(root_header, root_size - 1); - return size_t(v / 2); // v = 1 + 2*total_elems_in_tree -} - -inline void Array::ensure_bptree_offsets(Array& offsets) -{ - int_fast64_t first_value = get(0); - if (first_value % 2 == 0) { - offsets.init_from_ref(to_ref(first_value)); - } - else { - create_bptree_offsets(offsets, first_value); // Throws - } - offsets.set_parent(this, 0); -} - - -template -ref_type Array::bptree_append(TreeInsert& state) -{ - // FIXME: Consider exception safety. Especially, how can the split - // be carried out in an exception safe manner? - // - // Can split be done as a separate preparation step, such that if - // the actual insert fails, the split will still have occured. - // - // Unfortunately, it requires a rather significant rearrangement - // of the insertion flow. Instead of returning the sibling ref - // from insert functions, the leaf-insert functions must instead - // call the special bptree_insert() function on the parent, which - // will then cascade the split towards the root as required. - // - // At each level where a split is required (starting at the leaf): - // - // 1. Create the new sibling. - // - // 2. Copy relevant entries over such that new sibling is in - // its final state. - // - // 3. Call Array::bptree_insert() on parent with sibling ref. - // - // 4. Rearrange entries in original sibling and truncate as - // required (must not throw). - // - // What about the 'offsets' array? It will always be - // present. Consider this carefully. - - REALM_ASSERT_DEBUG(size() >= 1 + 1 + 1); // At least one child - - ArrayParent& childs_parent = *this; - size_t child_ref_ndx = size() - 2; - ref_type child_ref = get_as_ref(child_ref_ndx), new_sibling_ref; - char* child_header = static_cast(m_alloc.translate(child_ref)); - - bool child_is_leaf = !get_is_inner_bptree_node_from_header(child_header); - if (child_is_leaf) { - size_t elem_ndx_in_child = npos; // Append - new_sibling_ref = TreeTraits::leaf_insert(MemRef(child_header, child_ref, m_alloc), childs_parent, - child_ref_ndx, m_alloc, elem_ndx_in_child, state); // Throws - } - else { - Array child(m_alloc); - child.init_from_mem(MemRef(child_header, child_ref, m_alloc)); - child.set_parent(&childs_parent, child_ref_ndx); - new_sibling_ref = child.bptree_append(state); // Throws - } - - if (REALM_LIKELY(!new_sibling_ref)) { - // +2 because stored value is 1 + 2*total_elems_in_subtree - adjust(size() - 1, +2); // Throws - return 0; // Child was not split, so parent was not split either - } - - Array offsets(m_alloc); - int_fast64_t first_value = get(0); - if (first_value % 2 == 0) { - // Offsets array is present (general form) - offsets.init_from_ref(to_ref(first_value)); - offsets.set_parent(this, 0); - } - size_t child_ndx = child_ref_ndx - 1; - return insert_bptree_child(offsets, child_ndx, new_sibling_ref, state); // Throws -} - - -template -ref_type Array::bptree_insert(size_t elem_ndx, TreeInsert& state) -{ - REALM_ASSERT_3(size(), >=, 1 + 1 + 1); // At least one child - - // Conversion to general form if in compact form. Since this - // conversion will occur from root to leaf, it will maintain - // invar:bptree-node-form. - Array offsets(m_alloc); - ensure_bptree_offsets(offsets); // Throws - - size_t child_ndx, elem_ndx_in_child; - if (elem_ndx == 0) { - // Optimization for prepend - child_ndx = 0; - elem_ndx_in_child = 0; - } - else { - // There is a choice to be made when the element is to be - // inserted between two subtrees. It can either be appended to - // the first subtree, or it can be prepended to the second - // one. We currently always append to the first subtree. It is - // essentially a matter of using the lower vs. the upper bound - // when searching through the offsets array. - child_ndx = offsets.lower_bound_int(elem_ndx); - REALM_ASSERT_3(child_ndx, <, size() - 2); - size_t elem_ndx_offset = child_ndx == 0 ? 0 : to_size_t(offsets.get(child_ndx - 1)); - elem_ndx_in_child = elem_ndx - elem_ndx_offset; - } - - ArrayParent& childs_parent = *this; - size_t child_ref_ndx = child_ndx + 1; - ref_type child_ref = get_as_ref(child_ref_ndx), new_sibling_ref; - char* child_header = static_cast(m_alloc.translate(child_ref)); - bool child_is_leaf = !get_is_inner_bptree_node_from_header(child_header); - if (child_is_leaf) { - REALM_ASSERT_3(elem_ndx_in_child, <=, REALM_MAX_BPNODE_SIZE); - new_sibling_ref = TreeTraits::leaf_insert(MemRef(child_header, child_ref, m_alloc), childs_parent, - child_ref_ndx, m_alloc, elem_ndx_in_child, state); // Throws - } - else { - Array child(m_alloc); - child.init_from_mem(MemRef(child_header, child_ref, m_alloc)); - child.set_parent(&childs_parent, child_ref_ndx); - new_sibling_ref = child.bptree_insert(elem_ndx_in_child, state); // Throws - } - - if (REALM_LIKELY(!new_sibling_ref)) { - // +2 because stored value is 1 + 2*total_elems_in_subtree - adjust(size() - 1, +2); // Throws - offsets.adjust(child_ndx, offsets.size(), +1); - return 0; // Child was not split, so parent was not split either - } - - return insert_bptree_child(offsets, child_ndx, new_sibling_ref, state); // Throws -} - //************************************************************************************* // Finding code * diff --git a/Pods/Realm/include/core/realm/array_direct.hpp b/Pods/Realm/include/core/realm/array_direct.hpp new file mode 100644 index 0000000..e337392 --- /dev/null +++ b/Pods/Realm/include/core/realm/array_direct.hpp @@ -0,0 +1,372 @@ +/************************************************************************* + * + * Copyright 2016 Realm Inc. + * + * 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 REALM_ARRAY_DIRECT_HPP +#define REALM_ARRAY_DIRECT_HPP + +#include +#include + +using namespace realm::util; + +// clang-format off +/* wid == 16/32 likely when accessing offsets in B tree */ +#define REALM_TEMPEX(fun, wid, arg) \ + if (wid == 16) {fun<16> arg;} \ + else if (wid == 32) {fun<32> arg;} \ + else if (wid == 0) {fun<0> arg;} \ + else if (wid == 1) {fun<1> arg;} \ + else if (wid == 2) {fun<2> arg;} \ + else if (wid == 4) {fun<4> arg;} \ + else if (wid == 8) {fun<8> arg;} \ + else if (wid == 64) {fun<64> arg;} \ + else {REALM_ASSERT_DEBUG(false); fun<0> arg;} + +#define REALM_TEMPEX2(fun, targ, wid, arg) \ + if (wid == 16) {fun arg;} \ + else if (wid == 32) {fun arg;} \ + else if (wid == 0) {fun arg;} \ + else if (wid == 1) {fun arg;} \ + else if (wid == 2) {fun arg;} \ + else if (wid == 4) {fun arg;} \ + else if (wid == 8) {fun arg;} \ + else if (wid == 64) {fun arg;} \ + else {REALM_ASSERT_DEBUG(false); fun arg;} + +#define REALM_TEMPEX3(fun, targ1, targ2, wid, arg) \ + if (wid == 16) {fun arg;} \ + else if (wid == 32) {fun arg;} \ + else if (wid == 0) {fun arg;} \ + else if (wid == 1) {fun arg;} \ + else if (wid == 2) {fun arg;} \ + else if (wid == 4) {fun arg;} \ + else if (wid == 8) {fun arg;} \ + else if (wid == 64) {fun arg;} \ + else {REALM_ASSERT_DEBUG(false); fun arg;} + +#define REALM_TEMPEX4(fun, targ1, targ2, wid, targ3, arg) \ + if (wid == 16) {fun arg;} \ + else if (wid == 32) {fun arg;} \ + else if (wid == 0) {fun arg;} \ + else if (wid == 1) {fun arg;} \ + else if (wid == 2) {fun arg;} \ + else if (wid == 4) {fun arg;} \ + else if (wid == 8) {fun arg;} \ + else if (wid == 64) {fun arg;} \ + else {REALM_ASSERT_DEBUG(false); fun arg;} + +#define REALM_TEMPEX5(fun, targ1, targ2, targ3, targ4, wid, arg) \ + if (wid == 16) {fun arg;} \ + else if (wid == 32) {fun arg;} \ + else if (wid == 0) {fun arg;} \ + else if (wid == 1) {fun arg;} \ + else if (wid == 2) {fun arg;} \ + else if (wid == 4) {fun arg;} \ + else if (wid == 8) {fun arg;} \ + else if (wid == 64) {fun arg;} \ + else {REALM_ASSERT_DEBUG(false); fun arg;} +// clang-format on + +namespace realm { + +// Direct access methods + +template +void set_direct(char* data, size_t ndx, int_fast64_t value) noexcept +{ + if (width == 0) { + REALM_ASSERT_DEBUG(value == 0); + return; + } + else if (width == 1) { + REALM_ASSERT_DEBUG(0 <= value && value <= 0x01); + size_t byte_ndx = ndx / 8; + size_t bit_ndx = ndx % 8; + typedef unsigned char uchar; + uchar* p = reinterpret_cast(data) + byte_ndx; + *p = uchar((*p & ~(0x01 << bit_ndx)) | (int(value) & 0x01) << bit_ndx); + } + else if (width == 2) { + REALM_ASSERT_DEBUG(0 <= value && value <= 0x03); + size_t byte_ndx = ndx / 4; + size_t bit_ndx = ndx % 4 * 2; + typedef unsigned char uchar; + uchar* p = reinterpret_cast(data) + byte_ndx; + *p = uchar((*p & ~(0x03 << bit_ndx)) | (int(value) & 0x03) << bit_ndx); + } + else if (width == 4) { + REALM_ASSERT_DEBUG(0 <= value && value <= 0x0F); + size_t byte_ndx = ndx / 2; + size_t bit_ndx = ndx % 2 * 4; + typedef unsigned char uchar; + uchar* p = reinterpret_cast(data) + byte_ndx; + *p = uchar((*p & ~(0x0F << bit_ndx)) | (int(value) & 0x0F) << bit_ndx); + } + else if (width == 8) { + REALM_ASSERT_DEBUG(std::numeric_limits::min() <= value && + value <= std::numeric_limits::max()); + *(reinterpret_cast(data) + ndx) = int8_t(value); + } + else if (width == 16) { + REALM_ASSERT_DEBUG(std::numeric_limits::min() <= value && + value <= std::numeric_limits::max()); + *(reinterpret_cast(data) + ndx) = int16_t(value); + } + else if (width == 32) { + REALM_ASSERT_DEBUG(std::numeric_limits::min() <= value && + value <= std::numeric_limits::max()); + *(reinterpret_cast(data) + ndx) = int32_t(value); + } + else if (width == 64) { + REALM_ASSERT_DEBUG(std::numeric_limits::min() <= value && + value <= std::numeric_limits::max()); + *(reinterpret_cast(data) + ndx) = int64_t(value); + } + else { + REALM_ASSERT_DEBUG(false); + } +} + +template +void fill_direct(char* data, size_t begin, size_t end, int_fast64_t value) noexcept +{ + for (size_t i = begin; i != end; ++i) + set_direct(data, i, value); +} + +template +int64_t get_direct(const char* data, size_t ndx) noexcept +{ + if (w == 0) { + return 0; + } + if (w == 1) { + size_t offset = ndx >> 3; + return (data[offset] >> (ndx & 7)) & 0x01; + } + if (w == 2) { + size_t offset = ndx >> 2; + return (data[offset] >> ((ndx & 3) << 1)) & 0x03; + } + if (w == 4) { + size_t offset = ndx >> 1; + return (data[offset] >> ((ndx & 1) << 2)) & 0x0F; + } + if (w == 8) { + return *reinterpret_cast(data + ndx); + } + if (w == 16) { + size_t offset = ndx * 2; + return *reinterpret_cast(data + offset); + } + if (w == 32) { + size_t offset = ndx * 4; + return *reinterpret_cast(data + offset); + } + if (w == 64) { + size_t offset = ndx * 8; + return *reinterpret_cast(data + offset); + } + REALM_ASSERT_DEBUG(false); + return int64_t(-1); +} + +inline int64_t get_direct(const char* data, size_t width, size_t ndx) noexcept +{ + REALM_TEMPEX(return get_direct, width, (data, ndx)); +} + + +template +inline std::pair get_two(const char* data, size_t ndx) noexcept +{ + return std::make_pair(to_size_t(get_direct(data, ndx + 0)), to_size_t(get_direct(data, ndx + 1))); +} + +inline std::pair get_two(const char* data, size_t width, size_t ndx) noexcept +{ + REALM_TEMPEX(return get_two, width, (data, ndx)); +} + + +template +inline void get_three(const char* data, size_t ndx, ref_type& v0, ref_type& v1, ref_type& v2) noexcept +{ + v0 = to_ref(get_direct(data, ndx + 0)); + v1 = to_ref(get_direct(data, ndx + 1)); + v2 = to_ref(get_direct(data, ndx + 2)); +} + +inline void get_three(const char* data, size_t width, size_t ndx, ref_type& v0, ref_type& v1, ref_type& v2) noexcept +{ + REALM_TEMPEX(get_three, width, (data, ndx, v0, v1, v2)); +} + + +// Lower/upper bound in sorted sequence +// ------------------------------------ +// +// 3 3 3 4 4 4 5 6 7 9 9 9 +// ^ ^ ^ ^ ^ +// | | | | | +// | | | | -- Lower and upper bound of 15 +// | | | | +// | | | -- Lower and upper bound of 8 +// | | | +// | | -- Upper bound of 4 +// | | +// | -- Lower bound of 4 +// | +// -- Lower and upper bound of 1 +// +// These functions are semantically identical to std::lower_bound() and +// std::upper_bound(). +// +// We currently use binary search. See for example +// http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary. +template +inline size_t lower_bound(const char* data, size_t size, int64_t value) noexcept +{ + // The binary search used here is carefully optimized. Key trick is to use a single + // loop controlling variable (size) instead of high/low pair, and to keep updates + // to size done inside the loop independent of comparisons. Further key to speed + // is to avoid branching inside the loop, using conditional moves instead. This + // provides robust performance for random searches, though predictable searches + // might be slightly faster if we used branches instead. The loop unrolling yields + // a final 5-20% speedup depending on circumstances. + + size_t low = 0; + + while (size >= 8) { + // The following code (at X, Y and Z) is 3 times manually unrolled instances of (A) below. + // These code blocks must be kept in sync. Meassurements indicate 3 times unrolling to give + // the best performance. See (A) for comments on the loop body. + // (X) + size_t half = size / 2; + size_t other_half = size - half; + size_t probe = low + half; + size_t other_low = low + other_half; + int64_t v = get_direct(data, probe); + size = half; + low = (v < value) ? other_low : low; + + // (Y) + half = size / 2; + other_half = size - half; + probe = low + half; + other_low = low + other_half; + v = get_direct(data, probe); + size = half; + low = (v < value) ? other_low : low; + + // (Z) + half = size / 2; + other_half = size - half; + probe = low + half; + other_low = low + other_half; + v = get_direct(data, probe); + size = half; + low = (v < value) ? other_low : low; + } + while (size > 0) { + // (A) + // To understand the idea in this code, please note that + // for performance, computation of size for the next iteration + // MUST be INDEPENDENT of the conditional. This allows the + // processor to unroll the loop as fast as possible, and it + // minimizes the length of dependence chains leading up to branches. + // Making the unfolding of the loop independent of the data being + // searched, also minimizes the delays incurred by branch + // mispredictions, because they can be determined earlier + // and the speculation corrected earlier. + + // Counterintuitive: + // To make size independent of data, we cannot always split the + // range at the theoretical optimal point. When we determine that + // the key is larger than the probe at some index K, and prepare + // to search the upper part of the range, you would normally start + // the search at the next index, K+1, to get the shortest range. + // We can only do this when splitting a range with odd number of entries. + // If there is an even number of entries we search from K instead of K+1. + // This potentially leads to redundant comparisons, but in practice we + // gain more performance by making the changes to size predictable. + + // if size is even, half and other_half are the same. + // if size is odd, half is one less than other_half. + size_t half = size / 2; + size_t other_half = size - half; + size_t probe = low + half; + size_t other_low = low + other_half; + int64_t v = get_direct(data, probe); + size = half; + // for max performance, the line below should compile into a conditional + // move instruction. Not all compilers do this. To maximize chance + // of succes, no computation should be done in the branches of the + // conditional. + low = (v < value) ? other_low : low; + }; + + return low; +} + +// See lower_bound() +template +inline size_t upper_bound(const char* data, size_t size, int64_t value) noexcept +{ + size_t low = 0; + while (size >= 8) { + size_t half = size / 2; + size_t other_half = size - half; + size_t probe = low + half; + size_t other_low = low + other_half; + int64_t v = get_direct(data, probe); + size = half; + low = (value >= v) ? other_low : low; + + half = size / 2; + other_half = size - half; + probe = low + half; + other_low = low + other_half; + v = get_direct(data, probe); + size = half; + low = (value >= v) ? other_low : low; + + half = size / 2; + other_half = size - half; + probe = low + half; + other_low = low + other_half; + v = get_direct(data, probe); + size = half; + low = (value >= v) ? other_low : low; + } + + while (size > 0) { + size_t half = size / 2; + size_t other_half = size - half; + size_t probe = low + half; + size_t other_low = low + other_half; + int64_t v = get_direct(data, probe); + size = half; + low = (value >= v) ? other_low : low; + }; + + return low; +} +} + +#endif /* ARRAY_TPL_HPP_ */ diff --git a/Pods/Realm/include/core/realm/bptree.hpp b/Pods/Realm/include/core/realm/bptree.hpp index 752facf..7a5195e 100644 --- a/Pods/Realm/include/core/realm/bptree.hpp +++ b/Pods/Realm/include/core/realm/bptree.hpp @@ -35,6 +35,146 @@ class BpTree; class ArrayInteger; class ArrayIntNull; +class BpTreeNode : public Array { +public: + using Array::Array; + /// Get the number of elements in the B+-tree rooted at this array + /// node. The root must not be a leaf. + /// + /// Please avoid using this function (consider it deprecated). It + /// will have to be removed if we choose to get rid of the last + /// element of the main array of an inner B+-tree node that stores + /// the total number of elements in the subtree. The motivation + /// for removing it, is that it will significantly improve the + /// efficiency when inserting after, and erasing the last element. + size_t get_bptree_size() const noexcept; + + /// The root must not be a leaf. + static size_t get_bptree_size_from_header(const char* root_header) noexcept; + + + /// Find the leaf node corresponding to the specified element + /// index index. The specified element index must refer to an + /// element that exists in the tree. This function must be called + /// on an inner B+-tree node, never a leaf. Note that according to + /// invar:bptree-nonempty-inner and invar:bptree-nonempty-leaf, an + /// inner B+-tree node can never be empty. + /// + /// This function is not obliged to instantiate intermediate array + /// accessors. For this reason, this function cannot be used for + /// operations that modify the tree, as that requires an unbroken + /// chain of parent array accessors between the root and the + /// leaf. Thus, despite the fact that the returned MemRef object + /// appears to allow modification of the referenced memory, the + /// caller must handle the memory reference as if it was + /// const-qualified. + /// + /// \return (`leaf_header`, `ndx_in_leaf`) where `leaf_header` + /// points to the the header of the located leaf, and + /// `ndx_in_leaf` is the local index within that leaf + /// corresponding to the specified element index. + std::pair get_bptree_leaf(size_t elem_ndx) const noexcept; + + + class NodeInfo; + class VisitHandler; + + /// Visit leaves of the B+-tree rooted at this inner node, + /// starting with the leaf that contains the element at the + /// specified element index start offset, and ending when the + /// handler returns false. The specified element index offset must + /// refer to an element that exists in the tree. This function + /// must be called on an inner B+-tree node, never a leaf. Note + /// that according to invar:bptree-nonempty-inner and + /// invar:bptree-nonempty-leaf, an inner B+-tree node can never be + /// empty. + /// + /// \param elem_ndx_offset The start position (must be valid). + /// + /// \param elems_in_tree The total number of elements in the tree. + /// + /// \param handler The callback which will get called for each leaf. + /// + /// \return True if, and only if the handler has returned true for + /// all visited leafs. + bool visit_bptree_leaves(size_t elem_ndx_offset, size_t elems_in_tree, VisitHandler& handler); + + + class UpdateHandler; + + /// Call the handler for every leaf. This function must be called + /// on an inner B+-tree node, never a leaf. + void update_bptree_leaves(UpdateHandler&); + + /// Call the handler for the leaf that contains the element at the + /// specified index. This function must be called on an inner + /// B+-tree node, never a leaf. + void update_bptree_elem(size_t elem_ndx, UpdateHandler&); + + + class EraseHandler; + + /// Erase the element at the specified index in the B+-tree with + /// the specified root. When erasing the last element, you must + /// pass npos in place of the index. This function must be called + /// with a root that is an inner B+-tree node, never a leaf. + /// + /// This function is guaranteed to succeed (not throw) if the + /// specified element was inserted during the current transaction, + /// and no other modifying operation has been carried out since + /// then (noexcept:bptree-erase-alt). + /// + /// FIXME: ExceptionSafety: The exception guarantee explained + /// above is not as powerfull as we would like it to be. Here is + /// what we would like: This function is guaranteed to succeed + /// (not throw) if the specified element was inserted during the + /// current transaction (noexcept:bptree-erase). This must be true + /// even if the element is modified after insertion, and/or if + /// other elements are inserted or erased around it. There are two + /// aspects of the current design that stand in the way of this + /// guarantee: (A) The fact that the node accessor, that is cached + /// in the column accessor, has to be reallocated/reinstantiated + /// when the root switches between being a leaf and an inner + /// node. This problem would go away if we always cached the last + /// used leaf accessor in the column accessor instead. (B) The + /// fact that replacing one child ref with another can fail, + /// because it may require reallocation of memory to expand the + /// bit-width. This can be fixed in two ways: Either have the + /// inner B+-tree nodes always have a bit-width of 64, or allow + /// the root node to be discarded and the column ref to be set to + /// zero in Table::m_columns. + static void erase_bptree_elem(BpTreeNode* root, size_t elem_ndx, EraseHandler&); + + template + struct TreeInsert : TreeInsertBase { + typename TreeTraits::value_type m_value; + bool m_nullable; + }; + + /// Same as bptree_insert() but insert after the last element. + template + ref_type bptree_append(TreeInsert& state); + + /// Insert an element into the B+-subtree rooted at this array + /// node. The element is inserted before the specified element + /// index. This function must be called on an inner B+-tree node, + /// never a leaf. If this inner node had to be split, this + /// function returns the `ref` of the new sibling. + template + ref_type bptree_insert(size_t elem_ndx, TreeInsert& state); + +protected: + /// Insert a new child after original. If the parent has to be + /// split, this function returns the `ref` of the new parent node. + ref_type insert_bptree_child(Array& offsets, size_t orig_child_ndx, ref_type new_sibling_ref, + TreeInsertBase& state); + + void ensure_bptree_offsets(Array& offsets); + void create_bptree_offsets(Array& offsets, int_fast64_t first_value); + + bool do_erase_bptree_elem(size_t elem_ndx, EraseHandler&); +}; + class BpTreeBase { public: struct unattached_tag { @@ -55,7 +195,9 @@ class BpTreeBase { const Array& root() const noexcept; Array& root() noexcept; bool root_is_leaf() const noexcept; - void introduce_new_root(ref_type new_sibling_ref, Array::TreeInsertBase& state, bool is_append); + BpTreeNode& root_as_node(); + const BpTreeNode& root_as_node() const; + void introduce_new_root(ref_type new_sibling_ref, TreeInsertBase& state, bool is_append); void replace_root(std::unique_ptr leaf); protected: @@ -70,7 +212,7 @@ class BpTreeBase { { } }; - static ref_type write_subtree(const Array& root, size_t slice_offset, size_t slice_size, size_t table_size, + static ref_type write_subtree(const BpTreeNode& root, size_t slice_offset, size_t slice_size, size_t table_size, SliceHandler&, _impl::OutputStream&); friend class ColumnBase; friend class ColumnBaseSimple; @@ -107,9 +249,15 @@ class BpTree : public BpTreeBase { BpTree(); explicit BpTree(BpTreeBase::unattached_tag); explicit BpTree(Allocator& alloc); - explicit BpTree(std::unique_ptr init_root) + REALM_DEPRECATED("Initialize with MemRef instead") explicit BpTree(std::unique_ptr init_root) : BpTreeBase(std::move(init_root)) { + + } + explicit BpTree(Allocator& alloc, MemRef mem) + : BpTreeBase(std::unique_ptr(new LeafType(alloc))) + { + init_from_mem(alloc, mem); } BpTree(BpTree&&) = default; BpTree& operator=(BpTree&&) = default; @@ -137,7 +285,7 @@ class BpTree : public BpTreeBase { size_t find_first(T value, size_t begin = 0, size_t end = npos) const; void find_all(IntegerColumn& out_indices, T value, size_t begin = 0, size_t end = npos) const; - static MemRef create_leaf(Array::Type, size_t size, T value, Allocator&); + static MemRef create_leaf(Array::Type leaf_type, size_t size, T value, Allocator&); /// See LeafInfo for information about what to put in the inout_leaf /// parameter. @@ -149,8 +297,8 @@ class BpTree : public BpTreeBase { /// and never directly through the specfied fallback accessor. void get_leaf(size_t ndx, size_t& out_ndx_in_leaf, LeafInfo& inout_leaf) const noexcept; - void update_each(Array::UpdateHandler&); - void update_elem(size_t, Array::UpdateHandler&); + void update_each(BpTreeNode::UpdateHandler&); + void update_elem(size_t, BpTreeNode::UpdateHandler&); void adjust(size_t ndx, T diff); void adjust(T diff); @@ -183,7 +331,68 @@ class BpTree : public BpTreeBase { struct LeafNullInserter; template - void bptree_insert(size_t row_ndx, Array::TreeInsert& state, size_t num_rows); + void bptree_insert(size_t row_ndx, BpTreeNode::TreeInsert& state, size_t num_rows); +}; + + +class BpTreeNode::NodeInfo { +public: + MemRef m_mem; + Array* m_parent; + size_t m_ndx_in_parent; + size_t m_offset, m_size; +}; + +class BpTreeNode::VisitHandler { +public: + virtual bool visit(const NodeInfo& leaf_info) = 0; + virtual ~VisitHandler() noexcept + { + } +}; + + +class BpTreeNode::UpdateHandler { +public: + virtual void update(MemRef, ArrayParent*, size_t leaf_ndx_in_parent, size_t elem_ndx_in_leaf) = 0; + virtual ~UpdateHandler() noexcept + { + } +}; + + +class BpTreeNode::EraseHandler { +public: + /// If the specified leaf has more than one element, this function + /// must erase the specified element from the leaf and return + /// false. Otherwise, when the leaf has a single element, this + /// function must return true without modifying the leaf. If \a + /// elem_ndx_in_leaf is `npos`, it refers to the last element in + /// the leaf. The implementation of this function must be + /// exception safe. This function is guaranteed to be called at + /// most once during each execution of Array::erase_bptree_elem(), + /// and *exactly* once during each *successful* execution of + /// Array::erase_bptree_elem(). + virtual bool erase_leaf_elem(MemRef, ArrayParent*, size_t leaf_ndx_in_parent, size_t elem_ndx_in_leaf) = 0; + + virtual void destroy_leaf(MemRef leaf_mem) noexcept = 0; + + /// Must replace the current root with the specified leaf. The + /// implementation of this function must not destroy the + /// underlying root node, or any of its children, as that will be + /// done by Array::erase_bptree_elem(). The implementation of this + /// function must be exception safe. + virtual void replace_root_by_leaf(MemRef leaf_mem) = 0; + + /// Same as replace_root_by_leaf(), but must replace the root with + /// an empty leaf. Also, if this function is called during an + /// execution of Array::erase_bptree_elem(), it is guaranteed that + /// it will be preceeded by a call to erase_leaf_elem(). + virtual void replace_root_by_empty_leaf() = 0; + + virtual ~EraseHandler() noexcept + { + } }; @@ -220,6 +429,21 @@ inline bool BpTreeBase::root_is_leaf() const noexcept return !m_root->is_inner_bptree_node(); } +inline BpTreeNode& BpTreeBase::root_as_node() +{ + REALM_ASSERT_DEBUG(!root_is_leaf()); + REALM_ASSERT_DEBUG(dynamic_cast(m_root.get()) != nullptr); + return static_cast(root()); +} + +inline const BpTreeNode& BpTreeBase::root_as_node() const +{ + Array* arr = m_root.get(); + REALM_ASSERT_DEBUG(!root_is_leaf()); + REALM_ASSERT_DEBUG(dynamic_cast(arr) != nullptr); + return static_cast(*arr); +} + inline void BpTreeBase::set_parent(ArrayParent* parent, size_t ndx_in_parent) noexcept { m_root->set_parent(parent, ndx_in_parent); @@ -255,6 +479,159 @@ inline Array& BpTreeBase::root() noexcept return *m_root; } +inline size_t BpTreeNode::get_bptree_size() const noexcept +{ + REALM_ASSERT_DEBUG(is_inner_bptree_node()); + int_fast64_t v = back(); + return size_t(v / 2); // v = 1 + 2*total_elems_in_tree +} + +inline size_t BpTreeNode::get_bptree_size_from_header(const char* root_header) noexcept +{ + REALM_ASSERT_DEBUG(get_is_inner_bptree_node_from_header(root_header)); + size_t root_size = get_size_from_header(root_header); + int_fast64_t v = get(root_header, root_size - 1); + return size_t(v / 2); // v = 1 + 2*total_elems_in_tree +} + +inline void BpTreeNode::ensure_bptree_offsets(Array& offsets) +{ + int_fast64_t first_value = get(0); + if (first_value % 2 == 0) { + offsets.init_from_ref(to_ref(first_value)); + } + else { + create_bptree_offsets(offsets, first_value); // Throws + } + offsets.set_parent(this, 0); +} + + +template +ref_type BpTreeNode::bptree_append(TreeInsert& state) +{ + // FIXME: Consider exception safety. Especially, how can the split + // be carried out in an exception safe manner? + // + // Can split be done as a separate preparation step, such that if + // the actual insert fails, the split will still have occured. + // + // Unfortunately, it requires a rather significant rearrangement + // of the insertion flow. Instead of returning the sibling ref + // from insert functions, the leaf-insert functions must instead + // call the special bptree_insert() function on the parent, which + // will then cascade the split towards the root as required. + // + // At each level where a split is required (starting at the leaf): + // + // 1. Create the new sibling. + // + // 2. Copy relevant entries over such that new sibling is in + // its final state. + // + // 3. Call Array::bptree_insert() on parent with sibling ref. + // + // 4. Rearrange entries in original sibling and truncate as + // required (must not throw). + // + // What about the 'offsets' array? It will always be + // present. Consider this carefully. + + REALM_ASSERT_DEBUG(size() >= 1 + 1 + 1); // At least one child + + ArrayParent& childs_parent = *this; + size_t child_ref_ndx = size() - 2; + ref_type child_ref = get_as_ref(child_ref_ndx), new_sibling_ref; + char* child_header = static_cast(m_alloc.translate(child_ref)); + + bool child_is_leaf = !get_is_inner_bptree_node_from_header(child_header); + if (child_is_leaf) { + size_t elem_ndx_in_child = npos; // Append + new_sibling_ref = TreeTraits::leaf_insert(MemRef(child_header, child_ref, m_alloc), childs_parent, + child_ref_ndx, m_alloc, elem_ndx_in_child, state); // Throws + } + else { + BpTreeNode child(m_alloc); + child.init_from_mem(MemRef(child_header, child_ref, m_alloc)); + child.set_parent(&childs_parent, child_ref_ndx); + new_sibling_ref = child.bptree_append(state); // Throws + } + + if (REALM_LIKELY(!new_sibling_ref)) { + // +2 because stored value is 1 + 2*total_elems_in_subtree + adjust(size() - 1, +2); // Throws + return 0; // Child was not split, so parent was not split either + } + + Array offsets(m_alloc); + int_fast64_t first_value = get(0); + if (first_value % 2 == 0) { + // Offsets array is present (general form) + offsets.init_from_ref(to_ref(first_value)); + offsets.set_parent(this, 0); + } + size_t child_ndx = child_ref_ndx - 1; + return insert_bptree_child(offsets, child_ndx, new_sibling_ref, state); // Throws +} + + +template +ref_type BpTreeNode::bptree_insert(size_t elem_ndx, TreeInsert& state) +{ + REALM_ASSERT_3(size(), >=, 1 + 1 + 1); // At least one child + + // Conversion to general form if in compact form. Since this + // conversion will occur from root to leaf, it will maintain + // invar:bptree-node-form. + Array offsets(m_alloc); + ensure_bptree_offsets(offsets); // Throws + + size_t child_ndx, elem_ndx_in_child; + if (elem_ndx == 0) { + // Optimization for prepend + child_ndx = 0; + elem_ndx_in_child = 0; + } + else { + // There is a choice to be made when the element is to be + // inserted between two subtrees. It can either be appended to + // the first subtree, or it can be prepended to the second + // one. We currently always append to the first subtree. It is + // essentially a matter of using the lower vs. the upper bound + // when searching through the offsets array. + child_ndx = offsets.lower_bound_int(elem_ndx); + REALM_ASSERT_3(child_ndx, <, size() - 2); + size_t elem_ndx_offset = child_ndx == 0 ? 0 : to_size_t(offsets.get(child_ndx - 1)); + elem_ndx_in_child = elem_ndx - elem_ndx_offset; + } + + ArrayParent& childs_parent = *this; + size_t child_ref_ndx = child_ndx + 1; + ref_type child_ref = get_as_ref(child_ref_ndx), new_sibling_ref; + char* child_header = static_cast(m_alloc.translate(child_ref)); + bool child_is_leaf = !get_is_inner_bptree_node_from_header(child_header); + if (child_is_leaf) { + REALM_ASSERT_3(elem_ndx_in_child, <=, REALM_MAX_BPNODE_SIZE); + new_sibling_ref = TreeTraits::leaf_insert(MemRef(child_header, child_ref, m_alloc), childs_parent, + child_ref_ndx, m_alloc, elem_ndx_in_child, state); // Throws + } + else { + BpTreeNode child(m_alloc); + child.init_from_mem(MemRef(child_header, child_ref, m_alloc)); + child.set_parent(&childs_parent, child_ref_ndx); + new_sibling_ref = child.bptree_insert(elem_ndx_in_child, state); // Throws + } + + if (REALM_LIKELY(!new_sibling_ref)) { + // +2 because stored value is 1 + 2*total_elems_in_subtree + adjust(size() - 1, +2); // Throws + offsets.adjust(child_ndx, offsets.size(), +1); + return 0; // Child was not split, so parent was not split either + } + + return insert_bptree_child(offsets, child_ndx, new_sibling_ref, state); // Throws +} + template BpTree::BpTree() : BpTree(Allocator::get_default()) @@ -294,7 +671,7 @@ std::unique_ptr BpTree::create_root_from_mem(Allocator& alloc, MemRef // Not reusing root note, allocating a new one. if (is_inner_bptree_node) { - new_root.reset(new Array{alloc}); + new_root.reset(new BpTreeNode{alloc}); new_root->init_from_mem(mem); } else { @@ -330,11 +707,16 @@ template void BpTree::init_from_parent() { ref_type ref = root().get_ref_from_parent(); - ArrayParent* parent = m_root->get_parent(); - size_t ndx_in_parent = m_root->get_ndx_in_parent(); - auto new_root = create_root_from_ref(get_alloc(), ref); - new_root->set_parent(parent, ndx_in_parent); - m_root = std::move(new_root); + if (ref) { + ArrayParent* parent = m_root->get_parent(); + size_t ndx_in_parent = m_root->get_ndx_in_parent(); + auto new_root = create_root_from_ref(get_alloc(), ref); + new_root->set_parent(parent, ndx_in_parent); + m_root = std::move(new_root); + } + else { + m_root->detach(); + } } template @@ -359,7 +741,7 @@ size_t BpTree::size() const noexcept if (root_is_leaf()) { return root_as_leaf().size(); } - return root().get_bptree_size(); + return root_as_node().get_bptree_size(); } template @@ -423,7 +805,7 @@ T BpTree::get(size_t ndx) const noexcept } // Use direct getter to avoid initializing leaf array: - std::pair p = root().get_bptree_leaf(ndx); + std::pair p = root_as_node().get_bptree_leaf(ndx); const char* leaf_header = p.first.get_addr(); size_t ndx_in_leaf = p.second; return LeafType::get(leaf_header, ndx_in_leaf); @@ -431,7 +813,7 @@ T BpTree::get(size_t ndx) const noexcept template template -void BpTree::bptree_insert(size_t row_ndx, Array::TreeInsert& state, size_t num_rows) +void BpTree::bptree_insert(size_t row_ndx, BpTreeNode::TreeInsert& state, size_t num_rows) { ref_type new_sibling_ref; for (size_t i = 0; i < num_rows; ++i) { @@ -442,10 +824,10 @@ void BpTree::bptree_insert(size_t row_ndx, Array::TreeInsert& sta } else { if (row_ndx_2 == realm::npos) { - new_sibling_ref = root().bptree_append(state); // Throws + new_sibling_ref = root_as_node().bptree_append(state); // Throws } else { - new_sibling_ref = root().bptree_insert(row_ndx_2, state); // Throws + new_sibling_ref = root_as_node().bptree_insert(row_ndx_2, state); // Throws } } @@ -467,7 +849,7 @@ struct BpTree::LeafValueInserter { // TreeTraits concept: static ref_type leaf_insert(MemRef leaf_mem, ArrayParent& parent, size_t ndx_in_parent, Allocator& alloc, - size_t ndx_in_leaf, Array::TreeInsert& state) + size_t ndx_in_leaf, BpTreeNode::TreeInsert& state) { LeafType leaf{alloc}; leaf.init_from_mem(leaf_mem); @@ -483,7 +865,7 @@ struct BpTree::LeafNullInserter { using value_type = null; // TreeTraits concept: static ref_type leaf_insert(MemRef leaf_mem, ArrayParent& parent, size_t ndx_in_parent, Allocator& alloc, - size_t ndx_in_leaf, Array::TreeInsert& state) + size_t ndx_in_leaf, BpTreeNode::TreeInsert& state) { LeafType leaf{alloc}; leaf.init_from_mem(leaf_mem); @@ -496,14 +878,14 @@ template void BpTree::insert(size_t row_ndx, T value, size_t num_rows) { REALM_ASSERT_DEBUG(row_ndx == npos || row_ndx < size()); - Array::TreeInsert inserter; + BpTreeNode::TreeInsert inserter; inserter.m_value = std::move(value); inserter.m_nullable = std::is_same>::value; // FIXME bptree_insert(row_ndx, inserter, num_rows); // Throws } template -struct BpTree::UpdateHandler : Array::UpdateHandler { +struct BpTree::UpdateHandler : BpTreeNode::UpdateHandler { LeafType m_leaf; const T m_value; UpdateHandler(BpTreeBase& tree, T value) noexcept @@ -520,7 +902,7 @@ struct BpTree::UpdateHandler : Array::UpdateHandler { }; template -struct BpTree::SetNullHandler : Array::UpdateHandler { +struct BpTree::SetNullHandler : BpTreeNode::UpdateHandler { LeafType m_leaf; SetNullHandler(BpTreeBase& tree) noexcept : m_leaf(tree.get_alloc()) @@ -542,7 +924,7 @@ void BpTree::set(size_t ndx, T value) } else { UpdateHandler set_leaf_elem(*this, std::move(value)); - m_root->update_bptree_elem(ndx, set_leaf_elem); // Throws + static_cast(m_root.get())->update_bptree_elem(ndx, set_leaf_elem); // Throws } } @@ -554,12 +936,12 @@ void BpTree::set_null(size_t ndx) } else { SetNullHandler set_leaf_elem(*this); - m_root->update_bptree_elem(ndx, set_leaf_elem); // Throws; + static_cast(m_root.get())->update_bptree_elem(ndx, set_leaf_elem); // Throws; } } template -struct BpTree::EraseHandler : Array::EraseHandler { +struct BpTree::EraseHandler : BpTreeNode::EraseHandler { BpTreeBase& m_tree; LeafType m_leaf; bool m_leaves_have_refs; // FIXME: Should be able to eliminate this. @@ -618,7 +1000,7 @@ void BpTree::erase(size_t ndx, bool is_last) else { size_t ndx_2 = is_last ? npos : ndx; EraseHandler handler(*this); - Array::erase_bptree_elem(m_root.get(), ndx_2, handler); + BpTreeNode::erase_bptree_elem(&root_as_node(), ndx_2, handler); } } @@ -656,7 +1038,7 @@ void BpTree::clear() template -struct BpTree::AdjustHandler : Array::UpdateHandler { +struct BpTree::AdjustHandler : BpTreeNode::UpdateHandler { LeafType m_leaf; const T m_diff; AdjustHandler(BpTreeBase& tree, T diff) @@ -681,7 +1063,7 @@ void BpTree::adjust(T diff) } else { AdjustHandler adjust_leaf_elem(*this, std::move(diff)); - m_root->update_bptree_leaves(adjust_leaf_elem); // Throws + root_as_node().update_bptree_leaves(adjust_leaf_elem); // Throws } } @@ -693,7 +1075,7 @@ void BpTree::adjust(size_t ndx, T diff) } template -struct BpTree::AdjustGEHandler : Array::UpdateHandler { +struct BpTree::AdjustGEHandler : BpTreeNode::UpdateHandler { LeafType m_leaf; const T m_limit, m_diff; @@ -720,7 +1102,7 @@ void BpTree::adjust_ge(T limit, T diff) } else { AdjustGEHandler adjust_leaf_elem(*this, std::move(limit), std::move(diff)); - m_root->update_bptree_leaves(adjust_leaf_elem); // Throws + root_as_node().update_bptree_leaves(adjust_leaf_elem); // Throws } } @@ -757,7 +1139,7 @@ ref_type BpTree::write(size_t slice_offset, size_t slice_size, size_t table_s } else { SliceHandler handler(get_alloc()); - ref = write_subtree(root(), slice_offset, slice_size, table_size, handler, out); // Throws + ref = write_subtree(root_as_node(), slice_offset, slice_size, table_size, handler, out); // Throws } return ref; } @@ -766,7 +1148,8 @@ template MemRef BpTree::create_leaf(Array::Type leaf_type, size_t size, T value, Allocator& alloc) { bool context_flag = false; - return LeafType::create_array(leaf_type, context_flag, size, std::move(value), alloc); + MemRef mem = LeafType::create_array(leaf_type, context_flag, size, std::move(value), alloc); + return mem; } template @@ -777,7 +1160,7 @@ void BpTree::get_leaf(size_t ndx, size_t& ndx_in_leaf, LeafInfo& inout_leaf_i *inout_leaf_info.out_leaf = &root_as_leaf(); return; } - std::pair p = root().get_bptree_leaf(ndx); + std::pair p = root_as_node().get_bptree_leaf(ndx); inout_leaf_info.fallback->init_from_mem(p.first); ndx_in_leaf = p.second; *inout_leaf_info.out_leaf = inout_leaf_info.fallback; diff --git a/Pods/Realm/include/core/realm/column.hpp b/Pods/Realm/include/core/realm/column.hpp index 96d6a74..5f3cfd8 100644 --- a/Pods/Realm/include/core/realm/column.hpp +++ b/Pods/Realm/include/core/realm/column.hpp @@ -76,25 +76,28 @@ template class ColumnRandIterator : public std::iterator { public: ColumnRandIterator(const Column* src_col, size_t ndx = 0); - operator bool() const; - bool operator==(const ColumnRandIterator& other) const; - bool operator!=(const ColumnRandIterator& other) const; - ColumnRandIterator& operator+=(const ptrdiff_t& movement); - ColumnRandIterator& operator-=(const ptrdiff_t& movement); + bool operator==(const ColumnRandIterator& rhs) const; + bool operator!=(const ColumnRandIterator& rhs) const; + bool operator<(const ColumnRandIterator& rhs) const; + bool operator>(const ColumnRandIterator& rhs) const; + bool operator<=(const ColumnRandIterator& rhs) const; + bool operator>=(const ColumnRandIterator& rhs) const; + ColumnRandIterator& operator+=(ptrdiff_t movement); + ColumnRandIterator& operator-=(ptrdiff_t movement); ColumnRandIterator& operator++(); ColumnRandIterator& operator--(); ColumnRandIterator operator++(int); ColumnRandIterator operator--(int); - ColumnRandIterator operator+(const ptrdiff_t& movement); - ColumnRandIterator operator-(const ptrdiff_t& movement); + ColumnRandIterator operator+(ptrdiff_t movement); + ColumnRandIterator operator-(ptrdiff_t movement); ptrdiff_t operator-(const ColumnRandIterator& rawIterator); const ColumnDataType operator*() const; + const ColumnDataType operator->() const; + const ColumnDataType operator[](ptrdiff_t offset) const; size_t get_col_ndx() const; - protected: - size_t col_ndx; - size_t cached_column_size; - const Column* col; + size_t m_col_ndx; + const Column* m_col; }; /// Base class for all column types. @@ -281,7 +284,7 @@ class ColumnBase { /// See Table::adj_acc_move_over() virtual void adj_acc_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept; virtual void adj_acc_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept; - virtual void adj_acc_subsume_row(size_t old_row_ndx, size_t new_row_ndx) noexcept; + virtual void adj_acc_merge_rows(size_t old_row_ndx, size_t new_row_ndx) noexcept; virtual void adj_acc_clear_root_table() noexcept; enum { @@ -461,7 +464,7 @@ class ColumnBaseSimple : public ColumnBase { /// Introduce a new root node which increments the height of the /// tree by one. - void introduce_new_root(ref_type new_sibling_ref, Array::TreeInsertBase& state, bool is_append); + void introduce_new_root(ref_type new_sibling_ref, TreeInsertBase& state, bool is_append); static ref_type write(const Array* root, size_t slice_offset, size_t slice_size, size_t table_size, SliceHandler&, _impl::OutputStream&); @@ -529,7 +532,7 @@ class Column : public ColumnBaseWithIndex { , m_tree(Allocator::get_default()) { } - explicit Column(std::unique_ptr root) noexcept; + REALM_DEPRECATED("Initialize with ref instead") explicit Column(std::unique_ptr root) noexcept; Column(Allocator&, ref_type, size_t column_ndx = npos); Column(unattached_root_tag, Allocator&); Column(Column&&) noexcept = default; @@ -741,6 +744,7 @@ class Column : public ColumnBaseWithIndex { #ifdef REALM_DEBUG static void dump_node_structure(const Array& root, std::ostream&, int level); #endif + std::pair get_to_dot_parent(size_t ndx_in_parent) const; private: class EraseLeafElem; @@ -843,7 +847,7 @@ inline void ColumnBase::adj_acc_swap_rows(size_t, size_t) noexcept // Noop } -inline void ColumnBase::adj_acc_subsume_row(size_t, size_t) noexcept +inline void ColumnBase::adj_acc_merge_rows(size_t, size_t) noexcept { // Noop } @@ -1068,7 +1072,7 @@ inline size_t ColumnBase::get_size_from_ref(ref_type root_ref, Allocator& alloc) bool root_is_leaf = !Array::get_is_inner_bptree_node_from_header(root_header); if (root_is_leaf) return Array::get_size_from_header(root_header); - return Array::get_bptree_size_from_header(root_header); + return BpTreeNode::get_bptree_size_from_header(root_header); } template @@ -1690,60 +1694,92 @@ void Column::dump_node_structure(const Array& root, std::ostream& out, int le root.dump_bptree_structure(out, level, &_impl::leaf_dumper); } -#endif // LCOV_EXCL_STOP ignore debug functions +#endif + +template +std::pair Column::get_to_dot_parent(size_t ndx_in_parent) const +{ + auto root = get_root_array(); + if (root->is_inner_bptree_node()) { + std::pair p = static_cast(root)->get_bptree_leaf(ndx_in_parent); + return std::make_pair(p.first.get_ref(), p.second); + } + else { + return std::make_pair(root->get_ref(), ndx_in_parent); + } +} + +// LCOV_EXCL_STOP ignore debug functions template ColumnRandIterator::ColumnRandIterator(const Column* src_col, size_t ndx) - : col_ndx(ndx) - , col(src_col) + : m_col_ndx(ndx) + , m_col(src_col) +{ +} + +template +bool ColumnRandIterator::operator==(const ColumnRandIterator& rhs) const +{ + return (m_col_ndx == rhs.m_col_ndx); +} + +template +bool ColumnRandIterator::operator!=(const ColumnRandIterator& rhs) const +{ + return !(*this == rhs); +} + +template +bool ColumnRandIterator::operator<(const ColumnRandIterator& rhs) const { - cached_column_size = col->size(); + return m_col_ndx < rhs.m_col_ndx; } template -ColumnRandIterator::operator bool() const +bool ColumnRandIterator::operator>(const ColumnRandIterator& rhs) const { - return col_ndx >= 0 && col_ndx < cached_column_size; + return rhs < *this; } template -bool ColumnRandIterator::operator==(const ColumnRandIterator& other) const +bool ColumnRandIterator::operator<=(const ColumnRandIterator& rhs) const { - return (col_ndx == other.col_ndx); + return !(rhs < *this); } template -bool ColumnRandIterator::operator!=(const ColumnRandIterator& other) const +bool ColumnRandIterator::operator>=(const ColumnRandIterator& rhs) const { - return !(*this == other); + return !(*this < rhs); } template -ColumnRandIterator& ColumnRandIterator::operator+=(const ptrdiff_t& movement) +ColumnRandIterator& ColumnRandIterator::operator+=(ptrdiff_t movement) { - col_ndx += movement; + m_col_ndx += movement; return (*this); } template -ColumnRandIterator& ColumnRandIterator::operator-=(const ptrdiff_t& movement) +ColumnRandIterator& ColumnRandIterator::operator-=(ptrdiff_t movement) { - col_ndx -= movement; + m_col_ndx -= movement; return (*this); } template ColumnRandIterator& ColumnRandIterator::operator++() { - ++col_ndx; + ++m_col_ndx; return (*this); } template ColumnRandIterator& ColumnRandIterator::operator--() { - --col_ndx; + --m_col_ndx; return (*this); } @@ -1751,7 +1787,7 @@ template ColumnRandIterator ColumnRandIterator::operator++(int) { auto temp(*this); - ++col_ndx; + ++m_col_ndx; return temp; } @@ -1759,40 +1795,58 @@ template ColumnRandIterator ColumnRandIterator::operator--(int) { auto temp(*this); - --col_ndx; + --m_col_ndx; return temp; } template -ColumnRandIterator ColumnRandIterator::operator+(const ptrdiff_t& movement) +ColumnRandIterator ColumnRandIterator::operator+(ptrdiff_t movement) { - return ColumnRandIterator(col, col_ndx + movement); + return ColumnRandIterator(m_col, m_col_ndx + movement); } template -ColumnRandIterator ColumnRandIterator::operator-(const ptrdiff_t& movement) +ColumnRandIterator ColumnRandIterator::operator-(ptrdiff_t movement) { - return ColumnRandIterator(col, col_ndx - movement); + return ColumnRandIterator(m_col, m_col_ndx - movement); } template ptrdiff_t ColumnRandIterator::operator-(const ColumnRandIterator& other) { - return col_ndx - other.col_ndx; + return m_col_ndx - other.m_col_ndx; } template const ColumnDataType ColumnRandIterator::operator*() const { - return col->get(col_ndx); + return m_col->get(m_col_ndx); +} + +template +const ColumnDataType ColumnRandIterator::operator->() const +{ + return m_col->get(m_col_ndx); +} + +template +const ColumnDataType ColumnRandIterator::operator[](ptrdiff_t offset) const +{ + return m_col->get(m_col_ndx + offset); } template size_t ColumnRandIterator::get_col_ndx() const { - return col_ndx; + return m_col_ndx; } +template +std::ostream& operator<<(std::ostream& out, const ColumnRandIterator& it) +{ + out << "ColumnRandIterator at index: " << it.get_col_ndx(); + return out; +} } // namespace realm diff --git a/Pods/Realm/include/core/realm/column_binary.hpp b/Pods/Realm/include/core/realm/column_binary.hpp index f0dc7a1..c891297 100644 --- a/Pods/Realm/include/core/realm/column_binary.hpp +++ b/Pods/Realm/include/core/realm/column_binary.hpp @@ -108,9 +108,9 @@ class BinaryColumn : public ColumnBaseSimple { // Called by Array::bptree_insert(). static ref_type leaf_insert(MemRef leaf_mem, ArrayParent&, size_t ndx_in_parent, Allocator&, size_t insert_ndx, - Array::TreeInsert& state); + BpTreeNode::TreeInsert& state); - struct InsertState : Array::TreeInsert { + struct InsertState : BpTreeNode::TreeInsert { bool m_add_zero_term; }; @@ -130,7 +130,7 @@ class BinaryColumn : public ColumnBaseSimple { void leaf_to_dot(MemRef, ArrayParent*, size_t ndx_in_parent, std::ostream&) const override; - friend class Array; + friend class BpTreeNode; friend class ColumnBase; }; @@ -200,7 +200,7 @@ inline size_t BinaryColumn::size() const noexcept return leaf->size(); } // Non-leaf root - return m_array->get_bptree_size(); + return static_cast(m_array.get())->get_bptree_size(); } inline bool BinaryColumn::is_nullable() const noexcept @@ -251,7 +251,7 @@ inline BinaryData BinaryColumn::get(size_t ndx) const noexcept } // Non-leaf root - std::pair p = m_array->get_bptree_leaf(ndx); + std::pair p = static_cast(m_array.get())->get_bptree_leaf(ndx); const char* leaf_header = p.first.get_addr(); size_t ndx_in_leaf = p.second; Allocator& alloc = m_array->get_alloc(); @@ -420,7 +420,7 @@ inline size_t BinaryColumn::get_size_from_ref(ref_type root_ref, Allocator& allo // Big blobs leaf return ArrayBigBlobs::get_size_from_header(root_header); } - return Array::get_bptree_size_from_header(root_header); + return BpTreeNode::get_bptree_size_from_header(root_header); } diff --git a/Pods/Realm/include/core/realm/column_linklist.hpp b/Pods/Realm/include/core/realm/column_linklist.hpp index 2f32cda..445066e 100644 --- a/Pods/Realm/include/core/realm/column_linklist.hpp +++ b/Pods/Realm/include/core/realm/column_linklist.hpp @@ -79,7 +79,7 @@ class LinkListColumn : public LinkColumnBase, public ArrayParent { void adj_acc_erase_row(size_t) noexcept override; void adj_acc_move_over(size_t, size_t) noexcept override; void adj_acc_swap_rows(size_t, size_t) noexcept override; - void adj_acc_subsume_row(size_t, size_t) noexcept override; + void adj_acc_merge_rows(size_t, size_t) noexcept override; void refresh_accessor_tree(size_t, const Spec&) override; void verify() const override; diff --git a/Pods/Realm/include/core/realm/column_string.hpp b/Pods/Realm/include/core/realm/column_string.hpp index 3484fe9..50bab6f 100644 --- a/Pods/Realm/include/core/realm/column_string.hpp +++ b/Pods/Realm/include/core/realm/column_string.hpp @@ -168,7 +168,7 @@ class StringColumn : public ColumnBaseSimple { // Called by Array::bptree_insert(). static ref_type leaf_insert(MemRef leaf_mem, ArrayParent&, size_t ndx_in_parent, Allocator&, size_t insert_ndx, - Array::TreeInsert& state); + BpTreeNode::TreeInsert& state); class EraseLeafElem; class CreateHandler; @@ -188,7 +188,7 @@ class StringColumn : public ColumnBaseSimple { void leaf_to_dot(MemRef, ArrayParent*, size_t ndx_in_parent, std::ostream&) const override; - friend class Array; + friend class BpTreeNode; friend class ColumnBase; }; @@ -215,7 +215,8 @@ inline size_t StringColumn::size() const noexcept return leaf->size(); } // Non-leaf root - return m_array->get_bptree_size(); + BpTreeNode* node = static_cast(m_array.get()); + return node->get_bptree_size(); } inline void StringColumn::add(StringData value) @@ -325,7 +326,8 @@ inline size_t StringColumn::get_size_from_ref(ref_type root_ref, Allocator& allo // Big strings leaf return ArrayBigBlobs::get_size_from_header(root_header); } - return Array::get_bptree_size_from_header(root_header); + + return BpTreeNode::get_bptree_size_from_header(root_header); } // Implementing pure virtual method of ColumnBase. diff --git a/Pods/Realm/include/core/realm/exceptions.hpp b/Pods/Realm/include/core/realm/exceptions.hpp index 4a7bc61..a2dcd55 100644 --- a/Pods/Realm/include/core/realm/exceptions.hpp +++ b/Pods/Realm/include/core/realm/exceptions.hpp @@ -68,6 +68,16 @@ class FileFormatUpgradeRequired : public std::exception { const char* what() const noexcept override; }; + +/// Thrown when a sync agent attempts to join a session in which there is +/// already a sync agent. A session may only contain one sync agent at any given +/// time. +class MultipleSyncAgents : public std::exception { +public: + const char* what() const noexcept override; +}; + + /// Thrown when memory can no longer be mapped to. When mmap/remap fails. class AddressSpaceExhausted : public std::runtime_error { public: @@ -232,6 +242,11 @@ inline const char* FileFormatUpgradeRequired::what() const noexcept return "Database upgrade required but prohibited"; } +inline const char* MultipleSyncAgents::what() const noexcept +{ + return "Multiple sync agents attempted to join the same session"; +} + // LCOV_EXCL_STOP inline AddressSpaceExhausted::AddressSpaceExhausted(const std::string& msg) diff --git a/Pods/Realm/include/core/realm/group.hpp b/Pods/Realm/include/core/realm/group.hpp index 5a7f67d..490dd26 100644 --- a/Pods/Realm/include/core/realm/group.hpp +++ b/Pods/Realm/include/core/realm/group.hpp @@ -403,7 +403,7 @@ class Group : private Table::Parent { /// types that are derived from util::File::AccessError, the /// derived exception type is thrown. In particular, /// util::File::Exists will be thrown if the file exists already. - void write(const std::string& file, const char* encryption_key = 0) const; + void write(const std::string& file, const char* encryption_key = nullptr) const; /// Write this database to a memory buffer. /// diff --git a/Pods/Realm/include/core/realm/group_shared.hpp b/Pods/Realm/include/core/realm/group_shared.hpp index 8a78a38..6b36b97 100644 --- a/Pods/Realm/include/core/realm/group_shared.hpp +++ b/Pods/Realm/include/core/realm/group_shared.hpp @@ -384,7 +384,7 @@ class SharedGroup { /// therefore, if it throws, the application should not attempt to /// continue. If may not even be safe to destroy the SharedGroup object. /// - /// WARNING / FIXME: compact() should NOT be exposed publicly on Windows + /// WARNING / FIXME: compact() should NOT be exposed publicly on Windows /// because it's not crash safe! It may corrupt your database if something fails bool compact(); diff --git a/Pods/Realm/include/core/realm/impl/continuous_transactions_history.hpp b/Pods/Realm/include/core/realm/impl/continuous_transactions_history.hpp index a04d033..c9e43bb 100644 --- a/Pods/Realm/include/core/realm/impl/continuous_transactions_history.hpp +++ b/Pods/Realm/include/core/realm/impl/continuous_transactions_history.hpp @@ -174,7 +174,7 @@ class InRealmHistory : public History { void verify() const override; private: - Group* m_group = 0; + Group* m_group = nullptr; /// Version on which the first changeset in the history is based, or if the /// history is empty, the version associatede with currently bound diff --git a/Pods/Realm/include/core/realm/impl/instructions.hpp b/Pods/Realm/include/core/realm/impl/instructions.hpp index 14715cd..9f54d81 100644 --- a/Pods/Realm/include/core/realm/impl/instructions.hpp +++ b/Pods/Realm/include/core/realm/impl/instructions.hpp @@ -49,7 +49,7 @@ class InputStream; X(Remove) \ X(MoveLastOver) \ X(Swap) \ - X(ChangeLinkTargets) \ + X(MergeRows) \ X(Set) \ X(SetDefault) \ X(SetUnique) \ @@ -150,7 +150,7 @@ template <> struct Instr { size_t row_ndx_2; }; -template <> struct Instr { +template <> struct Instr { size_t row_ndx; size_t new_row_ndx; }; diff --git a/Pods/Realm/include/core/realm/impl/sequential_getter.hpp b/Pods/Realm/include/core/realm/impl/sequential_getter.hpp index 938ae24..c6c8a21 100644 --- a/Pods/Realm/include/core/realm/impl/sequential_getter.hpp +++ b/Pods/Realm/include/core/realm/impl/sequential_getter.hpp @@ -64,8 +64,13 @@ class SequentialGetter : public SequentialGetterBase { REALM_FORCEINLINE bool cache_next(size_t index) { - // Return whether or not leaf array has changed (could be useful to know for caller) - if (index >= m_leaf_end || index < m_leaf_start) { + // Set m_leaf_ptr to point at the leaf that contains the value at column row `index`. Return whether or not + // the leaf has changed (could be useful to know for caller). + + // FIXME: Below line has been commented away because array leafs might relocate during the lifetime of the + // object that owns this SequentialGetter. Enable again when we have proper support for that. +// if (index >= m_leaf_end || index < m_leaf_start) + { typename ColType::LeafInfo leaf{&m_leaf_ptr, m_array_ptr.get()}; size_t ndx_in_leaf; m_column->get_leaf(index, ndx_in_leaf, leaf); @@ -84,7 +89,10 @@ class SequentialGetter : public SequentialGetterBase { #pragma warning(push) #pragma warning(disable : 4800) // Disable the Microsoft warning about bool performance issue. #endif + return m_column->get(index); + // FIXME: Below optimization is skipped because array leafs might relocate during the lifetime of the + // object that owns this SequentialGetter. Enable again when we have proper support for that. cache_next(index); T av = m_leaf_ptr->get(index - m_leaf_start); return av; diff --git a/Pods/Realm/include/core/realm/impl/transact_log.hpp b/Pods/Realm/include/core/realm/impl/transact_log.hpp index 26b3c39..fa748a1 100644 --- a/Pods/Realm/include/core/realm/impl/transact_log.hpp +++ b/Pods/Realm/include/core/realm/impl/transact_log.hpp @@ -57,7 +57,7 @@ enum Instruction { instr_InsertEmptyRows = 13, instr_EraseRows = 14, // Remove (multiple) rows instr_SwapRows = 15, - instr_ChangeLinkTargets = 16, // Replace links pointing to row A with links to row B + instr_MergeRows = 16, // Replace links pointing to row A with links to row B instr_ClearTable = 17, // Remove all rows in selected table instr_OptimizeTable = 18, instr_SelectDescriptor = 19, // Select descriptor from currently selected root table @@ -167,7 +167,7 @@ class NullInstructionObserver { { return true; } - bool change_link_targets(size_t, size_t) + bool merge_rows(size_t, size_t) { return true; } @@ -339,7 +339,7 @@ class TransactLogEncoder { bool insert_empty_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, bool unordered); bool erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, bool unordered); bool swap_rows(size_t row_ndx_1, size_t row_ndx_2); - bool change_link_targets(size_t row_ndx, size_t new_row_ndx); + bool merge_rows(size_t row_ndx, size_t new_row_ndx); bool clear_table(); bool set_int(size_t col_ndx, size_t row_ndx, int_fast64_t, Instruction = instr_Set, size_t = 0); @@ -413,8 +413,8 @@ class TransactLogEncoder { // These two delimit a contiguous region of free space in a // transaction log buffer following the last written data. It may // be empty. - char* m_transact_log_free_begin = 0; - char* m_transact_log_free_end = 0; + char* m_transact_log_free_begin = nullptr; + char* m_transact_log_free_end = nullptr; char* reserve(size_t size); /// \param ptr Must be in the range [m_transact_log_free_begin, m_transact_log_free_end] @@ -482,7 +482,7 @@ class TransactLogConvenientEncoder { bool is_move_last_over); void swap_rows(const Table*, size_t row_ndx_1, size_t row_ndx_2); - void change_link_targets(const Table*, size_t row_ndx, size_t new_row_ndx); + void merge_rows(const Table*, size_t row_ndx, size_t new_row_ndx); void add_search_index(const Table*, size_t col_ndx); void remove_search_index(const Table*, size_t col_ndx); void set_link_type(const Table*, size_t col_ndx, LinkType); @@ -1442,16 +1442,16 @@ inline void TransactLogConvenientEncoder::swap_rows(const Table* t, size_t row_n m_encoder.swap_rows(row_ndx_1, row_ndx_2); } -inline bool TransactLogEncoder::change_link_targets(size_t row_ndx, size_t new_row_ndx) +inline bool TransactLogEncoder::merge_rows(size_t row_ndx, size_t new_row_ndx) { - append_simple_instr(instr_ChangeLinkTargets, util::tuple(row_ndx, new_row_ndx)); // Throws + append_simple_instr(instr_MergeRows, util::tuple(row_ndx, new_row_ndx)); // Throws return true; } -inline void TransactLogConvenientEncoder::change_link_targets(const Table* t, size_t row_ndx, size_t new_row_ndx) +inline void TransactLogConvenientEncoder::merge_rows(const Table* t, size_t row_ndx, size_t new_row_ndx) { select_table(t); // Throws - m_encoder.change_link_targets(row_ndx, new_row_ndx); + m_encoder.merge_rows(row_ndx, new_row_ndx); } inline bool TransactLogEncoder::add_search_index(size_t col_ndx) @@ -1872,10 +1872,10 @@ void TransactLogParser::parse_one(InstructionHandler& handler) parser_error(); return; } - case instr_ChangeLinkTargets: { + case instr_MergeRows: { size_t row_ndx = read_int(); // Throws size_t new_row_ndx = read_int(); // Throws - if (!handler.change_link_targets(row_ndx, new_row_ndx)) // Throws + if (!handler.merge_rows(row_ndx, new_row_ndx)) // Throws parser_error(); return; } @@ -2423,7 +2423,7 @@ class TransactReverser { return true; } - bool change_link_targets(size_t row_ndx, size_t new_row_ndx) + bool merge_rows(size_t row_ndx, size_t new_row_ndx) { static_cast(row_ndx); static_cast(new_row_ndx); diff --git a/Pods/Realm/include/core/realm/index_string.hpp b/Pods/Realm/include/core/realm/index_string.hpp index e9ae508..f215d67 100644 --- a/Pods/Realm/include/core/realm/index_string.hpp +++ b/Pods/Realm/include/core/realm/index_string.hpp @@ -67,6 +67,29 @@ namespace realm { class Spec; class Timestamp; +class IndexArray : public Array { +public: + IndexArray(Allocator& allocator) + : Array(allocator) + { + } + + size_t index_string_find_first(StringData value, ColumnBase* column) const; + void index_string_find_all(IntegerColumn& result, StringData value, ColumnBase* column) const; + FindRes index_string_find_all_no_copy(StringData value, ColumnBase* column, InternalFindResult& result) const; + size_t index_string_count(StringData value, ColumnBase* column) const; + +private: + template + size_t from_list(StringData value, IntegerColumn& result, InternalFindResult& result_ref, + const IntegerColumn& rows, ColumnBase* column) const; + + template + size_t index_string(StringData value, IntegerColumn& result, InternalFindResult& result_ref, + ColumnBase* column) const; +}; + + class StringIndex { public: StringIndex(ColumnBase* target_column, Allocator&); @@ -171,7 +194,7 @@ class StringIndex { // type 2, or type 3 (no shifting in either case). // References point to a list if the context header flag is NOT set. // If the header flag is set, references point to a sub-StringIndex (nesting). - std::unique_ptr m_array; + std::unique_ptr m_array; ColumnBase* m_target_column; bool m_deny_duplicate_values; @@ -179,7 +202,7 @@ class StringIndex { }; StringIndex(inner_node_tag, Allocator&); - static Array* create_node(Allocator&, bool is_leaf); + static IndexArray* create_node(Allocator&, bool is_leaf); void insert_with_offset(size_t row_ndx, StringData value, size_t offset); void insert_row_list(size_t ref, size_t offset, StringData value); @@ -329,7 +352,7 @@ inline StringIndex::StringIndex(ColumnBase* target_column, Allocator& alloc) inline StringIndex::StringIndex(ref_type ref, ArrayParent* parent, size_t ndx_in_parent, ColumnBase* target_column, bool deny_duplicate_values, Allocator& alloc) - : m_array(new Array(alloc)) + : m_array(new IndexArray(alloc)) , m_target_column(target_column) , m_deny_duplicate_values(deny_duplicate_values) { @@ -516,7 +539,7 @@ void StringIndex::find_all(IntegerColumn& result, T value) const return m_array->index_string_find_all(result, to_str(value, buffer), m_target_column); } -template +template FindRes StringIndex::find_all_no_copy(T value, InternalFindResult& result) const { // Use direct access method diff --git a/Pods/Realm/include/core/realm/link_view.hpp b/Pods/Realm/include/core/realm/link_view.hpp index 92b9297..89ce9da 100644 --- a/Pods/Realm/include/core/realm/link_view.hpp +++ b/Pods/Realm/include/core/realm/link_view.hpp @@ -174,10 +174,8 @@ inline LinkView::LinkView(const ctor_cookie&, Table* origin_table, LinkListColum , m_origin_table(origin_table->get_table_ref()) , m_origin_column(column) { - Array& root = *m_row_indexes.get_root_array(); - root.set_parent(&column, row_ndx); - if (ref_type ref = root.get_ref_from_parent()) - root.init_from_ref(ref); + m_row_indexes.set_parent(&m_origin_column, row_ndx); + m_row_indexes.init_from_parent(); } inline std::shared_ptr LinkView::create(Table* origin_table, LinkListColumn& column, size_t row_ndx) @@ -329,14 +327,8 @@ inline Table& LinkView::get_target_table() noexcept inline void LinkView::refresh_accessor_tree(size_t new_row_ndx) noexcept { - Array& root = *m_row_indexes.get_root_array(); - root.set_ndx_in_parent(new_row_ndx); - if (ref_type ref = root.get_ref_from_parent()) { - root.init_from_ref(ref); - } - else { - root.detach(); - } + set_origin_row_index(new_row_ndx); + m_row_indexes.init_from_parent(); } inline void LinkView::update_from_parent(size_t old_baseline) noexcept diff --git a/Pods/Realm/include/core/realm/null.hpp b/Pods/Realm/include/core/realm/null.hpp index 92c8d68..be010b8 100644 --- a/Pods/Realm/include/core/realm/null.hpp +++ b/Pods/Realm/include/core/realm/null.hpp @@ -122,7 +122,7 @@ struct null { int64_t double_nan = 0x7ff80000000000aa; i = std::is_same::value ? 0x7fc000aa : static_cast(double_nan); T d = type_punning(i); - REALM_ASSERT_DEBUG(std::isnan(static_cast(d))); + REALM_ASSERT_DEBUG(std::isnan(d)); REALM_ASSERT_DEBUG(!is_signaling(d)); return d; } diff --git a/Pods/Realm/include/core/realm/query.hpp b/Pods/Realm/include/core/realm/query.hpp index d62a1df..f166cd9 100644 --- a/Pods/Realm/include/core/realm/query.hpp +++ b/Pods/Realm/include/core/realm/query.hpp @@ -210,6 +210,7 @@ class Query final { Query& begins_with(size_t column_ndx, StringData value, bool case_sensitive = true); Query& ends_with(size_t column_ndx, StringData value, bool case_sensitive = true); Query& contains(size_t column_ndx, StringData value, bool case_sensitive = true); + Query& like(size_t column_ndx, StringData value, bool case_sensitive = true); // These are shortcuts for equal(StringData(c_str)) and // not_equal(StringData(c_str)), and are needed to avoid unwanted diff --git a/Pods/Realm/include/core/realm/query_conditions.hpp b/Pods/Realm/include/core/realm/query_conditions.hpp index ef1ef6d..dc66d93 100644 --- a/Pods/Realm/include/core/realm/query_conditions.hpp +++ b/Pods/Realm/include/core/realm/query_conditions.hpp @@ -85,6 +85,42 @@ struct Contains : public HackClass { static const int condition = -1; }; +// Does v2 contain something like v1 (wildcard matching)? +struct Like : public HackClass { + bool operator()(StringData v1, const char*, const char*, StringData v2, bool = false, bool = false) const + { + return v2.like(v1); + } + bool operator()(StringData v1, StringData v2, bool = false, bool = false) const + { + return v2.like(v1); + } + bool operator()(BinaryData, BinaryData, bool = false, bool = false) const + { + REALM_ASSERT(false); + return false; + } + + template bool operator()(A, B) const + { + REALM_ASSERT(false); + return false; + } + + template bool operator()(A, B, C, D) const + { + REALM_ASSERT(false); + return false; + } + + bool operator()(int64_t, int64_t, bool, bool) const { + REALM_ASSERT(false); + return false; + } + + static const int condition = -1; +}; + // Does v2 begin with v1? struct BeginsWith : public HackClass { bool operator()(StringData v1, const char*, const char*, StringData v2, bool = false, bool = false) const @@ -263,6 +299,36 @@ struct ContainsIns : public HackClass { static const int condition = -1; }; +// Does v2 contain something like v1 (wildcard matching)? +struct LikeIns : public HackClass { + bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false, bool = false) const + { + if (v2.is_null() || v1.is_null()) { + return (v2.is_null() && v1.is_null()); + } + + return string_like_ins(v2, v1_lower, v1_upper); + } + + // Slow version, used if caller hasn't stored an upper and lower case version + bool operator()(StringData v1, StringData v2, bool = false, bool = false) const + { + if (v2.is_null() || v1.is_null()) { + return (v2.is_null() && v1.is_null()); + } + + std::string v1_upper = case_map(v1, true, IgnoreErrors); + std::string v1_lower = case_map(v1, false, IgnoreErrors); + return string_like_ins(v2, v1_lower, v1_upper); + } + + template bool operator()(A, B) const { REALM_ASSERT(false); return false; } + template bool operator()(A, B, C, D) const { REALM_ASSERT(false); return false; } + bool operator()(int64_t, int64_t, bool, bool) const { REALM_ASSERT(false); return false; } + + static const int condition = -1; +}; + // Does v2 begin with v1? struct BeginsWithIns : public HackClass { bool operator()(StringData v1, const char* v1_upper, const char* v1_lower, StringData v2, bool = false, diff --git a/Pods/Realm/include/core/realm/query_engine.hpp b/Pods/Realm/include/core/realm/query_engine.hpp index 066a16a..c0cc7db 100644 --- a/Pods/Realm/include/core/realm/query_engine.hpp +++ b/Pods/Realm/include/core/realm/query_engine.hpp @@ -240,7 +240,7 @@ class ParentNode { , m_dT(from.m_dT) , m_probes(from.m_probes) , m_matches(from.m_matches) - , m_table(from.m_table) + , m_table(patches ? ConstTableRef{} : from.m_table) { } @@ -300,10 +300,8 @@ class ParentNode { const QueryNodeHandoverPatches* patches) { if (src.m_column) { - if (patches) { + if (patches) dst_idx = src.m_column->get_column_index(); - REALM_ASSERT_DEBUG(dst_idx < m_table->get_column_count()); - } else dst.init(src.m_column); } @@ -1215,22 +1213,23 @@ class StringNode : public StringNodeBase { switch (fr) { case FindRes_single: - m_index_matches.reset(new IntegerColumn(IntegerColumn::unattached_root_tag(), Allocator::get_default())); // Throws - m_index_matches->get_root_array()->create(Array::type_Normal); // Throws + m_index_matches.reset( + new IntegerColumn(IntegerColumn::unattached_root_tag(), Allocator::get_default())); // Throws + m_index_matches->get_root_array()->create(Array::type_Normal); // Throws m_index_matches->add(res.payload); - m_index_matches_destroy = true; // we own m_index_matches, so we must destroy it + m_index_matches_destroy = true; // we own m_index_matches, so we must destroy it m_results_start = 0; m_results_end = 1; break; case FindRes_column: - // todo: Apparently we can't use m_index.get_alloc() because it uses default allocator which simply makes + // todo: Apparently we can't use m_index.get_alloc() because it uses default allocator which + // simply makes // translate(x) = x. Shouldn't it inherit owner column's allocator?! - m_index_matches.reset(new IntegerColumn(IntegerColumn::unattached_root_tag(), m_condition_column->get_alloc())); // Throws - m_index_matches->get_root_array()->init_from_ref(res.payload); + m_index_matches.reset(new IntegerColumn(m_condition_column->get_alloc(), res.payload)); // Throws m_results_start = res.start_ndx; m_results_end = res.end_ndx; - //FIXME: handle start and end of find_result! + // FIXME: handle start and end of find_result! break; case FindRes_not_found: m_index_matches.reset(); diff --git a/Pods/Realm/include/core/realm/query_expression.hpp b/Pods/Realm/include/core/realm/query_expression.hpp index 1a29aed..2d7b0a6 100644 --- a/Pods/Realm/include/core/realm/query_expression.hpp +++ b/Pods/Realm/include/core/realm/query_expression.hpp @@ -478,6 +478,10 @@ Query create(L left, const Subexpr2& right) q.contains(column->column_ndx(), only_string(left)); else if (std::is_same::value) q.contains(column->column_ndx(), only_string(left), false); + else if (std::is_same::value) + q.like(column->column_ndx(), only_string(left)); + else if (std::is_same::value) + q.like(column->column_ndx(), only_string(left), false); else { // query_engine.hpp does not support this Cond. Please either add support for it in query_engine.hpp or // fallback to using use 'return new Compare<>' instead. @@ -1626,11 +1630,12 @@ class LinkMap { LinkMap(LinkMap const& other, QueryNodeHandoverPatches* patches) : LinkMap(other) { - if (!patches || m_link_column_indexes.empty()) + if (!patches) return; m_link_column_indexes.clear(); const Table* table = m_base_table; + m_base_table = nullptr; for (auto column : m_link_columns) { m_link_column_indexes.push_back(column->get_column_index()); if (table->get_real_column_type(m_link_column_indexes.back()) == col_type_BackLink) @@ -1960,6 +1965,16 @@ class Columns : public SimpleQuerySupport { { return string_compare(*this, col, case_sensitive); } + + Query like(StringData sd, bool case_sensitive = true) + { + return string_compare(*this, sd, case_sensitive); + } + + Query like(const Columns& col, bool case_sensitive = true) + { + return string_compare(*this, col, case_sensitive); + } }; @@ -2445,9 +2460,11 @@ class Columns : public Subexpr2 { template void evaluate_internal(size_t index, ValueBase& destination) { + REALM_ASSERT_DEBUG(m_sg.get()); + REALM_ASSERT_DEBUG(dynamic_cast*>(m_sg.get())); + using U = typename ColType2::value_type; auto sgc = static_cast*>(m_sg.get()); - REALM_ASSERT_DEBUG(dynamic_cast*>(m_sg.get())); REALM_ASSERT_DEBUG(sgc->m_column); if (links_exist()) { diff --git a/Pods/Realm/include/core/realm/replication.hpp b/Pods/Realm/include/core/realm/replication.hpp index c31e5ca..857ab2a 100644 --- a/Pods/Realm/include/core/realm/replication.hpp +++ b/Pods/Realm/include/core/realm/replication.hpp @@ -360,6 +360,12 @@ class Replication : public _impl::TransactLogConvenientEncoder, protected _impl: /// returns \ref hist_None. virtual _impl::History* get_history() = 0; + /// Returns false by default, but must return true if, and only if this + /// history object represents a session participant that is a sync + /// agent. This is used to enforce the "maximum one sync agent per session" + /// constraint. + virtual bool is_sync_agent() const noexcept; + virtual ~Replication() noexcept { } @@ -487,6 +493,11 @@ inline void Replication::clear_interrupt() noexcept do_clear_interrupt(); } +inline bool Replication::is_sync_agent() const noexcept +{ + return false; +} + inline TrivialReplication::TrivialReplication(const std::string& database_file) : m_database_file(database_file) { diff --git a/Pods/Realm/include/core/realm/string_data.hpp b/Pods/Realm/include/core/realm/string_data.hpp index e1234cf..14230cc 100644 --- a/Pods/Realm/include/core/realm/string_data.hpp +++ b/Pods/Realm/include/core/realm/string_data.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -138,6 +139,10 @@ class StringData { bool begins_with(StringData) const noexcept; bool ends_with(StringData) const noexcept; bool contains(StringData) const noexcept; + + // Wildcard matching ('?' for single char, '*' for zero or more chars) + // case insensitive version in unicode.hpp + bool like(StringData) const noexcept; //@{ /// Undefined behavior if \a n, \a i, or i+n is greater than @@ -156,6 +161,8 @@ class StringData { private: const char* m_data; size_t m_size; + + static bool matchlike(const StringData& text, const StringData& pattern) noexcept; }; @@ -285,6 +292,83 @@ inline bool StringData::contains(StringData d) const noexcept return d.m_size == 0 || std::search(m_data, m_data + m_size, d.m_data, d.m_data + d.m_size) != m_data + m_size; } +inline bool StringData::matchlike(const StringData& text, const StringData& pattern) noexcept +{ + std::vector textpos; + std::vector patternpos; + size_t p1 = 0; // position in text (haystack) + size_t p2 = 0; // position in pattern (needle) + + while (true) { + if (p1 == text.size()) { + if (p2 == pattern.size()) + return true; + if (p2 == pattern.size()-1 && pattern[p2] == '*') + return true; + goto no_match; + } + if (p2 == pattern.size()) + goto no_match; + + if (pattern[p2] == '*') { + textpos.push_back(p1); + patternpos.push_back(++p2); + continue; + } + if (pattern[p2] == '?') { + // utf-8 encoded characters may take up multiple bytes + if ((text[p1] & 0x80) == 0) { + ++p1; + ++p2; + continue; + } + else { + size_t p = 1; + while (p1+p != text.size() && (text[p1+p] & 0xc0) == 0x80) + ++p; + p1 += p; + ++p2; + continue; + } + } + + if (pattern[p2] == text[p1]) { + ++p1; + ++p2; + continue; + } + + no_match: + if (textpos.empty()) + return false; + else { + if (p1 == text.size()) { + textpos.pop_back(); + patternpos.pop_back(); + + if (textpos.empty()) + return false; + + p1 = textpos.back(); + } + else { + p1 = textpos.back(); + textpos.back() = ++p1; + } + p2 = patternpos.back(); + } + } +} + +inline bool StringData::like(StringData d) const noexcept +{ + if (is_null() || d.is_null()) { + return (is_null() && d.is_null()); + } + + return matchlike(*this, d); +} + inline StringData StringData::prefix(size_t n) const noexcept { return substr(0, n); diff --git a/Pods/Realm/include/core/realm/sync/client.hpp b/Pods/Realm/include/core/realm/sync/client.hpp index d5907e7..a6e9959 100644 --- a/Pods/Realm/include/core/realm/sync/client.hpp +++ b/Pods/Realm/include/core/realm/sync/client.hpp @@ -184,10 +184,11 @@ class BadServerUrl; // Exception /// thread-safe, while others are not. class Session { public: - using port_type = util::network::endpoint::port_type; + using port_type = util::network::Endpoint::port_type; using version_type = _impl::History::version_type; using SyncTransactCallback = void(VersionID old_version, VersionID new_version); using ErrorHandler = Client::ErrorHandler; + using WaitOperCompletionHandler = std::function; /// \brief Start a new session for the specified client-side Realm. /// @@ -271,7 +272,7 @@ class Session { /// that callback function will start to be called as changesets are /// downloaded and integrated locally. It is important to understand that /// callback functions are executed by the event loop thread (Client::run()) - /// and the callback function may therfore be called before bind() returns. + /// and the callback function may therefore be called before bind() returns. /// /// Note: It is an error if this function is called more than once per /// Session object. @@ -353,57 +354,106 @@ class Session { /// any thread, and by multiple threads concurrently. void nonsync_transact_notify(version_type new_version); - /// \brief Wait for upload to complete - /// - /// This function waits for all currently outstanding client-side changesets - /// to be uploaded to, and acknowledged by the server. More specifically, it - /// waits until all changesets that must be uploaded, and that precede a - /// certain client version threshold have been uploaded. The threshold is - /// the highest client version passed to nonsync_transact_notify() prior to - /// the invocation of wait_for_upload_complete_or_client_stopped(). - /// - /// If nonsync_transact_notify() is called while - /// wait_for_upload_complete_or_client_stopped() executes, and with a - /// version that greater than the currently applying threashold, then that - /// may, or may not cause the threshold to be pushed forward and the wait to - /// be extended. - /// - /// It is an error to call this function before bind() has been called, and - /// has returned. + /// @{ \brief Wait for upload, download, or upload+download completion. + /// + /// async_wait_for_upload_completion() initiates an asynchronous wait for + /// upload to complete, async_wait_for_download_completion() initiates an + /// asynchronous wait for download to complete, and + /// async_wait_for_sync_completion() initiates an asynchronous wait for + /// upload and download to complete. + /// + /// Upload is considered complete when all non-empty changesets of local + /// origin have been uploaded to the server, and the server has acknowledged + /// reception of them. Changesets of local origin introduced after the + /// initiation of the session (after bind() is called) will generally not be + /// considered for upload unless they are announced to this client through + /// nonsync_transact_notify() prior to the initiation of the wait operation, + /// i.e., prior to the invocation of async_wait_for_upload_completion() or + /// async_wait_for_sync_completion(). Unannounced changesets may get picked + /// up, but there is no guarantee that they will be, however, if a certain + /// changeset is announced, then all previous changesets are implicitely + /// announced. Also all preexisting changesets are implicitely announced + /// when the session is initiated. + /// + /// Download is considered complete when all non-empty changesets of remote + /// origin have been downloaded from the server, and integrated into the + /// local Realm state. To know what is currently outstanding on the server, + /// the client always sends a special "marker" message to the server, and + /// waits until it has downloaded all outstanding changesets that were + /// present on the server at the time when the server received that marker + /// message. Each call to async_wait_for_download_completion() and + /// async_wait_for_sync_completion() therefore requires a full client <-> + /// server round-trip. + /// + /// If a new wait operation is initiated while other wait operations are in + /// progress, the waiting period of operations in progress may, or may not + /// get extended. The client must not assume either. The client may assume, + /// however, that async_wait_for_upload_completion() will not affect the + /// waiting period of async_wait_for_download_completion(), and vice versa. + /// + /// It is an error to call these functions before bind() has been called, + /// and has returned. + /// + /// The specified completion handlers will always be executed by the thread + /// that executes the event loop (the thread that calls Client::run()). If + /// the handler throws an exception, that exception will "travel" out + /// through Client::run(). /// - /// Note: This function is fully thread-safe. That is, it may be called by - /// any thread, and by multiple threads concurrently. - void wait_for_upload_complete_or_client_stopped(); + /// If incomplete wait operations exist when the session is terminated, + /// those wait operations will be canceled. Session termination is an event + /// that happens in the context of the client's event loop thread shortly + /// after the destruction of the session object. The std::error_code + /// argument passed to the completion handler of a canceled wait operation + /// will be `util::error::operation_aborted`. For uncanceled wait operations + /// it will be `std::error_code{}`. Note that as long as the client's event + /// loop thread is running, all completion handlers will be called + /// regardless of whether the operations get canceled or not. + /// + /// CAUTION: The specified completion handlers may be called before the + /// initiation function returns (e.g. before + /// async_wait_for_upload_completion() returns), and it may be called (or + /// continue to execute) after the session object is destroyed. The + /// application must pass a handler that can be safely called, and can + /// safely continue to execute from the point in time where the initiating + /// function starts executing, and up until the point in time where the last + /// invocation of `clint.run()` returns. Here, `client` refers to the + /// associated Client object. + /// + /// Note: These functions are fully thread-safe. That is, they may be called + /// by any thread, and by multiple threads concurrently. + void async_wait_for_sync_completion(WaitOperCompletionHandler); + void async_wait_for_upload_completion(WaitOperCompletionHandler); + void async_wait_for_download_completion(WaitOperCompletionHandler); + /// @} - /// \brief Wait for download to complete + /// @{ \brief Synchronous wait for upload or download completion. /// - /// This function waits for all currently outstanding server-side changesets - /// to be downloaded. More specifically, it waits until all changesets that - /// must be downloaded, and that precede a certain server version threshold - /// have been downloaded (FIXME: Shouldn't it have been downloaded and - /// integrated?). The threshold is the currently latest server version at - /// the time where wait_for_download_complete_or_client_stopped() is called, - /// or shortly thereafter. + /// These functions are synchronous equivalents to + /// async_wait_for_upload_completion() and + /// async_wait_for_download_completion() respectively. This means that they + /// block the caller until the completion condition is satisfied, or the + /// client event loop is stopped (Client::stop()). /// - /// If wait_for_download_complete_or_client_stopped() is called by one - /// thread while it is being executed by another thread, then the later call - /// may, or may not push forward the threshold that applies the the earlier - /// call, and cause its wait to be correspondingly extended. + /// It is an error to call these functions before bind() has been called, + /// and has returned. /// - /// It is an error to call this function before bind() has been called, and - /// has returned. - /// - /// Note: This function is fully thread-safe. That is, it may be called by - /// any thread, and by multiple threads concurrently. + /// Note: These functions are fully thread-safe. That is, they may be called + /// by any thread, and by multiple threads concurrently. + void wait_for_upload_complete_or_client_stopped(); void wait_for_download_complete_or_client_stopped(); + /// @} private: class Impl; Impl* m_impl; + + void async_wait_for(bool upload_completion, bool download_completion, + WaitOperCompletionHandler); }; + // Implementation class BadServerUrl: public std::exception { @@ -414,6 +464,24 @@ class BadServerUrl: public std::exception { } }; +inline void Session::async_wait_for_sync_completion(WaitOperCompletionHandler handler) +{ + bool upload_completion = true, download_completion = true; + async_wait_for(upload_completion, download_completion, std::move(handler)); // Throws +} + +inline void Session::async_wait_for_upload_completion(WaitOperCompletionHandler handler) +{ + bool upload_completion = true, download_completion = false; + async_wait_for(upload_completion, download_completion, std::move(handler)); // Throws +} + +inline void Session::async_wait_for_download_completion(WaitOperCompletionHandler handler) +{ + bool upload_completion = false, download_completion = true; + async_wait_for(upload_completion, download_completion, std::move(handler)); // Throws +} + } // namespace sync } // namespace realm diff --git a/Pods/Realm/include/core/realm/sync/history.hpp b/Pods/Realm/include/core/realm/sync/history.hpp index 4bee7da..3c69468 100644 --- a/Pods/Realm/include/core/realm/sync/history.hpp +++ b/Pods/Realm/include/core/realm/sync/history.hpp @@ -201,7 +201,21 @@ class SyncHistory: }; -std::unique_ptr make_sync_history(const std::string& realm_path); +/// \brief Create a "sync history" implementation of the realm::Replication +/// interface. +/// +/// The main function of such an object is as a plugin for new +/// realm::SharedGroup objects. +/// +/// \param owner_is_sync_agent Must be set to true if, and only if the created +/// history object represents (is owned by) the sync agent of the specified +/// Realm file. At most one such instance is allowed to participate in a Realm +/// file access session at any point in time. Ordinarily the sync agent is +/// encapsulated by the sync::Client class, and the history instance +/// representing the agent is created transparently by sync::Client (one history +/// instance per sync::Session object). +std::unique_ptr make_sync_history(const std::string& realm_path, + bool owner_is_sync_agent = false); diff --git a/Pods/Realm/include/core/realm/sync/protocol.hpp b/Pods/Realm/include/core/realm/sync/protocol.hpp index 38bf662..bb3691a 100644 --- a/Pods/Realm/include/core/realm/sync/protocol.hpp +++ b/Pods/Realm/include/core/realm/sync/protocol.hpp @@ -20,6 +20,7 @@ #ifndef REALM_SYNC_PROTOCOL_HPP #define REALM_SYNC_PROTOCOL_HPP +#include // NOTE: The protocol specification is in `/doc/protocol.md` @@ -74,13 +75,20 @@ namespace sync { // make previous versions incompatible. // 14 Further bugfixes related to primary keys and link lists. Add support for // LinkListSwap. +// 15 Deleting an object with a primary key deletes all objects on other +// with the same primary key. constexpr int get_current_protocol_version() noexcept { - return 14; + return 15; } -// Reserve 0 for compatibility with std::error_condition. -enum class Error { +// Reserve 0 for compatibility with std::error_code. +// +// ATTENTION: Please remember to update is_session_level_error() and +// is_connection_level_error() definitions when adding/removing error codes. +enum class ProtocolError { + invalid_error = 99, // Server sent an invalid error code (ERROR) + // Connection level and protocol errors connection_closed = 100, // Connection closed (no error) other_error = 101, // Other connection level error @@ -107,16 +115,34 @@ enum class Error { bad_client_version = 210, // Bad client version (IDENT, UPLOAD) diverging_histories = 211, // Diverging histories (IDENT) bad_changeset = 212, // Bad changeset (UPLOAD) + disabled_session = 213, // Disabled session }; -inline constexpr bool is_session_level_error(Error error) +inline constexpr bool is_session_level_error(ProtocolError error) +{ + return int(error) >= 200 && int(error) <= 213; +} + +inline constexpr bool is_connection_level_error(ProtocolError error) { - return int(error) >= 200; + return int(error) >= 100 && int(error) <= 109; } -const char* get_error_message(Error error_code); +const char* get_error_message(ProtocolError) noexcept; + +const std::error_category& protocol_error_category() noexcept; + +std::error_code make_error_code(ProtocolError) noexcept; } // namespace sync } // namespace realm +namespace std { + +template<> struct is_error_code_enum { + static const bool value = true; +}; + +} // namespace std + #endif // REALM_SYNC_PROTOCOL_HPP diff --git a/Pods/Realm/include/core/realm/sync/server.hpp b/Pods/Realm/include/core/realm/sync/server.hpp index 5250abe..166b4be 100644 --- a/Pods/Realm/include/core/realm/sync/server.hpp +++ b/Pods/Realm/include/core/realm/sync/server.hpp @@ -134,7 +134,7 @@ class Server { bool reuse_address = true); /// Return the resolved and bound endpoint of the listening socket. - util::network::endpoint listen_endpoint() const; + util::network::Endpoint listen_endpoint() const; /// Run the internal event-loop of the server. At most one thread may /// execute run() at any given time. It is an error if run() is called diff --git a/Pods/Realm/include/core/realm/sync/version.hpp b/Pods/Realm/include/core/realm/sync/version.hpp index d4a0198..752917a 100644 --- a/Pods/Realm/include/core/realm/sync/version.hpp +++ b/Pods/Realm/include/core/realm/sync/version.hpp @@ -24,7 +24,7 @@ #define REALM_SYNC_VER_MAJOR 1 #define REALM_SYNC_VER_MINOR 0 -#define REALM_SYNC_VER_PATCH 0-BETA-1.3 +#define REALM_SYNC_VER_PATCH 0-BETA-5.0 #define REALM_SYNC_PRODUCT_NAME "realm-sync" #define REALM_SYNC_VER_STRING REALM_QUOTE(REALM_SYNC_VER_MAJOR) "." \ diff --git a/Pods/Realm/include/core/realm/table.hpp b/Pods/Realm/include/core/realm/table.hpp index 7e95a5d..01c44ac 100644 --- a/Pods/Realm/include/core/realm/table.hpp +++ b/Pods/Realm/include/core/realm/table.hpp @@ -398,7 +398,7 @@ class Table { /// \sa Table::set_int_unique() /// \sa Table::set_string_unique() /// \sa Table::set_null_unique() - void change_link_targets(size_t row_ndx, size_t new_row_ndx); + void merge_rows(size_t row_ndx, size_t new_row_ndx); // Get cell values. Will assert if the requested type does not match the column type int64_t get_int(size_t column_ndx, size_t row_ndx) const noexcept; @@ -448,7 +448,7 @@ class Table { /// are intended to be used in the implementation of primary key support. They /// check if the given column already contains one or more values that are /// equal to \a value, and if there are conflicts, it calls - /// Table::change_link_targets() for the row_ndx to be replaced by the + /// Table::merge_rows() for the row_ndx to be replaced by the /// existing row, followed by a Table::move_last_over() of row_ndx. The /// return value is always a row index of a row that contains \a value in /// the specified column, possibly different from \a row_ndx if a conflict @@ -952,15 +952,15 @@ class Table { void do_remove(size_t row_ndx, bool broken_reciprocal_backlinks); void do_move_last_over(size_t row_ndx, bool broken_reciprocal_backlinks); void do_swap_rows(size_t row_ndx_1, size_t row_ndx_2); - void do_change_link_targets(size_t row_ndx, size_t new_row_ndx); + void do_merge_rows(size_t row_ndx, size_t new_row_ndx); void do_clear(bool broken_reciprocal_backlinks); size_t do_set_link(size_t col_ndx, size_t row_ndx, size_t target_row_ndx); template - size_t do_find_unique(ColType& col, size_t ndx, T&& value); + size_t do_find_unique(ColType& col, size_t ndx, T&& value, bool& conflict); template - size_t do_set_unique_null(ColType& col, size_t ndx); + size_t do_set_unique_null(ColType& col, size_t ndx, bool& conflict); template - size_t do_set_unique(ColType& column, size_t row_ndx, T&& value); + size_t do_set_unique(ColType& column, size_t row_ndx, T&& value, bool& conflict); void upgrade_file_format(size_t target_file_format_version); @@ -1321,7 +1321,7 @@ class Table { void adj_acc_insert_rows(size_t row_ndx, size_t num_rows) noexcept; void adj_acc_erase_row(size_t row_ndx) noexcept; void adj_acc_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept; - void adj_acc_subsume_row(size_t old_row_ndx, size_t new_row_ndx) noexcept; + void adj_acc_merge_rows(size_t old_row_ndx, size_t new_row_ndx) noexcept; /// Adjust this table accessor and its subordinates after move_last_over() /// (or its inverse). @@ -1361,7 +1361,7 @@ class Table { void adj_row_acc_insert_rows(size_t row_ndx, size_t num_rows) noexcept; void adj_row_acc_erase_row(size_t row_ndx) noexcept; void adj_row_acc_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept; - void adj_row_acc_subsume_row(size_t old_row_ndx, size_t new_row_ndx) noexcept; + void adj_row_acc_merge_rows(size_t old_row_ndx, size_t new_row_ndx) noexcept; /// Called by adj_acc_move_over() to adjust row accessors. void adj_row_acc_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept; @@ -2191,9 +2191,9 @@ class _impl::TableFriend { table.do_swap_rows(row_ndx_1, row_ndx_2); // Throws } - static void do_change_link_targets(Table& table, size_t row_ndx, size_t new_row_ndx) + static void do_merge_rows(Table& table, size_t row_ndx, size_t new_row_ndx) { - table.do_change_link_targets(row_ndx, new_row_ndx); // Throws + table.do_merge_rows(row_ndx, new_row_ndx); // Throws } static void do_clear(Table& table) @@ -2299,9 +2299,9 @@ class _impl::TableFriend { table.adj_acc_swap_rows(row_ndx_1, row_ndx_2); } - static void adj_acc_subsume_row(Table& table, size_t row_ndx_1, size_t row_ndx_2) noexcept + static void adj_acc_merge_rows(Table& table, size_t row_ndx_1, size_t row_ndx_2) noexcept { - table.adj_acc_subsume_row(row_ndx_1, row_ndx_2); + table.adj_acc_merge_rows(row_ndx_1, row_ndx_2); } static void adj_acc_move_over(Table& table, size_t from_row_ndx, size_t to_row_ndx) noexcept diff --git a/Pods/Realm/include/core/realm/table_accessors.hpp b/Pods/Realm/include/core/realm/table_accessors.hpp index e3e5cba..c0a9a5f 100644 --- a/Pods/Realm/include/core/realm/table_accessors.hpp +++ b/Pods/Realm/include/core/realm/table_accessors.hpp @@ -935,7 +935,7 @@ class FieldAccessor template BasicTableRef get_subtable() const { - REALM_ASSERT(!Base::is_subtable() || Base::template is_subtable()); + REALM_ASSERT(!Base::is_subtable() || this->Base::template is_subtable()); return unchecked_cast(get_subtable()); } @@ -987,7 +987,7 @@ class FieldAccessor template BasicTableRef get_subtable() const { - REALM_ASSERT(!Base::is_subtable() || Base::template is_subtable()); + REALM_ASSERT(!Base::is_subtable() || this->Base::template is_subtable()); return unchecked_cast(get_subtable()); } @@ -1887,6 +1887,12 @@ class QueryColumn : public QueryColumnBasem_impl.contains(col_idx, value, case_sensitive); return *Base::m_query; } + + Query& like(StringData value, bool case_sensitive=true) const + { + Base::m_query->m_impl.like(col_idx, value, case_sensitive); + return *Base::m_query; + } }; diff --git a/Pods/Realm/include/core/realm/table_view.hpp b/Pods/Realm/include/core/realm/table_view.hpp index 636284a..9d5429b 100644 --- a/Pods/Realm/include/core/realm/table_view.hpp +++ b/Pods/Realm/include/core/realm/table_view.hpp @@ -596,7 +596,6 @@ class ConstTableView : public TableViewBase { using TableViewBase::TableViewBase; ConstTableView() = default; - ~ConstTableView() noexcept = default; ConstTableView(const TableView&); ConstTableView(TableView&&); @@ -722,7 +721,7 @@ inline TableViewBase::TableViewBase(Table* parent) _impl::DeepArrayRefDestroyGuard ref_guard(alloc); ref_guard.reset(IntegerColumn::create(alloc)); // Throws parent->register_view(this); // Throws - m_row_indexes.get_root_array()->init_from_ref(ref_guard.release()); + m_row_indexes.init_from_ref(alloc, ref_guard.release()); } inline TableViewBase::TableViewBase(Table* parent, Query& query, size_t start, size_t end, size_t limit) @@ -741,7 +740,7 @@ inline TableViewBase::TableViewBase(Table* parent, Query& query, size_t start, s _impl::DeepArrayRefDestroyGuard ref_guard(alloc); ref_guard.reset(IntegerColumn::create(alloc)); // Throws parent->register_view(this); // Throws - m_row_indexes.get_root_array()->init_from_ref(ref_guard.release()); + m_row_indexes.init_from_ref(alloc, ref_guard.release()); } inline TableViewBase::TableViewBase(Table* parent, size_t column, BasicRowExpr row) @@ -758,7 +757,7 @@ inline TableViewBase::TableViewBase(Table* parent, size_t column, BasicRowExprregister_view(this); // Throws - m_row_indexes.get_root_array()->init_from_ref(ref_guard.release()); + m_row_indexes.init_from_ref(alloc, ref_guard.release()); } inline TableViewBase::TableViewBase(const TableViewBase& tv) @@ -778,14 +777,14 @@ inline TableViewBase::TableViewBase(const TableViewBase& tv) , m_num_detached_refs(tv.m_num_detached_refs) { // FIXME: This code is unreasonably complicated because it uses `IntegerColumn` as - // a free-standing container, and beause `IntegerColumn` does not conform to the + // a free-standing container, and because `IntegerColumn` does not conform to the // RAII idiom (nor should it). Allocator& alloc = m_row_indexes.get_alloc(); MemRef mem = tv.m_row_indexes.get_root_array()->clone_deep(alloc); // Throws _impl::DeepArrayRefDestroyGuard ref_guard(mem.get_ref(), alloc); if (m_table) m_table->register_view(this); // Throws - m_row_indexes.get_root_array()->init_from_mem(mem); + m_row_indexes.init_from_mem(alloc, mem); ref_guard.release(); } diff --git a/Pods/Realm/include/core/realm/table_view_basic.hpp b/Pods/Realm/include/core/realm/table_view_basic.hpp index 39ef9d3..a38f125 100644 --- a/Pods/Realm/include/core/realm/table_view_basic.hpp +++ b/Pods/Realm/include/core/realm/table_view_basic.hpp @@ -200,6 +200,8 @@ class BasicTableView : public BasicTableViewBase, Table BasicTableView() { } + BasicTableView(const BasicTableView&) = default; + BasicTableView(BasicTableView&&) = default; BasicTableView& operator=(BasicTableView); friend BasicTableView move(BasicTableView& tv) { diff --git a/Pods/Realm/include/core/realm/unicode.hpp b/Pods/Realm/include/core/realm/unicode.hpp index 8ffbc37..e1b2ee4 100644 --- a/Pods/Realm/include/core/realm/unicode.hpp +++ b/Pods/Realm/include/core/realm/unicode.hpp @@ -150,6 +150,10 @@ bool equal_case_fold(StringData haystack, const char* needle_upper, const char* /// needle was not found. size_t search_case_fold(StringData haystack, const char* needle_upper, const char* needle_lower, size_t needle_size); +/// Case insensitive wildcard matching ('?' for single char, '*' for zero or more chars) +bool string_like_ins(StringData text, StringData pattern) noexcept; +bool string_like_ins(StringData text, StringData upper, StringData lower) noexcept; + } // namespace realm #endif // REALM_UNICODE_HPP diff --git a/Pods/Realm/include/core/realm/util/buffer_stream.hpp b/Pods/Realm/include/core/realm/util/buffer_stream.hpp index 9fbe462..7ef3cf1 100644 --- a/Pods/Realm/include/core/realm/util/buffer_stream.hpp +++ b/Pods/Realm/include/core/realm/util/buffer_stream.hpp @@ -34,7 +34,7 @@ class BasicResettableExpandableOutputStreambuf: public std::basic_stringbuf -inline void BasicResettableExpandableOutputStreambuf::reset() +inline void BasicResettableExpandableOutputStreambuf::reset() noexcept { char_type* pbeg = this->pbase(); char_type* pend = this->epptr(); diff --git a/Pods/Realm/include/core/realm/util/compression.hpp b/Pods/Realm/include/core/realm/util/compression.hpp index 89f3907..0ffb51e 100644 --- a/Pods/Realm/include/core/realm/util/compression.hpp +++ b/Pods/Realm/include/core/realm/util/compression.hpp @@ -32,68 +32,70 @@ namespace compression { enum class error { out_of_memory = 1, - deflate_buffer_too_small = 2, - deflate_error = 3, + compress_buffer_too_small = 2, + compress_error = 3, corrupt_input = 4, - incorrect_inflated_size = 5, - inflate_error = 6 + incorrect_decompressed_size = 5, + decompress_error = 6 }; +const std::error_category& error_category() noexcept; -class error_category: public std::error_category { -public: - const char* name() const noexcept final; - std::string message(int) const final; -}; - -const std::error_category& compression_error_category(); - - -std::error_condition make_error_condition(error); +std::error_code make_error_code(error) noexcept; } // namespace compression } // namespace util } // namespace realm namespace std { - template<> - struct is_error_condition_enum { - static const bool value = true; - }; -} + +template<> struct is_error_code_enum { + static const bool value = true; +}; + +} // namespace std namespace realm { namespace util { namespace compression { -/// deflate_bound() calculates an upper bound on the size of the compressed data. The caller can use this function to -/// allocate memory buffer calling deflate(). -/// \param uncompressed_buf is the buffer with uncompresed data. The size of the uncompressed data is \param -/// uncompressed_size. -/// \param compression_level is described under deflate(). -/// \param bound is set to the upper bound at return. -/// The return value is a error_condition of category compression::error_category. -std::error_condition deflate_bound(const char* uncompressed_buf, size_t uncompressed_size, size_t& bound, int compression_level = 1); - -/// deflate() deflates the data in the \param uncompressed_buf of size \param uncompressed_size -/// into compressed_buf. deflate() resizes compressed_buf. At return, \param compressed_buf has the -/// size of the deflated data. -/// \param compression_level is [1-9] with 1 the fastest for the current zlib implementation. -/// The return value is a error_condition of category compression::error_category. -std::error_condition deflate(const char* uncompressed_buf, size_t uncompressed_size, - char* compressed_buf, size_t compressed_buf_size, - size_t& compressed_size, int compression_level = 1); - -/// inflate() inflates the data in \param compressed_buf of size \param compresed_size into -/// \param decompressed_buf. \param decompressed_size is the expected size of the inflated data. -/// \param decompressed_buf must have size at least \param decompressed_size. -/// inflate() throws on errors, including the error where the size of the decompressed data is unequal to -/// decompressed_size. -/// The return value is a error_condition of category compression::error_category. -std::error_condition inflate(const char* compressed_buf, size_t compressed_size, char* decompressed_buf, size_t decompressed_size); - - +class Alloc { +public: + // Returns null on "out of memory" + virtual void* alloc(std::size_t size) = 0; + virtual void free(void* addr) noexcept = 0; + virtual ~Alloc() {} +}; +/// compress_bound() calculates an upper bound on the size of the compressed +/// data. The caller can use this function to allocate memory buffer calling +/// compress(). \a uncompressed_buf is the buffer with uncompresed data. The +/// size of the uncompressed data is \a uncompressed_size. \a compression_level +/// is described under compress(). \a bound is set to the upper bound at +/// return. The returned error code is of category compression::error_category. +std::error_code compress_bound(const char* uncompressed_buf, size_t uncompressed_size, + size_t& bound, int compression_level = 1); + +/// compress() compresses the data in the \a uncompressed_buf of size \a +/// uncompressed_size into \a compressed_buf. compress() resizes \a +/// compressed_buf. At return, \a compressed_buf has the size of the compressed +/// data. \a compression_level is [1-9] with 1 the fastest for the current zlib +/// implementation. The returned error code is of category +/// compression::error_category. +std::error_code compress(const char* uncompressed_buf, size_t uncompressed_size, + char* compressed_buf, size_t compressed_buf_size, + size_t& compressed_size, int compression_level = 1, + Alloc* custom_allocator = nullptr); + +/// decompress() decompresses the data in \param compressed_buf of size \a +/// compresed_size into \a decompressed_buf. \a decompressed_size is the +/// expected size of the decompressed data. \a decompressed_buf must have size +/// at least \a decompressed_size. decompress() throws on errors, including the +/// error where the size of the decompressed data is unequal to +/// decompressed_size. The returned error code is of category +/// compression::error_category. +std::error_code decompress(const char* compressed_buf, size_t compressed_size, + char* decompressed_buf, size_t decompressed_size); } // namespace compression } // namespace util diff --git a/Pods/Realm/include/core/realm/util/config.h b/Pods/Realm/include/core/realm/util/config.h index 2a670be..970e045 100644 --- a/Pods/Realm/include/core/realm/util/config.h +++ b/Pods/Realm/include/core/realm/util/config.h @@ -8,12 +8,12 @@ #define REALM_VERSION "unknown" -#define REALM_INSTALL_PREFIX "/Users/realm/workspace/core_osx/install" -#define REALM_INSTALL_EXEC_PREFIX "/Users/realm/workspace/core_osx/install" -#define REALM_INSTALL_INCLUDEDIR "/Users/realm/workspace/core_osx/install/include" -#define REALM_INSTALL_BINDIR "/Users/realm/workspace/core_osx/install/bin" -#define REALM_INSTALL_LIBDIR "/Users/realm/workspace/core_osx/install/lib" -#define REALM_INSTALL_LIBEXECDIR "/Users/realm/workspace/core_osx/install/libexec" +#define REALM_INSTALL_PREFIX "/Users/realm/workspace/ealm_realm-core_jed_release-YGQB2PVKDDWIOF4AUR65UBRZXF6KQQXMSIJBK4GREIG4T4XI73JA/install" +#define REALM_INSTALL_EXEC_PREFIX "/Users/realm/workspace/ealm_realm-core_jed_release-YGQB2PVKDDWIOF4AUR65UBRZXF6KQQXMSIJBK4GREIG4T4XI73JA/install" +#define REALM_INSTALL_INCLUDEDIR "/Users/realm/workspace/ealm_realm-core_jed_release-YGQB2PVKDDWIOF4AUR65UBRZXF6KQQXMSIJBK4GREIG4T4XI73JA/install/include" +#define REALM_INSTALL_BINDIR "/Users/realm/workspace/ealm_realm-core_jed_release-YGQB2PVKDDWIOF4AUR65UBRZXF6KQQXMSIJBK4GREIG4T4XI73JA/install/bin" +#define REALM_INSTALL_LIBDIR "/Users/realm/workspace/ealm_realm-core_jed_release-YGQB2PVKDDWIOF4AUR65UBRZXF6KQQXMSIJBK4GREIG4T4XI73JA/install/lib" +#define REALM_INSTALL_LIBEXECDIR "/Users/realm/workspace/ealm_realm-core_jed_release-YGQB2PVKDDWIOF4AUR65UBRZXF6KQQXMSIJBK4GREIG4T4XI73JA/install/libexec" #ifdef REALM_DEBUG # define REALM_MAX_BPNODE_SIZE 1000 diff --git a/Pods/Realm/include/core/realm/util/features.h b/Pods/Realm/include/core/realm/util/features.h index db57b2b..3aab461 100644 --- a/Pods/Realm/include/core/realm/util/features.h +++ b/Pods/Realm/include/core/realm/util/features.h @@ -155,6 +155,14 @@ #define REALM_UNUSED #endif +/* The way to specify that a function is deprecated + * not be used. Use it to suppress a warning from the compiler. */ +#if __GNUC__ +#define REALM_DEPRECATED(x) [[deprecated(x)]] +#else +#define REALM_DEPRECATED(x) __declspec(deprecated(x)) +#endif + #if __GNUC__ || defined __INTEL_COMPILER #define REALM_UNLIKELY(expr) __builtin_expect(!!(expr), 0) diff --git a/Pods/Realm/include/core/realm/util/file.hpp b/Pods/Realm/include/core/realm/util/file.hpp index 4d08e03..5b73585 100644 --- a/Pods/Realm/include/core/realm/util/file.hpp +++ b/Pods/Realm/include/core/realm/util/file.hpp @@ -416,7 +416,13 @@ class File { /// provides the information to unambiguously distinguish that /// particular reason). static void move(const std::string& old_path, const std::string& new_path); - static bool copy(std::string source, std::string destination); + + /// Copy the file at the specified origin path to the specified target path. + static void copy(const std::string& origin_path, const std::string& target_path); + + /// Compare the two files at the specified paths for equality. Returns true + /// if, and only if they are equal. + static bool compare(const std::string& path_1, const std::string& path_2); /// Check whether two open file descriptors refer to the same /// underlying file, that is, if writing via one of them, will diff --git a/Pods/Realm/include/core/realm/util/file_mapper.hpp b/Pods/Realm/include/core/realm/util/file_mapper.hpp index f3375d7..dfb9c05 100644 --- a/Pods/Realm/include/core/realm/util/file_mapper.hpp +++ b/Pods/Realm/include/core/realm/util/file_mapper.hpp @@ -65,7 +65,7 @@ void inline encryption_write_barrier(const void* addr, size_t size, EncryptedFil } -extern util::Mutex mapping_mutex; +extern util::Mutex& mapping_mutex; inline void do_encryption_read_barrier(const void* addr, size_t size, HeaderToSize header_to_size, EncryptedFileMapping* mapping) diff --git a/Pods/Realm/include/core/realm/util/interprocess_mutex.hpp b/Pods/Realm/include/core/realm/util/interprocess_mutex.hpp index 23330b8..83a0489 100644 --- a/Pods/Realm/include/core/realm/util/interprocess_mutex.hpp +++ b/Pods/Realm/include/core/realm/util/interprocess_mutex.hpp @@ -95,8 +95,18 @@ class InterprocessMutex { /// InterprocessMutex created on the same file (same inode on POSIX) share the same LockInfo. /// LockInfo will be saved in a static map as a weak ptr and use the UniqueID as the key. /// Operations on the map need to be protected by s_mutex - static std::map> s_info_map; - static Mutex s_mutex; + static std::map>* s_info_map; + static Mutex* s_mutex; + /// We manually initialize these static variables when first needed, + /// creating them on the heap so that they last for the entire lifetime + /// of the process. The destructor of these is never called; the + /// process will clean up their memory when exiting. It is not enough + /// to count instances of InterprocessMutex and clean up these statics when + /// the count reaches zero because the program can create more + /// InterprocessMutex instances before the process ends, so we really need + /// these variables for the entire lifetime of the process. + static std::once_flag s_init_flag; + static void initialize_statics(); /// Only used for release_shared_part std::string m_filename; @@ -107,14 +117,16 @@ class InterprocessMutex { /// If it is the last reference, underly resources will be freed as well. void free_lock_info(); #else - SharedPart* m_shared_part = 0; + SharedPart* m_shared_part = nullptr; #endif friend class InterprocessCondVar; }; - inline InterprocessMutex::InterprocessMutex() { +#ifdef REALM_ROBUST_MUTEX_EMULATION + std::call_once(s_init_flag, initialize_statics); +#endif } inline InterprocessMutex::~InterprocessMutex() noexcept @@ -138,14 +150,19 @@ inline void InterprocessMutex::free_lock_info() if (!m_lock_info) return; - std::lock_guard guard(s_mutex); + std::lock_guard guard(*s_mutex); m_lock_info.reset(); - if (s_info_map[m_fileuid].expired()) { - s_info_map.erase(m_fileuid); + if ((*s_info_map)[m_fileuid].expired()) { + s_info_map->erase(m_fileuid); } m_filename.clear(); } + +inline void InterprocessMutex::initialize_statics() { + s_mutex = new Mutex(); + s_info_map = new std::map>(); +} #endif inline void InterprocessMutex::set_shared_part(SharedPart& shared_part, const std::string& path, @@ -158,12 +175,12 @@ inline void InterprocessMutex::set_shared_part(SharedPart& shared_part, const st m_filename = path + "." + mutex_name + ".mx"; - std::lock_guard guard(s_mutex); + std::lock_guard guard(*s_mutex); // Try to get the file uid if the file exists if (File::get_unique_id(m_filename, m_fileuid)) { - auto result = s_info_map.find(m_fileuid); - if (result != s_info_map.end()) { + auto result = s_info_map->find(m_fileuid); + if (result != s_info_map->end()) { // File exists and the lock info has been created in the map. m_lock_info = result->second.lock(); return; @@ -177,7 +194,7 @@ inline void InterprocessMutex::set_shared_part(SharedPart& shared_part, const st m_lock_info->m_file.open(m_filename, File::mode_Write); m_fileuid = m_lock_info->m_file.get_unique_id(); - s_info_map[m_fileuid] = m_lock_info; + (*s_info_map)[m_fileuid] = m_lock_info; #else m_shared_part = &shared_part; static_cast(path); @@ -192,14 +209,14 @@ inline void InterprocessMutex::set_shared_part(SharedPart& shared_part, File&& l free_lock_info(); - std::lock_guard guard(s_mutex); + std::lock_guard guard(*s_mutex); m_fileuid = lock_file.get_unique_id(); - auto result = s_info_map.find(m_fileuid); - if (result == s_info_map.end()) { + auto result = s_info_map->find(m_fileuid); + if (result == s_info_map->end()) { m_lock_info = std::make_shared(); m_lock_info->m_file = std::move(lock_file); - s_info_map[m_fileuid] = m_lock_info; + (*s_info_map)[m_fileuid] = m_lock_info; } else { // File exists and the lock info has been created in the map. diff --git a/Pods/Realm/include/core/realm/util/network.hpp b/Pods/Realm/include/core/realm/util/network.hpp index a908cd3..ae3a1a8 100644 --- a/Pods/Realm/include/core/realm/util/network.hpp +++ b/Pods/Realm/include/core/realm/util/network.hpp @@ -39,8 +39,42 @@ #include #include +// Linux epoll +// +// Require Linux kernel version >= 2.6.27 such that we have epoll_create1(), +// `O_CLOEXEC`, and `EPOLLRDHUP`. +#if defined(__linux__) +# include +# if !defined(REALM_HAVE_EPOLL) +# if !defined(REALM_DISABLE_UTIL_NETWORK_EPOLL) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +# define REALM_HAVE_EPOLL 1 +# endif +# endif +# endif +#endif +#if !defined(REALM_HAVE_EPOLL) +# define REALM_HAVE_EPOLL 0 +#endif + +// FreeBSD Kqueue. +// +// Available on Mac OS X, FreeBSD, NetBSD, OpenBSD +#if (defined(__MACH__) && defined(__APPLE__)) || defined(__FreeBSD__) || \ + defined(__NetBSD__) || defined(__OpenBSD__) +# if !defined(REALM_HAVE_KQUEUE) +# if !defined(REALM_DISABLE_UTIL_NETWORK_KQUEUE) +# define REALM_HAVE_KQUEUE 1 +# endif +# endif +#endif +#if !defined(REALM_HAVE_KQUEUE) +# define REALM_HAVE_KQUEUE 0 +#endif + + -// FIXME: Unfinished business around `ip_address.m_ip_v6_scope_id`. +// FIXME: Unfinished business around `Address::m_ip_v6_scope_id`. namespace realm { @@ -55,15 +89,14 @@ namespace util { /// ### Thread safety /// /// A *service context* is a set of objects consisting of an instance of -/// io_service, and all the objects that are associated with that instance (\ref -/// resolver, \ref acceptor`, \ref socket`, \ref deadline_timer, and \ref +/// Service, and all the objects that are associated with that instance (\ref +/// Resolver, \ref Socket`, \ref Acceptor`, \ref DeadlineTimer, and \ref /// ssl::Stream). /// /// In general, it is unsafe for two threads to call functions on the same /// object, or on different objects in the same service context. This also /// applies to destructors. Notable exceptions are the fully thread-safe -/// functions, such as io_service::post(), io_service::stop(), and -/// io_service::reset(). +/// functions, such as Service::post(), Service::stop(), and Service::reset(). /// /// On the other hand, it is always safe for two threads to call functions on /// objects belonging to different service contexts. @@ -73,12 +106,12 @@ namespace util { /// thread is allowed to access objects in the same service context (with the /// mentioned exceptions). /// -/// Unless otherwise specified, free-staing objects, such as \ref -/// stream_protocol, \ref ip_address, \ref endpoint, and \ref endpoint::list are +/// Unless otherwise specified, free-standing objects, such as \ref +/// StreamProtocol, \ref Address, \ref Endpoint, and \ref Endpoint::List are /// fully thread-safe as long as they are not mutated. If one thread is mutating /// such an object, no other thread may access it. Note that these free-standing -/// objects are not associcated with an instance of io_service, and are -/// therefore not part of a service context. +/// objects are not associcated with an instance of Service, and are therefore +/// not part of a service context. /// /// /// ### Comparison with ASIO @@ -91,15 +124,15 @@ namespace util { /// until that point in time. In particular, if `cancel()` is called on a socket /// or a deadline timer object before the completion handler starts to execute, /// then that operation will be canceled, and will receive -/// `error::operation_aborted`. This guarantee is possible (and free of -/// ambiguities) precisely because this library prohibits multiple threads from -/// executing the event loop concurrently, and because `cancel()` is allowed to -/// be called only from a completion handler (executed by the event loop thread) -/// or while no thread is executing the event loop. This guarantee allows for -/// safe destruction of sockets and deadline timers as long as the completion -/// handlers react appropriately to `error::operation_aborted`, in particular, -/// that they do not attempt to access the socket or deadline timer object in -/// such cases. +/// `error::operation_aborted`. This guarantee is possible to provide (and free +/// of ambiguities) precisely because this library prohibits multiple threads +/// from executing the event loop concurrently, and because `cancel()` is +/// allowed to be called only from a completion handler (executed by the event +/// loop thread) or while no thread is executing the event loop. This guarantee +/// allows for safe destruction of sockets and deadline timers as long as the +/// completion handlers react appropriately to `error::operation_aborted`, in +/// particular, that they do not attempt to access the socket or deadline timer +/// object in such cases. /// /// ASIO, on the other hand, allows for an asynchronous operation to complete /// and become **uncancellable** before the completion handler starts to @@ -115,22 +148,22 @@ namespace util { /// /// IMPORTANT: Even if ASIO is used in a way where at most one thread executes /// the event loop, there is still no guarantee that an asynchronous operation -/// remains cancelable up until the point in timer where the completion handler +/// remains cancelable up until the point in time where the completion handler /// starts to execute. namespace network { std::string host_name(); -class stream_protocol; -class ip_address; -class endpoint; -class io_service; -class resolver; -class socket_base; -class socket; -class acceptor; -class deadline_timer; +class StreamProtocol; +class Address; +class Endpoint; +class Service; +class Resolver; +class SocketBase; +class Socket; +class Acceptor; +class DeadlineTimer; class ReadAheadBuffer; namespace ssl { class Stream; @@ -138,10 +171,10 @@ class Stream; /// \brief An IP protocol descriptor. -class stream_protocol { +class StreamProtocol { public: - static stream_protocol ip_v4(); - static stream_protocol ip_v6(); + static StreamProtocol ip_v4(); + static StreamProtocol ip_v6(); bool is_ip_v4() const; bool is_ip_v6() const; @@ -149,34 +182,34 @@ class stream_protocol { int protocol() const; int family() const; - stream_protocol(); - ~stream_protocol() noexcept {} + StreamProtocol(); + ~StreamProtocol() noexcept {} private: int m_family; int m_socktype; int m_protocol; - friend class resolver; - friend class socket_base; + friend class Resolver; + friend class SocketBase; }; /// \brief An IP address (IPv4 or IPv6). -class ip_address { +class Address { public: bool is_ip_v4() const; bool is_ip_v6() const; template - friend std::basic_ostream& operator<<(std::basic_ostream&, const ip_address&); + friend std::basic_ostream& operator<<(std::basic_ostream&, const Address&); - ip_address(); - ~ip_address() noexcept {} + Address(); + ~Address() noexcept {} private: - typedef in_addr ip_v4_type; - typedef in6_addr ip_v6_type; + using ip_v4_type = in_addr; + using ip_v6_type = in6_addr; union union_type { ip_v4_type m_ip_v4; ip_v6_type m_ip_v6; @@ -185,39 +218,39 @@ class ip_address { std::uint_least32_t m_ip_v6_scope_id = 0; bool m_is_ip_v6 = false; - friend ip_address make_address(const char*, std::error_code&) noexcept; - friend class endpoint; + friend Address make_address(const char*, std::error_code&) noexcept; + friend class Endpoint; }; -ip_address make_address(const char* c_str); -ip_address make_address(const char* c_str, std::error_code& ec) noexcept; -ip_address make_address(const std::string&); -ip_address make_address(const std::string&, std::error_code& ec) noexcept; +Address make_address(const char* c_str); +Address make_address(const char* c_str, std::error_code& ec) noexcept; +Address make_address(const std::string&); +Address make_address(const std::string&, std::error_code& ec) noexcept; /// \brief An IP endpoint. /// /// An IP endpoint is a triplet (`protocol`, `address`, `port`). -class endpoint { +class Endpoint { public: - using port_type = uint_fast16_t; - class list; + using port_type = std::uint_fast16_t; + class List; - stream_protocol protocol() const; - ip_address address() const; + StreamProtocol protocol() const; + Address address() const; port_type port() const; - endpoint(); - endpoint(const stream_protocol&, port_type); - endpoint(const ip_address&, port_type); - ~endpoint() noexcept {} + Endpoint(); + Endpoint(const StreamProtocol&, port_type); + Endpoint(const Address&, port_type); + ~Endpoint() noexcept {} using data_type = sockaddr; data_type* data(); const data_type* data() const; private: - stream_protocol m_protocol; + StreamProtocol m_protocol; using sockaddr_base_type = sockaddr; using sockaddr_ip_v4_type = sockaddr_in; @@ -229,38 +262,38 @@ class endpoint { }; sockaddr_union_type m_sockaddr_union; - friend class resolver; - friend class socket_base; - friend class socket; - friend class acceptor; + friend class Service; + friend class Resolver; + friend class SocketBase; + friend class Socket; }; /// \brief A list of IP endpoints. -class endpoint::list { +class Endpoint::List { public: - typedef const endpoint* iterator; + using iterator = const Endpoint*; iterator begin() const; iterator end() const; - size_t size() const; + std::size_t size() const; - list() = default; - list(list&&) noexcept = default; - ~list() noexcept = default; + List() = default; + List(List&&) noexcept = default; + ~List() noexcept = default; private: - Buffer m_endpoints; + Buffer m_endpoints; - friend class resolver; + friend class Resolver; }; /// \brief TCP/IP networking service. -class io_service { +class Service { public: - io_service(); - ~io_service() noexcept; + Service(); + ~Service() noexcept; /// \brief Execute the event loop. /// @@ -278,7 +311,7 @@ class io_service { /// Exceptions thrown by completion handlers will always propagate back /// through run(). /// - /// Syncronous operations (e.g., socket::connect()) execute independently of + /// Syncronous operations (e.g., Socket::connect()) execute independently of /// the event loop, and do not require that any thread calls run(). void run(); @@ -330,82 +363,162 @@ class io_service { private: enum class Want { nothing = 0, read, write }; - class async_oper; - class wait_oper_base; - class post_oper_base; - template class post_oper; + template class OperQueue; + class Descriptor; + class AsyncOper; + class WaitOperBase; + class PostOperBase; + template class PostOper; class IoOper; class UnusedOper; // Allocated, but currently unused memory - template class OperQueue; template class BasicStreamOps; struct OwnersOperDeleter { - void operator()(async_oper*) const noexcept; + void operator()(AsyncOper*) const noexcept; }; struct LendersOperDeleter { - void operator()(async_oper*) const noexcept; + void operator()(AsyncOper*) const noexcept; }; - using OwnersOperPtr = std::unique_ptr; - using LendersOperPtr = std::unique_ptr; - using LendersWaitOperPtr = std::unique_ptr; - using LendersIoOperPtr = std::unique_ptr; + using OwnersOperPtr = std::unique_ptr; + using LendersOperPtr = std::unique_ptr; + using LendersWaitOperPtr = std::unique_ptr; + using LendersIoOperPtr = std::unique_ptr; - class impl; - const std::unique_ptr m_impl; + class IoReactor; + class Impl; + const std::unique_ptr m_impl; template static std::unique_ptr alloc(OwnersOperPtr&, Args&&...); template static void execute(std::unique_ptr&); - template - static void initiate_io_oper(std::unique_ptr, Args&&...); - - enum io_op { io_op_Read, io_op_Write }; - void add_io_oper(int fd, LendersIoOperPtr, io_op type); - void add_wait_oper(LendersWaitOperPtr); - void add_completed_oper(LendersOperPtr) noexcept; - void cancel_incomplete_io_ops(int fd) noexcept; - - using PostOperConstr = post_oper_base*(void* addr, size_t size, impl&, void* cookie); - void do_post(PostOperConstr, size_t size, void* cookie); + using PostOperConstr = PostOperBase*(void* addr, std::size_t size, Impl&, void* cookie); + void do_post(PostOperConstr, std::size_t size, void* cookie); template - static post_oper_base* post_oper_constr(void* addr, size_t size, impl&, void* cookie); - static void recycle_post_oper(impl&, post_oper_base*) noexcept; + static PostOperBase* post_oper_constr(void* addr, std::size_t size, Impl&, void* cookie); + static void recycle_post_oper(Impl&, PostOperBase*) noexcept; using clock = std::chrono::steady_clock; - friend class socket_base; - friend class socket; - friend class acceptor; - friend class deadline_timer; + friend class Resolver; + friend class SocketBase; + friend class Socket; + friend class Acceptor; + friend class DeadlineTimer; friend class ReadAheadBuffer; friend class ssl::Stream; }; -class resolver { +template class Service::OperQueue { +public: + using LendersOperPtr = std::unique_ptr; + bool empty() const noexcept; + void push_back(LendersOperPtr) noexcept; + template void push_back(OperQueue&) noexcept; + LendersOperPtr pop_front() noexcept; + void clear() noexcept; + OperQueue() noexcept = default; + OperQueue(OperQueue&&) noexcept; + ~OperQueue() noexcept; +private: + Oper* m_back = nullptr; + template friend class OperQueue; +}; + + +class Service::Descriptor { +public: + using native_handle_type = int; + + Impl& service_impl; + + Descriptor(Impl& service) noexcept; + ~Descriptor() noexcept; + + /// \param in_blocking_mode Must be true if, and only if the passed file + /// descriptor refers to a file description in which the file status flag + /// O_NONBLOCK is not set. + /// + /// The passed file descriptor must have the file descriptor flag FD_CLOEXEC + /// set. + void assign(int fd, bool in_blocking_mode) noexcept; + void close() noexcept; + + bool is_open() const noexcept; + + native_handle_type native_handle() const noexcept; + bool in_blocking_mode() const noexcept; + + void accept(Descriptor&, StreamProtocol, Endpoint*, std::error_code&) noexcept; + std::size_t read_some(char* buffer, std::size_t size, std::error_code&) noexcept; + std::size_t write_some(const char* data, std::size_t size, std::error_code&) noexcept; + + /// \tparam Oper An operation type inherited from IoOper with an initate() + /// function that initiates the operation and figures out whether it needs + /// to read from, or write to the underlying descriptor to + /// proceed. `initiate()` must return Want::read if the operation needs to + /// read, or Want::write if the operation needs to write. If the operation + /// completes immediately (e.g. due to a failure during initialization), + /// `initiate()` must return Want::nothing. + template + void initiate_oper(std::unique_ptr, Args&&...); + + void ensure_blocking_mode(); + void ensure_nonblocking_mode(); + +private: + int m_fd = -1; + bool m_in_blocking_mode; // Not in nonblocking mode + +#if REALM_HAVE_EPOLL || REALM_HAVE_KQUEUE + bool m_read_ready; + bool m_write_ready; + bool m_imminent_end_of_input; // Kernel has seen the end of input + bool m_is_registered; + OperQueue m_suspended_read_ops, m_suspended_write_ops; + + void deregister_for_async() noexcept; +#endif + + bool assume_read_would_block() const noexcept; + bool assume_write_would_block() const noexcept; + + void set_read_ready(bool) noexcept; + void set_write_ready(bool) noexcept; + + void set_nonblock_flag(bool value); + void add_initiated_oper(LendersIoOperPtr, Want); + + void do_close() noexcept; + + friend class IoReactor; +}; + + +class Resolver { public: - class query; + class Query; - resolver(io_service&); - ~resolver() noexcept {} + Resolver(Service&); + ~Resolver() noexcept {} /// Thread-safe. - io_service& get_io_service() noexcept; + Service& get_service() noexcept; /// @{ \brief Resolve the specified query to one or more endpoints. - void resolve(const query&, endpoint::list&); - std::error_code resolve(const query&, endpoint::list&, std::error_code&); + void resolve(const Query&, Endpoint::List&); + std::error_code resolve(const Query&, Endpoint::List&, std::error_code&); /// @} private: - io_service& m_service; + Service::Impl& m_service_impl; }; -class resolver::query { +class Resolver::Query { public: enum { /// Locally bound socket endpoint (server side) @@ -415,45 +528,48 @@ class resolver::query { address_configured = AI_ADDRCONFIG }; - query(std::string service_port, int init_flags = passive|address_configured); - query(const stream_protocol&, std::string service_port, + Query(std::string service_port, int init_flags = passive|address_configured); + Query(const StreamProtocol&, std::string service_port, int init_flags = passive|address_configured); - query(std::string host_name, std::string service_port, + Query(std::string host_name, std::string service_port, int init_flags = address_configured); - query(const stream_protocol&, std::string host_name, std::string service_port, + Query(const StreamProtocol&, std::string host_name, std::string service_port, int init_flags = address_configured); - ~query() noexcept; + ~Query() noexcept; int flags() const; - stream_protocol protocol() const; + StreamProtocol protocol() const; std::string host() const; std::string service() const; private: int m_flags; - stream_protocol m_protocol; + StreamProtocol m_protocol; std::string m_host; // hostname std::string m_service; // port - friend class resolver; + friend class Resolver; }; -class socket_base { +class SocketBase { public: - ~socket_base() noexcept; + using native_handle_type = Service::Descriptor::native_handle_type; + + ~SocketBase() noexcept; /// Thread-safe. - io_service& get_io_service() noexcept; + Service& get_service() noexcept; bool is_open() const noexcept; + native_handle_type native_handle() const noexcept; /// @{ \brief Open the socket for use with the specified protocol. /// /// It is an error to call open() on a socket that is already open. - void open(const stream_protocol&); - std::error_code open(const stream_protocol&, std::error_code&); + void open(const StreamProtocol&); + std::error_code open(const StreamProtocol&, std::error_code&); /// @} /// \brief Close this socket. @@ -491,11 +607,11 @@ class socket_base { template std::error_code set_option(const O& opt, std::error_code&); - void bind(const endpoint&); - std::error_code bind(const endpoint&, std::error_code&); + void bind(const Endpoint&); + std::error_code bind(const Endpoint&, std::error_code&); - endpoint local_endpoint() const; - endpoint local_endpoint(std::error_code&) const; + Endpoint local_endpoint() const; + Endpoint local_endpoint(std::error_code&) const; private: enum opt_enum { @@ -503,65 +619,54 @@ class socket_base { opt_Linger, ///< `SOL_SOCKET`, `SO_LINGER` }; - template class option; + template class Option; public: - typedef option reuse_address; + using reuse_address = Option; // linger struct defined by POSIX sys/socket.h. struct linger_opt; - typedef option linger; + using linger = Option; + +protected: + Service::Descriptor m_desc; private: - int m_sock_fd; - bool m_in_blocking_mode; // Not in nonblocking mode - stream_protocol m_protocol; + StreamProtocol m_protocol; protected: - io_service& m_service; - io_service::OwnersOperPtr m_read_oper; // Read or accept - io_service::OwnersOperPtr m_write_oper; // Write or connect + Service::OwnersOperPtr m_read_oper; // Read or accept + Service::OwnersOperPtr m_write_oper; // Write or connect - socket_base(io_service&); + SocketBase(Service&); - int get_sock_fd() const noexcept; - const stream_protocol& get_protocol() const noexcept; - std::error_code do_assign(const stream_protocol&, int sock_fd, std::error_code& ec); + const StreamProtocol& get_protocol() const noexcept; + std::error_code do_assign(const StreamProtocol&, int sock_fd, std::error_code& ec); void do_close() noexcept; - void get_option(opt_enum, void* value_data, size_t& value_size, std::error_code&) const; - void set_option(opt_enum, const void* value_data, size_t value_size, std::error_code&); + void get_option(opt_enum, void* value_data, std::size_t& value_size, std::error_code&) const; + void set_option(opt_enum, const void* value_data, std::size_t value_size, std::error_code&); void map_option(opt_enum, int& level, int& option_name) const; - // `ec` untouched on success - std::error_code ensure_blocking_mode(std::error_code& ec) noexcept; - std::error_code ensure_nonblocking_mode(std::error_code& ec) noexcept; - -private: - // `ec` untouched on success - std::error_code set_nonblocking_mode(bool enable, std::error_code&) noexcept; - - friend class io_service; - friend class acceptor; + friend class Acceptor; }; -template -class socket_base::option { +template class SocketBase::Option { public: - option(T value = T()); + Option(T value = T()); T value() const; private: T m_value; - void get(const socket_base&, std::error_code&); - void set(socket_base&, std::error_code&) const; + void get(const SocketBase&, std::error_code&); + void set(SocketBase&, std::error_code&) const; - friend class socket_base; + friend class SocketBase; }; -struct socket_base::linger_opt { +struct SocketBase::linger_opt { linger_opt(bool enable, int timeout_seconds = 0) { m_linger.l_onoff = enable ? 1 : 0; @@ -582,23 +687,21 @@ struct socket_base::linger_opt { /// allowed to run concurrently with an asynchronous one on the same /// socket. Note that an asynchronous operation is considered to be running /// until its completion handler starts executing. -class socket: public socket_base { +class Socket: public SocketBase { public: - using native_handle_type = int; - - socket(io_service&); + Socket(Service&); /// \brief Create a socket with an already-connected native socket handle. /// /// This constructor is shorthand for creating the socket with the /// one-argument constructor, and then calling the two-argument assign() /// with the specified protocol and native handle. - socket(io_service&, const stream_protocol&, native_handle_type); + Socket(Service&, const StreamProtocol&, native_handle_type); - ~socket() noexcept; + ~Socket() noexcept; - void connect(const endpoint&); - std::error_code connect(const endpoint&, std::error_code&); + void connect(const Endpoint&); + std::error_code connect(const Endpoint&, std::error_code&); /// @{ \brief Perform a synchronous read operation. /// @@ -631,13 +734,12 @@ class socket: public socket_base { /// /// \return The number of bytes places in the specified buffer upon return. std::size_t read(char* buffer, std::size_t size); - std::size_t read(char* buffer, std::size_t size, std::error_code& ec) noexcept; + std::size_t read(char* buffer, std::size_t size, std::error_code& ec); std::size_t read(char* buffer, std::size_t size, ReadAheadBuffer&); - std::size_t read(char* buffer, std::size_t size, ReadAheadBuffer&, - std::error_code& ec) noexcept; + std::size_t read(char* buffer, std::size_t size, ReadAheadBuffer&, std::error_code& ec); std::size_t read_until(char* buffer, std::size_t size, char delim, ReadAheadBuffer&); std::size_t read_until(char* buffer, std::size_t size, char delim, ReadAheadBuffer&, - std::error_code& ec) noexcept; + std::error_code& ec); /// @} /// @{ \brief Perform a synchronous write operation. @@ -654,7 +756,7 @@ class socket: public socket_base { /// failure. On success it returns \a size. On faulure it returns the number /// of bytes written before the failure occured. std::size_t write(const char* data, std::size_t size); - std::size_t write(const char* data, std::size_t size, std::error_code& ec) noexcept; + std::size_t write(const char* data, std::size_t size, std::error_code& ec); /// @} /// @{ \brief Read at least one byte from this socket. @@ -691,8 +793,8 @@ class socket: public socket_base { /// always return a value that is greater than zero, while the three /// argument version will return a value greater than zero when, and only /// when \a ec is set to indicate success (no error, and no end of input). - size_t read_some(char* buffer, size_t size); - size_t read_some(char* buffer, size_t size, std::error_code& ec) noexcept; + std::size_t read_some(char* buffer, std::size_t size); + std::size_t read_some(char* buffer, std::size_t size, std::error_code& ec); /// @} /// @{ \brief Write at least one byte to this socket. @@ -723,8 +825,8 @@ class socket: public socket_base { /// always return a value that is greater than zero, while the three /// argument version will return a value greater than zero when, and only /// when \a ec is set to indicate success. - size_t write_some(const char* data, size_t size); - size_t write_some(const char* data, size_t size, std::error_code&) noexcept; + std::size_t write_some(const char* data, std::size_t size); + std::size_t write_some(const char* data, std::size_t size, std::error_code&); /// @} /// \brief Perform an asynchronous connect operation. @@ -734,15 +836,15 @@ class socket: public socket_base { /// connection is established, or an error occurs. /// /// The completion handler is always executed by the event loop thread, - /// i.e., by a thread that is executing io_service::run(). Conversely, the + /// i.e., by a thread that is executing Service::run(). Conversely, the /// completion handler is guaranteed to not be called while no thread is - /// executing io_service::run(). The execution of the completion handler is + /// executing Service::run(). The execution of the completion handler is /// always deferred to the event loop, meaning that it never happens as a /// synchronous side effect of the execution of async_connect(), even when /// async_connect() is executed by the event loop thread. The completion /// handler is guaranteed to be called eventually, as long as there is time /// enough for the operation to complete or fail, and a thread is executing - /// io_service::run() for long enough. + /// Service::run() for long enough. /// /// The operation can be canceled by calling cancel(), and will be /// automatically canceled if the socket is closed. If the operation is @@ -770,7 +872,7 @@ class socket: public socket_base { /// completion handler starts to execute. /// /// \param ep The remote endpoint of the connection to be established. - template void async_connect(const endpoint& ep, H handler); + template void async_connect(const Endpoint& ep, H handler); /// @{ \brief Perform an asynchronous read operation. /// @@ -797,16 +899,16 @@ class socket: public socket_base { /// buffer is passed to the next read operation. /// /// The completion handler is always executed by the event loop thread, - /// i.e., by a thread that is executing io_service::run(). Conversely, the + /// i.e., by a thread that is executing Service::run(). Conversely, the /// completion handler is guaranteed to not be called while no thread is - /// executing io_service::run(). The execution of the completion handler is + /// executing Service::run(). The execution of the completion handler is /// always deferred to the event loop, meaning that it never happens as a /// synchronous side effect of the execution of async_read() or /// async_read_until(), even when async_read() or async_read_until() is /// executed by the event loop thread. The completion handler is guaranteed /// to be called eventually, as long as there is time enough for the - /// operation to complete or fail, and a thread is executing - /// io_service::run() for long enough. + /// operation to complete or fail, and a thread is executing Service::run() + /// for long enough. /// /// The operation can be canceled by calling cancel() on the associated /// socket, and will be automatically canceled if the associated socket is @@ -847,15 +949,15 @@ class socket: public socket_base { /// the specified bytes have been written to the socket, or an error occurs. /// /// The completion handler is always executed by the event loop thread, - /// i.e., by a thread that is executing io_service::run(). Conversely, the + /// i.e., by a thread that is executing Service::run(). Conversely, the /// completion handler is guaranteed to not be called while no thread is - /// executing io_service::run(). The execution of the completion handler is + /// executing Service::run(). The execution of the completion handler is /// always deferred to the event loop, meaning that it never happens as a /// synchronous side effect of the execution of async_write(), even when /// async_write() is executed by the event loop thread. The completion /// handler is guaranteed to be called eventually, as long as there is time /// enough for the operation to complete or fail, and a thread is executing - /// io_service::run() for long enough. + /// Service::run() for long enough. /// /// The operation can be canceled by calling cancel(), and will be /// automatically canceled if the socket is closed. If the operation is @@ -869,8 +971,9 @@ class socket: public socket_base { /// /// The specified handler will be executed by an expression on the form /// `handler(ec, n)` where `ec` is the error code, and `n` is the number of - /// bytes written (of type `size_t`). If the the handler object is movable, - /// it will never be copied. Otherwise, it will be copied as necessary. + /// bytes written (of type `std::size_t`). If the the handler object is + /// movable, it will never be copied. Otherwise, it will be copied as + /// necessary. /// /// It is an error to start an asynchronous write operation before the /// socket is connected. @@ -881,7 +984,7 @@ class socket: public socket_base { /// completion handler starts to execute. This means that a new write /// operation can be started from the completion handler of another /// asynchronous write operation. - template void async_write(const char* data, size_t size, H handler); + template void async_write(const char* data, std::size_t size, H handler); template void async_read_some(char* buffer, std::size_t size, H handler); template void async_write_some(const char* data, std::size_t size, H handler); @@ -903,7 +1006,7 @@ class socket: public socket_base { /// It is an error to call this function when the socket is not both open /// and connected. void shutdown(shutdown_type); - std::error_code shutdown(shutdown_type, std::error_code&) noexcept; + std::error_code shutdown(shutdown_type, std::error_code&); /// @} /// @{ \brief Initialize socket with an already-connected native socket @@ -922,32 +1025,29 @@ class socket: public socket_base { /// /// It is an error to call this function on a socket object that is already /// open. - void assign(const stream_protocol&, native_handle_type); - std::error_code assign(const stream_protocol&, native_handle_type, std::error_code&); + void assign(const StreamProtocol&, native_handle_type); + std::error_code assign(const StreamProtocol&, native_handle_type, std::error_code&); /// @} /// Returns a reference to this socket, as this socket is the lowest layer /// of a stream. - socket& lowest_layer() noexcept; + Socket& lowest_layer() noexcept; private: - using Want = io_service::Want; - using StreamOps = io_service::BasicStreamOps; + using Want = Service::Want; + using StreamOps = Service::BasicStreamOps; class ConnectOperBase; template class ConnectOper; - using LendersConnectOperPtr = - std::unique_ptr; + using LendersConnectOperPtr = std::unique_ptr; // `ec` untouched on success, but no immediate completion - bool initiate_async_connect(const endpoint&, std::error_code& ec) noexcept; + bool initiate_async_connect(const Endpoint&, std::error_code& ec); // `ec` untouched on success std::error_code finalize_async_connect(std::error_code& ec) noexcept; - // See io_service::BasicStreamOps for details on these these 8 functions. - void do_init_read_sync(std::error_code&) noexcept; - void do_init_write_sync(std::error_code&) noexcept; + // See Service::BasicStreamOps for details on these these 6 functions. void do_init_read_async(std::error_code&, Want&) noexcept; void do_init_write_async(std::error_code&, Want&) noexcept; std::size_t do_read_some_sync(char* buffer, std::size_t size, @@ -959,8 +1059,8 @@ class socket: public socket_base { std::size_t do_write_some_async(const char* data, std::size_t size, std::error_code&, Want&) noexcept; - friend class io_service::BasicStreamOps; - friend class io_service::BasicStreamOps; + friend class Service::BasicStreamOps; + friend class Service::BasicStreamOps; friend class ReadAheadBuffer; friend class ssl::Stream; }; @@ -971,20 +1071,20 @@ class socket: public socket_base { /// allowed to run concurrently with an asynchronous one on the same /// acceptor. Note that an asynchronous operation is considered to be running /// until its completion handler starts executing. -class acceptor: public socket_base { +class Acceptor: public SocketBase { public: - acceptor(io_service&); - ~acceptor() noexcept; + Acceptor(Service&); + ~Acceptor() noexcept; static constexpr int max_connections = SOMAXCONN; void listen(int backlog = max_connections); std::error_code listen(int backlog, std::error_code&); - void accept(socket&); - void accept(socket&, endpoint&); - std::error_code accept(socket&, std::error_code&); - std::error_code accept(socket&, endpoint&, std::error_code&); + void accept(Socket&); + void accept(Socket&, Endpoint&); + std::error_code accept(Socket&, std::error_code&); + std::error_code accept(Socket&, Endpoint&, std::error_code&); /// @{ \brief Perform an asynchronous accept operation. /// @@ -995,15 +1095,15 @@ class acceptor: public socket_base { /// socket. /// /// The completion handler is always executed by the event loop thread, - /// i.e., by a thread that is executing io_service::run(). Conversely, the + /// i.e., by a thread that is executing Service::run(). Conversely, the /// completion handler is guaranteed to not be called while no thread is - /// executing io_service::run(). The execution of the completion handler is + /// executing Service::run(). The execution of the completion handler is /// always deferred to the event loop, meaning that it never happens as a /// synchronous side effect of the execution of async_accept(), even when /// async_accept() is executed by the event loop thread. The completion /// handler is guaranteed to be called eventually, as long as there is time /// enough for the operation to complete or fail, and a thread is executing - /// io_service::run() for long enough. + /// Service::run() for long enough. /// /// The operation can be canceled by calling cancel(), and will be /// automatically canceled if the acceptor is closed. If the operation is @@ -1028,38 +1128,37 @@ class acceptor: public socket_base { /// /// \param sock This is the local socket, that upon successful completion /// will have become connected to the remote socket. It must be in the - /// closed state (socket::is_open()) when async_accept() is called. + /// closed state (Socket::is_open()) when async_accept() is called. /// /// \param ep Upon completion, the remote peer endpoint will have been /// assigned to this variable. - template void async_accept(socket& sock, H handler); - template void async_accept(socket& sock, endpoint& ep, H handler); + template void async_accept(Socket& sock, H handler); + template void async_accept(Socket& sock, Endpoint& ep, H handler); /// @} private: - using Want = io_service::Want; + using Want = Service::Want; class AcceptOperBase; template class AcceptOper; - using LendersAcceptOperPtr = std::unique_ptr; + using LendersAcceptOperPtr = std::unique_ptr; - std::error_code accept(socket&, endpoint*, std::error_code&); - void do_accept_sync(socket&, endpoint*, std::error_code&) noexcept; - Want do_accept_async(socket&, endpoint*, std::error_code&) noexcept; + std::error_code accept(Socket&, Endpoint*, std::error_code&); + Want do_accept_async(Socket&, Endpoint*, std::error_code&) noexcept; - template void async_accept(socket&, endpoint*, H); + template void async_accept(Socket&, Endpoint*, H); }; /// \brief A timer object supporting asynchronous wait operations. -class deadline_timer { +class DeadlineTimer { public: - deadline_timer(io_service&); - ~deadline_timer() noexcept; + DeadlineTimer(Service&); + ~DeadlineTimer() noexcept; /// Thread-safe. - io_service& get_io_service() noexcept; + Service& get_service() noexcept; /// \brief Perform an asynchronous wait operation. /// @@ -1071,15 +1170,15 @@ class deadline_timer { /// expiration time was reached. /// /// The completion handler is always executed by the event loop thread, - /// i.e., by a thread that is executing io_service::run(). Conversely, the + /// i.e., by a thread that is executing Service::run(). Conversely, the /// completion handler is guaranteed to not be called while no thread is - /// executing io_service::run(). The execution of the completion handler is + /// executing Service::run(). The execution of the completion handler is /// always deferred to the event loop, meaning that it never happens as a /// synchronous side effect of the execution of async_wait(), even when /// async_wait() is executed by the event loop thread. The completion /// handler is guaranteed to be called eventually, as long as there is time /// enough for the operation to complete or fail, and a thread is executing - /// io_service::run() for long enough. + /// Service::run() for long enough. /// /// The operation can be canceled by calling cancel(), and will be /// automatically canceled if the timer is destroyed. If the operation is @@ -1115,12 +1214,14 @@ class deadline_timer { void cancel() noexcept; private: - template class wait_oper; + template class WaitOper; + + using clock = Service::clock; - using clock = io_service::clock; + Service::Impl& m_service_impl; + Service::OwnersOperPtr m_wait_oper; - io_service& m_service; - io_service::OwnersOperPtr m_wait_oper; + void add_oper(Service::LendersWaitOperPtr); }; @@ -1132,7 +1233,7 @@ class ReadAheadBuffer { void clear() noexcept; private: - using Want = io_service::Want; + using Want = Service::Want; char* m_begin = nullptr; char* m_end = nullptr; @@ -1144,7 +1245,7 @@ class ReadAheadBuffer { template void refill_sync(S& stream, std::error_code&) noexcept; template bool refill_async(S& stream, std::error_code&, Want&) noexcept; - template friend class io_service::BasicStreamOps; + template friend class Service::BasicStreamOps; }; @@ -1186,9 +1287,7 @@ std::error_code make_error_code(errors); namespace std { -template<> -struct is_error_code_enum -{ +template<> class is_error_code_enum { public: static const bool value = true; }; @@ -1205,63 +1304,63 @@ namespace network { // Implementation -// ---------------- stream_protocol ---------------- +// ---------------- StreamProtocol ---------------- -inline stream_protocol stream_protocol::ip_v4() +inline StreamProtocol StreamProtocol::ip_v4() { - stream_protocol prot; + StreamProtocol prot; prot.m_family = AF_INET; return prot; } -inline stream_protocol stream_protocol::ip_v6() +inline StreamProtocol StreamProtocol::ip_v6() { - stream_protocol prot; + StreamProtocol prot; prot.m_family = AF_INET6; return prot; } -inline bool stream_protocol::is_ip_v4() const +inline bool StreamProtocol::is_ip_v4() const { return m_family == AF_INET; } -inline bool stream_protocol::is_ip_v6() const +inline bool StreamProtocol::is_ip_v6() const { return m_family == AF_INET6; } -inline int stream_protocol::family() const +inline int StreamProtocol::family() const { return m_family; } -inline int stream_protocol::protocol() const +inline int StreamProtocol::protocol() const { return m_protocol; } -inline stream_protocol::stream_protocol(): - m_family(AF_UNSPEC), // Allow both IPv4 and IPv6 - m_socktype(SOCK_STREAM), // Or SOCK_DGRAM for UDP - m_protocol(0) // Any protocol +inline StreamProtocol::StreamProtocol(): + m_family{AF_UNSPEC}, // Allow both IPv4 and IPv6 + m_socktype{SOCK_STREAM}, // Or SOCK_DGRAM for UDP + m_protocol{0} // Any protocol { } -// ---------------- ip_address ---------------- +// ---------------- Address ---------------- -inline bool ip_address::is_ip_v4() const +inline bool Address::is_ip_v4() const { return !m_is_ip_v6; } -inline bool ip_address::is_ip_v6() const +inline bool Address::is_ip_v6() const { return m_is_ip_v6; } template -inline std::basic_ostream& operator<<(std::basic_ostream& out, const ip_address& addr) +inline std::basic_ostream& operator<<(std::basic_ostream& out, const Address& addr) { // FIXME: Not taking `addr.m_ip_v6_scope_id` into account. What does ASIO // do? @@ -1280,44 +1379,44 @@ inline std::basic_ostream& operator<<(std::basic_ostream& out, const i return out; } -inline ip_address::ip_address() +inline Address::Address() { m_union.m_ip_v4 = ip_v4_type(); } -inline ip_address make_address(const char* c_str) +inline Address make_address(const char* c_str) { std::error_code ec; - ip_address addr = make_address(c_str, ec); + Address addr = make_address(c_str, ec); if (ec) throw std::system_error(ec); return addr; } -inline ip_address make_address(const std::string& str) +inline Address make_address(const std::string& str) { std::error_code ec; - ip_address addr = make_address(str, ec); + Address addr = make_address(str, ec); if (ec) throw std::system_error(ec); return addr; } -inline ip_address make_address(const std::string& str, std::error_code& ec) noexcept +inline Address make_address(const std::string& str, std::error_code& ec) noexcept { return make_address(str.c_str(), ec); } -// ---------------- endpoint ---------------- +// ---------------- Endpoint ---------------- -inline stream_protocol endpoint::protocol() const +inline StreamProtocol Endpoint::protocol() const { return m_protocol; } -inline ip_address endpoint::address() const +inline Address Endpoint::address() const { - ip_address addr; + Address addr; if (m_protocol.is_ip_v4()) { addr.m_union.m_ip_v4 = m_sockaddr_union.m_ip_v4.sin_addr; } @@ -1329,29 +1428,29 @@ inline ip_address endpoint::address() const return addr; } -inline endpoint::port_type endpoint::port() const +inline Endpoint::port_type Endpoint::port() const { return ntohs(m_protocol.is_ip_v4() ? m_sockaddr_union.m_ip_v4.sin_port : m_sockaddr_union.m_ip_v6.sin6_port); } -inline endpoint::data_type* endpoint::data() +inline Endpoint::data_type* Endpoint::data() { return &m_sockaddr_union.m_base; } -inline const endpoint::data_type* endpoint::data() const +inline const Endpoint::data_type* Endpoint::data() const { return &m_sockaddr_union.m_base; } -inline endpoint::endpoint(): - endpoint(stream_protocol::ip_v4(), 0) +inline Endpoint::Endpoint(): + Endpoint{StreamProtocol::ip_v4(), 0} { } -inline endpoint::endpoint(const stream_protocol& protocol, port_type port): - m_protocol(protocol) +inline Endpoint::Endpoint(const StreamProtocol& protocol, port_type port): + m_protocol{protocol} { int family = m_protocol.family(); if (family == AF_INET) { @@ -1373,10 +1472,10 @@ inline endpoint::endpoint(const stream_protocol& protocol, port_type port): } } -inline endpoint::endpoint(const ip_address& addr, port_type port) +inline Endpoint::Endpoint(const Address& addr, port_type port) { if (addr.m_is_ip_v6) { - m_protocol = stream_protocol::ip_v6(); + m_protocol = StreamProtocol::ip_v6(); m_sockaddr_union.m_ip_v6.sin6_family = AF_INET6; m_sockaddr_union.m_ip_v6.sin6_port = htons(port); m_sockaddr_union.m_ip_v6.sin6_flowinfo = 0; @@ -1384,41 +1483,229 @@ inline endpoint::endpoint(const ip_address& addr, port_type port) m_sockaddr_union.m_ip_v6.sin6_scope_id = addr.m_ip_v6_scope_id; } else { - m_protocol = stream_protocol::ip_v4(); + m_protocol = StreamProtocol::ip_v4(); m_sockaddr_union.m_ip_v4.sin_family = AF_INET; m_sockaddr_union.m_ip_v4.sin_port = htons(port); m_sockaddr_union.m_ip_v4.sin_addr = addr.m_union.m_ip_v4; } } -inline endpoint::list::iterator endpoint::list::begin() const +inline Endpoint::List::iterator Endpoint::List::begin() const { return m_endpoints.data(); } -inline endpoint::list::iterator endpoint::list::end() const +inline Endpoint::List::iterator Endpoint::List::end() const { return m_endpoints.data() + m_endpoints.size(); } -inline size_t endpoint::list::size() const +inline std::size_t Endpoint::List::size() const { return m_endpoints.size(); } -// ---------------- io_service ---------------- +// ---------------- Service::OperQueue ---------------- + +template inline bool Service::OperQueue::empty() const noexcept +{ + return !m_back; +} + +template inline void Service::OperQueue::push_back(LendersOperPtr op) noexcept +{ + REALM_ASSERT(!op->m_next); + if (m_back) { + op->m_next = m_back->m_next; + m_back->m_next = op.get(); + } + else { + op->m_next = op.get(); + } + m_back = op.release(); +} + +template template +inline void Service::OperQueue::push_back(OperQueue& q) noexcept +{ + if (!q.m_back) + return; + if (m_back) + std::swap(m_back->m_next, q.m_back->m_next); + m_back = q.m_back; + q.m_back = nullptr; +} + +template inline auto Service::OperQueue::pop_front() noexcept -> LendersOperPtr +{ + Oper* op = nullptr; + if (m_back) { + op = static_cast(m_back->m_next); + if (op != m_back) { + m_back->m_next = op->m_next; + } + else { + m_back = nullptr; + } + op->m_next = nullptr; + } + return LendersOperPtr(op); +} + +template inline void Service::OperQueue::clear() noexcept +{ + if (m_back) { + LendersOperPtr op(m_back); + while (op->m_next != m_back) + op.reset(static_cast(op->m_next)); + m_back = nullptr; + } +} + +template inline Service::OperQueue::OperQueue(OperQueue&& q) noexcept: + m_back{q.m_back} +{ + q.m_back = nullptr; +} + +template inline Service::OperQueue::~OperQueue() noexcept +{ + clear(); +} + +// ---------------- Service::Descriptor ---------------- + +inline Service::Descriptor::Descriptor(Impl& s) noexcept: + service_impl{s} +{ +} + +inline Service::Descriptor::~Descriptor() noexcept +{ + if (is_open()) + close(); +} + +inline void Service::Descriptor::assign(int fd, bool in_blocking_mode) noexcept +{ + REALM_ASSERT(!is_open()); + m_fd = fd; + m_in_blocking_mode = in_blocking_mode; +#if REALM_HAVE_EPOLL || REALM_HAVE_KQUEUE + m_read_ready = false; + m_write_ready = false; + m_imminent_end_of_input = false; + m_is_registered = false; +#endif +} + +inline void Service::Descriptor::close() noexcept +{ + REALM_ASSERT(is_open()); +#if REALM_HAVE_EPOLL || REALM_HAVE_KQUEUE + if (m_is_registered) + deregister_for_async(); + m_is_registered = false; +#endif + do_close(); +} + +inline bool Service::Descriptor::is_open() const noexcept +{ + return (m_fd != -1); +} + +inline auto Service::Descriptor::native_handle() const noexcept -> native_handle_type +{ + return m_fd; +} + +inline bool Service::Descriptor::in_blocking_mode() const noexcept +{ + return m_in_blocking_mode; +} + +template +inline void Service::Descriptor::initiate_oper(std::unique_ptr op, + Args&&... args) +{ + Service::Want want = op->initiate(std::forward(args)...); // Throws + add_initiated_oper(std::move(op), want); // Throws +} + +inline void Service::Descriptor::ensure_blocking_mode() +{ + // Assuming that descriptors are either used mostly in blocking mode, or + // mostly in nonblocking mode. + if (REALM_UNLIKELY(!m_in_blocking_mode)) { + bool value = false; + set_nonblock_flag(value); // Throws + m_in_blocking_mode = true; + } +} -class io_service::async_oper { +inline void Service::Descriptor::ensure_nonblocking_mode() +{ + // Assuming that descriptors are either used mostly in blocking mode, or + // mostly in nonblocking mode. + if (REALM_UNLIKELY(m_in_blocking_mode)) { + bool value = true; + set_nonblock_flag(value); // Throws + m_in_blocking_mode = false; + } +} + +inline bool Service::Descriptor::assume_read_would_block() const noexcept +{ +#if REALM_HAVE_EPOLL || REALM_HAVE_KQUEUE + return !m_in_blocking_mode && !m_read_ready; +#else + return false; +#endif +} + +inline bool Service::Descriptor::assume_write_would_block() const noexcept +{ +#if REALM_HAVE_EPOLL || REALM_HAVE_KQUEUE + return !m_in_blocking_mode && !m_write_ready; +#else + return false; +#endif +} + +inline void Service::Descriptor::set_read_ready(bool value) noexcept +{ +#if REALM_HAVE_EPOLL || REALM_HAVE_KQUEUE + m_read_ready = value; +#else + // No-op + static_cast(value); +#endif +} + +inline void Service::Descriptor::set_write_ready(bool value) noexcept +{ +#if REALM_HAVE_EPOLL || REALM_HAVE_KQUEUE + m_write_ready = value; +#else + // No-op + static_cast(value); +#endif +} + +// ---------------- Service ---------------- + +class Service::AsyncOper { public: bool in_use() const noexcept; bool is_complete() const noexcept; - bool is_uncanceled() const noexcept; + bool is_canceled() const noexcept; void cancel() noexcept; - /// Every object of type \ref async_oper must be desroyed either by a call + /// Every object of type \ref AsyncOper must be destroyed either by a call /// to this function or to recycle(). This function recycles the operation /// object (commits suicide), even if it throws. virtual void recycle_and_execute() = 0; - /// Every object of type \ref async_oper must be destroyed either by a call + /// Every object of type \ref AsyncOper must be destroyed either by a call /// to recycle_and_execute() or to this function. This function destroys the /// object (commits suicide). virtual void recycle() noexcept = 0; @@ -1426,29 +1713,36 @@ class io_service::async_oper { /// instance of UnusedOper). virtual void orphan() noexcept = 0; protected: - async_oper(size_t size, bool in_use) noexcept; - virtual ~async_oper() noexcept {} - bool is_canceled() const noexcept; + AsyncOper(std::size_t size, bool in_use) noexcept; + virtual ~AsyncOper() noexcept {} void set_is_complete(bool value) noexcept; template void do_recycle_and_execute(bool orphaned, H& handler, Args&&...); void do_recycle(bool orphaned) noexcept; private: - size_t m_size; // Allocated number of bytes + std::size_t m_size; // Allocated number of bytes bool m_in_use = false; - bool m_complete = false; // Always false when not in use - bool m_canceled = false; // Always false when not in use - async_oper* m_next = nullptr; // Always null when not in use - friend class io_service; + // Set to true when the operation completes successfully or fails. If the + // operation is canceled before this happens, it will never be set to + // true. Always false when not in use + bool m_complete = false; + // Set to true when the operation is canceled. Always false when not in use. + bool m_canceled = false; + AsyncOper* m_next = nullptr; // Always null when not in use + friend class Service; }; -class io_service::wait_oper_base: public async_oper { +class Service::WaitOperBase: public AsyncOper { public: - wait_oper_base(size_t size, deadline_timer& timer, clock::time_point expiration_time): - async_oper(size, true), // Second argument is `in_use` - m_timer(&timer), - m_expiration_time(expiration_time) + WaitOperBase(std::size_t size, DeadlineTimer& timer, clock::time_point expiration_time): + AsyncOper{size, true}, // Second argument is `in_use` + m_timer{&timer}, + m_expiration_time{expiration_time} + { + } + void expired() noexcept { + set_is_complete(true); } void recycle() noexcept override final { @@ -1461,37 +1755,36 @@ class io_service::wait_oper_base: public async_oper { m_timer = 0; } protected: - deadline_timer* m_timer; + DeadlineTimer* m_timer; clock::time_point m_expiration_time; - friend class io_service; + friend class Service; }; -class io_service::post_oper_base: - public async_oper { +class Service::PostOperBase: public AsyncOper { public: - post_oper_base(size_t size, impl& serv): - async_oper(size, true), // Second argument is `in_use` - m_service(serv) + PostOperBase(std::size_t size, Impl& service): + AsyncOper{size, true}, // Second argument is `in_use` + m_service{service} { } void recycle() noexcept override final { - // io_service::recycle_post_oper() destroys this operation object - io_service::recycle_post_oper(m_service, this); + // Service::recycle_post_oper() destroys this operation object + Service::recycle_post_oper(m_service, this); } void orphan() noexcept override final { REALM_ASSERT(false); // Never called } protected: - impl& m_service; + Impl& m_service; }; -template class io_service::post_oper: public post_oper_base { +template class Service::PostOper: public PostOperBase { public: - post_oper(size_t size, impl& serv, H handler): - post_oper_base(size, serv), - m_handler(std::move(handler)) + PostOper(std::size_t size, Impl& service, H handler): + PostOperBase{size, service}, + m_handler{std::move(handler)} { } void recycle_and_execute() override final @@ -1502,15 +1795,15 @@ template class io_service::post_oper: public post_oper_base { bool was_recycled = false; try { H handler = std::move(m_handler); // Throws - // io_service::recycle_post_oper() destroys this operation object - io_service::recycle_post_oper(m_service, this); + // Service::recycle_post_oper() destroys this operation object + Service::recycle_post_oper(m_service, this); was_recycled = true; handler(); // Throws } catch (...) { if (!was_recycled) { - // io_service::recycle_post_oper() destroys this operation object - io_service::recycle_post_oper(m_service, this); + // Service::recycle_post_oper() destroys this operation object + Service::recycle_post_oper(m_service, this); } throw; } @@ -1519,19 +1812,26 @@ template class io_service::post_oper: public post_oper_base { H m_handler; }; -class io_service::IoOper: public async_oper { +class Service::IoOper: public AsyncOper { public: IoOper(std::size_t size) noexcept: - async_oper(size, true) // Second argument is `in_use` + AsyncOper{size, true} // Second argument is `in_use` { } - virtual Want proceed() noexcept = 0; + virtual Descriptor& descriptor() noexcept = 0; + /// Advance this operation and figure out out whether it needs to read from, + /// or write to the underlying descriptor to advance further. This function + /// must return Want::read if the operation needs to read, or Want::write if + /// the operation needs to write to advance further. If the operation + /// completes (due to success or failure), this function must return + /// Want::nothing. + virtual Want advance() noexcept = 0; }; -class io_service::UnusedOper: public async_oper { +class Service::UnusedOper: public AsyncOper { public: - UnusedOper(size_t size) noexcept: - async_oper(size, false) // Second argument is `in_use` + UnusedOper(std::size_t size) noexcept: + AsyncOper{size, false} // Second argument is `in_use` { } void recycle_and_execute() override final @@ -1553,8 +1853,8 @@ class io_service::UnusedOper: public async_oper { // `S` must be a stream class with the following member functions: // -// void do_init_read_sync(std::error_code& ec) noexcept; -// void do_init_write_sync(std::error_code& ec) noexcept; +// Socket& lowest_layer() noexcept; +// // void do_init_read_async(std::error_code& ec, Want& want) noexcept; // void do_init_write_async(std::error_code& ec, Want& want) noexcept; // @@ -1567,14 +1867,7 @@ class io_service::UnusedOper: public async_oper { // std::size_t do_write_some_async(const char* data, std::size_t size, // std::error_code& ec, Want& want) noexcept; // -// Additionally, `S` must have members `m_read_oper` and `m_write_oper`, which -// both must be of type `LendersIoOperPtr` (or equivalent smart pointer to a -// derivative of IoOper). -// -// The do_init_*_sync() functions must enable blocking mode. The -// do_init_*_async() function must disable blocking mode. -// -// If an error occurs during any of the 8 functions, the `ec` argument must be +// If an error occurs during any of these 6 functions, the `ec` argument must be // set accordingly. Otherwise the `ec` argument must be set to // `std::error_code()`. // @@ -1584,7 +1877,7 @@ class io_service::UnusedOper: public async_oper { // Want::read Wait for read readiness, then call do_*_some_async(). // Want::write Wait for write readiness, then call do_*_some_async(). // Want::nothing Call do_*_some_async() immediately without waiting for -// read or write readyness. +// read or write readiness. // // If end-of-input occurs while reading, do_read_some_*() must fail, set `ec` to // `network::end_of_input`, and return zero. @@ -1594,7 +1887,7 @@ class io_service::UnusedOper: public async_oper { // zero. Otherwise they must set `ec` to `std::system_error()` and return the // number of bytes read or written, which **must** be at least 1. If the // underlying socket is in nonblocking mode, and no bytes could be immediately -// read or written these functinos must fail with +// read or written these functions must fail with // `error::resource_unavailable_try_again`. // // If an error occurs during reading or writing, do_*_some_async() must set `ec` @@ -1614,7 +1907,7 @@ class io_service::UnusedOper: public async_oper { // Want::read Wait for read readiness, then call do_*_some_async() again. // Want::write Wait for write readiness, then call do_*_some_async() again. // Want::nothing Call do_*_some_async() again without waiting for read or -// write readyness. +// write readiness. // // NOTE: If, for example, do_read_some_async() sets `want` to `Want::write`, it // means that the stream needs to write data to the underlying TCP socket before @@ -1627,14 +1920,14 @@ class io_service::UnusedOper: public async_oper { // // n > 0 Bytes were transferred. // ec != std::error_code() An error occured. -// want != Want::nothing Wait for read/write readyness. +// want != Want::nothing Wait for read/write readiness. // // This is of critical importance, as it is the only way we can avoid falling // into a busy loop of repeated invocations of do_*_some_async(). // // NOTE: do_*_some_async() are allowed to set `want` to `Want::read` or // `Want::write`, even when they succesfully transfer a nonzero number of bytes. -template class io_service::BasicStreamOps { +template class Service::BasicStreamOps { public: class StreamOper; class ReadOperBase; @@ -1648,12 +1941,13 @@ template class io_service::BasicStreamOps { using LendersWriteOperPtr = std::unique_ptr; using LendersBufferedReadOperPtr = std::unique_ptr; - static std::size_t read(S& stream, char* buffer, std::size_t size, std::error_code& ec) noexcept + // Synchronous read + static std::size_t read(S& stream, char* buffer, std::size_t size, + std::error_code& ec) { - REALM_ASSERT(!stream.m_read_oper || !stream.m_read_oper->in_use()); - stream.do_init_read_sync(ec); - if (REALM_UNLIKELY(ec)) - return 0; + REALM_ASSERT(!stream.lowest_layer().m_read_oper || + !stream.lowest_layer().m_read_oper->in_use()); + stream.lowest_layer().m_desc.ensure_blocking_mode(); // Throws char* begin = buffer; char* end = buffer + size; char* curr = begin; @@ -1675,12 +1969,13 @@ template class io_service::BasicStreamOps { return n; } - static std::size_t write(S& stream, const char* data, std::size_t size, std::error_code& ec) noexcept + // Synchronous write + static std::size_t write(S& stream, const char* data, std::size_t size, + std::error_code& ec) { - REALM_ASSERT(!stream.m_write_oper || !stream.m_write_oper->in_use()); - stream.do_init_write_sync(ec); - if (REALM_UNLIKELY(ec)) - return 0; + REALM_ASSERT(!stream.lowest_layer().m_write_oper || + !stream.lowest_layer().m_write_oper->in_use()); + stream.lowest_layer().m_desc.ensure_blocking_mode(); // Throws const char* begin = data; const char* end = data + size; const char* curr = begin; @@ -1702,14 +1997,13 @@ template class io_service::BasicStreamOps { return n; } + // Synchronous read static std::size_t buffered_read(S& stream, char* buffer, std::size_t size, int delim, - ReadAheadBuffer& rab, std::error_code& ec) noexcept + ReadAheadBuffer& rab, std::error_code& ec) { - REALM_ASSERT(!stream.m_read_oper || !stream.m_read_oper->in_use()); - stream.do_init_read_sync(ec); - if (REALM_UNLIKELY(ec)) - return 0; - + REALM_ASSERT(!stream.lowest_layer().m_read_oper || + !stream.lowest_layer().m_read_oper->in_use()); + stream.lowest_layer().m_desc.ensure_blocking_mode(); // Throws char* begin = buffer; char* end = buffer + size; char* curr = begin; @@ -1726,23 +2020,23 @@ template class io_service::BasicStreamOps { return n; } + // Synchronous read static std::size_t read_some(S& stream, char* buffer, std::size_t size, - std::error_code& ec) noexcept + std::error_code& ec) { - REALM_ASSERT(!stream.m_read_oper || !stream.m_read_oper->in_use()); - stream.do_init_read_sync(ec); - if (REALM_UNLIKELY(ec)) - return 0; + REALM_ASSERT(!stream.lowest_layer().m_read_oper || + !stream.lowest_layer().m_read_oper->in_use()); + stream.lowest_layer().m_desc.ensure_blocking_mode(); // Throws return stream.do_read_some_sync(buffer, size, ec); } + // Synchronous write static std::size_t write_some(S& stream, const char* data, std::size_t size, - std::error_code& ec) noexcept + std::error_code& ec) { - REALM_ASSERT(!stream.m_write_oper || !stream.m_write_oper->in_use()); - stream.do_init_write_sync(ec); - if (REALM_UNLIKELY(ec)) - return 0; + REALM_ASSERT(!stream.lowest_layer().m_write_oper || + !stream.lowest_layer().m_write_oper->in_use()); + stream.lowest_layer().m_desc.ensure_blocking_mode(); // Throws return stream.do_write_some_sync(data, size, ec); } @@ -1752,9 +2046,9 @@ template class io_service::BasicStreamOps { char* begin = buffer; char* end = buffer + size; LendersReadOperPtr op = - io_service::alloc>(stream.m_read_oper, stream, is_read_some, begin, end, - std::move(handler)); // Throws - initiate_io_oper(std::move(op)); // Throws + Service::alloc>(stream.lowest_layer().m_read_oper, stream, is_read_some, + begin, end, std::move(handler)); // Throws + stream.lowest_layer().m_desc.initiate_oper(std::move(op)); // Throws } template @@ -1764,9 +2058,9 @@ template class io_service::BasicStreamOps { const char* begin = data; const char* end = data + size; LendersWriteOperPtr op = - io_service::alloc>(stream.m_write_oper, stream, is_write_some, begin, end, - std::move(handler)); // Throws - initiate_io_oper(std::move(op)); // Throws + Service::alloc>(stream.lowest_layer().m_write_oper, stream, is_write_some, + begin, end, std::move(handler)); // Throws + stream.lowest_layer().m_desc.initiate_oper(std::move(op)); // Throws } template @@ -1776,17 +2070,18 @@ template class io_service::BasicStreamOps { char* begin = buffer; char* end = buffer + size; LendersBufferedReadOperPtr op = - io_service::alloc>(stream.m_read_oper, stream, begin, end, delim, - rab, std::move(handler)); // Throws - initiate_io_oper(std::move(op)); // Throws + Service::alloc>(stream.lowest_layer().m_read_oper, stream, + begin, end, delim, rab, + std::move(handler)); // Throws + stream.lowest_layer().m_desc.initiate_oper(std::move(op)); // Throws } }; -template class io_service::BasicStreamOps::StreamOper: public IoOper { +template class Service::BasicStreamOps::StreamOper: public IoOper { public: StreamOper(std::size_t size, S& stream) noexcept: - IoOper(size), - m_stream(&stream) + IoOper{size}, + m_stream{&stream} { } void recycle() noexcept override final @@ -1799,28 +2094,28 @@ template class io_service::BasicStreamOps::StreamOper: public IoOper { m_stream = nullptr; } - socket_base& get_socket() noexcept + Descriptor& descriptor() noexcept override final { - return m_stream->lowest_layer(); + return m_stream->lowest_layer().m_desc; } protected: S* m_stream; std::error_code m_error_code; }; -template class io_service::BasicStreamOps::ReadOperBase: public StreamOper { +template class Service::BasicStreamOps::ReadOperBase: public StreamOper { public: ReadOperBase(std::size_t size, S& stream, bool is_read_some, char* begin, char* end) noexcept: - StreamOper(size, stream), - m_is_read_some(is_read_some), - m_begin(begin), - m_end(end) + StreamOper{size, stream}, + m_is_read_some{is_read_some}, + m_begin{begin}, + m_end{end} { } - Want initiate() noexcept + Want initiate() { auto& s = *this; - REALM_ASSERT(this == s.m_stream->m_read_oper.get()); + REALM_ASSERT(this == s.m_stream->lowest_layer().m_read_oper.get()); REALM_ASSERT(!s.is_complete()); REALM_ASSERT(s.m_curr <= s.m_end); Want want = Want::nothing; @@ -1828,19 +2123,20 @@ template class io_service::BasicStreamOps::ReadOperBase: public Stre s.set_is_complete(true); // Success } else { + s.m_stream->lowest_layer().m_desc.ensure_nonblocking_mode(); // Throws s.m_stream->do_init_read_async(s.m_error_code, want); if (want == Want::nothing) { if (REALM_UNLIKELY(s.m_error_code)) { s.set_is_complete(true); // Failure } else { - want = proceed(); + want = advance(); } } } return want; } - Want proceed() noexcept override final + Want advance() noexcept override final { auto& s = *this; REALM_ASSERT(!s.is_complete()); @@ -1864,6 +2160,7 @@ template class io_service::BasicStreamOps::ReadOperBase: public Stre // Got nothing, but want something return want; } + REALM_ASSERT(!s.m_error_code); // Check for completion REALM_ASSERT(n <= size); s.m_curr += n; @@ -1873,6 +2170,7 @@ template class io_service::BasicStreamOps::ReadOperBase: public Stre } if (want != Want::nothing) return want; + REALM_ASSERT(n < size); } } protected: @@ -1882,20 +2180,20 @@ template class io_service::BasicStreamOps::ReadOperBase: public Stre char* m_curr = m_begin; // May be dangling after cancellation }; -template class io_service::BasicStreamOps::WriteOperBase: public StreamOper { +template class Service::BasicStreamOps::WriteOperBase: public StreamOper { public: WriteOperBase(std::size_t size, S& stream, bool is_write_some, const char* begin, const char* end) noexcept: - StreamOper(size, stream), - m_is_write_some(is_write_some), - m_begin(begin), - m_end(end) + StreamOper{size, stream}, + m_is_write_some{is_write_some}, + m_begin{begin}, + m_end{end} { } - Want initiate() noexcept + Want initiate() { auto& s = *this; - REALM_ASSERT(this == s.m_stream->m_write_oper.get()); + REALM_ASSERT(this == s.m_stream->lowest_layer().m_write_oper.get()); REALM_ASSERT(!s.is_complete()); REALM_ASSERT(s.m_curr <= s.m_end); Want want = Want::nothing; @@ -1903,19 +2201,20 @@ template class io_service::BasicStreamOps::WriteOperBase: public Str s.set_is_complete(true); // Success } else { + s.m_stream->lowest_layer().m_desc.ensure_nonblocking_mode(); // Throws s.m_stream->do_init_write_async(s.m_error_code, want); if (want == Want::nothing) { if (REALM_UNLIKELY(s.m_error_code)) { s.set_is_complete(true); // Failure } else { - want = proceed(); + want = advance(); } } } return want; } - Want proceed() noexcept override final + Want advance() noexcept override final { auto& s = *this; REALM_ASSERT(!s.is_complete()); @@ -1939,6 +2238,7 @@ template class io_service::BasicStreamOps::WriteOperBase: public Str // Wrote nothing, but want something written return want; } + REALM_ASSERT(!s.m_error_code); // Check for completion REALM_ASSERT(n <= size); s.m_curr += n; @@ -1948,6 +2248,7 @@ template class io_service::BasicStreamOps::WriteOperBase: public Str } if (want != Want::nothing) return want; + REALM_ASSERT(n < size); } } protected: @@ -1957,21 +2258,21 @@ template class io_service::BasicStreamOps::WriteOperBase: public Str const char* m_curr = m_begin; // May be dangling after cancellation }; -template class io_service::BasicStreamOps::BufferedReadOperBase: public StreamOper { +template class Service::BasicStreamOps::BufferedReadOperBase: public StreamOper { public: BufferedReadOperBase(std::size_t size, S& stream, char* begin, char* end, int delim, ReadAheadBuffer& rab) noexcept: - StreamOper(size, stream), - m_read_ahead_buffer(rab), - m_begin(begin), - m_end(end), - m_delim(delim) + StreamOper{size, stream}, + m_read_ahead_buffer{rab}, + m_begin{begin}, + m_end{end}, + m_delim{delim} { } - Want initiate() noexcept + Want initiate() { auto& s = *this; - REALM_ASSERT(this == s.m_stream->m_read_oper.get()); + REALM_ASSERT(this == s.m_stream->lowest_layer().m_read_oper.get()); REALM_ASSERT(!s.is_complete()); Want want = Want::nothing; bool complete = s.m_read_ahead_buffer.read(s.m_curr, s.m_end, s.m_delim, s.m_error_code); @@ -1979,19 +2280,20 @@ template class io_service::BasicStreamOps::BufferedReadOperBase: pub s.set_is_complete(true); // Success or failure } else { + s.m_stream->lowest_layer().m_desc.ensure_nonblocking_mode(); // Throws s.m_stream->do_init_read_async(s.m_error_code, want); if (want == Want::nothing) { if (REALM_UNLIKELY(s.m_error_code)) { s.set_is_complete(true); // Failure } else { - want = proceed(); + want = advance(); } } } return want; } - Want proceed() noexcept override final + Want advance() noexcept override final { auto& s = *this; REALM_ASSERT(!s.is_complete()); @@ -2034,11 +2336,11 @@ template class io_service::BasicStreamOps::BufferedReadOperBase: pub }; template template -class io_service::BasicStreamOps::ReadOper: public ReadOperBase { +class Service::BasicStreamOps::ReadOper: public ReadOperBase { public: ReadOper(std::size_t size, S& stream, bool is_read_some, char* begin, char* end, H handler): - ReadOperBase(size, stream, is_read_some, begin, end), - m_handler(std::move(handler)) + ReadOperBase{size, stream, is_read_some, begin, end}, + m_handler{std::move(handler)} { } void recycle_and_execute() override final @@ -2062,12 +2364,12 @@ class io_service::BasicStreamOps::ReadOper: public ReadOperBase { }; template template -class io_service::BasicStreamOps::WriteOper: public WriteOperBase { +class Service::BasicStreamOps::WriteOper: public WriteOperBase { public: WriteOper(std::size_t size, S& stream, bool is_write_some, const char* begin, const char* end, H handler): - WriteOperBase(size, stream, is_write_some, begin, end), - m_handler(std::move(handler)) + WriteOperBase{size, stream, is_write_some, begin, end}, + m_handler{std::move(handler)} { } void recycle_and_execute() override final @@ -2091,12 +2393,12 @@ class io_service::BasicStreamOps::WriteOper: public WriteOperBase { }; template template -class io_service::BasicStreamOps::BufferedReadOper: public BufferedReadOperBase { +class Service::BasicStreamOps::BufferedReadOper: public BufferedReadOperBase { public: BufferedReadOper(std::size_t size, S& stream, char* begin, char* end, int delim, ReadAheadBuffer& rab, H handler): - BufferedReadOperBase(size, stream, begin, end, delim, rab), - m_handler(std::move(handler)) + BufferedReadOperBase{size, stream, begin, end, delim, rab}, + m_handler{std::move(handler)} { } void recycle_and_execute() override final @@ -2122,33 +2424,33 @@ class io_service::BasicStreamOps::BufferedReadOper: public BufferedReadOperBa H m_handler; }; -template inline void io_service::post(H handler) +template inline void Service::post(H handler) { - do_post(&io_service::post_oper_constr, sizeof (post_oper), &handler); + do_post(&Service::post_oper_constr, sizeof (PostOper), &handler); } -inline void io_service::OwnersOperDeleter::operator()(async_oper* op) const noexcept +inline void Service::OwnersOperDeleter::operator()(AsyncOper* op) const noexcept { if (op->in_use()) { op->orphan(); } else { void* addr = op; - op->~async_oper(); + op->~AsyncOper(); delete[] static_cast(addr); } } -inline void io_service::LendersOperDeleter::operator()(async_oper* op) const noexcept +inline void Service::LendersOperDeleter::operator()(AsyncOper* op) const noexcept { op->recycle(); // Suicide } -template std::unique_ptr -io_service::alloc(OwnersOperPtr& owners_ptr, Args&&... args) +template std::unique_ptr +Service::alloc(OwnersOperPtr& owners_ptr, Args&&... args) { void* addr = owners_ptr.get(); - size_t size; + std::size_t size; if (REALM_LIKELY(addr)) { REALM_ASSERT(!owners_ptr->in_use()); size = owners_ptr->m_size; @@ -2166,7 +2468,7 @@ io_service::alloc(OwnersOperPtr& owners_ptr, Args&&... args) no_object: addr = new char[sizeof (Oper)]; // Throws size = sizeof (Oper); - owners_ptr.reset(static_cast(addr)); + owners_ptr.reset(static_cast(addr)); } std::unique_ptr lenders_ptr; try { @@ -2180,73 +2482,47 @@ io_service::alloc(OwnersOperPtr& owners_ptr, Args&&... args) } template -inline void io_service::execute(std::unique_ptr& lenders_ptr) +inline void Service::execute(std::unique_ptr& lenders_ptr) { lenders_ptr.release()->recycle_and_execute(); // Throws } -template -inline void io_service::initiate_io_oper(std::unique_ptr op, - Args&&... args) -{ - socket_base& sock = op->get_socket(); - io_service& service = sock.get_io_service(); - Want want = op->initiate(std::forward(args)...); - switch (want) { - case Want::nothing: - service.add_completed_oper(std::move(op)); - return; - case Want::read: - service.add_io_oper(sock.get_sock_fd(), std::move(op), io_op_Read); // Throws - return; - case Want::write: - service.add_io_oper(sock.get_sock_fd(), std::move(op), io_op_Write); // Throws - return; - } - REALM_ASSERT(false); -} - -template inline io_service::post_oper_base* -io_service::post_oper_constr(void* addr, size_t size, impl& serv, void* cookie) +template inline Service::PostOperBase* +Service::post_oper_constr(void* addr, std::size_t size, Impl& service, void* cookie) { H& handler = *static_cast(cookie); - return new (addr) post_oper(size, serv, std::move(handler)); // Throws + return new (addr) PostOper(size, service, std::move(handler)); // Throws } -inline bool io_service::async_oper::in_use() const noexcept +inline bool Service::AsyncOper::in_use() const noexcept { return m_in_use; } -inline bool io_service::async_oper::is_complete() const noexcept +inline bool Service::AsyncOper::is_complete() const noexcept { return m_complete; } -inline bool io_service::async_oper::is_uncanceled() const noexcept -{ - return m_in_use && !m_canceled; -} - -inline void io_service::async_oper::cancel() noexcept +inline void Service::AsyncOper::cancel() noexcept { REALM_ASSERT(m_in_use); REALM_ASSERT(!m_canceled); m_canceled = true; } -inline io_service::async_oper::async_oper(size_t size, bool is_in_use) noexcept: - m_size(size), - m_in_use(is_in_use) +inline Service::AsyncOper::AsyncOper(std::size_t size, bool is_in_use) noexcept: + m_size{size}, + m_in_use{is_in_use} { } -inline bool io_service::async_oper::is_canceled() const noexcept +inline bool Service::AsyncOper::is_canceled() const noexcept { return m_canceled; } -inline void io_service::async_oper::set_is_complete(bool value) noexcept +inline void Service::AsyncOper::set_is_complete(bool value) noexcept { REALM_ASSERT(!m_complete); REALM_ASSERT(!value || m_in_use); @@ -2254,8 +2530,7 @@ inline void io_service::async_oper::set_is_complete(bool value) noexcept } template -inline void io_service::async_oper::do_recycle_and_execute(bool orphaned, H& handler, - Args&&... args) +inline void Service::AsyncOper::do_recycle_and_execute(bool orphaned, H& handler, Args&&... args) { // Recycle the operation object before the handler is exceuted, such that // the memory is available for a new post operation that might be initiated @@ -2263,7 +2538,7 @@ inline void io_service::async_oper::do_recycle_and_execute(bool orphaned, H& han bool was_recycled = false; try { H handler_2 = std::move(handler); // Throws - // The caller (various subclasses of `async_oper`) must not pass any + // The caller (various subclasses of `AsyncOper`) must not pass any // arguments to the completion handler by reference if they refer to // this operation object, or parts of it. Due to the recycling of the // operation object (`do_recycle()`), such references would become @@ -2283,12 +2558,12 @@ inline void io_service::async_oper::do_recycle_and_execute(bool orphaned, H& han } } -inline void io_service::async_oper::do_recycle(bool orphaned) noexcept +inline void Service::AsyncOper::do_recycle(bool orphaned) noexcept { REALM_ASSERT(in_use()); void* addr = this; - size_t size = m_size; - this->~async_oper(); // Suicide + std::size_t size = m_size; + this->~AsyncOper(); // Suicide if (orphaned) { delete[] static_cast(addr); } @@ -2297,119 +2572,113 @@ inline void io_service::async_oper::do_recycle(bool orphaned) noexcept } } -// ---------------- resolver ---------------- +// ---------------- Resolver ---------------- -inline resolver::resolver(io_service& serv): - m_service(serv) +inline Resolver::Resolver(Service& service): + m_service_impl{*service.m_impl} { } -inline io_service& resolver::get_io_service() noexcept -{ - return m_service; -} - -inline void resolver::resolve(const query& q, endpoint::list& l) +inline void Resolver::resolve(const Query& q, Endpoint::List& l) { std::error_code ec; if (resolve(q, l, ec)) throw std::system_error(ec); } -inline resolver::query::query(std::string service_port, int init_flags): - m_flags(init_flags), - m_service(service_port) +inline Resolver::Query::Query(std::string service_port, int init_flags): + m_flags{init_flags}, + m_service{service_port} { } -inline resolver::query::query(const stream_protocol& prot, std::string service_port, +inline Resolver::Query::Query(const StreamProtocol& prot, std::string service_port, int init_flags): - m_flags(init_flags), - m_protocol(prot), - m_service(service_port) + m_flags{init_flags}, + m_protocol{prot}, + m_service{service_port} { } -inline resolver::query::query(std::string host_name, std::string service_port, int init_flags): - m_flags(init_flags), - m_host(host_name), - m_service(service_port) +inline Resolver::Query::Query(std::string host_name, std::string service_port, int init_flags): + m_flags{init_flags}, + m_host{host_name}, + m_service{service_port} { } -inline resolver::query::query(const stream_protocol& prot, std::string host_name, +inline Resolver::Query::Query(const StreamProtocol& prot, std::string host_name, std::string service_port, int init_flags): - m_flags(init_flags), - m_protocol(prot), - m_host(host_name), - m_service(service_port) + m_flags{init_flags}, + m_protocol{prot}, + m_host{host_name}, + m_service{service_port} { } -inline resolver::query::~query() noexcept +inline Resolver::Query::~Query() noexcept { } -inline int resolver::query::flags() const +inline int Resolver::Query::flags() const { return m_flags; } -inline stream_protocol resolver::query::protocol() const +inline StreamProtocol Resolver::Query::protocol() const { return m_protocol; } -inline std::string resolver::query::host() const +inline std::string Resolver::Query::host() const { return m_host; } -inline std::string resolver::query::service() const +inline std::string Resolver::Query::service() const { return m_service; } -// ---------------- socket_base ---------------- +// ---------------- SocketBase ---------------- -inline socket_base::socket_base(io_service& s): - m_sock_fd(-1), - m_service(s) +inline SocketBase::SocketBase(Service& service): + m_desc{*service.m_impl} { } -inline socket_base::~socket_base() noexcept +inline SocketBase::~SocketBase() noexcept { close(); } -inline io_service& socket_base::get_io_service() noexcept +inline bool SocketBase::is_open() const noexcept { - return m_service; + return m_desc.is_open(); } -inline bool socket_base::is_open() const noexcept +inline auto SocketBase::native_handle() const noexcept -> native_handle_type { - return m_sock_fd != -1; + return m_desc.native_handle(); } -inline void socket_base::open(const stream_protocol& prot) +inline void SocketBase::open(const StreamProtocol& prot) { std::error_code ec; if (open(prot, ec)) throw std::system_error(ec); } -inline void socket_base::close() noexcept +inline void SocketBase::close() noexcept { if (!is_open()) return; cancel(); - do_close(); + m_desc.close(); } template -inline void socket_base::get_option(O& opt) const +inline void SocketBase::get_option(O& opt) const { std::error_code ec; if (get_option(opt, ec)) @@ -2417,14 +2686,14 @@ inline void socket_base::get_option(O& opt) const } template -inline std::error_code socket_base::get_option(O& opt, std::error_code& ec) const +inline std::error_code SocketBase::get_option(O& opt, std::error_code& ec) const { opt.get(*this, ec); return ec; } template -inline void socket_base::set_option(const O& opt) +inline void SocketBase::set_option(const O& opt) { std::error_code ec; if (set_option(opt, ec)) @@ -2432,84 +2701,53 @@ inline void socket_base::set_option(const O& opt) } template -inline std::error_code socket_base::set_option(const O& opt, std::error_code& ec) +inline std::error_code SocketBase::set_option(const O& opt, std::error_code& ec) { opt.set(*this, ec); return ec; } -inline void socket_base::bind(const endpoint& ep) +inline void SocketBase::bind(const Endpoint& ep) { std::error_code ec; if (bind(ep, ec)) throw std::system_error(ec); } -inline endpoint socket_base::local_endpoint() const +inline Endpoint SocketBase::local_endpoint() const { std::error_code ec; - endpoint ep = local_endpoint(ec); + Endpoint ep = local_endpoint(ec); if (ec) throw std::system_error(ec); return ep; } -inline int socket_base::get_sock_fd() const noexcept -{ - return m_sock_fd; -} - -inline const stream_protocol& socket_base::get_protocol() const noexcept +inline const StreamProtocol& SocketBase::get_protocol() const noexcept { return m_protocol; } -inline std::error_code socket_base::ensure_blocking_mode(std::error_code& ec) noexcept -{ - // Assuming that sockets are either used mostly in blocking mode, or mostly - // in nonblocking mode. - if (REALM_UNLIKELY(!m_in_blocking_mode)) { - bool enable = false; - if (set_nonblocking_mode(enable, ec)) - return ec; - m_in_blocking_mode = true; - } - return std::error_code(); // Success -} - -inline std::error_code socket_base::ensure_nonblocking_mode(std::error_code& ec) noexcept -{ - // Assuming that sockets are either used mostly in blocking mode, or mostly - // in nonblocking mode. - if (REALM_UNLIKELY(m_in_blocking_mode)) { - bool enable = true; - if (set_nonblocking_mode(enable, ec)) - return ec; - m_in_blocking_mode = false; - } - return std::error_code(); // Success -} - template -inline socket_base::option::option(T init_value): - m_value(init_value) +inline SocketBase::Option::Option(T init_value): + m_value{init_value} { } template -inline T socket_base::option::value() const +inline T SocketBase::Option::value() const { return m_value; } template -inline void socket_base::option::get(const socket_base& sock, std::error_code& ec) +inline void SocketBase::Option::get(const SocketBase& sock, std::error_code& ec) { union { U value; char strut[sizeof (U) + 1]; }; - size_t value_size = sizeof strut; + std::size_t value_size = sizeof strut; sock.get_option(opt_enum(opt), &value, value_size, ec); if (!ec) { REALM_ASSERT(value_size == sizeof value); @@ -2518,31 +2756,31 @@ inline void socket_base::option::get(const socket_base& sock, std::er } template -inline void socket_base::option::set(socket_base& sock, std::error_code& ec) const +inline void SocketBase::Option::set(SocketBase& sock, std::error_code& ec) const { U value_to_set = U(m_value); sock.set_option(opt_enum(opt), &value_to_set, sizeof value_to_set, ec); } -// ---------------- socket ---------------- +// ---------------- Socket ---------------- -class socket::ConnectOperBase: public io_service::IoOper { +class Socket::ConnectOperBase: public Service::IoOper { public: - ConnectOperBase(std::size_t size, socket& sock) noexcept: - IoOper(size), - m_socket(&sock) + ConnectOperBase(std::size_t size, Socket& sock) noexcept: + IoOper{size}, + m_socket{&sock} { } - Want initiate(const endpoint& ep) noexcept + Want initiate(const Endpoint& ep) { REALM_ASSERT(this == m_socket->m_write_oper.get()); - if (m_socket->initiate_async_connect(ep, m_error_code)) { + if (m_socket->initiate_async_connect(ep, m_error_code)) { // Throws set_is_complete(true); // Failure, or immediate completion return Want::nothing; } return Want::write; } - Want proceed() noexcept override final + Want advance() noexcept override final { REALM_ASSERT(!is_complete()); REALM_ASSERT(!is_canceled()); @@ -2561,20 +2799,20 @@ class socket::ConnectOperBase: public io_service::IoOper { { m_socket = nullptr; } - socket_base& get_socket() noexcept + Service::Descriptor& descriptor() noexcept override final { - return *m_socket; + return m_socket->m_desc; } protected: - socket* m_socket; + Socket* m_socket; std::error_code m_error_code; }; -template class socket::ConnectOper: public ConnectOperBase { +template class Socket::ConnectOper: public ConnectOperBase { public: - ConnectOper(size_t size, socket& sock, H handler): - ConnectOperBase(size, sock), - m_handler(std::move(handler)) + ConnectOper(std::size_t size, Socket& sock, H handler): + ConnectOperBase{size, sock}, + m_handler{std::move(handler)} { } void recycle_and_execute() override final @@ -2591,224 +2829,219 @@ template class socket::ConnectOper: public ConnectOperBase { H m_handler; }; -inline socket::socket(io_service& s): - socket_base(s) +inline Socket::Socket(Service& service): + SocketBase{service} { } -inline socket::socket(io_service& s, const stream_protocol& prot, native_handle_type native_socket): - socket_base(s) +inline Socket::Socket(Service& service, const StreamProtocol& prot, + native_handle_type native_socket): + SocketBase{service} { assign(prot, native_socket); // Throws } -inline socket::~socket() noexcept +inline Socket::~Socket() noexcept { } -inline void socket::connect(const endpoint& ep) +inline void Socket::connect(const Endpoint& ep) { std::error_code ec; - if (connect(ep, ec)) + if (connect(ep, ec)) // Throws throw std::system_error(ec); } -inline std::size_t socket::read(char* buffer, std::size_t size) +inline std::size_t Socket::read(char* buffer, std::size_t size) { std::error_code ec; - read(buffer, size, ec); + read(buffer, size, ec); // Throws if (ec) throw std::system_error(ec); return size; } -inline std::size_t socket::read(char* buffer, std::size_t size, std::error_code& ec) noexcept +inline std::size_t Socket::read(char* buffer, std::size_t size, std::error_code& ec) { - return StreamOps::read(*this, buffer, size, ec); + return StreamOps::read(*this, buffer, size, ec); // Throws } -inline std::size_t socket::read(char* buffer, std::size_t size, ReadAheadBuffer& rab) +inline std::size_t Socket::read(char* buffer, std::size_t size, ReadAheadBuffer& rab) { std::error_code ec; - read(buffer, size, rab, ec); + read(buffer, size, rab, ec); // Throws if (ec) throw std::system_error(ec); return size; } -inline std::size_t socket::read(char* buffer, std::size_t size, ReadAheadBuffer& rab, - std::error_code& ec) noexcept +inline std::size_t Socket::read(char* buffer, std::size_t size, ReadAheadBuffer& rab, + std::error_code& ec) { int delim = std::char_traits::eof(); - return StreamOps::buffered_read(*this, buffer, size, delim, rab, ec); + return StreamOps::buffered_read(*this, buffer, size, delim, rab, ec); // Throws } -inline std::size_t socket::read_until(char* buffer, std::size_t size, char delim, +inline std::size_t Socket::read_until(char* buffer, std::size_t size, char delim, ReadAheadBuffer& rab) { std::error_code ec; - std::size_t n = read_until(buffer, size, delim, rab, ec); + std::size_t n = read_until(buffer, size, delim, rab, ec); // Throws if (ec) throw std::system_error(ec); return n; } -inline std::size_t socket::read_until(char* buffer, std::size_t size, char delim, - ReadAheadBuffer& rab, std::error_code& ec) noexcept +inline std::size_t Socket::read_until(char* buffer, std::size_t size, char delim, + ReadAheadBuffer& rab, std::error_code& ec) { int delim_2 = std::char_traits::to_int_type(delim); - return StreamOps::buffered_read(*this, buffer, size, delim_2, rab, ec); + return StreamOps::buffered_read(*this, buffer, size, delim_2, rab, ec); // Throws } -inline std::size_t socket::write(const char* data, std::size_t size) +inline std::size_t Socket::write(const char* data, std::size_t size) { std::error_code ec; - write(data, size, ec); + write(data, size, ec); // Throws if (ec) throw std::system_error(ec); return size; } -inline std::size_t socket::write(const char* data, std::size_t size, std::error_code& ec) noexcept +inline std::size_t Socket::write(const char* data, std::size_t size, std::error_code& ec) { - return StreamOps::write(*this, data, size, ec); + return StreamOps::write(*this, data, size, ec); // Throws } -inline std::size_t socket::read_some(char* buffer, std::size_t size) +inline std::size_t Socket::read_some(char* buffer, std::size_t size) { std::error_code ec; - std::size_t n = read_some(buffer, size, ec); + std::size_t n = read_some(buffer, size, ec); // Throws if (ec) throw std::system_error(ec); return n; } -inline std::size_t socket::read_some(char* buffer, std::size_t size, std::error_code& ec) noexcept +inline std::size_t Socket::read_some(char* buffer, std::size_t size, std::error_code& ec) { - return StreamOps::read_some(*this, buffer, size, ec); + return StreamOps::read_some(*this, buffer, size, ec); // Throws } -inline std::size_t socket::write_some(const char* data, std::size_t size) +inline std::size_t Socket::write_some(const char* data, std::size_t size) { std::error_code ec; - std::size_t n = write_some(data, size, ec); + std::size_t n = write_some(data, size, ec); // Throws if (ec) throw std::system_error(ec); return n; } -inline std::size_t socket::write_some(const char* data, std::size_t size, - std::error_code& ec) noexcept +inline std::size_t Socket::write_some(const char* data, std::size_t size, std::error_code& ec) { - return StreamOps::write_some(*this, data, size, ec); + return StreamOps::write_some(*this, data, size, ec); // Throws } -template inline void socket::async_connect(const endpoint& ep, H handler) +template inline void Socket::async_connect(const Endpoint& ep, H handler) { LendersConnectOperPtr op = - io_service::alloc>(m_write_oper, *this, std::move(handler)); // Throws - io_service::initiate_io_oper(std::move(op), ep); // Throws + Service::alloc>(m_write_oper, *this, std::move(handler)); // Throws + m_desc.initiate_oper(std::move(op), ep); // Throws } -template inline void socket::async_read(char* buffer, std::size_t size, H handler) +template inline void Socket::async_read(char* buffer, std::size_t size, H handler) { bool is_read_some = false; StreamOps::async_read(*this, buffer, size, is_read_some, std::move(handler)); // Throws } template -inline void socket::async_read(char* buffer, std::size_t size, ReadAheadBuffer& rab, H handler) +inline void Socket::async_read(char* buffer, std::size_t size, ReadAheadBuffer& rab, H handler) { int delim = std::char_traits::eof(); StreamOps::async_buffered_read(*this, buffer, size, delim, rab, std::move(handler)); // Throws } template -inline void socket::async_read_until(char* buffer, std::size_t size, char delim, +inline void Socket::async_read_until(char* buffer, std::size_t size, char delim, ReadAheadBuffer& rab, H handler) { int delim_2 = std::char_traits::to_int_type(delim); StreamOps::async_buffered_read(*this, buffer, size, delim_2, rab, std::move(handler)); // Throws } -template inline void socket::async_write(const char* data, std::size_t size, H handler) +template inline void Socket::async_write(const char* data, std::size_t size, H handler) { bool is_write_some = false; StreamOps::async_write(*this, data, size, is_write_some, std::move(handler)); // Throws } -template inline void socket::async_read_some(char* buffer, size_t size, H handler) +template inline void Socket::async_read_some(char* buffer, std::size_t size, H handler) { bool is_read_some = true; StreamOps::async_read(*this, buffer, size, is_read_some, std::move(handler)); // Throws } template -inline void socket::async_write_some(const char* data, std::size_t size, H handler) +inline void Socket::async_write_some(const char* data, std::size_t size, H handler) { bool is_write_some = true; StreamOps::async_write(*this, data, size, is_write_some, std::move(handler)); // Throws } -inline void socket::shutdown(shutdown_type what) +inline void Socket::shutdown(shutdown_type what) { std::error_code ec; - if (shutdown(what, ec)) + if (shutdown(what, ec)) // Throws throw std::system_error(ec); } -inline void socket::assign(const stream_protocol& prot, native_handle_type native_socket) +inline void Socket::assign(const StreamProtocol& prot, native_handle_type native_socket) { std::error_code ec; if (assign(prot, native_socket, ec)) // Throws throw std::system_error(ec); } -inline std::error_code socket::assign(const stream_protocol& prot, +inline std::error_code Socket::assign(const StreamProtocol& prot, native_handle_type native_socket, std::error_code& ec) { return do_assign(prot, native_socket, ec); // Throws } -inline socket& socket::lowest_layer() noexcept +inline Socket& Socket::lowest_layer() noexcept { return *this; } -inline void socket::do_init_read_sync(std::error_code& ec) noexcept +inline void Socket::do_init_read_async(std::error_code&, Want& want) noexcept { - ensure_blocking_mode(ec); + want = Want::read; // Wait for read readiness before proceeding } -inline void socket::do_init_write_sync(std::error_code& ec) noexcept +inline void Socket::do_init_write_async(std::error_code&, Want& want) noexcept { - ensure_blocking_mode(ec); + want = Want::write; // Wait for write readiness before proceeding } -inline void socket::do_init_read_async(std::error_code& ec, Want& want) noexcept +inline std::size_t Socket::do_read_some_sync(char* buffer, std::size_t size, + std::error_code& ec) noexcept { - if (REALM_UNLIKELY(ensure_nonblocking_mode(ec))) { - want = Want::nothing; // Failure - return; - } - want = Want::read; // Wait for read readiness before proceeding + return m_desc.read_some(buffer, size, ec); } -inline void socket::do_init_write_async(std::error_code& ec, Want& want) noexcept +inline std::size_t Socket::do_write_some_sync(const char* data, std::size_t size, + std::error_code& ec) noexcept { - if (REALM_UNLIKELY(ensure_nonblocking_mode(ec))) { - want = Want::nothing; // Failure - return; - } - want = Want::write; // Wait for write readiness before proceeding + return m_desc.write_some(data, size, ec); } -inline std::size_t socket::do_read_some_async(char* buffer, std::size_t size, +inline std::size_t Socket::do_read_some_async(char* buffer, std::size_t size, std::error_code& ec, Want& want) noexcept { std::error_code ec_2; - std::size_t n = do_read_some_sync(buffer, size, ec_2); - if (REALM_UNLIKELY(ec_2 && ec_2 != error::resource_unavailable_try_again)) { + std::size_t n = m_desc.read_some(buffer, size, ec_2); + bool success = (!ec_2 || ec_2 == error::resource_unavailable_try_again); + if (REALM_UNLIKELY(!success)) { ec = ec_2; want = Want::nothing; // Failure return 0; @@ -2818,12 +3051,13 @@ inline std::size_t socket::do_read_some_async(char* buffer, std::size_t size, return n; } -inline std::size_t socket::do_write_some_async(const char* data, std::size_t size, +inline std::size_t Socket::do_write_some_async(const char* data, std::size_t size, std::error_code& ec, Want& want) noexcept { std::error_code ec_2; - std::size_t n = do_write_some_sync(data, size, ec_2); - if (REALM_UNLIKELY(ec_2 && ec_2 != error::resource_unavailable_try_again)) { + std::size_t n = m_desc.write_some(data, size, ec_2); + bool success = (!ec_2 || ec_2 == error::resource_unavailable_try_again); + if (REALM_UNLIKELY(!success)) { ec = ec_2; want = Want::nothing; // Failure return 0; @@ -2833,28 +3067,25 @@ inline std::size_t socket::do_write_some_async(const char* data, std::size_t siz return n; } -// ---------------- acceptor ---------------- +// ---------------- Acceptor ---------------- -class acceptor::AcceptOperBase: public io_service::IoOper { +class Acceptor::AcceptOperBase: public Service::IoOper { public: - AcceptOperBase(std::size_t size, acceptor& a, socket& s, endpoint* e): - IoOper(size), - m_acceptor(&a), - m_socket(s), - m_endpoint(e) + AcceptOperBase(std::size_t size, Acceptor& a, Socket& s, Endpoint* e): + IoOper{size}, + m_acceptor{&a}, + m_socket{s}, + m_endpoint{e} { } - Want initiate() noexcept + Want initiate() { REALM_ASSERT(this == m_acceptor->m_read_oper.get()); REALM_ASSERT(!is_complete()); - if (m_acceptor->ensure_nonblocking_mode(m_error_code)) { - set_is_complete(true); // Failure - return Want::nothing; - } + m_acceptor->m_desc.ensure_nonblocking_mode(); // Throws return Want::read; } - Want proceed() noexcept override final + Want advance() noexcept override final { REALM_ASSERT(!is_complete()); REALM_ASSERT(!is_canceled()); @@ -2875,22 +3106,22 @@ class acceptor::AcceptOperBase: public io_service::IoOper { { m_acceptor = 0; } - socket_base& get_socket() noexcept + Service::Descriptor& descriptor() noexcept override final { - return *m_acceptor; + return m_acceptor->m_desc; } protected: - acceptor* m_acceptor; - socket& m_socket; // May be dangling after cancellation - endpoint* const m_endpoint; // May be dangling after cancellation + Acceptor* m_acceptor; + Socket& m_socket; // May be dangling after cancellation + Endpoint* const m_endpoint; // May be dangling after cancellation std::error_code m_error_code; }; -template class acceptor::AcceptOper: public AcceptOperBase { +template class Acceptor::AcceptOper: public AcceptOperBase { public: - AcceptOper(size_t size, acceptor& a, socket& s, endpoint* e, H handler): - AcceptOperBase(size, a, s, e), - m_handler(std::move(handler)) + AcceptOper(std::size_t size, Acceptor& a, Socket& s, Endpoint* e, H handler): + AcceptOperBase{size, a, s, e}, + m_handler{std::move(handler)} { } void recycle_and_execute() override final @@ -2908,97 +3139,96 @@ template class acceptor::AcceptOper: public AcceptOperBase { H m_handler; }; -inline acceptor::acceptor(io_service& s): - socket_base(s) +inline Acceptor::Acceptor(Service& service): + SocketBase{service} { } -inline acceptor::~acceptor() noexcept +inline Acceptor::~Acceptor() noexcept { } -inline void acceptor::listen(int backlog) +inline void Acceptor::listen(int backlog) { std::error_code ec; - if (listen(backlog, ec)) + if (listen(backlog, ec)) // Throws throw std::system_error(ec); } -inline void acceptor::accept(socket& sock) +inline void Acceptor::accept(Socket& sock) { std::error_code ec; if (accept(sock, ec)) // Throws throw std::system_error(ec); } -inline void acceptor::accept(socket& sock, endpoint& ep) +inline void Acceptor::accept(Socket& sock, Endpoint& ep) { std::error_code ec; if (accept(sock, ep, ec)) // Throws throw std::system_error(ec); } -inline std::error_code acceptor::accept(socket& sock, std::error_code& ec) +inline std::error_code Acceptor::accept(Socket& sock, std::error_code& ec) { - endpoint* ep = nullptr; + Endpoint* ep = nullptr; return accept(sock, ep, ec); // Throws } -inline std::error_code acceptor::accept(socket& sock, endpoint& ep, std::error_code& ec) +inline std::error_code Acceptor::accept(Socket& sock, Endpoint& ep, std::error_code& ec) { return accept(sock, &ep, ec); // Throws } -template inline void acceptor::async_accept(socket& sock, H handler) +template inline void Acceptor::async_accept(Socket& sock, H handler) { - endpoint* ep = nullptr; + Endpoint* ep = nullptr; async_accept(sock, ep, std::move(handler)); // Throws } -template inline void acceptor::async_accept(socket& sock, endpoint& ep, H handler) +template inline void Acceptor::async_accept(Socket& sock, Endpoint& ep, H handler) { async_accept(sock, &ep, std::move(handler)); // Throws } -inline std::error_code acceptor::accept(socket& sock, endpoint* ep, std::error_code& ec) +inline std::error_code Acceptor::accept(Socket& socket, Endpoint* ep, std::error_code& ec) { REALM_ASSERT(!m_read_oper || !m_read_oper->in_use()); - if (REALM_UNLIKELY(sock.is_open())) + if (REALM_UNLIKELY(socket.is_open())) throw std::runtime_error("Socket is already open"); - if (ensure_blocking_mode(ec)) - return ec; - do_accept_sync(sock, ep, ec); + m_desc.ensure_blocking_mode(); // Throws + m_desc.accept(socket.m_desc, m_protocol, ep, ec); return ec; } -inline acceptor::Want acceptor::do_accept_async(socket& socket, endpoint* ep, std::error_code& ec) noexcept +inline Acceptor::Want Acceptor::do_accept_async(Socket& socket, Endpoint* ep, + std::error_code& ec) noexcept { std::error_code ec_2; - do_accept_sync(socket, ep, ec_2); + m_desc.accept(socket.m_desc, m_protocol, ep, ec_2); if (ec_2 == error::resource_unavailable_try_again) return Want::read; ec = ec_2; return Want::nothing; } -template inline void acceptor::async_accept(socket& sock, endpoint* ep, H handler) +template inline void Acceptor::async_accept(Socket& sock, Endpoint* ep, H handler) { if (REALM_UNLIKELY(sock.is_open())) throw std::runtime_error("Socket is already open"); - LendersAcceptOperPtr op = io_service::alloc>(m_read_oper, *this, sock, ep, - std::move(handler)); // Throws - io_service::initiate_io_oper(std::move(op)); // Throws + LendersAcceptOperPtr op = Service::alloc>(m_read_oper, *this, sock, ep, + std::move(handler)); // Throws + m_desc.initiate_oper(std::move(op)); // Throws } -// ---------------- deadline_timer ---------------- +// ---------------- DeadlineTimer ---------------- template -class deadline_timer::wait_oper: - public io_service::wait_oper_base { +class DeadlineTimer::WaitOper: public Service::WaitOperBase { public: - wait_oper(size_t size, deadline_timer& timer, clock::time_point expiration_time, H handler): - io_service::wait_oper_base(size, timer, expiration_time), - m_handler(std::move(handler)) + WaitOper(std::size_t size, DeadlineTimer& timer, clock::time_point expiration_time, H handler): + Service::WaitOperBase{size, timer, expiration_time}, + m_handler{std::move(handler)} { } void recycle_and_execute() override final @@ -3014,39 +3244,34 @@ class deadline_timer::wait_oper: H m_handler; }; -inline deadline_timer::deadline_timer(io_service& serv): - m_service(serv) +inline DeadlineTimer::DeadlineTimer(Service& service): + m_service_impl{*service.m_impl} { } -inline deadline_timer::~deadline_timer() noexcept +inline DeadlineTimer::~DeadlineTimer() noexcept { cancel(); } -inline io_service& deadline_timer::get_io_service() noexcept -{ - return m_service; -} - template -inline void deadline_timer::async_wait(std::chrono::duration delay, H handler) +inline void DeadlineTimer::async_wait(std::chrono::duration delay, H handler) { clock::time_point now = clock::now(); auto max_add = clock::time_point::max() - now; if (delay > max_add) throw std::runtime_error("Expiration time overflow"); clock::time_point expiration_time = now + delay; - io_service::LendersWaitOperPtr op = - io_service::alloc>(m_wait_oper, *this, expiration_time, - std::move(handler)); // Throws - m_service.add_wait_oper(std::move(op)); // Throws + Service::LendersWaitOperPtr op = + Service::alloc>(m_wait_oper, *this, expiration_time, + std::move(handler)); // Throws + add_oper(std::move(op)); // Throws } // ---------------- ReadAheadBuffer ---------------- inline ReadAheadBuffer::ReadAheadBuffer(): - m_buffer(new char[s_size]) // Throws + m_buffer{new char[s_size]} // Throws { } diff --git a/Pods/Realm/include/core/realm/util/network_ssl.hpp b/Pods/Realm/include/core/realm/util/network_ssl.hpp index 0964fa9..ddced77 100644 --- a/Pods/Realm/include/core/realm/util/network_ssl.hpp +++ b/Pods/Realm/include/core/realm/util/network_ssl.hpp @@ -87,6 +87,12 @@ class Context { /// `SSL_CTX_use_PrivateKey_file()`. void use_private_key_file(const std::string& path); + /// Calling use_default_verify() will make a client use the + /// device default certificates for server verification. + /// For OpenSSL, use_default_verify() corresponds to + /// SSL_CTX_set_default_verify_paths(SSL_CTX*); + void use_default_verify(); + /// The verify file is a PEM file containing trust /// certificates that the client will use to /// verify the server crtificate. If use_verify_file() @@ -101,6 +107,7 @@ class Context { void ssl_destroy() noexcept; void ssl_use_certificate_chain_file(const std::string& path, std::error_code&); void ssl_use_private_key_file(const std::string& path, std::error_code&); + void ssl_use_default_verify(std::error_code&); void ssl_use_verify_file(const std::string& path, std::error_code&); #if REALM_HAVE_OPENSSL @@ -152,7 +159,7 @@ class Stream { public: enum HandshakeType { client, server }; - Stream(socket&, Context&, HandshakeType); + Stream(Socket&, Context&, HandshakeType); ~Stream() noexcept; /// \brief Set the certificate verification mode for this SSL stream. @@ -186,7 +193,7 @@ class Stream { /// @{ /// /// Read and write operations behave the same way as they do on \ref - /// network::socket, except that after cancellation of asynchronous + /// network::Socket, except that after cancellation of asynchronous /// operations (`lowest_layer().cancel()`), the stream may be left in a bad /// state (see below). /// @@ -221,28 +228,27 @@ class Stream { /// destroy the stream object. Other stream objects are not affected. void handshake(); - std::error_code handshake(std::error_code&) noexcept; + std::error_code handshake(std::error_code&); std::size_t read(char* buffer, std::size_t size); - std::size_t read(char* buffer, std::size_t size, std::error_code& ec) noexcept; + std::size_t read(char* buffer, std::size_t size, std::error_code& ec); std::size_t read(char* buffer, std::size_t size, ReadAheadBuffer&); - std::size_t read(char* buffer, std::size_t size, ReadAheadBuffer&, - std::error_code& ec) noexcept; + std::size_t read(char* buffer, std::size_t size, ReadAheadBuffer&, std::error_code& ec); std::size_t read_until(char* buffer, std::size_t size, char delim, ReadAheadBuffer&); std::size_t read_until(char* buffer, std::size_t size, char delim, ReadAheadBuffer&, - std::error_code& ec) noexcept; + std::error_code& ec); std::size_t write(const char* data, std::size_t size); - std::size_t write(const char* data, std::size_t size, std::error_code& ec) noexcept; + std::size_t write(const char* data, std::size_t size, std::error_code& ec); std::size_t read_some(char* buffer, std::size_t size); - std::size_t read_some(char* buffer, std::size_t size, std::error_code&) noexcept; + std::size_t read_some(char* buffer, std::size_t size, std::error_code&); std::size_t write_some(const char* data, std::size_t size); - std::size_t write_some(const char* data, std::size_t size, std::error_code&) noexcept; + std::size_t write_some(const char* data, std::size_t size, std::error_code&); void shutdown(); - std::error_code shutdown(std::error_code&) noexcept; + std::error_code shutdown(std::error_code&); template void async_handshake(H handler); @@ -251,7 +257,7 @@ class Stream { template void async_read_until(char* buffer, std::size_t size, char delim, ReadAheadBuffer&, H handler); - template void async_write(const char* data, size_t size, H handler); + template void async_write(const char* data, std::size_t size, H handler); template void async_read_some(char* buffer, std::size_t size, H handler); @@ -262,38 +268,28 @@ class Stream { /// @} /// Returns a reference to the underlying socket. - socket& lowest_layer() noexcept; + Socket& lowest_layer() noexcept; private: - using Want = io_service::Want; - using StreamOps = io_service::BasicStreamOps; + using Want = Service::Want; + using StreamOps = Service::BasicStreamOps; class HandshakeOperBase; template class HandshakeOper; class ShutdownOperBase; template class ShutdownOper; - using LendersHandshakeOperPtr = - std::unique_ptr; - using LendersShutdownOperPtr = - std::unique_ptr; + using LendersHandshakeOperPtr = std::unique_ptr; + using LendersShutdownOperPtr = std::unique_ptr; - socket& m_tcp_socket; + Socket& m_tcp_socket; Context& m_ssl_context; const HandshakeType m_handshake_type; // The host name that the certificate should be checked against. std::string m_host_name; - // For async_handshake(), async_read_some() - io_service::OwnersOperPtr m_read_oper; - - // For async_write_some(), async_shutdown() - io_service::OwnersOperPtr m_write_oper; - - // See io_service::BasicStreamOps for details on these these 8 functions. - void do_init_read_sync(std::error_code&) noexcept; - void do_init_write_sync(std::error_code&) noexcept; + // See Service::BasicStreamOps for details on these these 6 functions. void do_init_read_async(std::error_code&, Want&) noexcept; void do_init_write_async(std::error_code&, Want&) noexcept; std::size_t do_read_some_sync(char* buffer, std::size_t size, @@ -374,9 +370,14 @@ class Stream { }; util::Optional m_last_operation; - // Details of the underlying I/O error that lead to errSecIO being returned from a SecureTransport function. + // Details of the underlying I/O error that lead to errSecIO being returned + // from a SecureTransport function. std::error_code m_last_error; + // The number of bytes accepted by SSWrite() but not yet confirmed to be + // written to the underlying socket. + std::size_t m_num_partially_written_bytes = 0; + template std::size_t ssl_perform(Oper oper, std::error_code& ec, Want& want) noexcept; @@ -385,16 +386,16 @@ class Stream { std::pair do_ssl_read(char* buffer, std::size_t size) noexcept; std::pair do_ssl_write(const char* data, std::size_t size) noexcept; - static OSStatus tcp_read(SSLConnectionRef, void*, size_t* length) noexcept; - static OSStatus tcp_write(SSLConnectionRef, const void*, size_t* length) noexcept; + static OSStatus tcp_read(SSLConnectionRef, void*, std::size_t* length) noexcept; + static OSStatus tcp_write(SSLConnectionRef, const void*, std::size_t* length) noexcept; - OSStatus tcp_read(void*, size_t* length) noexcept; - OSStatus tcp_write(const void*, size_t* length) noexcept; + OSStatus tcp_read(void*, std::size_t* length) noexcept; + OSStatus tcp_write(const void*, std::size_t* length) noexcept; OSStatus verify_peer() noexcept; #endif - friend class io_service::BasicStreamOps; + friend class Service::BasicStreamOps; friend class network::ReadAheadBuffer; }; @@ -434,6 +435,14 @@ inline void Context::use_private_key_file(const std::string& path) throw std::system_error(ec); } +inline void Context::use_default_verify() +{ + std::error_code ec; + ssl_use_default_verify(ec); + if (ec) + throw std::system_error(ec); +} + inline void Context::use_verify_file(const std::string& path) { std::error_code ec; @@ -443,24 +452,21 @@ inline void Context::use_verify_file(const std::string& path) } -class Stream::HandshakeOperBase: public io_service::IoOper { +class Stream::HandshakeOperBase: public Service::IoOper { public: HandshakeOperBase(std::size_t size, Stream& stream): - IoOper(size), - m_stream(&stream) + IoOper{size}, + m_stream{&stream} { } - Want initiate() noexcept + Want initiate() { - REALM_ASSERT(this == m_stream->m_read_oper.get()); + REALM_ASSERT(this == m_stream->m_tcp_socket.m_read_oper.get()); REALM_ASSERT(!is_complete()); - if (m_stream->lowest_layer().ensure_nonblocking_mode(m_error_code)) { - set_is_complete(true); // Failure - return Want::nothing; - } - return proceed(); + m_stream->m_tcp_socket.m_desc.ensure_nonblocking_mode(); // Throws + return advance(); } - Want proceed() noexcept override final + Want advance() noexcept override final { REALM_ASSERT(!is_complete()); REALM_ASSERT(!is_canceled()); @@ -480,9 +486,9 @@ class Stream::HandshakeOperBase: public io_service::IoOper { { m_stream = nullptr; } - socket_base& get_socket() noexcept + Service::Descriptor& descriptor() noexcept override final { - return m_stream->lowest_layer(); + return m_stream->lowest_layer().m_desc; } protected: Stream* m_stream; @@ -492,8 +498,8 @@ class Stream::HandshakeOperBase: public io_service::IoOper { template class Stream::HandshakeOper: public HandshakeOperBase { public: HandshakeOper(std::size_t size, Stream& stream, H handler): - HandshakeOperBase(size, stream), - m_handler(std::move(handler)) + HandshakeOperBase{size, stream}, + m_handler{std::move(handler)} { } void recycle_and_execute() override final @@ -510,24 +516,21 @@ template class Stream::HandshakeOper: public HandshakeOperBase { H m_handler; }; -class Stream::ShutdownOperBase: public io_service::IoOper { +class Stream::ShutdownOperBase: public Service::IoOper { public: ShutdownOperBase(std::size_t size, Stream& stream): - IoOper(size), - m_stream(&stream) + IoOper{size}, + m_stream{&stream} { } - Want initiate() noexcept + Want initiate() { - REALM_ASSERT(this == m_stream->m_write_oper.get()); + REALM_ASSERT(this == m_stream->m_tcp_socket.m_write_oper.get()); REALM_ASSERT(!is_complete()); - if (m_stream->lowest_layer().ensure_nonblocking_mode(m_error_code)) { - set_is_complete(true); // Failure - return Want::nothing; - } - return proceed(); + m_stream->m_tcp_socket.m_desc.ensure_nonblocking_mode(); // Throws + return advance(); } - Want proceed() noexcept override final + Want advance() noexcept override final { REALM_ASSERT(!is_complete()); REALM_ASSERT(!is_canceled()); @@ -548,9 +551,9 @@ class Stream::ShutdownOperBase: public io_service::IoOper { { m_stream = nullptr; } - socket_base& get_socket() noexcept + Service::Descriptor& descriptor() noexcept override final { - return m_stream->lowest_layer(); + return m_stream->lowest_layer().m_desc; } protected: Stream* m_stream; @@ -560,8 +563,8 @@ class Stream::ShutdownOperBase: public io_service::IoOper { template class Stream::ShutdownOper: public ShutdownOperBase { public: ShutdownOper(std::size_t size, Stream& stream, H handler): - ShutdownOperBase(size, stream), - m_handler(std::move(handler)) + ShutdownOperBase{size, stream}, + m_handler{std::move(handler)} { } void recycle_and_execute() override final @@ -578,31 +581,17 @@ template class Stream::ShutdownOper: public ShutdownOperBase { H m_handler; }; -inline Stream::Stream(socket& socket, Context& context, HandshakeType type): - m_tcp_socket(socket), - m_ssl_context(context), - m_handshake_type(type) +inline Stream::Stream(Socket& socket, Context& context, HandshakeType type): + m_tcp_socket{socket}, + m_ssl_context{context}, + m_handshake_type{type} { ssl_init(); // Throws } inline Stream::~Stream() noexcept { - bool any_incomplete = false; - if (m_read_oper && m_read_oper->is_uncanceled()) { - m_read_oper->cancel(); - if (!m_read_oper->is_complete()) - any_incomplete = true; - } - if (m_write_oper && m_write_oper->is_uncanceled()) { - m_write_oper->cancel(); - if (!m_write_oper->is_complete()) - any_incomplete = true; - } - if (any_incomplete) { - io_service& service = m_tcp_socket.get_io_service(); - service.cancel_incomplete_io_ops(m_tcp_socket.get_sock_fd()); - } + m_tcp_socket.cancel(); ssl_destroy(); } @@ -625,112 +614,112 @@ inline void Stream::set_check_host(std::string host_name) inline void Stream::handshake() { std::error_code ec; - if (handshake(ec)) + if (handshake(ec)) // Throws throw std::system_error(ec); } inline std::size_t Stream::read(char* buffer, std::size_t size) { std::error_code ec; - read(buffer, size, ec); + read(buffer, size, ec); // Throws if (ec) throw std::system_error(ec); return size; } -inline std::size_t Stream::read(char* buffer, std::size_t size, std::error_code& ec) noexcept +inline std::size_t Stream::read(char* buffer, std::size_t size, std::error_code& ec) { - return StreamOps::read(*this, buffer, size, ec); + return StreamOps::read(*this, buffer, size, ec); // Throws } inline std::size_t Stream::read(char* buffer, std::size_t size, ReadAheadBuffer& rab) { std::error_code ec; - read(buffer, size, rab, ec); + read(buffer, size, rab, ec); // Throws if (ec) throw std::system_error(ec); return size; } inline std::size_t Stream::read(char* buffer, std::size_t size, ReadAheadBuffer& rab, - std::error_code& ec) noexcept + std::error_code& ec) { int delim = std::char_traits::eof(); - return StreamOps::buffered_read(*this, buffer, size, delim, rab, ec); + return StreamOps::buffered_read(*this, buffer, size, delim, rab, ec); // Throws } inline std::size_t Stream::read_until(char* buffer, std::size_t size, char delim, ReadAheadBuffer& rab) { std::error_code ec; - std::size_t n = read_until(buffer, size, delim, rab, ec); + std::size_t n = read_until(buffer, size, delim, rab, ec); // Throws if (ec) throw std::system_error(ec); return n; } inline std::size_t Stream::read_until(char* buffer, std::size_t size, char delim, - ReadAheadBuffer& rab, std::error_code& ec) noexcept + ReadAheadBuffer& rab, std::error_code& ec) { int delim_2 = std::char_traits::to_int_type(delim); - return StreamOps::buffered_read(*this, buffer, size, delim_2, rab, ec); + return StreamOps::buffered_read(*this, buffer, size, delim_2, rab, ec); // Throws } inline std::size_t Stream::write(const char* data, std::size_t size) { std::error_code ec; - write(data, size, ec); + write(data, size, ec); // Throws if (ec) throw std::system_error(ec); return size; } -inline std::size_t Stream::write(const char* data, std::size_t size, std::error_code& ec) noexcept +inline std::size_t Stream::write(const char* data, std::size_t size, std::error_code& ec) { - return StreamOps::write(*this, data, size, ec); + return StreamOps::write(*this, data, size, ec); // Throws } inline std::size_t Stream::read_some(char* buffer, std::size_t size) { std::error_code ec; - std::size_t n = read_some(buffer, size, ec); + std::size_t n = read_some(buffer, size, ec); // Throws if (ec) throw std::system_error(ec); return n; } -inline std::size_t Stream::read_some(char* buffer, std::size_t size, std::error_code& ec) noexcept +inline std::size_t Stream::read_some(char* buffer, std::size_t size, std::error_code& ec) { - return StreamOps::read_some(*this, buffer, size, ec); + return StreamOps::read_some(*this, buffer, size, ec); // Throws } inline std::size_t Stream::write_some(const char* data, std::size_t size) { std::error_code ec; - std::size_t n = write_some(data, size, ec); + std::size_t n = write_some(data, size, ec); // Throws if (ec) throw std::system_error(ec); return n; } -inline std::size_t Stream::write_some(const char* data, std::size_t size, - std::error_code& ec) noexcept +inline std::size_t Stream::write_some(const char* data, std::size_t size, std::error_code& ec) { - return StreamOps::write_some(*this, data, size, ec); + return StreamOps::write_some(*this, data, size, ec); // Throws } inline void Stream::shutdown() { std::error_code ec; - if (shutdown(ec)) + if (shutdown(ec)) // Throws throw std::system_error(ec); } template inline void Stream::async_handshake(H handler) { LendersHandshakeOperPtr op = - io_service::alloc>(m_read_oper, *this, std::move(handler)); // Throws - io_service::initiate_io_oper(std::move(op)); // Throws + Service::alloc>(m_tcp_socket.m_read_oper, *this, + std::move(handler)); // Throws + m_tcp_socket.m_desc.initiate_oper(std::move(op)); // Throws } template inline void Stream::async_read(char* buffer, std::size_t size, H handler) @@ -775,29 +764,18 @@ template inline void Stream::async_write_some(const char* data, std::si template inline void Stream::async_shutdown(H handler) { LendersShutdownOperPtr op = - io_service::alloc>(m_write_oper, *this, std::move(handler)); // Throws - io_service::initiate_io_oper(std::move(op)); // Throws + Service::alloc>(m_tcp_socket.m_write_oper, *this, + std::move(handler)); // Throws + m_tcp_socket.m_desc.initiate_oper(std::move(op)); // Throws } -inline void Stream::do_init_read_sync(std::error_code& ec) noexcept +inline void Stream::do_init_read_async(std::error_code&, Want& want) noexcept { - lowest_layer().ensure_blocking_mode(ec); -} - -inline void Stream::do_init_write_sync(std::error_code& ec) noexcept -{ - lowest_layer().ensure_blocking_mode(ec); -} - -inline void Stream::do_init_read_async(std::error_code& ec, Want& want) noexcept -{ - lowest_layer().ensure_nonblocking_mode(ec); want = Want::nothing; // Proceed immediately unless there is an error } -inline void Stream::do_init_write_async(std::error_code& ec, Want& want) noexcept +inline void Stream::do_init_write_async(std::error_code&, Want& want) noexcept { - lowest_layer().ensure_nonblocking_mode(ec); want = Want::nothing; // Proceed immediately unless there is an error } @@ -833,7 +811,7 @@ inline std::size_t Stream::do_write_some_async(const char* data, std::size_t siz return ssl_write(data, size, ec, want); } -inline socket& Stream::lowest_layer() noexcept +inline Socket& Stream::lowest_layer() noexcept { return m_tcp_socket; } @@ -947,7 +925,10 @@ inline bool Stream::ssl_shutdown(std::error_code& ec, Want& want) noexcept // // First of all, if the operation remains incomplete (neither successfully // completed, nor failed), ssl_perform() will set `ec` to `std::system_error()`, -// `want` to something other than `Want::nothing`, and return zero. +// `want` to something other than `Want::nothing`, and return zero. Note that +// read and write operations are partial in the sense that they do not need to +// read or write everything before completing successfully. They only nead to +// read or write at least one byte to complete successfully. // // Such a situation will normally only happen when the underlying TCP socket is // in nonblocking mode, and the read/write requirements of the operation could diff --git a/Pods/Realm/include/core/realm/util/thread.hpp b/Pods/Realm/include/core/realm/util/thread.hpp index fc6f001..9231f7f 100644 --- a/Pods/Realm/include/core/realm/util/thread.hpp +++ b/Pods/Realm/include/core/realm/util/thread.hpp @@ -103,7 +103,6 @@ class Mutex { struct process_shared_tag { }; - /// Initialize this mutex for use across multiple processes. When /// constructed this way, the instance may be placed in memory /// shared by multiple processes, as well as in a memory mapped diff --git a/Pods/Realm/include/core/realm/version.hpp b/Pods/Realm/include/core/realm/version.hpp index 6b96100..f60f363 100644 --- a/Pods/Realm/include/core/realm/version.hpp +++ b/Pods/Realm/include/core/realm/version.hpp @@ -25,8 +25,8 @@ #define REALM_VER_MAJOR 2 -#define REALM_VER_MINOR 0 -#define REALM_VER_PATCH 1 +#define REALM_VER_MINOR 2 +#define REALM_VER_PATCH 0 #define REALM_VER_EXTRA "" #define REALM_PRODUCT_NAME "realm-core" diff --git a/Pods/Realm/include/impl/apple/keychain_helper.hpp b/Pods/Realm/include/impl/apple/keychain_helper.hpp index ea6f578..fd3c27a 100644 --- a/Pods/Realm/include/impl/apple/keychain_helper.hpp +++ b/Pods/Realm/include/impl/apple/keychain_helper.hpp @@ -19,21 +19,21 @@ #ifndef REALM_OS_KEYCHAIN_HELPER_HPP #define REALM_OS_KEYCHAIN_HELPER_HPP +#include +#include #include namespace realm { - namespace keychain { std::vector metadata_realm_encryption_key(); class KeychainAccessException : public std::runtime_error { public: - KeychainAccessException(size_t error_code); + KeychainAccessException(int32_t error_code); }; } } - #endif // REALM_OS_KEYCHAIN_HELPER_HPP diff --git a/Pods/Realm/include/impl/collection_notifier.hpp b/Pods/Realm/include/impl/collection_notifier.hpp index 862a98f..c52a02c 100644 --- a/Pods/Realm/include/impl/collection_notifier.hpp +++ b/Pods/Realm/include/impl/collection_notifier.hpp @@ -21,7 +21,7 @@ #include "impl/collection_change_builder.hpp" -#include +#include #include #include @@ -32,8 +32,12 @@ namespace realm { class Realm; +class SharedGroup; +class Table; namespace _impl { +class RealmCoordinator; + struct ListChangeInfo { size_t table_ndx; size_t row_ndx; @@ -46,6 +50,19 @@ struct TransactionChangeInfo { std::vector table_moves_needed; std::vector lists; std::vector tables; + bool track_all = false; + +#if __GNUC__ < 5 + // GCC 4.9 does not support C++14 braced-init with NSDMIs + TransactionChangeInfo() {} + TransactionChangeInfo(std::vector table_modifications_needed, + std::vector table_moves_needed, + std::vector lists) + : table_modifications_needed(std::move(table_modifications_needed)), + table_moves_needed(std::move(table_moves_needed)), + lists(std::move(lists)) + {} +#endif }; class DeepChangeChecker { @@ -115,14 +132,18 @@ class CollectionNotifier { // called from any thread. void remove_callback(size_t token); + void suppress_next_notification(size_t token); + // ------------------------------------------------------------------------ // API for RealmCoordinator to manage running things and calling callbacks + bool is_for_realm(Realm&) const noexcept; Realm* get_realm() const noexcept { return m_realm.get(); } // Get the SharedGroup version which this collection can attach to (if it's // in handover mode), or can deliver to (if it's been handed over to the BG worker alredad) - SharedGroup::VersionID version() const noexcept { return m_sg_version; } + // precondition: RealmCoordinator::m_notifier_mutex is locked + VersionID version() const noexcept { return m_sg_version; } // Release references to all core types // This is called on the worker thread to ensure that non-thread-safe things @@ -130,44 +151,54 @@ class CollectionNotifier { // CollectionNotifier is released on a different thread virtual void release_data() noexcept = 0; - // Prepare to deliver the new collection and call callbacks. Returns the - // transaction version which it can deliver to if applicable, and a - // default-constructed version if this notifier has nothing to deliver to - // this Realm (either due to being for a different Realm, or just because - // nothing has changed since it last delivered). - SharedGroup::VersionID package_for_delivery(Realm&); + // Prepare to deliver the new collection and call callbacks. + // Returns whether or not it has anything to deliver. + // precondition: RealmCoordinator::m_notifier_mutex is locked + bool package_for_delivery(); // Deliver the new state to the target collection using the given SharedGroup + // precondition: RealmCoordinator::m_notifier_mutex is unlocked virtual void deliver(SharedGroup&) { } // Pass the given error to all registered callbacks, then remove them + // precondition: RealmCoordinator::m_notifier_mutex is unlocked void deliver_error(std::exception_ptr); // Call each of the given callbacks with the changesets prepared by package_for_delivery() + // precondition: RealmCoordinator::m_notifier_mutex is unlocked void before_advance(); void after_advance(); bool is_alive() const noexcept; + // precondition: RealmCoordinator::m_notifier_mutex is locked *or* is called on worker thread + bool has_run() const noexcept { return m_has_run; } + // Attach the handed-over query to `sg`. Must not be already attached to a SharedGroup. + // precondition: RealmCoordinator::m_notifier_mutex is locked void attach_to(SharedGroup& sg); // Create a new query handover object and stop using the previously attached // SharedGroup + // precondition: RealmCoordinator::m_notifier_mutex is locked void detach(); // Set `info` as the new ChangeInfo that will be populated by the next // transaction advance, and register all required information in it + // precondition: RealmCoordinator::m_notifier_mutex is locked void add_required_change_info(TransactionChangeInfo& info); + // precondition: RealmCoordinator::m_notifier_mutex is unlocked virtual void run() = 0; + + // precondition: RealmCoordinator::m_notifier_mutex is locked void prepare_handover(); template class Handle; -protected: bool have_callbacks() const noexcept { return m_have_callbacks; } - void add_changes(CollectionChangeBuilder change) { m_accumulated_changes.merge(std::move(change)); } +protected: + void add_changes(CollectionChangeBuilder change); void set_table(Table const& table); std::unique_lock lock_target(); @@ -183,19 +214,20 @@ class CollectionNotifier { mutable std::mutex m_realm_mutex; std::shared_ptr m_realm; - SharedGroup::VersionID m_sg_version; + VersionID m_sg_version; SharedGroup* m_sg = nullptr; + bool m_has_run = false; bool m_error = false; - CollectionChangeBuilder m_accumulated_changes; - CollectionChangeSet m_changes_to_deliver; - std::vector m_related_tables; struct Callback { CollectionChangeCallback fn; + CollectionChangeBuilder accumulated_changes; + CollectionChangeSet changes_to_deliver; size_t token; bool initial_delivered; + bool skip_next; }; // Currently registered callbacks and a mutex which must always be held @@ -211,9 +243,12 @@ class CollectionNotifier { // Iteration variable for looping over callbacks // remove_callback() updates this when needed - size_t m_callback_index = npos; + size_t m_callback_index = -1; + + template + void for_each_callback(Fn&& fn); - CollectionChangeCallback next_callback(bool has_changes, bool pre); + std::vector::iterator find_callback(size_t token); }; // A smart pointer to a CollectionNotifier that unregisters the notifier when @@ -253,6 +288,41 @@ class CollectionNotifier::Handle : public std::shared_ptr { } }; +// A package of CollectionNotifiers for a single Realm instance which is passed +// around to the various places which need to actually trigger the notifications +class NotifierPackage { +public: + NotifierPackage() = default; + NotifierPackage(std::exception_ptr error, + std::vector> notifiers, + RealmCoordinator* coordinator); + + explicit operator bool() { return !m_notifiers.empty(); } + + // Get the version which this package can deliver into, or VersionID{} if + // it has not yet been packaged + util::Optional version() { return m_version; } + + // Package the notifiers for delivery, blocking if they aren't ready for + // the given version. + // No-op if called multiple times + void package_and_wait(util::Optional target_version); + + // Send the before-change notifications + void before_advance(); + // Deliver the payload associated with the contained notifiers and/or the error + void deliver(SharedGroup& sg); + // Send the after-change notifications + void after_advance(); + +private: + util::Optional m_version; + std::vector> m_notifiers; + + RealmCoordinator* m_coordinator = nullptr; + std::exception_ptr m_error; +}; + } // namespace _impl } // namespace realm diff --git a/Pods/Realm/include/impl/external_commit_helper.hpp b/Pods/Realm/include/impl/external_commit_helper.hpp index 920f978..7af8e13 100644 --- a/Pods/Realm/include/impl/external_commit_helper.hpp +++ b/Pods/Realm/include/impl/external_commit_helper.hpp @@ -21,10 +21,14 @@ #include +#if (defined(REALM_HAVE_EPOLL) && REALM_HAVE_EPOLL) || REALM_ANDROID || (REALM_PLATFORM_NODE && !REALM_PLATFORM_APPLE) +#define REALM_USE_EPOLL 1 +#endif + #if REALM_PLATFORM_APPLE #include "impl/apple/external_commit_helper.hpp" -#elif REALM_ANDROID || REALM_PLATFORM_NODE -#include "impl/android/external_commit_helper.hpp" +#elif REALM_USE_EPOLL +#include "impl/epoll/external_commit_helper.hpp" #else #include "impl/generic/external_commit_helper.hpp" #endif diff --git a/Pods/Realm/include/impl/realm_coordinator.hpp b/Pods/Realm/include/impl/realm_coordinator.hpp index 0635b92..7317152 100644 --- a/Pods/Realm/include/impl/realm_coordinator.hpp +++ b/Pods/Realm/include/impl/realm_coordinator.hpp @@ -21,6 +21,7 @@ #include "shared_realm.hpp" +#include #include namespace realm { @@ -28,7 +29,7 @@ class Replication; class Schema; class SharedGroup; class StringData; -struct SyncSession; +class SyncSession; namespace _impl { class CollectionNotifier; @@ -41,6 +42,8 @@ class RealmCoordinator : public std::enable_shared_from_this { public: // Get the coordinator for the given path, creating it if neccesary static std::shared_ptr get_coordinator(StringData path); + // Get the coordinator for the given config, creating it if neccesary + static std::shared_ptr get_coordinator(const Realm::Config&); // Get the coordinator for the given path, or null if there is none static std::shared_ptr get_existing_coordinator(StringData path); @@ -61,6 +64,8 @@ class RealmCoordinator : public std::enable_shared_from_this { // Asynchronously call notify() on every Realm instance for this coordinator's // path, including those in other processes void send_commit_notifications(Realm&); + + void wake_up_notifier_worker(); // Clear the weak Realm cache for all paths // Should only be called in test code, as continuing to use the previously @@ -89,9 +94,27 @@ class RealmCoordinator : public std::enable_shared_from_this { // Advance the Realm to the most recent transaction version which all async // work is complete for void advance_to_ready(Realm& realm); + + // Advance the Realm to the most recent transaction version, blocking if + // async notifiers are not yet ready for that version + // returns whether it actually changed the version + bool advance_to_latest(Realm& realm); + + // Deliver any notifications which are ready for the Realm's version void process_available_async(Realm& realm); - void notify_others(); + void set_transaction_callback(std::function); + + // Deliver notifications for the Realm, blocking if some aren't ready yet + // The calling Realm must be in a write transaction + void promote_to_write(Realm& realm); + + // Commit a Realm's current write transaction and send notifications to all + // other Realm instances for that path, including in other processes + void commit_write(Realm& realm); + + template + std::unique_lock wait_for_notifiers(Pred&& wait_predicate); private: Realm::Config m_config; @@ -102,8 +125,10 @@ class RealmCoordinator : public std::enable_shared_from_this { std::vector m_weak_realm_notifiers; std::mutex m_notifier_mutex; + std::condition_variable m_notifier_cv; std::vector> m_new_notifiers; std::vector> m_notifiers; + VersionID m_notifier_skip_version = {0, 0}; // SharedGroup used for actually running async notifiers // Will have a read transaction iff m_notifiers is non-empty @@ -118,19 +143,42 @@ class RealmCoordinator : public std::enable_shared_from_this { std::exception_ptr m_async_error; std::unique_ptr<_impl::ExternalCommitHelper> m_notifier; + std::function m_transaction_callback; std::shared_ptr m_sync_session; // must be called with m_notifier_mutex locked - void pin_version(uint_fast64_t version, uint_fast32_t index); + void pin_version(VersionID version); + + void set_config(const Realm::Config&); + void create_sync_session(); void run_async_notifiers(); void open_helper_shared_group(); void advance_helper_shared_group_to_latest(); void clean_up_dead_notifiers(); - std::vector> notifiers_to_deliver(Realm&); + + std::vector> notifiers_for_realm(Realm&); }; + +template +std::unique_lock RealmCoordinator::wait_for_notifiers(Pred&& wait_predicate) +{ + std::unique_lock lock(m_notifier_mutex); + bool first = true; + m_notifier_cv.wait(lock, [&] { + if (wait_predicate()) + return true; + if (first) { + wake_up_notifier_worker(); + first = false; + } + return false; + }); + return lock; +} + } // namespace _impl } // namespace realm diff --git a/Pods/Realm/include/impl/results_notifier.hpp b/Pods/Realm/include/impl/results_notifier.hpp index c978e22..c84181a 100644 --- a/Pods/Realm/include/impl/results_notifier.hpp +++ b/Pods/Realm/include/impl/results_notifier.hpp @@ -62,10 +62,6 @@ class ResultsNotifier : public CollectionNotifier { CollectionChangeBuilder m_changes; TransactionChangeInfo* m_info = nullptr; - // Flag for whether or not the query has been run at all, as goofy timing - // can lead to deliver() being called before that - bool m_initial_run_complete = false; - bool need_to_run(); void calculate_changes(); void deliver(SharedGroup&) override; diff --git a/Pods/Realm/include/impl/transact_log_handler.hpp b/Pods/Realm/include/impl/transact_log_handler.hpp index ea1f820..0e535b7 100644 --- a/Pods/Realm/include/impl/transact_log_handler.hpp +++ b/Pods/Realm/include/impl/transact_log_handler.hpp @@ -19,30 +19,35 @@ #ifndef REALM_TRANSACT_LOG_HANDLER_HPP #define REALM_TRANSACT_LOG_HANDLER_HPP -#include +#include +#include namespace realm { class BindingContext; +class SharedGroup; enum class SchemaMode : uint8_t; namespace _impl { +class NotifierPackage; struct TransactionChangeInfo; namespace transaction { // Advance the read transaction version, with change notifications sent to delegate // Must not be called from within a write transaction. void advance(SharedGroup& sg, BindingContext* binding_context, - SchemaMode schema_mode, - SharedGroup::VersionID version=SharedGroup::VersionID{}); + SchemaMode schema_mode, NotifierPackage&); +void advance(SharedGroup& sg, BindingContext* binding_context, + SchemaMode schema_mode, VersionID); // Begin a write transaction // If the read transaction version is not up to date, will first advance to the // most recent read transaction and sent notifications to delegate -void begin(SharedGroup& sg, BindingContext* binding_context, SchemaMode schema_mode); +void begin(SharedGroup& sg, BindingContext* binding_context, SchemaMode schema_mode, + NotifierPackage&); void begin_without_validation(SharedGroup& sg); // Commit a write transaction -void commit(SharedGroup& sg, BindingContext* binding_context); +void commit(SharedGroup& sg); // Cancel a write transaction and roll back all changes, with change notifications // for reverting to the old values sent to delegate @@ -51,7 +56,7 @@ void cancel(SharedGroup& sg, BindingContext* binding_context); // Advance the read transaction version, with change information gathered in info void advance(SharedGroup& sg, TransactionChangeInfo& info, - SharedGroup::VersionID version=SharedGroup::VersionID{}); + VersionID version=VersionID{}); } // namespace transaction } // namespace _impl } // namespace realm diff --git a/Pods/Realm/include/object_schema.hpp b/Pods/Realm/include/object_schema.hpp index 5c4d200..90f6c0a 100644 --- a/Pods/Realm/include/object_schema.hpp +++ b/Pods/Realm/include/object_schema.hpp @@ -53,6 +53,7 @@ class ObjectSchema { const Property *primary_key_property() const { return property_for_name(primary_key); } + bool property_is_computed(Property const& property) const; void validate(Schema const& schema, std::vector& exceptions) const; diff --git a/Pods/Realm/include/results.hpp b/Pods/Realm/include/results.hpp index 8a7f6a8..d5705de 100644 --- a/Pods/Realm/include/results.hpp +++ b/Pods/Realm/include/results.hpp @@ -43,8 +43,8 @@ class Results { // the tableview as needed Results(); Results(SharedRealm r, Table& table); - Results(SharedRealm r, Query q, SortDescriptor s = {}); - Results(SharedRealm r, TableView tv, SortDescriptor s = {}); + Results(SharedRealm r, Query q, SortDescriptor s = {}, SortDescriptor d = {}); + Results(SharedRealm r, TableView tv, SortDescriptor s = {}, SortDescriptor d = {}); Results(SharedRealm r, LinkViewRef lv, util::Optional q = {}, SortDescriptor s = {}); ~Results(); @@ -67,6 +67,9 @@ class Results { // Get the currently applied sort order for this Results SortDescriptor const& get_sort() const noexcept { return m_sort; } + // Get the currently applied distinct condition for this Results + SortDescriptor const& get_distinct() const noexcept { return m_distinct; } + // Get a tableview containing the same rows as this Results TableView get_tableview(); @@ -104,6 +107,13 @@ class Results { Results filter(Query&& q) const; Results sort(SortDescriptor&& sort) const; + // Create a new Results by removing duplicates + // FIXME: The current implementation of distinct() breaks the Results API. + // This is tracked by the following issues: + // - https://github.com/realm/realm-object-store/issues/266 + // - https://github.com/realm/realm-core/issues/2332 + Results distinct(SortDescriptor&& uniqueness); + // Return a snapshot of this Results that never updates to reflect changes in the underlying data. Results snapshot() const &; Results snapshot() &&; @@ -198,6 +208,7 @@ class Results { LinkViewRef m_link_view; Table* m_table = nullptr; SortDescriptor m_sort; + SortDescriptor m_distinct; _impl::CollectionNotifier::Handle<_impl::ResultsNotifier> m_notifier; diff --git a/Pods/Realm/include/shared_realm.hpp b/Pods/Realm/include/shared_realm.hpp index 8927bc4..a54262f 100644 --- a/Pods/Realm/include/shared_realm.hpp +++ b/Pods/Realm/include/shared_realm.hpp @@ -22,8 +22,11 @@ #include "schema.hpp" #include +#include +#if REALM_ENABLE_SYNC #include +#endif #include #include @@ -38,9 +41,16 @@ class Replication; class SharedGroup; class StringData; struct SyncConfig; +struct VersionID; typedef std::shared_ptr SharedRealm; typedef std::weak_ptr WeakRealm; +// Sets a path to a directory where Realm can write temporary files and named pipes. +// This string should include a trailing slash '/'. +void set_temporary_directory(std::string directory_path); + +const std::string& get_temporary_directory() noexcept; + namespace _impl { class AnyHandover; class CollectionNotifier; @@ -56,11 +66,11 @@ enum class SchemaMode : uint8_t { // changes, then call the migration function. // // If the schema version has not changed, verify that the only - // changes are to add new tables and add or remvoe indexes, and then + // changes are to add new tables and add or remove indexes, and then // apply them if so. Does not call the migration function. // // This mode does not automatically remove tables which are not - // present in the schea; that must be manually done in the migration + // present in the schema that must be manually done in the migration // function, to support sharing a Realm file between processes using // different class subsets. // @@ -211,7 +221,7 @@ class Realm : public std::enable_shared_from_this { Realm(Realm&&) = delete; Realm& operator=(Realm&&) = delete; ~Realm(); - + // Pins the current version and exports each object for handover. HandoverPackage package_for_handover(std::vector objects_to_hand_over); @@ -234,24 +244,6 @@ class Realm : public std::enable_shared_from_this { friend HandoverPackage Realm::package_for_handover(std::vector objects_to_hand_over); friend std::vector Realm::accept_handover(Realm::HandoverPackage handover); - struct VersionID { // SharedGroup::VersionID without including header - uint_fast64_t version; - uint_fast32_t index; - - VersionID(); - - template - VersionID(T value) : version(value.version), index(value.index) { } - - template - operator T() const { - T version_id; // Don't use initializer list for better type safety - version_id.version = version; - version_id.index = index; - return version_id; - } - }; - VersionID m_version_id; std::vector<_impl::AnyHandover> m_objects; SharedRealm m_source_realm; // Strong reference keeps alive so version stays pinned! Don't touch!! @@ -289,6 +281,8 @@ class Realm : public std::enable_shared_from_this { // coordinator to wake up the worker thread when a callback is // added, and coordinators need to be able to get themselves from a Realm static _impl::RealmCoordinator& get_coordinator(Realm& realm) { return *realm.m_coordinator; } + + static void begin_read(Realm&, VersionID); }; static void open_with_config(const Config& config, @@ -320,8 +314,10 @@ class Realm : public std::enable_shared_from_this { // File format versions populated when a file format upgrade takes place during realm opening int upgrade_initial_version = 0, upgrade_final_version = 0; + bool m_is_sending_notifications = false; + void set_schema(Schema schema, uint64_t version); - void reset_file_if_needed(Schema const& schema, uint64_t version, std::vector& changes_required); + bool reset_file_if_needed(Schema& schema, uint64_t version, std::vector& changes_required); // Ensure that m_schema and m_schema_version match that of the current // version of the file, and return true if it changed @@ -341,6 +337,8 @@ class RealmFileException : public std::runtime_error { enum class Kind { /** Thrown for any I/O related exception scenarios when a realm is opened. */ AccessError, + /** Thrown if the history type of the on-disk Realm is unexpected or incompatible. */ + BadHistoryError, /** Thrown if the user does not have permission to open or create the specified file in the specified access mode when the realm is opened. */ PermissionDenied, diff --git a/Pods/Realm/include/impl/sync_client.hpp b/Pods/Realm/include/sync/impl/sync_client.hpp similarity index 100% rename from Pods/Realm/include/impl/sync_client.hpp rename to Pods/Realm/include/sync/impl/sync_client.hpp diff --git a/Pods/Realm/include/sync/impl/sync_file.hpp b/Pods/Realm/include/sync/impl/sync_file.hpp new file mode 100644 index 0000000..6a78de3 --- /dev/null +++ b/Pods/Realm/include/sync/impl/sync_file.hpp @@ -0,0 +1,93 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// 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 REALM_OS_SYNC_FILE_HPP +#define REALM_OS_SYNC_FILE_HPP + +#include + +namespace realm { + +namespace util { + +enum class FilePathType { + File, Directory +}; + +// FIXME: Does it make sense to use realm::StringData arguments for these functions instead of std::string? + +/// Given a string, turn it into a percent-encoded string. +std::string make_percent_encoded_string(const std::string& raw_string); + +/// Given a percent-encoded string, turn it into the original (non-encoded) string. +std::string make_raw_string(const std::string& percent_encoded_string); + +/// Given a file path and a path component, return a new path created by appending the component to the path. +std::string file_path_by_appending_component(const std::string& path, + const std::string& component, + FilePathType path_type=FilePathType::File); + +/// Given a file path and an extension, append the extension to the path. +std::string file_path_by_appending_extension(const std::string& path, const std::string& extension); + +/// Remove a directory, including non-empty directories. +void remove_nonempty_dir(const std::string& path); + +} // util + +class SyncFileManager { +public: + SyncFileManager(std::string base_path) : m_base_path(std::move(base_path)) { } + + /// Return the user directory for a given user, creating it if it does not already exist. + std::string user_directory(const std::string& user_identity) const; + + /// Remove the user directory for a given user. + void remove_user_directory(const std::string& user_identity) const; // throws + + /// Return the path for a given Realm, creating the user directory if it does not already exist. + std::string path(const std::string& user_identity, const std::string& raw_realm_path) const; + + /// Remove the Realm at a given path for a given user. Returns `true` if the remove operation fully succeeds. + bool remove_realm(const std::string& user_identity, const std::string& raw_realm_path) const; + + /// Return the path for the metadata Realm files. + std::string metadata_path() const; + + /// Remove the metadata Realm. + bool remove_metadata_realm() const; + + const std::string& base_path() const { + return m_base_path; + } + +private: + std::string m_base_path; + + static constexpr const char c_sync_directory[] = "realm-object-server"; + static constexpr const char c_utility_directory[] = "io.realm.object-server-utility"; + static constexpr const char c_metadata_directory[] = "metadata"; + static constexpr const char c_metadata_realm[] = "sync_metadata.realm"; + + std::string get_utility_directory() const; + std::string get_base_sync_directory() const; +}; + +} // realm + +#endif // REALM_OS_SYNC_FILE_HPP diff --git a/Pods/Realm/include/sync_metadata.hpp b/Pods/Realm/include/sync/impl/sync_metadata.hpp similarity index 97% rename from Pods/Realm/include/sync_metadata.hpp rename to Pods/Realm/include/sync/impl/sync_metadata.hpp index 000f823..e07305b 100644 --- a/Pods/Realm/include/sync_metadata.hpp +++ b/Pods/Realm/include/sync/impl/sync_metadata.hpp @@ -62,7 +62,7 @@ class SyncUserMetadata { // set operations are no-ops and all get operations cause an assert to fail. // // If `make_if_absent` is true and the user was previously marked for deletion, it will be unmarked. - SyncUserMetadata(SyncMetadataManager& manager, std::string identity, bool make_if_absent=true); + SyncUserMetadata(const SyncMetadataManager& manager, std::string identity, bool make_if_absent=true); SyncUserMetadata(Schema schema, SharedRealm realm, RowExpr row); diff --git a/Pods/Realm/include/sync_config.hpp b/Pods/Realm/include/sync/sync_config.hpp similarity index 54% rename from Pods/Realm/include/sync_config.hpp rename to Pods/Realm/include/sync/sync_config.hpp index a85d926..5eb8f5a 100644 --- a/Pods/Realm/include/sync_config.hpp +++ b/Pods/Realm/include/sync/sync_config.hpp @@ -20,37 +20,39 @@ #define REALM_OS_SYNC_CONFIG_HPP #include +#include #include namespace realm { +class SyncUser; +class SyncSession; + enum class SyncSessionStopPolicy; enum class SyncSessionError { - Debug, // An informational error, nothing to do. Only for debug purposes. - SessionFatal, // The session is invalid and should be killed. - AccessDenied, // Permissions error with the session. - UserFatal, // The user associated with the session is invalid. + Debug, // An informational error, nothing to do. Only for debug purposes. + SessionFatal, // The session is invalid and should be killed. + AccessDenied, // Permissions error with the session. + UserFatal, // The user associated with the session is invalid. }; -using SyncSessionErrorHandler = void(int error_code, std::string message, SyncSessionError); +struct SyncConfig; +using SyncBindSessionHandler = void(const std::string&, // path on disk of the Realm file. + const SyncConfig&, // the sync configuration object. + std::shared_ptr // the session which should be bound. + ); + +using SyncSessionErrorHandler = void(std::shared_ptr, int error_code, std::string message, SyncSessionError); struct SyncConfig { - SyncConfig(std::string user_tag, std::string realm_url, std::function error_handler, - SyncSessionStopPolicy stop_policy) - : user_tag(std::move(user_tag)) - , realm_url(std::move(realm_url)) - , error_handler(std::move(error_handler)) - , stop_policy(stop_policy) - { - } - - std::string user_tag; + std::shared_ptr user; std::string realm_url; - std::function error_handler; SyncSessionStopPolicy stop_policy; + std::function bind_session_handler; + std::function error_handler; }; -} // realm +} // namespace realm #endif // REALM_OS_SYNC_CONFIG_HPP diff --git a/Pods/Realm/include/sync_manager.hpp b/Pods/Realm/include/sync/sync_manager.hpp similarity index 60% rename from Pods/Realm/include/sync_manager.hpp rename to Pods/Realm/include/sync/sync_manager.hpp index e90fc52..11919bc 100644 --- a/Pods/Realm/include/sync_manager.hpp +++ b/Pods/Realm/include/sync/sync_manager.hpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -31,7 +32,10 @@ namespace realm { struct SyncConfig; -struct SyncSession; +class SyncSession; +class SyncUser; +class SyncFileManager; +class SyncMetadataManager; namespace _impl { struct SyncClient; @@ -43,32 +47,66 @@ enum class SyncSessionStopPolicy { AfterChangesUploaded, // Once all Realms/Sessions go out of scope, wait for uploads to complete and stop. }; -using SyncLoginFunction = std::function; - class SyncLoggerFactory { public: virtual std::unique_ptr make_logger(util::Logger::Level) = 0; }; class SyncManager { -friend struct SyncSession; +friend class SyncSession; public: + enum class MetadataMode { + NoEncryption, // Enable metadata, but disable encryption. + Encryption, // Enable metadata, and use encryption (automatic if possible). + NoMetadata, // Disable metadata. + }; + static SyncManager& shared(); + // Configure the metadata and file management subsystems. This MUST be called upon startup. + void configure_file_system(const std::string& base_file_path, + MetadataMode metadata_mode=MetadataMode::Encryption, + util::Optional> custom_encryption_key=none, + bool reset_metadata_on_error=false); + void set_log_level(util::Logger::Level) noexcept; void set_logger_factory(SyncLoggerFactory&) noexcept; void set_error_handler(std::function); - void set_login_function(SyncLoginFunction); /// Control whether the sync client attempts to reconnect immediately. Only set this to `true` for testing purposes. void set_client_should_reconnect_immediately(bool reconnect_immediately); + bool client_should_reconnect_immediately() const noexcept; + /// Control whether the sync client validates SSL certificates. Should *always* be `true` in production use. void set_client_should_validate_ssl(bool validate_ssl); + bool client_should_validate_ssl() const noexcept; + + util::Logger::Level log_level() const noexcept; std::shared_ptr get_session(const std::string& path, const SyncConfig& config); std::shared_ptr get_existing_active_session(const std::string& path) const; - SyncLoginFunction& get_sync_login_function(); + // If the metadata manager is configured, perform an update. Returns `true` iff the code was run. + bool perform_metadata_update(std::function update_function) const; + + // Get a sync user for a given identity, or create one if none exists yet, and set its token. + // If a logged-out user exists, it will marked as logged back in. + std::shared_ptr get_user(const std::string& identity, + std::string refresh_token, + util::Optional auth_server_url=none, + bool is_admin=false); + // Get an existing user for a given identity, if one exists and is logged in. + std::shared_ptr get_existing_logged_in_user(const std::string& identity) const; + // Get all the users that are logged in and not errored out. + std::vector> all_logged_in_users() const; + + // Get the default path for a Realm for the given user and absolute unresolved URL. + std::string path_for_realm(const std::string& user_identity, const std::string& raw_realm_url) const; + + // Reset the singleton state for testing purposes. DO NOT CALL OUTSIDE OF TESTING CODE. + // Precondition: any synced Realms or `SyncSession`s must be closed or rendered inactive prior to + // calling this method. + void reset_for_testing(); private: void dropped_last_reference_to_session(SyncSession*); @@ -90,8 +128,6 @@ friend struct SyncSession; mutable std::mutex m_mutex; - SyncLoginFunction m_login_function; - // FIXME: Should probably be util::Logger::Level::error util::Logger::Level m_log_level = util::Logger::Level::info; SyncLoggerFactory* m_logger_factory = nullptr; @@ -99,11 +135,22 @@ friend struct SyncSession; sync::Client::Reconnect m_client_reconnect_mode = sync::Client::Reconnect::normal; bool m_client_validate_ssl = true; + // Protects m_users + mutable std::mutex m_user_mutex; + + // A map of user identities to (shared pointers to) SyncUser objects. + std::unordered_map> m_users; + mutable std::shared_ptr<_impl::SyncClient> m_sync_client; // Protects m_active_sessions and m_inactive_sessions mutable std::mutex m_session_mutex; + // Protects m_file_manager and m_metadata_manager + mutable std::mutex m_file_system_mutex; + std::unique_ptr m_file_manager; + std::unique_ptr m_metadata_manager; + // Active sessions are sessions which the client code holds a strong // reference to. When the last strong reference is released, the session is // moved to inactive sessions. Inactive sessions are promoted back to active diff --git a/Pods/Realm/include/sync_session.hpp b/Pods/Realm/include/sync/sync_session.hpp similarity index 76% rename from Pods/Realm/include/sync_session.hpp rename to Pods/Realm/include/sync/sync_session.hpp index 144db91..1b5617e 100644 --- a/Pods/Realm/include/sync_session.hpp +++ b/Pods/Realm/include/sync/sync_session.hpp @@ -29,6 +29,7 @@ namespace realm { class SyncManager; +class SyncUser; namespace _impl { class RealmCoordinator; @@ -49,19 +50,37 @@ class Session; using SyncSessionTransactCallback = void(VersionID old_version, VersionID new_version); -struct SyncSession : public std::enable_shared_from_this { - bool is_valid() const; +class SyncSession : public std::enable_shared_from_this { +public: + enum class PublicState { + WaitingForAccessToken, + Active, + Dying, + Inactive, + Error, + }; + PublicState state() const; + + bool is_in_error_state() const { + return state() == PublicState::Error; + } std::string const& path() const { return m_realm_path; } - void wait_for_upload_completion(std::function callback); - void wait_for_download_completion(std::function callback); + bool wait_for_upload_completion(std::function callback); + bool wait_for_download_completion(std::function callback); + + // Wait for any pending uploads to complete, blocking the calling thread. + // Returns `false` if the method did not attempt to wait, either because the + // session is in an error state or because it hasn't yet been `bind()`ed. + bool wait_for_upload_completion_blocking(); // If the sync session is currently `Dying`, ask it to stay alive instead. // If the sync session is currently `Inactive`, recreate it. Otherwise, a no-op. - void revive_if_needed(); + static void revive_if_needed(std::shared_ptr session); void refresh_access_token(std::string access_token, util::Optional server_url); + void bind_with_admin_token(std::string admin_token, std::string server_url); // Inform the sync session that it should close. void close(); @@ -72,6 +91,21 @@ struct SyncSession : public std::enable_shared_from_this { // Inform the sync session that it should log out. void log_out(); + std::shared_ptr user() const + { + return m_config.user; + } + + const SyncConfig& config() const + { + return m_config; + } + + util::Optional full_realm_url() const + { + return m_server_url; + } + // Expose some internal functionality to other parts of the ObjectStore // without making it public to everyone class Internal { @@ -105,11 +139,10 @@ struct SyncSession : public std::enable_shared_from_this { friend class realm::SyncManager; // Called by SyncManager { SyncSession(std::shared_ptr<_impl::SyncClient>, std::string realm_path, SyncConfig); - - // Check if this sync session is actually inactive - bool is_inactive() const; // } + bool can_wait_for_network_completion() const; + void set_sync_transact_callback(std::function); void set_error_handler(std::function); void nonsync_transact_notify(VersionID::version_type); @@ -125,7 +158,7 @@ struct SyncSession : public std::enable_shared_from_this { mutable std::mutex m_state_mutex; const State* m_state = nullptr; - size_t m_pending_upload_threads = 0; + size_t m_death_count = 0; SyncConfig m_config; diff --git a/Pods/Realm/include/sync/sync_user.hpp b/Pods/Realm/include/sync/sync_user.hpp new file mode 100644 index 0000000..de1d69d --- /dev/null +++ b/Pods/Realm/include/sync/sync_user.hpp @@ -0,0 +1,122 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2016 Realm Inc. +// +// 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 REALM_OS_SYNC_USER_HPP +#define REALM_OS_SYNC_USER_HPP + +#include +#include +#include +#include +#include + +#include + +namespace realm { + +class SyncSession; + +// A `SyncUser` represents a single user account. Each user manages the sessions that +// are associated with it. +class SyncUser { +friend class SyncSession; +public: + enum class State { + LoggedOut, + Active, + Error, + }; + + // Don't use this directly; use the `SyncManager` APIs. Public for use with `make_shared`. + SyncUser(std::string refresh_token, + std::string identity, + util::Optional server_url, + bool is_admin=false); + + // Return a list of all sessions belonging to this user. + std::vector> all_sessions(); + + // Return a session for a given URL. + std::shared_ptr session_for_url(const std::string& url); + + // Update the user's refresh token. If the user is logged out, it will log itself back in. + // Note that this is called by the SyncManager, and should not be directly called. + void update_refresh_token(std::string token); + + // Log the user out and mark it as such. This will also close its associated Sessions. + void log_out(); + + // Whether the user was configured as an 'admin user' (directly uses its user token + // to open Realms). + bool is_admin() const + { + return m_is_admin; + } + + std::string identity() const + { + return m_identity; + } + + // FIXME: remove this APIs once the new token system is implemented. + const std::string& server_url() const + { + return m_server_url; + } + + std::string refresh_token() const; + State state() const; + + // Register a session to this user. + // A registered session will be bound at the earliest opportunity: either + // immediately, or upon the user becoming Active. + // Note that this is called by the SyncManager, and should not be directly called. + void register_session(std::shared_ptr session); + +private: + State m_state; + + // The auth server URL. Bindings should set this appropriately when they retrieve + // instances of `SyncUser`s. + // FIXME: once the new token system is implemented, this can be removed completely. + std::string m_server_url; + + // Mark the user as invalid, since a fatal user-related error was encountered. + void invalidate(); + + mutable std::mutex m_mutex; + + // Whether the user is an 'admin' user. Admin users use the admin tokens they were + // configured with to directly open sessions, and do not make network requests. + bool m_is_admin; + // The user's refresh token. + std::string m_refresh_token; + // Set by the server. The unique ID of the user account on the Realm Object Server. + std::string m_identity; + + // Sessions are owned by the SyncManager, but the user keeps a map of weak references + // to them. + std::unordered_map> m_sessions; + + // Waiting sessions are those that should be asked to connect once this user is logged in. + std::unordered_map> m_waiting_sessions; +}; + +} + +#endif // REALM_OS_SYNC_USER_HPP diff --git a/Pods/Realm/include/util/atomic_shared_ptr.hpp b/Pods/Realm/include/util/atomic_shared_ptr.hpp index 1d07e02..b4eb52f 100644 --- a/Pods/Realm/include/util/atomic_shared_ptr.hpp +++ b/Pods/Realm/include/util/atomic_shared_ptr.hpp @@ -76,6 +76,11 @@ class AtomicSharedPtr { return std::atomic_exchange(&m_ptr, std::move(ptr)); } + std::shared_ptr load() const noexcept + { + return std::atomic_load(&m_ptr); + } + private: std::shared_ptr m_ptr = nullptr; }; @@ -126,8 +131,14 @@ class AtomicSharedPtr { return ptr; } + std::shared_ptr load() const noexcept + { + std::lock_guard lock(m_mutex); + return m_ptr; + } + private: - std::mutex m_mutex; + mutable std::mutex m_mutex; std::shared_ptr m_ptr = nullptr; }; diff --git a/Pods/Realm/include/util/event_loop_signal.hpp b/Pods/Realm/include/util/event_loop_signal.hpp index 4e084eb..08d370b 100644 --- a/Pods/Realm/include/util/event_loop_signal.hpp +++ b/Pods/Realm/include/util/event_loop_signal.hpp @@ -21,8 +21,12 @@ #include -#if REALM_PLATFORM_NODE -#include "util/node/event_loop_signal.hpp" +#if (defined(REALM_HAVE_UV) && REALM_HAVE_UV && !REALM_PLATFORM_APPLE) || REALM_PLATFORM_NODE +#define REALM_USE_UV 1 +#endif + +#if REALM_USE_UV +#include "util/uv/event_loop_signal.hpp" #elif REALM_PLATFORM_APPLE #include "util/apple/event_loop_signal.hpp" #elif REALM_ANDROID diff --git a/Pods/Target Support Files/Pods-VBB/Pods-VBB-acknowledgements.plist b/Pods/Target Support Files/Pods-VBB/Pods-VBB-acknowledgements.plist index 266896a..550fae3 100644 --- a/Pods/Target Support Files/Pods-VBB/Pods-VBB-acknowledgements.plist +++ b/Pods/Target Support Files/Pods-VBB/Pods-VBB-acknowledgements.plist @@ -243,13 +243,13 @@ EXPORT COMPLIANCE You understand that the Software may contain cryptographic functions that may be subject to export restrictions, and you represent and warrant that you are not (i) located in a jurisdiction that is subject to United States economic -sanctions (“Prohibited Jurisdiction”), including Cuba, Iran, North Korea, +sanctions (“Prohibited Jurisdiction”), including Cuba, Iran, North Korea, Sudan, Syria or the Crimea region, (ii) a person listed on any U.S. government blacklist (to include the List of Specially Designated Nationals and Blocked Persons or the Consolidated Sanctions List administered by the U.S. Department -of the Treasury’s Office of Foreign Assets Control, or the Denied Persons List +of the Treasury’s Office of Foreign Assets Control, or the Denied Persons List or Entity List administered by the U.S. Department of Commerce) -(“Sanctioned Person”), or (iii) controlled or 50% or more owned by a Sanctioned +(“Sanctioned Person”), or (iii) controlled or 50% or more owned by a Sanctioned Person. You agree to comply with all export, re-export and import restrictions and diff --git a/Pods/Target Support Files/Pods-VBB/Pods-VBB-resources.sh b/Pods/Target Support Files/Pods-VBB/Pods-VBB-resources.sh index 0a15615..25e9d37 100755 --- a/Pods/Target Support Files/Pods-VBB/Pods-VBB-resources.sh +++ b/Pods/Target Support Files/Pods-VBB/Pods-VBB-resources.sh @@ -23,12 +23,6 @@ case "${TARGETED_DEVICE_FAMILY}" in ;; esac -realpath() { - DIRECTORY="$(cd "${1%/*}" && pwd)" - FILENAME="${1##*/}" - echo "$DIRECTORY/$FILENAME" -} - install_resource() { if [[ "$1" = /* ]] ; then @@ -70,7 +64,7 @@ EOM xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" ;; *.xcassets) - ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") + ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") ;; *) @@ -93,7 +87,7 @@ then # Find all other xcassets (this unfortunately includes those of path pods and other targets). OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) while read line; do - if [[ $line != "`realpath $PODS_ROOT`*" ]]; then + if [[ $line != "${PODS_ROOT}*" ]]; then XCASSET_FILES+=("$line") fi done <<<"$OTHER_XCASSETS" diff --git a/Pods/Target Support Files/Pods-VBB/Pods-VBB-umbrella.h b/Pods/Target Support Files/Pods-VBB/Pods-VBB-umbrella.h index a2ff8e8..4026295 100644 --- a/Pods/Target Support Files/Pods-VBB/Pods-VBB-umbrella.h +++ b/Pods/Target Support Files/Pods-VBB/Pods-VBB-umbrella.h @@ -1,4 +1,6 @@ +#ifdef __OBJC__ #import +#endif FOUNDATION_EXPORT double Pods_VBBVersionNumber; diff --git a/Pods/Target Support Files/Pods-VBBNow/Pods-VBBNow-acknowledgements.plist b/Pods/Target Support Files/Pods-VBBNow/Pods-VBBNow-acknowledgements.plist index 266896a..550fae3 100644 --- a/Pods/Target Support Files/Pods-VBBNow/Pods-VBBNow-acknowledgements.plist +++ b/Pods/Target Support Files/Pods-VBBNow/Pods-VBBNow-acknowledgements.plist @@ -243,13 +243,13 @@ EXPORT COMPLIANCE You understand that the Software may contain cryptographic functions that may be subject to export restrictions, and you represent and warrant that you are not (i) located in a jurisdiction that is subject to United States economic -sanctions (“Prohibited Jurisdiction”), including Cuba, Iran, North Korea, +sanctions (“Prohibited Jurisdiction”), including Cuba, Iran, North Korea, Sudan, Syria or the Crimea region, (ii) a person listed on any U.S. government blacklist (to include the List of Specially Designated Nationals and Blocked Persons or the Consolidated Sanctions List administered by the U.S. Department -of the Treasury’s Office of Foreign Assets Control, or the Denied Persons List +of the Treasury’s Office of Foreign Assets Control, or the Denied Persons List or Entity List administered by the U.S. Department of Commerce) -(“Sanctioned Person”), or (iii) controlled or 50% or more owned by a Sanctioned +(“Sanctioned Person”), or (iii) controlled or 50% or more owned by a Sanctioned Person. You agree to comply with all export, re-export and import restrictions and diff --git a/Pods/Target Support Files/Pods-VBBNow/Pods-VBBNow-resources.sh b/Pods/Target Support Files/Pods-VBBNow/Pods-VBBNow-resources.sh index 0a15615..25e9d37 100755 --- a/Pods/Target Support Files/Pods-VBBNow/Pods-VBBNow-resources.sh +++ b/Pods/Target Support Files/Pods-VBBNow/Pods-VBBNow-resources.sh @@ -23,12 +23,6 @@ case "${TARGETED_DEVICE_FAMILY}" in ;; esac -realpath() { - DIRECTORY="$(cd "${1%/*}" && pwd)" - FILENAME="${1##*/}" - echo "$DIRECTORY/$FILENAME" -} - install_resource() { if [[ "$1" = /* ]] ; then @@ -70,7 +64,7 @@ EOM xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" ;; *.xcassets) - ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") + ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") ;; *) @@ -93,7 +87,7 @@ then # Find all other xcassets (this unfortunately includes those of path pods and other targets). OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) while read line; do - if [[ $line != "`realpath $PODS_ROOT`*" ]]; then + if [[ $line != "${PODS_ROOT}*" ]]; then XCASSET_FILES+=("$line") fi done <<<"$OTHER_XCASSETS" diff --git a/Pods/Target Support Files/Pods-VBBNow/Pods-VBBNow-umbrella.h b/Pods/Target Support Files/Pods-VBBNow/Pods-VBBNow-umbrella.h index 4df014e..8eeb7f7 100644 --- a/Pods/Target Support Files/Pods-VBBNow/Pods-VBBNow-umbrella.h +++ b/Pods/Target Support Files/Pods-VBBNow/Pods-VBBNow-umbrella.h @@ -1,4 +1,6 @@ +#ifdef __OBJC__ #import +#endif FOUNDATION_EXPORT double Pods_VBBNowVersionNumber; diff --git a/Pods/Target Support Files/Realm/Info.plist b/Pods/Target Support Files/Realm/Info.plist index bdac57c..92aaf05 100644 --- a/Pods/Target Support Files/Realm/Info.plist +++ b/Pods/Target Support Files/Realm/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 2.0.1 + 2.1.1 CFBundleSignature ???? CFBundleVersion diff --git a/Pods/Target Support Files/Realm/Realm.modulemap b/Pods/Target Support Files/Realm/Realm.modulemap index 3d6c640..ef2d102 100644 --- a/Pods/Target Support Files/Realm/Realm.modulemap +++ b/Pods/Target Support Files/Realm/Realm.modulemap @@ -19,6 +19,7 @@ framework module Realm { header "RLMResults_Private.h" header "RLMSchema_Private.h" header "RLMSyncConfiguration_Private.h" + header "RLMSyncUtil_Private.h" } explicit module Dynamic { diff --git a/VBB.xcodeproj/project.pbxproj b/VBB.xcodeproj/project.pbxproj index 89c0bc7..c58c7ed 100644 --- a/VBB.xcodeproj/project.pbxproj +++ b/VBB.xcodeproj/project.pbxproj @@ -95,7 +95,6 @@ E19086D71A79870300364EA2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; E19086EF1A79886400364EA2 /* VBBNetworkManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VBBNetworkManager.h; sourceTree = ""; }; E19086F01A79886400364EA2 /* VBBNetworkManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VBBNetworkManager.m; sourceTree = ""; }; - E1948A781A7A3D95005C9D97 /* vbb.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = vbb.entitlements; sourceTree = ""; }; E1948A7E1A7A3DEB005C9D97 /* NotificationCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NotificationCenter.framework; path = System/Library/Frameworks/NotificationCenter.framework; sourceTree = SDKROOT; }; E1948A951A7A3EB0005C9D97 /* VBBaseParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VBBaseParser.h; sourceTree = ""; }; E1948A961A7A3EB0005C9D97 /* VBBaseParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VBBaseParser.m; sourceTree = ""; }; @@ -190,7 +189,6 @@ isa = PBXGroup; children = ( E17A6ABA1C770CF900506B8A /* VBB.entitlements */, - E1948A781A7A3D95005C9D97 /* vbb.entitlements */, E1A5689C1A7990AE00C2EA16 /* Parser */, E19086EE1A79885600364EA2 /* Model */, E19086ED1A79885100364EA2 /* Manager */, @@ -661,6 +659,7 @@ CODE_SIGN_ENTITLEMENTS = VBBNow/vbbnow.entitlements; CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = YE33ZK7Z99; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -682,6 +681,7 @@ CODE_SIGN_ENTITLEMENTS = VBBNow/vbbnow.entitlements; CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = YE33ZK7Z99; INFOPLIST_FILE = VBBNow/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; diff --git a/VBB/Info.plist b/VBB/Info.plist index 99ad94c..9ddaf23 100644 --- a/VBB/Info.plist +++ b/VBB/Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0.1 + 1.0.2 CFBundleSignature ???? CFBundleVersion - 4 + 5 LSApplicationCategoryType public.app-category.travel LSMinimumSystemVersion