Skip to content

Commit 5106f2a

Browse files
committed
Simplified cache to store only strictly necessary data
1 parent 29ef714 commit 5106f2a

File tree

2 files changed

+21
-38
lines changed

2 files changed

+21
-38
lines changed

cache.go

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ package main
1919

2020
import (
2121
"context"
22+
"fmt"
2223
"sync"
2324
"time"
2425

2526
discovery "github.com/arduino/pluggable-discovery-protocol-handler"
2627
)
2728

28-
// cacheItem stores the Port discovered and its timer to handle TTL.
29+
// cacheItem stores TTL of discovered ports and its timer to handle TTL.
2930
type cacheItem struct {
30-
Port *discovery.Port
3131
timerTTL *time.Timer
3232
ctx context.Context
3333
cancelFunc context.CancelFunc
@@ -47,18 +47,20 @@ type portsCache struct {
4747
// newCache creates a new portsCache and returns it.
4848
// itemsTTL is the TTL of a single item, when it's reached
4949
// the stored item is deleted.
50-
func newCache(itemsTTL time.Duration) *portsCache {
50+
func newCache(itemsTTL time.Duration, deletionCallback func(port *discovery.Port)) *portsCache {
5151
return &portsCache{
52-
itemsTTL: itemsTTL,
53-
data: make(map[string]*cacheItem),
52+
itemsTTL: itemsTTL,
53+
data: make(map[string]*cacheItem),
54+
deletionCallback: deletionCallback,
5455
}
5556
}
5657

57-
// set stores a new port and sets its TTL.
58-
// If the specified key is already found the item's TTL is
59-
// renewed.
60-
// set is thread safe.
61-
func (c *portsCache) set(key string, port *discovery.Port) {
58+
// storeOrUpdate stores a new port and sets its TTL or
59+
// updates the TTL if already stored.
60+
// Return true if the port TTL has been updated, false otherwise
61+
// storeOrUpdate is thread safe.
62+
func (c *portsCache) storeOrUpdate(port *discovery.Port) bool {
63+
key := fmt.Sprintf("%s:%s %s", port.Address, port.Properties.Get("port"), port.Properties.Get("board"))
6264
c.dataMutex.Lock()
6365
defer c.dataMutex.Unlock()
6466
// We need a cancellable context to avoid leaving
@@ -77,20 +79,19 @@ func (c *portsCache) set(key string, port *discovery.Port) {
7779
item.cancelFunc = cancelFunc
7880
} else {
7981
item = &cacheItem{
80-
Port: port,
8182
timerTTL: timerTTL,
8283
ctx: ctx,
8384
cancelFunc: cancelFunc,
8485
}
8586
c.data[key] = item
8687
}
8788

88-
go func(key string, item *cacheItem) {
89+
go func(key string, item *cacheItem, port *discovery.Port) {
8990
select {
9091
case <-item.timerTTL.C:
9192
c.dataMutex.Lock()
9293
defer c.dataMutex.Unlock()
93-
c.deletionCallback(item.Port)
94+
c.deletionCallback(port)
9495
delete(c.data, key)
9596
return
9697
case <-item.ctx.Done():
@@ -102,19 +103,9 @@ func (c *portsCache) set(key string, port *discovery.Port) {
102103
// Using a context we handle this gracefully.
103104
return
104105
}
105-
}(key, item)
106-
}
106+
}(key, item, port)
107107

108-
// get returns the item stored with the specified key and true.
109-
// If the item is not found returns a nil port and false.
110-
// get is thread safe.
111-
func (c *portsCache) get(key string) (*discovery.Port, bool) {
112-
c.dataMutex.Lock()
113-
defer c.dataMutex.Unlock()
114-
if item, ok := c.data[key]; ok {
115-
return item.Port, ok
116-
}
117-
return nil, false
108+
return ok
118109
}
119110

120111
// clear removes all the stored items and stops their TTL timers.

main.go

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ type MDNSDiscovery struct {
6363
func (d *MDNSDiscovery) Hello(userAgent string, protocolVersion int) error {
6464
// The mdns library used has some logs statement that we must disable
6565
log.SetOutput(ioutil.Discard)
66-
d.portsCache = newCache(portsTTL)
6766
return nil
6867
}
6968

@@ -94,24 +93,21 @@ func (d *MDNSDiscovery) StartSync(eventCB discovery.EventCallback, errorCB disco
9493
return fmt.Errorf("already syncing")
9594
}
9695

97-
if d.portsCache.deletionCallback == nil {
98-
// We can't set the cache deletion callback at creation,
99-
// this is the only place we can get the callback
100-
d.portsCache.deletionCallback = func(port *discovery.Port) {
96+
if d.portsCache == nil {
97+
// Initialize the cache if not already done
98+
d.portsCache = newCache(portsTTL, func(port *discovery.Port) {
10199
eventCB("remove", port)
102-
}
100+
})
103101
}
104102

105103
d.entriesChan = make(chan *mdns.ServiceEntry, 4)
106104
go func() {
107105
for entry := range d.entriesChan {
108106
port := toDiscoveryPort(entry)
109-
key := portKey(port)
110-
if _, ok := d.portsCache.get(key); !ok {
107+
if updated := d.portsCache.storeOrUpdate(port); !updated {
111108
// Port is not cached so let the user know a new one has been found
112109
eventCB("add", port)
113110
}
114-
d.portsCache.set(portKey(port), port)
115111
}
116112
}()
117113

@@ -157,10 +153,6 @@ func (d *MDNSDiscovery) StartSync(eventCB discovery.EventCallback, errorCB disco
157153
return nil
158154
}
159155

160-
func portKey(p *discovery.Port) string {
161-
return fmt.Sprintf("%s:%s %s", p.Address, p.Properties.Get("port"), p.Properties.Get("board"))
162-
}
163-
164156
func toDiscoveryPort(entry *mdns.ServiceEntry) *discovery.Port {
165157
ip := ""
166158
if len(entry.AddrV4) > 0 {

0 commit comments

Comments
 (0)