added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / sync / sync_manager.hpp
1 ////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright 2016 Realm Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 ////////////////////////////////////////////////////////////////////////////
18
19 #ifndef REALM_OS_SYNC_MANAGER_HPP
20 #define REALM_OS_SYNC_MANAGER_HPP
21
22 #include "shared_realm.hpp"
23
24 #include "sync_user.hpp"
25
26 #include <realm/sync/client.hpp>
27 #include <realm/util/logger.hpp>
28 #include <realm/util/optional.hpp>
29
30 #include <memory>
31 #include <mutex>
32 #include <unordered_map>
33
34 namespace realm {
35
36 struct SyncConfig;
37 class SyncSession;
38 class SyncUser;
39 class SyncFileManager;
40 class SyncMetadataManager;
41 class SyncFileActionMetadata;
42
43 namespace _impl {
44 struct SyncClient;
45 }
46
47 enum class SyncSessionStopPolicy {
48     Immediately,                    // Immediately stop the session as soon as all Realms/Sessions go out of scope.
49     LiveIndefinitely,               // Never stop the session.
50     AfterChangesUploaded,           // Once all Realms/Sessions go out of scope, wait for uploads to complete and stop.
51 };
52
53 class SyncLoggerFactory {
54 public:
55     virtual std::unique_ptr<util::Logger> make_logger(util::Logger::Level) = 0;
56 };
57
58 class SyncManager {
59 friend class SyncSession;
60 public:
61     enum class MetadataMode {
62         NoEncryption,                   // Enable metadata, but disable encryption.
63         Encryption,                     // Enable metadata, and use encryption (automatic if possible).
64         NoMetadata,                     // Disable metadata.
65     };
66
67     static SyncManager& shared();
68
69     // Configure the metadata and file management subsystems. This MUST be called upon startup.
70     void configure_file_system(const std::string& base_file_path,
71                                MetadataMode metadata_mode=MetadataMode::Encryption,
72                                util::Optional<std::vector<char>> custom_encryption_key=none,
73                                bool reset_metadata_on_error=false);
74
75     // Immediately run file actions for a single Realm at a given original path.
76     // Returns whether or not a file action was successfully executed for the specified Realm.
77     // Preconditions: all references to the Realm at the given path must have already been invalidated.
78     // The metadata and file management subsystems must also have already been configured.
79     bool immediately_run_file_actions(const std::string& original_name);
80
81     // Use a single connection for all sync sessions for each host/port rather
82     // than one per session.
83     // This must be called before any sync sessions are created, cannot be
84     // disabled afterwards, and currently is incompatible with using a load
85     // balancer or automatic failover.
86     void enable_session_multiplexing();
87
88     void set_log_level(util::Logger::Level) noexcept;
89     void set_logger_factory(SyncLoggerFactory&) noexcept;
90
91     /// Control whether the sync client attempts to reconnect immediately. Only set this to `true` for testing purposes.
92     void set_client_should_reconnect_immediately(bool reconnect_immediately);
93     bool client_should_reconnect_immediately() const noexcept;
94
95     /// Ask all valid sync sessions to perform whatever tasks might be necessary to
96     /// re-establish connectivity with the Realm Object Server. It is presumed that
97     /// the caller knows that network connectivity has been restored.
98     ///
99     /// Refer to `SyncSession::handle_reconnect()` to see what sort of work is done
100     /// on a per-session basis.
101     void reconnect();
102
103     util::Logger::Level log_level() const noexcept;
104
105     std::shared_ptr<SyncSession> get_session(const std::string& path, const SyncConfig& config);
106     std::shared_ptr<SyncSession> get_existing_session(const std::string& path) const;
107     std::shared_ptr<SyncSession> get_existing_active_session(const std::string& path) const;
108
109     // If the metadata manager is configured, perform an update. Returns `true` iff the code was run.
110     bool perform_metadata_update(std::function<void(const SyncMetadataManager&)> update_function) const;
111
112     // Get a sync user for a given identity, or create one if none exists yet, and set its token.
113     // If a logged-out user exists, it will marked as logged back in.
114     std::shared_ptr<SyncUser> get_user(const SyncUserIdentifier& identifier, std::string refresh_token);
115
116     // Get or create an admin token user based on the given identity.
117     // Please note: a future version will remove this method and deprecate the
118     // use of identities for admin users completely.
119     // Warning: it is an error to create or get an admin token user with a given identity and
120     // specifying a URL, and later get that same user by specifying only the identity and no
121     // URL, or vice versa.
122     std::shared_ptr<SyncUser> get_admin_token_user_from_identity(const std::string& identity,
123                                                                  util::Optional<std::string> server_url,
124                                                                  const std::string& token);
125
126     // Get or create an admin token user for the given URL.
127     // If the user already exists, the token value will be ignored.
128     // If an old identity is provided and a directory for the user already exists, the directory
129     // will be renamed.
130     std::shared_ptr<SyncUser> get_admin_token_user(const std::string& server_url,
131                                                    const std::string& token,
132                                                    util::Optional<std::string> old_identity=none);
133
134     // Get an existing user for a given identifier, if one exists and is logged in.
135     std::shared_ptr<SyncUser> get_existing_logged_in_user(const SyncUserIdentifier&) const;
136
137     // Get all the users that are logged in and not errored out.
138     std::vector<std::shared_ptr<SyncUser>> all_logged_in_users() const;
139     // Gets the currently logged in user. If there are more than 1 users logged in, an exception is thrown.
140     std::shared_ptr<SyncUser> get_current_user() const;
141
142     // Get the default path for a Realm for the given user and absolute unresolved URL.
143     std::string path_for_realm(const SyncUser& user, const std::string& raw_realm_url) const;
144
145     // Get the path of the recovery directory for backed-up or recovered Realms.
146     std::string recovery_directory_path() const;
147
148     // Get the unique identifier of this client.
149     std::string client_uuid() const;
150
151     // Reset the singleton state for testing purposes. DO NOT CALL OUTSIDE OF TESTING CODE.
152     // Precondition: any synced Realms or `SyncSession`s must be closed or rendered inactive prior to
153     // calling this method.
154     void reset_for_testing();
155
156 private:
157     using ReconnectMode = sync::Client::ReconnectMode;
158     
159     static constexpr const char c_admin_identity[] = "__auth";
160
161     // Stop tracking the session for the given path if it is inactive.
162     // No-op if the session is either still active or in the active sessions list
163     // due to someone holding a strong reference to it.
164     void unregister_session(const std::string& path);
165
166     SyncManager() = default;
167     SyncManager(const SyncManager&) = delete;
168     SyncManager& operator=(const SyncManager&) = delete;
169
170     _impl::SyncClient& get_sync_client() const;
171     std::unique_ptr<_impl::SyncClient> create_sync_client() const;
172
173     std::shared_ptr<SyncSession> get_existing_session_locked(const std::string& path) const;
174
175     mutable std::mutex m_mutex;
176
177     // FIXME: Should probably be util::Logger::Level::error
178     util::Logger::Level m_log_level = util::Logger::Level::info;
179     SyncLoggerFactory* m_logger_factory = nullptr;
180     ReconnectMode m_client_reconnect_mode = ReconnectMode::normal;
181
182     bool run_file_action(const SyncFileActionMetadata&);
183
184     // Protects m_users
185     mutable std::mutex m_user_mutex;
186
187     // A map of user ID/auth server URL pairs to (shared pointers to) SyncUser objects.
188     std::unordered_map<SyncUserIdentifier, std::shared_ptr<SyncUser>> m_users;
189     // A map of local identifiers to admin token users.
190     std::unordered_map<std::string, std::shared_ptr<SyncUser>> m_admin_token_users;
191
192     mutable std::unique_ptr<_impl::SyncClient> m_sync_client;
193     bool m_multiplex_sessions = false;
194
195     // Protects m_file_manager and m_metadata_manager
196     mutable std::mutex m_file_system_mutex;
197     std::unique_ptr<SyncFileManager> m_file_manager;
198     std::unique_ptr<SyncMetadataManager> m_metadata_manager;
199
200     // Protects m_sessions
201     mutable std::mutex m_session_mutex;
202
203     // Map of sessions by path name.
204     // Sessions remove themselves from this map by calling `unregister_session` once they're
205     // inactive and have performed any necessary cleanup work.
206     std::unordered_map<std::string, std::shared_ptr<SyncSession>> m_sessions;
207 };
208
209 } // namespace realm
210
211 #endif // REALM_OS_SYNC_MANAGER_HPP