forked from deepkaran/goforestdb
-
Notifications
You must be signed in to change notification settings - Fork 6
/
pool.go
85 lines (77 loc) · 1.71 KB
/
pool.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package forestdb
import (
"fmt"
"sync"
)
// KVPool is a structure representing a pool of KVStores
// inside a file. Each has been opened with it's own
// File handle, so they can be used concurrently safely.
type KVPool struct {
closedMutex sync.RWMutex
closed bool
stores chan *KVStore
}
var PoolClosed = fmt.Errorf("pool already closed")
func NewKVPool(filename string, config *Config, kvstore string, kvconfig *KVStoreConfig, size int) (*KVPool, error) {
rv := KVPool{}
rv.stores = make(chan *KVStore, size)
for i := 0; i < size; i++ {
db, err := Open(filename, config)
if err != nil {
// close everything else we've already opened
rv.Close() // ignore errors closing? and return open error?
return nil, err
}
kvs, err := db.OpenKVStore(kvstore, kvconfig)
if err != nil {
// close the db file we just opened
db.Close()
// close everything else we've already opened
rv.Close() // ignore errors closing? and return open error?
return nil, err
}
rv.stores <- kvs
}
return &rv, nil
}
func (p *KVPool) Get() (*KVStore, error) {
rv, ok := <-p.stores
if !ok {
return nil, PoolClosed
}
return rv, nil
}
func (p *KVPool) Return(kvs *KVStore) error {
p.closedMutex.RLock()
defer p.closedMutex.RUnlock()
if !p.closed {
p.stores <- kvs
return nil
}
return PoolClosed
}
func (p *KVPool) Close() (rverr error) {
p.closedMutex.Lock()
if !p.closed {
close(p.stores)
}
p.closed = true
p.closedMutex.Unlock()
for kvs := range p.stores {
err := kvs.Close()
if err != nil {
if rverr == nil {
rverr = err
}
// keep going try to close file
}
db := kvs.File()
err = db.Close()
if err != nil {
if rverr == nil {
rverr = err
}
}
}
return
}