@@ -86,6 +86,7 @@ class GlobalRateLimiter:
86
86
handshaking_peers : set [HathorProtocol ]
87
87
whitelist_only : bool
88
88
_sync_factories : dict [SyncVersion , SyncAgentFactory ]
89
+ _enabled_sync_versions : set [SyncVersion ]
89
90
90
91
rate_limiter : RateLimiter
91
92
@@ -96,15 +97,7 @@ def __init__(self,
96
97
pubsub : PubSubManager ,
97
98
ssl : bool ,
98
99
rng : Random ,
99
- whitelist_only : bool ,
100
- enable_sync_v1 : bool ,
101
- enable_sync_v2 : bool ) -> None :
102
- from hathor .p2p .sync_v1 .factory import SyncV11Factory
103
- from hathor .p2p .sync_v2 .factory import SyncV2Factory
104
-
105
- if not (enable_sync_v1 or enable_sync_v2 ):
106
- raise TypeError (f'{ type (self ).__name__ } () at least one sync version is required' )
107
-
100
+ whitelist_only : bool ) -> None :
108
101
self .log = logger .new ()
109
102
self .rng = rng
110
103
self .manager = None
@@ -184,23 +177,57 @@ def __init__(self,
184
177
# Parameter to explicitly enable whitelist-only mode, when False it will still check the whitelist for sync-v1
185
178
self .whitelist_only = whitelist_only
186
179
187
- self .enable_sync_v1 = enable_sync_v1
188
- self .enable_sync_v2 = enable_sync_v2
189
-
190
180
# Timestamp when the last discovery ran
191
181
self ._last_discovery : float = 0.
192
182
193
183
# sync-manager factories
194
184
self ._sync_factories = {}
195
- if enable_sync_v1 :
196
- self ._sync_factories [SyncVersion .V1_1 ] = SyncV11Factory (self )
197
- if enable_sync_v2 :
198
- self ._sync_factories [SyncVersion .V2 ] = SyncV2Factory (self )
185
+ self ._enabled_sync_versions = set ()
186
+
187
+ def add_sync_factory (self , sync_version : SyncVersion , sync_factory : SyncAgentFactory ) -> None :
188
+ """Add factory for the given sync version, must use a sync version that does not already exist."""
189
+ # XXX: to allow code in `set_manager` to safely use the the available sync versions, we add this restriction:
190
+ assert self .manager is None , 'Cannot modify sync factories after a manager is set'
191
+ if sync_version in self ._sync_factories :
192
+ raise ValueError ('sync version already exists' )
193
+ self ._sync_factories [sync_version ] = sync_factory
194
+
195
+ def get_available_sync_versions (self ) -> set [SyncVersion ]:
196
+ """What sync versions the manager is capable of using, they are not necessarily enabled."""
197
+ return set (self ._sync_factories .keys ())
198
+
199
+ def is_sync_version_available (self , sync_version : SyncVersion ) -> bool :
200
+ """Whether the given sync version is available for use, is not necessarily enabled."""
201
+ return sync_version in self ._sync_factories
202
+
203
+ def get_enabled_sync_versions (self ) -> set [SyncVersion ]:
204
+ """What sync versions are enabled for use, it is necessarily a subset of the available versions."""
205
+ return self ._enabled_sync_versions .copy ()
206
+
207
+ def is_sync_version_enabled (self , sync_version : SyncVersion ) -> bool :
208
+ """Whether the given sync version is enabled for use, being enabled implies being available."""
209
+ return sync_version in self ._enabled_sync_versions
210
+
211
+ def enable_sync_version (self , sync_version : SyncVersion ) -> None :
212
+ """Enable using the given sync version on new connections, it must be available before being enabled."""
213
+ assert sync_version in self ._sync_factories
214
+ if sync_version in self ._enabled_sync_versions :
215
+ self .log .info ('tried to enable a sync verison that was already enabled, nothing to do' )
216
+ return
217
+ self ._enabled_sync_versions .add (sync_version )
218
+
219
+ def disable_sync_version (self , sync_version : SyncVersion ) -> None :
220
+ """Disable using the given sync version, closes connections using this sync version."""
221
+ if sync_version not in self ._enabled_sync_versions :
222
+ self .log .info ('tried to disable a sync verison that was already disabled, nothing to do' )
223
+ return
224
+ # TODO: close connections using the given sync version
225
+ self ._enabled_sync_versions .discard (sync_version )
199
226
200
227
def set_manager (self , manager : 'HathorManager' ) -> None :
201
228
"""Set the manager. This method must be called before start()."""
202
229
self .manager = manager
203
- if self .enable_sync_v2 :
230
+ if self .is_sync_version_available ( SyncVersion . V2 ) :
204
231
assert self .manager .tx_storage .indexes is not None
205
232
indexes = self .manager .tx_storage .indexes
206
233
self .log .debug ('enable sync-v2 indexes' )
@@ -235,6 +262,10 @@ def enable_rate_limiter(self, max_hits: int = 16, window_seconds: float = 1) ->
235
262
)
236
263
237
264
def start (self ) -> None :
265
+ """Listen on the given address descriptions and start accepting and processing connections."""
266
+ assert self .manager is not None , 'Cannot start without a manager'
267
+ assert len (self ._enabled_sync_versions ) > 0 , 'Cannot start without any sync version enabled'
268
+
238
269
self .lc_reconnect .start (5 , now = False )
239
270
self .lc_sync_update .start (self .lc_sync_update_interval , now = False )
240
271
@@ -278,20 +309,9 @@ def _get_peers_count(self) -> PeerConnectionsMetrics:
278
309
len (self .peer_storage )
279
310
)
280
311
281
- def get_sync_versions (self ) -> set [SyncVersion ]:
282
- """Set of versions that were enabled and are supported."""
283
- assert self .manager is not None
284
- if self .manager .has_sync_version_capability ():
285
- return set (self ._sync_factories .keys ())
286
- else :
287
- assert SyncVersion .V1_1 in self ._sync_factories , \
288
- 'sync-versions capability disabled, but sync-v1 not enabled'
289
- # XXX: this is to make it easy to simulate old behavior if we disable the sync-version capability
290
- return {SyncVersion .V1_1 }
291
-
292
312
def get_sync_factory (self , sync_version : SyncVersion ) -> SyncAgentFactory :
293
- """Get the sync factory for a given version, support MUST be checked beforehand or it will raise an assert."""
294
- assert sync_version in self ._sync_factories , 'get_sync_factory must be called for a supported version '
313
+ """Get the sync factory for a given version, MUST be available or it will raise an assert."""
314
+ assert sync_version in self ._sync_factories , f'sync_version { sync_version } is not available '
295
315
return self ._sync_factories [sync_version ]
296
316
297
317
def has_synced_peer (self ) -> bool :
0 commit comments