2 * Copyright (C) 2017-2018 "IoT.bzh"
3 * Author Sebastien Douheret <sebastien@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
24 st "gerrit.automotivelinux.org/gerrit/src/xds/xds-agent.git/lib/syncthing"
25 "gerrit.automotivelinux.org/gerrit/src/xds/xds-agent.git/lib/xaapiv1"
26 "gerrit.automotivelinux.org/gerrit/src/xds/xds-server.git/lib/xsapiv1"
29 // IPROJECT interface implementation for syncthing projects
32 type STProject struct {
35 folder *xsapiv1.FolderConfig
39 // NewProjectST Create a new instance of STProject
40 func NewProjectST(ctx *Context, svr *XdsServer) *STProject {
44 folder: &xsapiv1.FolderConfig{},
50 func (p *STProject) Add(cfg xaapiv1.ProjectConfig) (*xaapiv1.ProjectConfig, error) {
53 // Add project/folder into XDS Server
54 err = p.server.FolderAdd(p.server.ProjectToFolder(cfg), p.folder)
58 svrPrj := p.GetProject()
60 // Declare project into local Syncthing
61 id, err := p.SThg.FolderChange(st.FolderChangeArg{
64 RelativePath: cfg.ClientPath,
65 SyncThingID: p.server.ServerConfig.Builder.SyncThingID,
71 locPrj, err := p.SThg.FolderConfigGet(id)
73 svrPrj.Status = xaapiv1.StatusErrorConfig
76 if svrPrj.ID != locPrj.ID {
77 p.Log.Errorf("Project ID in XDSServer and local ST differ: %s != %s", svrPrj.ID, locPrj.ID)
80 // Use Setup function to setup remains fields
81 return p.Setup(*svrPrj)
85 func (p *STProject) Delete() error {
86 errSvr := p.server.FolderDelete(p.folder.ID)
87 errLoc := p.SThg.FolderDelete(p.folder.ID)
94 // GetProject Get public part of project config
95 func (p *STProject) GetProject() *xaapiv1.ProjectConfig {
96 prj := p.server.FolderToProject(*p.folder)
97 prj.ServerID = p.server.ID
101 // Setup Setup local project config
102 func (p *STProject) Setup(prj xaapiv1.ProjectConfig) (*xaapiv1.ProjectConfig, error) {
104 p.folder = p.server.ProjectToFolder(prj)
105 svrPrj := p.GetProject()
107 // Register events to update folder status
108 // Register to XDS Server events
109 if _, err := p.server.EventOn(xsapiv1.EVTFolderStateChange, "", p._cbServerFolderChanged); err != nil {
110 p.Log.Errorf("XDS Server EventOn '%s' failed: %v", xsapiv1.EVTFolderStateChange, err)
114 // Register to Local Syncthing events
115 for _, evName := range []string{st.EventStateChanged, st.EventFolderPaused} {
116 evID, err := p.SThg.Events.Register(evName, p._cbLocalSTEvents, svrPrj.ID, nil)
120 p.eventIDs = append(p.eventIDs, evID)
126 // Update Update some field of a project
127 func (p *STProject) Update(prj xaapiv1.ProjectConfig) (*xaapiv1.ProjectConfig, error) {
129 if p.folder.ID != prj.ID {
130 return nil, fmt.Errorf("Invalid id")
133 err := p.server.FolderUpdate(p.server.ProjectToFolder(prj), p.folder)
138 return p.GetProject(), nil
141 // GetServer Get the XdsServer that holds this project
142 func (p *STProject) GetServer() *XdsServer {
146 // Sync Force project files synchronization
147 func (p *STProject) Sync() error {
148 if err := p.server.FolderSync(p.folder.ID); err != nil {
151 return p.SThg.FolderScan(p.folder.ID, "")
154 // IsInSync Check if project files are in-sync
155 func (p *STProject) IsInSync() (bool, error) {
156 // Should be up-to-date by callbacks (see below)
157 return p.folder.IsInSync, nil
164 // callback use to update (XDS Server) folder IsInSync status
166 func (p *STProject) _cbServerFolderChanged(pData interface{}, data interface{}) error {
167 evt := xsapiv1.EventMsg{}
168 d, err := json.Marshal(data)
170 p.Log.Errorf("Cannot marshal XDS Server event folder-change err=%v", err)
173 if err = json.Unmarshal(d, &evt); err != nil {
174 p.Log.Errorf("Cannot unmarshal XDS Server event folder-change err=%v", err)
178 fld, err := evt.DecodeFolderConfig()
180 p.Log.Errorf("Cannot decode FolderChanged event: %v", data)
183 // Only process event that concerns this project/folder ID
184 if p.folder.ID != fld.ID {
188 if fld.IsInSync != p.folder.DataCloudSync.STSvrIsInSync ||
189 fld.Status != p.folder.DataCloudSync.STSvrStatus {
191 p.folder.DataCloudSync.STSvrIsInSync = fld.IsInSync
192 p.folder.DataCloudSync.STSvrStatus = fld.Status
194 if err := p.events.Emit(xaapiv1.EVTProjectChange, p.server.FolderToProject(*p.folder), ""); err != nil {
195 p.Log.Warningf("Cannot notify project change (from server): %v", err)
201 // callback use to update IsInSync status
202 func (p *STProject) _cbLocalSTEvents(ev st.Event, data *st.EventsCBData) {
204 inSync := p.folder.DataCloudSync.STLocIsInSync
205 sts := p.folder.DataCloudSync.STLocStatus
211 case st.EventStateChanged:
214 case "scanning", "syncing":
215 sts = xaapiv1.StatusSyncing
217 sts = xaapiv1.StatusEnable
219 inSync = (to == "idle")
221 case st.EventFolderPaused:
222 if sts == xaapiv1.StatusEnable {
223 sts = xaapiv1.StatusPause
228 if prevSync != inSync || prevStatus != sts {
230 p.folder.DataCloudSync.STLocIsInSync = inSync
231 p.folder.DataCloudSync.STLocStatus = sts
233 if err := p.events.Emit(xaapiv1.EVTProjectChange, p.server.FolderToProject(*p.folder), ""); err != nil {
234 p.Log.Warningf("Cannot notify project change (local): %v", err)