NewModel creates and starts a new model. The model starts in read-only mode, where it sends index information to connected peers and responds to requests for file data without altering the local folder in any way.
(cfg config.Wrapper, id protocol.DeviceID, sdb db.DB, protectedFiles []string, evLogger events.Logger, keyGen *protocol.KeyGenerator)
| 213 | // where it sends index information to connected peers and responds to requests |
| 214 | // for file data without altering the local folder in any way. |
| 215 | func NewModel(cfg config.Wrapper, id protocol.DeviceID, sdb db.DB, protectedFiles []string, evLogger events.Logger, keyGen *protocol.KeyGenerator) Model { |
| 216 | spec := svcutil.SpecWithDebugLogger() |
| 217 | m := &model{ |
| 218 | Supervisor: suture.New("model", spec), |
| 219 | |
| 220 | // constructor parameters |
| 221 | cfg: cfg, |
| 222 | id: id, |
| 223 | sdb: sdb, |
| 224 | protectedFiles: protectedFiles, |
| 225 | evLogger: evLogger, |
| 226 | |
| 227 | // constant or concurrency safe fields |
| 228 | progressEmitter: NewProgressEmitter(cfg, evLogger), |
| 229 | shortID: id.Short(), |
| 230 | globalRequestLimiter: semaphore.New(1024 * cfg.Options().MaxConcurrentIncomingRequestKiB()), |
| 231 | folderIOLimiter: semaphore.New(cfg.Options().MaxFolderConcurrency()), |
| 232 | fatalChan: make(chan error), |
| 233 | started: make(chan struct{}), |
| 234 | keyGen: keyGen, |
| 235 | promotionTimer: time.NewTimer(0), |
| 236 | observed: db.NewObservedDB(sdb), |
| 237 | |
| 238 | // fields protected by mut |
| 239 | folderCfgs: make(map[string]config.FolderConfiguration), |
| 240 | deviceStatRefs: make(map[protocol.DeviceID]*stats.DeviceStatisticsReference), |
| 241 | folderIgnores: make(map[string]*ignore.Matcher), |
| 242 | folderRunners: newServiceMap[string, service](evLogger), |
| 243 | folderVersioners: make(map[string]versioner.Versioner), |
| 244 | folderEncryptionPasswordTokens: make(map[string][]byte), |
| 245 | folderEncryptionFailures: make(map[string]map[protocol.DeviceID]error), |
| 246 | connections: make(map[string]protocol.Connection), |
| 247 | deviceConnIDs: make(map[protocol.DeviceID][]string), |
| 248 | promotedConnID: make(map[protocol.DeviceID]string), |
| 249 | connRequestLimiters: make(map[protocol.DeviceID]*semaphore.Semaphore), |
| 250 | closed: make(map[string]chan struct{}), |
| 251 | helloMessages: make(map[protocol.DeviceID]protocol.Hello), |
| 252 | deviceDownloads: make(map[protocol.DeviceID]*deviceDownloadState), |
| 253 | remoteFolderStates: make(map[protocol.DeviceID]map[string]remoteFolderState), |
| 254 | indexHandlers: newServiceMap[protocol.DeviceID, *indexHandlerRegistry](evLogger), |
| 255 | } |
| 256 | for devID, cfg := range cfg.Devices() { |
| 257 | m.deviceStatRefs[devID] = stats.NewDeviceStatisticsReference(db.NewTyped(sdb, "devicestats/"+devID.String())) |
| 258 | m.setConnRequestLimitersLocked(cfg) |
| 259 | } |
| 260 | m.Add(m.folderRunners) |
| 261 | m.Add(m.progressEmitter) |
| 262 | m.Add(m.indexHandlers) |
| 263 | m.Add(svcutil.AsService(m.serve, m.String())) |
| 264 | |
| 265 | return m |
| 266 | } |
| 267 | |
| 268 | func (m *model) serve(ctx context.Context) error { |
| 269 | defer m.closeAllConnectionsAndWait() |