Skip to content

Commit 88e424a

Browse files
committed
[EDITOR-512] Fix concurrent map read and map write (#585)
* update doc * add read write mutex synchronization to installed map
1 parent ee6b074 commit 88e424a

File tree

3 files changed

+29
-2
lines changed

3 files changed

+29
-2
lines changed

Diff for: docs/tools.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
```go
1111
type Tools struct {
1212
Directory string
13-
IndexURL string
13+
IndexURL string
14+
LastRefresh time.Time
1415
Logger log.StdLogger
1516
}
1617
```
@@ -20,6 +21,7 @@ to download a tool from the arduino servers.
2021

2122
- *Directory* contains the location where the tools are downloaded.
2223
- *IndexURL* contains the url where the tools description is contained.
24+
- *LastRefresh* contains the last update time
2325
- *Logger* is a StdLogger used for reporting debug and info messages
2426
- *installed* contains a map of the tools and their exact location
2527

Diff for: tools/download.go

+6
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,14 @@ func (t *Tools) Download(pack, name, version, behaviour string) error {
193193

194194
// Check if it already exists
195195
if behaviour == "keep" {
196+
t.mutex.RLock()
196197
location, ok := t.installed[key]
198+
t.mutex.RUnlock()
197199
if ok && pathExists(location) {
198200
// overwrite the default tool with this one
201+
t.mutex.Lock()
199202
t.installed[correctTool.Name] = location
203+
t.mutex.Unlock()
200204
t.Logger("The tool is already present on the system")
201205
return t.writeMap()
202206
}
@@ -267,8 +271,10 @@ func (t *Tools) Download(pack, name, version, behaviour string) error {
267271
// Update the tool map
268272
t.Logger("Updating map with location " + location)
269273

274+
t.mutex.Lock()
270275
t.installed[name] = location
271276
t.installed[name+"-"+correctTool.Version] = location
277+
t.mutex.Unlock()
272278
return t.writeMap()
273279
}
274280

Diff for: tools/tools.go

+20-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"path"
1010
"path/filepath"
1111
"strings"
12+
"sync"
1213
"time"
1314

1415
"github.com/xrash/smetrics"
@@ -35,21 +36,30 @@ type Tools struct {
3536
LastRefresh time.Time
3637
Logger func(msg string)
3738
installed map[string]string
39+
mutex sync.RWMutex
3840
}
3941

4042
// Init creates the Installed map and populates it from a file in .arduino-create
4143
func (t *Tools) Init(APIlevel string) {
4244
createDir(t.Directory)
45+
t.mutex.Lock()
4346
t.installed = make(map[string]string)
47+
t.mutex.Unlock()
4448
t.readMap()
49+
t.mutex.RLock()
4550
if t.installed["apilevel"] != APIlevel {
51+
t.mutex.RUnlock()
4652
// wipe the folder and reinitialize the data
4753
os.RemoveAll(t.Directory)
4854
createDir(t.Directory)
55+
t.mutex.Lock()
4956
t.installed = make(map[string]string)
5057
t.installed["apilevel"] = APIlevel
58+
t.mutex.Unlock()
5159
t.writeMap()
5260
t.readMap()
61+
} else {
62+
t.mutex.RUnlock()
5363
}
5464
}
5565

@@ -62,13 +72,17 @@ func (t *Tools) GetLocation(command string) (string, error) {
6272
var ok bool
6373

6474
// Load installed
75+
t.mutex.RLock()
6576
fmt.Println(t.installed)
77+
t.mutex.RUnlock()
6678

6779
err := t.readMap()
6880
if err != nil {
6981
return "", err
7082
}
7183

84+
t.mutex.RLock()
85+
defer t.mutex.RUnlock()
7286
fmt.Println(t.installed)
7387

7488
// use string similarity to resolve a runtime var with a "similar" map element
@@ -82,25 +96,30 @@ func (t *Tools) GetLocation(command string) (string, error) {
8296
}
8397
}
8498
}
85-
8699
return filepath.ToSlash(location), nil
87100
}
88101

102+
// writeMap() writes installed map to the json file "installed.json"
89103
func (t *Tools) writeMap() error {
104+
t.mutex.RLock()
90105
b, err := json.Marshal(t.installed)
106+
t.mutex.RUnlock()
91107
if err != nil {
92108
return err
93109
}
94110
filePath := path.Join(dir(), "installed.json")
95111
return ioutil.WriteFile(filePath, b, 0644)
96112
}
97113

114+
// readMap() reads the installed map from json file "installed.json"
98115
func (t *Tools) readMap() error {
99116
filePath := path.Join(dir(), "installed.json")
100117
b, err := ioutil.ReadFile(filePath)
101118
if err != nil {
102119
return err
103120
}
121+
t.mutex.Lock()
122+
defer t.mutex.Unlock()
104123
return json.Unmarshal(b, &t.installed)
105124
}
106125

0 commit comments

Comments
 (0)