promoteConnections checks for devices that have connections, but where the primary connection hasn't started index handlers etc. yet, and promotes the primary connection to be the index handling one. This should be called after adding new connections, and after closing a primary device connection.
()
| 2360 | // be called after adding new connections, and after closing a primary |
| 2361 | // device connection. |
| 2362 | func (m *model) promoteConnections() { |
| 2363 | // Slice of actions to take on connections after releasing the main |
| 2364 | // mutex. We do this so that we do not perform blocking network actions |
| 2365 | // inside the loop, and also to avoid a possible deadlock with calling |
| 2366 | // Start() on connections that are already executing a Close() with a |
| 2367 | // callback into the model... |
| 2368 | var postLockActions []func() |
| 2369 | |
| 2370 | m.mut.Lock() |
| 2371 | |
| 2372 | for deviceID, connIDs := range m.deviceConnIDs { |
| 2373 | cm, passwords := m.generateClusterConfigRLocked(deviceID) |
| 2374 | if m.promotedConnID[deviceID] != connIDs[0] { |
| 2375 | // The previously promoted connection is not the current |
| 2376 | // primary; we should promote the primary connection to be the |
| 2377 | // index handling one. We do this by sending a ClusterConfig on |
| 2378 | // it, which will cause the other side to start sending us index |
| 2379 | // messages there. (On our side, we manage index handlers based |
| 2380 | // on where we get ClusterConfigs from the peer.) |
| 2381 | conn := m.connections[connIDs[0]] |
| 2382 | l.Debugf("Promoting connection to %s at %s", deviceID.Short(), conn) |
| 2383 | postLockActions = append(postLockActions, func() { |
| 2384 | if conn.Statistics().StartedAt.IsZero() { |
| 2385 | conn.Start() |
| 2386 | } |
| 2387 | conn.ClusterConfig(cm, passwords) |
| 2388 | }) |
| 2389 | m.promotedConnID[deviceID] = connIDs[0] |
| 2390 | } |
| 2391 | |
| 2392 | // Make sure any other new connections also get started, and that |
| 2393 | // they get a secondary-marked ClusterConfig. |
| 2394 | for _, connID := range connIDs[1:] { |
| 2395 | conn := m.connections[connID] |
| 2396 | if conn.Statistics().StartedAt.IsZero() { |
| 2397 | postLockActions = append(postLockActions, func() { |
| 2398 | conn.Start() |
| 2399 | conn.ClusterConfig(&protocol.ClusterConfig{Secondary: true}, passwords) |
| 2400 | }) |
| 2401 | } |
| 2402 | } |
| 2403 | } |
| 2404 | |
| 2405 | m.mut.Unlock() |
| 2406 | |
| 2407 | for _, action := range postLockActions { |
| 2408 | action() |
| 2409 | } |
| 2410 | } |
| 2411 | |
| 2412 | func (m *model) DownloadProgress(conn protocol.Connection, p *protocol.DownloadProgress) error { |
| 2413 | deviceID := conn.DeviceID() |