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

This commit is contained in:
Jakob Borg 2014-09-30 17:52:05 +02:00
parent 25345f08e7
commit f3057c61a7

View File

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