Browse Source

Prepare for being able to start and stop folders at any time

Jakob Borg 11 years ago
parent
commit
f3057c61a7
1 changed files with 32 additions and 23 deletions
  1. 32 23
      internal/model/model.go

+ 32 - 23
internal/model/model.go

@@ -64,6 +64,11 @@ const (
 	indexBatchSize    = 1000       // Either way, don't include more files than this
 )
 
+type service interface {
+	Serve()
+	Stop()
+}
+
 type Model struct {
 	indexDir string
 	cfg      *config.Configuration
@@ -79,6 +84,7 @@ type Model struct {
 	deviceFolders  map[protocol.DeviceID][]string                         // deviceID -> folders
 	deviceStatRefs map[protocol.DeviceID]*stats.DeviceStatisticsReference // deviceID -> statsRef
 	folderIgnores  map[string]ignore.Patterns                             // folder -> list of ignore patterns
+	folderRunners  map[string]service                                     // folder -> puller or scanner
 	fmut           sync.RWMutex                                           // protects the above
 
 	folderState        map[string]folderState // folder -> state
@@ -116,6 +122,7 @@ func NewModel(indexDir string, cfg *config.Configuration, deviceName, clientName
 		deviceFolders:      make(map[protocol.DeviceID][]string),
 		deviceStatRefs:     make(map[protocol.DeviceID]*stats.DeviceStatisticsReference),
 		folderIgnores:      make(map[string]ignore.Patterns),
+		folderRunners:      make(map[string]service),
 		folderState:        make(map[string]folderState),
 		folderStateChanged: make(map[string]time.Time),
 		protoConn:          make(map[protocol.DeviceID]protocol.Connection),
@@ -142,18 +149,22 @@ func NewModel(indexDir string, cfg *config.Configuration, deviceName, clientName
 func (m *Model) StartFolderRW(folder string) {
 	m.fmut.Lock()
 	cfg, ok := m.folderCfgs[folder]
-	m.fmut.Unlock()
-
 	if !ok {
 		panic("cannot start nonexistent folder " + folder)
 	}
 
-	p := Puller{
+	_, ok = m.folderRunners[folder]
+	if ok {
+		panic("cannot start already running folder " + folder)
+	}
+	p := &Puller{
 		folder:   folder,
 		dir:      cfg.Path,
 		scanIntv: time.Duration(cfg.RescanIntervalS) * time.Second,
 		model:    m,
 	}
+	m.folderRunners[folder] = p
+	m.fmut.Unlock()
 
 	if len(cfg.Versioning.Type) > 0 {
 		factory, ok := versioner.Factories[cfg.Versioning.Type]
@@ -170,27 +181,25 @@ func (m *Model) StartFolderRW(folder string) {
 // read only mode the model will announce files to the cluster but not
 // pull in any external changes.
 func (m *Model) StartFolderRO(folder string) {
-	intv := time.Duration(m.folderCfgs[folder].RescanIntervalS) * time.Second
-	initialScanCompleted := false
-	go func() {
-		for {
-			if debug {
-				l.Debugln(m, "rescan", folder)
-			}
+	m.fmut.Lock()
+	cfg, ok := m.folderCfgs[folder]
+	if !ok {
+		panic("cannot start nonexistent folder " + folder)
+	}
 
-			m.setState(folder, FolderScanning)
-			if err := m.ScanFolder(folder); err != nil {
-				invalidateFolder(m.cfg, folder, err)
-				return
-			}
-			m.setState(folder, FolderIdle)
-			if !initialScanCompleted {
-				l.Infoln("Completed initial scan (ro) of folder", folder)
-				initialScanCompleted = true
-			}
-			time.Sleep(intv)
-		}
-	}()
+	_, ok = m.folderRunners[folder]
+	if ok {
+		panic("cannot start already running folder " + folder)
+	}
+	s := &Scanner{
+		folder: folder,
+		intv:   time.Duration(cfg.RescanIntervalS) * time.Second,
+		model:  m,
+	}
+	m.folderRunners[folder] = s
+	m.fmut.Unlock()
+
+	go s.Serve()
 }
 
 type ConnectionInfo struct {