8 "github.com/iotbzh/xds-agent/lib/syncthing"
9 "github.com/syncthing/syncthing/lib/sync"
12 // Projects Represent a an XDS Projects
13 type Projects struct {
16 projects map[string]*IPROJECT
19 // Mutex to make add/delete atomic
20 var pjMutex = sync.NewMutex()
22 // NewProjects Create a new instance of Project Model
23 func NewProjects(ctx *Context, st *st.SyncThing) *Projects {
27 projects: make(map[string]*IPROJECT),
31 // Init Load Projects configuration
32 func (p *Projects) Init(server *XdsServer) error {
33 svrList := make(map[string]*XdsServer)
34 // If server not set, load for all servers
36 svrList = p.xdsServers
38 svrList[server.ID] = server
41 for _, svr := range svrList {
45 xFlds := []XdsFolderConfig{}
46 if err := svr.GetFolders(&xFlds); err != nil {
47 errMsg += fmt.Sprintf("Cannot retrieve folders config of XDS server ID %s : %v \n", svr.ID, err.Error())
50 p.Log.Debugf("Connected to XDS Server %s, %d projects detected", svr.ID, len(xFlds))
51 for _, prj := range xFlds {
52 newP := svr.FolderToProject(prj)
53 if _, err := p.createUpdate(newP, false, true); err != nil {
54 errMsg += "Error while creating project id " + prj.ID + ": " + err.Error() + "\n "
60 p.Log.Infof("Number of loaded Projects: %d", len(p.projects))
63 return fmt.Errorf(errMsg)
68 // Get returns the folder config or nil if not existing
69 func (p *Projects) Get(id string) *IPROJECT {
73 fc, exist := p.projects[id]
80 // GetProjectArr returns the config of all folders as an array
81 func (p *Projects) GetProjectArr() []ProjectConfig {
83 defer pjMutex.Unlock()
85 return p.GetProjectArrUnsafe()
88 // GetProjectArrUnsafe Same as GetProjectArr without mutex protection
89 func (p *Projects) GetProjectArrUnsafe() []ProjectConfig {
90 conf := []ProjectConfig{}
91 for _, v := range p.projects {
92 prj := (*v).GetProject()
93 conf = append(conf, *prj)
98 // Add adds a new folder
99 func (p *Projects) Add(newF ProjectConfig) (*ProjectConfig, error) {
100 prj, err := p.createUpdate(newF, true, false)
105 // Notify client with event
106 if err := p.events.Emit(EVTProjectAdd, *prj); err != nil {
107 p.Log.Warningf("Cannot notify project deletion: %v", err)
113 // CreateUpdate creates or update a folder
114 func (p *Projects) createUpdate(newF ProjectConfig, create bool, initial bool) (*ProjectConfig, error) {
118 defer pjMutex.Unlock()
121 if _, exist := p.projects[newF.ID]; create && exist {
122 return nil, fmt.Errorf("ID already exists")
124 if newF.ClientPath == "" {
125 return nil, fmt.Errorf("ClientPath must be set")
127 if newF.ServerID == "" {
128 return nil, fmt.Errorf("Server ID must be set")
132 if svr, exist = p.xdsServers[newF.ServerID]; !exist {
133 return nil, fmt.Errorf("Unknown Server ID %s", newF.ServerID)
136 // Check type supported
137 b, exist := svr.ServerConfig.SupportedSharing[string(newF.Type)]
139 return nil, fmt.Errorf("Server doesn't support project type %s", newF.Type)
142 // Create a new folder object
148 fld = NewProjectST(p.Context, svr)
150 return nil, fmt.Errorf("Cloud Sync project not supported")
155 fld = NewProjectPathMap(p.Context, svr)
157 return nil, fmt.Errorf("Unsupported folder type")
160 var newPrj *ProjectConfig
162 // Add project on server
163 if newPrj, err = fld.Add(newF); err != nil {
164 newF.Status = StatusErrorConfig
165 log.Printf("ERROR Adding project: %v\n", err)
169 // Just update project config
170 if newPrj, err = fld.UpdateProject(newF); err != nil {
171 newF.Status = StatusErrorConfig
172 log.Printf("ERROR Updating project: %v\n", err)
179 log.Printf("ERROR project ID empty: %v", newF)
180 return newPrj, fmt.Errorf("Project ID empty")
183 // Add to folders list
184 p.projects[newPrj.ID] = &fld
186 // Force sync after creation
187 // (need to defer to be sure that WS events will arrive after HTTP creation reply)
189 time.Sleep(time.Millisecond * 500)
196 // Delete deletes a specific folder
197 func (p *Projects) Delete(id string) (ProjectConfig, error) {
201 defer pjMutex.Unlock()
203 fld := ProjectConfig{}
204 fc, exist := p.projects[id]
206 return fld, fmt.Errorf("unknown id")
209 prj := (*fc).GetProject()
211 if err = (*fc).Delete(); err != nil {
215 delete(p.projects, id)
217 // Notify client with event
218 if err := p.events.Emit(EVTProjectDelete, *prj); err != nil {
219 p.Log.Warningf("Cannot notify project deletion: %v", err)
225 // ForceSync Force the synchronization of a folder
226 func (p *Projects) ForceSync(id string) error {
229 return fmt.Errorf("Unknown id")
234 // IsProjectInSync Returns true when folder is in sync
235 func (p *Projects) IsProjectInSync(id string) (bool, error) {
238 return false, fmt.Errorf("Unknown id")
240 return (*fc).IsInSync()