X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=lib%2Fagent%2Fproject-st.go;h=a68bd19e2a0e726836e7aae2dfd06b2d9df4654c;hb=82ede02a56e12026b2dfb1baeacabfbd564006b1;hp=28a287cc5287ad5f6b02ec5a649743b163fecb5a;hpb=97ca1f277dc8b6973d6fa67add5593a9c395ce60;p=src%2Fxds%2Fxds-agent.git diff --git a/lib/agent/project-st.go b/lib/agent/project-st.go index 28a287c..a68bd19 100644 --- a/lib/agent/project-st.go +++ b/lib/agent/project-st.go @@ -1,16 +1,38 @@ +/* + * Copyright (C) 2017 "IoT.bzh" + * Author Sebastien Douheret + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package agent -import "github.com/iotbzh/xds-agent/lib/syncthing" +import ( + "fmt" -// SEB TODO + st "github.com/iotbzh/xds-agent/lib/syncthing" + "github.com/iotbzh/xds-agent/lib/xaapiv1" + "github.com/iotbzh/xds-server/lib/xsapiv1" +) // IPROJECT interface implementation for syncthing projects // STProject . type STProject struct { *Context - server *XdsServer - folder *FolderConfig + server *XdsServer + folder *xsapiv1.FolderConfig + eventIDs []int } // NewProjectST Create a new instance of STProject @@ -18,15 +40,16 @@ func NewProjectST(ctx *Context, svr *XdsServer) *STProject { p := STProject{ Context: ctx, server: svr, - folder: &FolderConfig{}, + folder: &xsapiv1.FolderConfig{}, } return &p } // Add a new project -func (p *STProject) Add(cfg ProjectConfig) (*ProjectConfig, error) { +func (p *STProject) Add(cfg xaapiv1.ProjectConfig) (*xaapiv1.ProjectConfig, error) { var err error + // Add project/folder into XDS Server err = p.server.FolderAdd(p.server.ProjectToFolder(cfg), p.folder) if err != nil { return nil, err @@ -34,60 +57,167 @@ func (p *STProject) Add(cfg ProjectConfig) (*ProjectConfig, error) { svrPrj := p.GetProject() // Declare project into local Syncthing - p.SThg.FolderChange(st.FolderChangeArg{ - ID: cfg.ID, - Label: cfg.Label, + id, err := p.SThg.FolderChange(st.FolderChangeArg{ + ID: svrPrj.ID, + Label: svrPrj.Label, RelativePath: cfg.ClientPath, SyncThingID: p.server.ServerConfig.Builder.SyncThingID, }) + if err != nil { + return nil, err + } - return svrPrj, nil + locPrj, err := p.SThg.FolderConfigGet(id) + if err != nil { + svrPrj.Status = xaapiv1.StatusErrorConfig + return nil, err + } + if svrPrj.ID != locPrj.ID { + p.Log.Errorf("Project ID in XDSServer and local ST differ: %s != %s", svrPrj.ID, locPrj.ID) + } + + // Use Setup function to setup remains fields + return p.Setup(*svrPrj) } // Delete a project func (p *STProject) Delete() error { - return p.server.FolderDelete(p.folder.ID) + errSvr := p.server.FolderDelete(p.folder.ID) + errLoc := p.SThg.FolderDelete(p.folder.ID) + if errSvr != nil { + return errSvr + } + return errLoc } // GetProject Get public part of project config -func (p *STProject) GetProject() *ProjectConfig { +func (p *STProject) GetProject() *xaapiv1.ProjectConfig { prj := p.server.FolderToProject(*p.folder) prj.ServerID = p.server.ID return &prj } -// SetProject Set project config -func (p *STProject) SetProject(prj ProjectConfig) *ProjectConfig { - // SEB TODO +// Setup Setup local project config +func (p *STProject) Setup(prj xaapiv1.ProjectConfig) (*xaapiv1.ProjectConfig, error) { + // Update folder p.folder = p.server.ProjectToFolder(prj) - return p.GetProject() + svrPrj := p.GetProject() + + // Register events to update folder status + // Register to XDS Server events + p.server.EventOn("event:folder-state-change", "", p._cbServerFolderChanged) + if err := p.server.EventRegister("folder-state-change", svrPrj.ID); err != nil { + p.Log.Warningf("XDS Server EventRegister failed: %v", err) + return svrPrj, err + } + + // Register to Local Syncthing events + for _, evName := range []string{st.EventStateChanged, st.EventFolderPaused} { + evID, err := p.SThg.Events.Register(evName, p._cbLocalSTEvents, svrPrj.ID, nil) + if err != nil { + return nil, err + } + p.eventIDs = append(p.eventIDs, evID) + } + + return svrPrj, nil +} + +// Update Update some field of a project +func (p *STProject) Update(prj xaapiv1.ProjectConfig) (*xaapiv1.ProjectConfig, error) { + + if p.folder.ID != prj.ID { + return nil, fmt.Errorf("Invalid id") + } + + err := p.server.FolderUpdate(p.server.ProjectToFolder(prj), p.folder) + if err != nil { + return nil, err + } + + return p.GetProject(), nil } // GetServer Get the XdsServer that holds this project func (p *STProject) GetServer() *XdsServer { - // SEB TODO return p.server } -// GetFullPath returns the full path of a directory (from server POV) -func (p *STProject) GetFullPath(dir string) string { - /* SEB - if &dir == nil { - return p.folder.DataSTProject.ServerPath - } - return filepath.Join(p.folder.DataSTProject.ServerPath, dir) - */ - return "SEB TODO" -} - // Sync Force project files synchronization func (p *STProject) Sync() error { - // SEB TODO - return nil + if err := p.server.FolderSync(p.folder.ID); err != nil { + return err + } + return p.SThg.FolderScan(p.folder.ID, "") } // IsInSync Check if project files are in-sync func (p *STProject) IsInSync() (bool, error) { - // SEB TODO - return false, nil + // Should be up-to-date by callbacks (see below) + return p.folder.IsInSync, nil +} + +/** +** Private functions +***/ + +// callback use to update (XDS Server) folder IsInSync status + +func (p *STProject) _cbServerFolderChanged(pData interface{}, data interface{}) error { + evt := data.(xsapiv1.EventMsg) + + // Only process event that concerns this project/folder ID + if p.folder.ID != evt.Folder.ID { + return nil + } + + if evt.Folder.IsInSync != p.folder.DataCloudSync.STSvrIsInSync || + evt.Folder.Status != p.folder.DataCloudSync.STSvrStatus { + + p.folder.DataCloudSync.STSvrIsInSync = evt.Folder.IsInSync + p.folder.DataCloudSync.STSvrStatus = evt.Folder.Status + + if err := p.events.Emit(xaapiv1.EVTProjectChange, p.server.FolderToProject(*p.folder), ""); err != nil { + p.Log.Warningf("Cannot notify project change (from server): %v", err) + } + } + return nil +} + +// callback use to update IsInSync status +func (p *STProject) _cbLocalSTEvents(ev st.Event, data *st.EventsCBData) { + + inSync := p.folder.DataCloudSync.STLocIsInSync + sts := p.folder.DataCloudSync.STLocStatus + prevSync := inSync + prevStatus := sts + + switch ev.Type { + + case st.EventStateChanged: + to := ev.Data["to"] + switch to { + case "scanning", "syncing": + sts = xaapiv1.StatusSyncing + case "idle": + sts = xaapiv1.StatusEnable + } + inSync = (to == "idle") + + case st.EventFolderPaused: + if sts == xaapiv1.StatusEnable { + sts = xaapiv1.StatusPause + } + inSync = false + } + + if prevSync != inSync || prevStatus != sts { + + p.folder.DataCloudSync.STLocIsInSync = inSync + p.folder.DataCloudSync.STLocStatus = sts + + if err := p.events.Emit(xaapiv1.EVTProjectChange, p.server.FolderToProject(*p.folder), ""); err != nil { + p.Log.Warningf("Cannot notify project change (local): %v", err) + } + } }