|
@@ -45,6 +45,12 @@ var (
|
|
|
startTime = time.Now()
|
|
startTime = time.Now()
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+const (
|
|
|
|
|
+ defaultEventMask = events.AllEvents &^ events.LocalChangeDetected &^ events.RemoteChangeDetected
|
|
|
|
|
+ diskEventMask = events.LocalChangeDetected | events.RemoteChangeDetected
|
|
|
|
|
+ eventSubBufferSize = 1000
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
type apiService struct {
|
|
type apiService struct {
|
|
|
id protocol.DeviceID
|
|
id protocol.DeviceID
|
|
|
cfg configIntf
|
|
cfg configIntf
|
|
@@ -52,8 +58,8 @@ type apiService struct {
|
|
|
httpsKeyFile string
|
|
httpsKeyFile string
|
|
|
statics *staticsServer
|
|
statics *staticsServer
|
|
|
model modelIntf
|
|
model modelIntf
|
|
|
- eventSub events.BufferedSubscription
|
|
|
|
|
- diskEventSub events.BufferedSubscription
|
|
|
|
|
|
|
+ eventSubs map[events.EventType]events.BufferedSubscription
|
|
|
|
|
+ eventSubsMut sync.Mutex
|
|
|
discoverer discover.CachingMux
|
|
discoverer discover.CachingMux
|
|
|
connectionsService connectionsIntf
|
|
connectionsService connectionsIntf
|
|
|
fss *folderSummaryService
|
|
fss *folderSummaryService
|
|
@@ -114,16 +120,19 @@ type connectionsIntf interface {
|
|
|
Status() map[string]interface{}
|
|
Status() map[string]interface{}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func newAPIService(id protocol.DeviceID, cfg configIntf, httpsCertFile, httpsKeyFile, assetDir string, m modelIntf, eventSub events.BufferedSubscription, diskEventSub events.BufferedSubscription, discoverer discover.CachingMux, connectionsService connectionsIntf, errors, systemLog logger.Recorder) *apiService {
|
|
|
|
|
|
|
+func newAPIService(id protocol.DeviceID, cfg configIntf, httpsCertFile, httpsKeyFile, assetDir string, m modelIntf, defaultSub, diskSub events.BufferedSubscription, discoverer discover.CachingMux, connectionsService connectionsIntf, errors, systemLog logger.Recorder) *apiService {
|
|
|
service := &apiService{
|
|
service := &apiService{
|
|
|
- id: id,
|
|
|
|
|
- cfg: cfg,
|
|
|
|
|
- httpsCertFile: httpsCertFile,
|
|
|
|
|
- httpsKeyFile: httpsKeyFile,
|
|
|
|
|
- statics: newStaticsServer(cfg.GUI().Theme, assetDir),
|
|
|
|
|
- model: m,
|
|
|
|
|
- eventSub: eventSub,
|
|
|
|
|
- diskEventSub: diskEventSub,
|
|
|
|
|
|
|
+ id: id,
|
|
|
|
|
+ cfg: cfg,
|
|
|
|
|
+ httpsCertFile: httpsCertFile,
|
|
|
|
|
+ httpsKeyFile: httpsKeyFile,
|
|
|
|
|
+ statics: newStaticsServer(cfg.GUI().Theme, assetDir),
|
|
|
|
|
+ model: m,
|
|
|
|
|
+ eventSubs: map[events.EventType]events.BufferedSubscription{
|
|
|
|
|
+ defaultEventMask: defaultSub,
|
|
|
|
|
+ diskEventMask: diskSub,
|
|
|
|
|
+ },
|
|
|
|
|
+ eventSubsMut: sync.NewMutex(),
|
|
|
discoverer: discoverer,
|
|
discoverer: discoverer,
|
|
|
connectionsService: connectionsService,
|
|
connectionsService: connectionsService,
|
|
|
systemConfigMut: sync.NewMutex(),
|
|
systemConfigMut: sync.NewMutex(),
|
|
@@ -234,7 +243,7 @@ func (s *apiService) Serve() {
|
|
|
getRestMux.HandleFunc("/rest/db/need", s.getDBNeed) // folder [perpage] [page]
|
|
getRestMux.HandleFunc("/rest/db/need", s.getDBNeed) // folder [perpage] [page]
|
|
|
getRestMux.HandleFunc("/rest/db/status", s.getDBStatus) // folder
|
|
getRestMux.HandleFunc("/rest/db/status", s.getDBStatus) // folder
|
|
|
getRestMux.HandleFunc("/rest/db/browse", s.getDBBrowse) // folder [prefix] [dirsonly] [levels]
|
|
getRestMux.HandleFunc("/rest/db/browse", s.getDBBrowse) // folder [prefix] [dirsonly] [levels]
|
|
|
- getRestMux.HandleFunc("/rest/events", s.getIndexEvents) // [since] [limit] [timeout]
|
|
|
|
|
|
|
+ getRestMux.HandleFunc("/rest/events", s.getIndexEvents) // [since] [limit] [timeout] [events]
|
|
|
getRestMux.HandleFunc("/rest/events/disk", s.getDiskEvents) // [since] [limit] [timeout]
|
|
getRestMux.HandleFunc("/rest/events/disk", s.getDiskEvents) // [since] [limit] [timeout]
|
|
|
getRestMux.HandleFunc("/rest/stats/device", s.getDeviceStats) // -
|
|
getRestMux.HandleFunc("/rest/stats/device", s.getDeviceStats) // -
|
|
|
getRestMux.HandleFunc("/rest/stats/folder", s.getFolderStats) // -
|
|
getRestMux.HandleFunc("/rest/stats/folder", s.getFolderStats) // -
|
|
@@ -1011,11 +1020,14 @@ func (s *apiService) postDBIgnores(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
|
|
func (s *apiService) getIndexEvents(w http.ResponseWriter, r *http.Request) {
|
|
func (s *apiService) getIndexEvents(w http.ResponseWriter, r *http.Request) {
|
|
|
s.fss.gotEventRequest()
|
|
s.fss.gotEventRequest()
|
|
|
- s.getEvents(w, r, s.eventSub)
|
|
|
|
|
|
|
+ mask := s.getEventMask(r.URL.Query().Get("events"))
|
|
|
|
|
+ sub := s.getEventSub(mask)
|
|
|
|
|
+ s.getEvents(w, r, sub)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (s *apiService) getDiskEvents(w http.ResponseWriter, r *http.Request) {
|
|
func (s *apiService) getDiskEvents(w http.ResponseWriter, r *http.Request) {
|
|
|
- s.getEvents(w, r, s.diskEventSub)
|
|
|
|
|
|
|
+ sub := s.getEventSub(diskEventMask)
|
|
|
|
|
+ s.getEvents(w, r, sub)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (s *apiService) getEvents(w http.ResponseWriter, r *http.Request, eventSub events.BufferedSubscription) {
|
|
func (s *apiService) getEvents(w http.ResponseWriter, r *http.Request, eventSub events.BufferedSubscription) {
|
|
@@ -1047,6 +1059,31 @@ func (s *apiService) getEvents(w http.ResponseWriter, r *http.Request, eventSub
|
|
|
sendJSON(w, evs)
|
|
sendJSON(w, evs)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func (s *apiService) getEventMask(evs string) events.EventType {
|
|
|
|
|
+ eventMask := defaultEventMask
|
|
|
|
|
+ if evs != "" {
|
|
|
|
|
+ eventList := strings.Split(evs, ",")
|
|
|
|
|
+ eventMask = 0
|
|
|
|
|
+ for _, ev := range eventList {
|
|
|
|
|
+ eventMask |= events.UnmarshalEventType(strings.TrimSpace(ev))
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return eventMask
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (s *apiService) getEventSub(mask events.EventType) events.BufferedSubscription {
|
|
|
|
|
+ s.eventSubsMut.Lock()
|
|
|
|
|
+ bufsub, ok := s.eventSubs[mask]
|
|
|
|
|
+ if !ok {
|
|
|
|
|
+ evsub := events.Default.Subscribe(mask)
|
|
|
|
|
+ bufsub = events.NewBufferedSubscription(evsub, eventSubBufferSize)
|
|
|
|
|
+ s.eventSubs[mask] = bufsub
|
|
|
|
|
+ }
|
|
|
|
|
+ s.eventSubsMut.Unlock()
|
|
|
|
|
+
|
|
|
|
|
+ return bufsub
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func (s *apiService) getSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
|
func (s *apiService) getSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
|
|
if noUpgradeFromEnv {
|
|
if noUpgradeFromEnv {
|
|
|
http.Error(w, upgrade.ErrUpgradeUnsupported.Error(), 500)
|
|
http.Error(w, upgrade.ErrUpgradeUnsupported.Error(), 500)
|