blob: c319d9989f5ceb95a68ee513ec48a24135b713fb [file] [log] [blame]
Scott Baker2c1c4822019-10-16 11:02:41 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
sbarbari1e3e29c2019-11-05 10:06:50 -050017package db
Scott Baker2c1c4822019-10-16 11:02:41 -070018
19import (
20 "errors"
21 "fmt"
Scott Bakerce767002019-10-23 13:30:24 -070022 "github.com/opencord/voltha-lib-go/v2/pkg/db/kvstore"
23 "github.com/opencord/voltha-lib-go/v2/pkg/log"
Scott Baker2c1c4822019-10-16 11:02:41 -070024 "strconv"
25 "sync"
Scott Baker2c1c4822019-10-16 11:02:41 -070026)
27
Scott Baker2c1c4822019-10-16 11:02:41 -070028// Backend structure holds details for accessing the kv store
29type Backend struct {
30 sync.RWMutex
31 Client kvstore.Client
32 StoreType string
33 Host string
34 Port int
35 Timeout int
36 PathPrefix string
37}
38
39// NewBackend creates a new instance of a Backend structure
40func NewBackend(storeType string, host string, port int, timeout int, pathPrefix string) *Backend {
41 var err error
42
43 b := &Backend{
44 StoreType: storeType,
45 Host: host,
46 Port: port,
47 Timeout: timeout,
48 PathPrefix: pathPrefix,
49 }
50
51 address := host + ":" + strconv.Itoa(port)
52 if b.Client, err = b.newClient(address, timeout); err != nil {
53 log.Errorw("failed-to-create-kv-client",
54 log.Fields{
55 "type": storeType, "host": host, "port": port,
56 "timeout": timeout, "prefix": pathPrefix,
57 "error": err.Error(),
58 })
59 }
60
61 return b
62}
63
64func (b *Backend) newClient(address string, timeout int) (kvstore.Client, error) {
65 switch b.StoreType {
66 case "consul":
67 return kvstore.NewConsulClient(address, timeout)
68 case "etcd":
69 return kvstore.NewEtcdClient(address, timeout)
70 }
71 return nil, errors.New("unsupported-kv-store")
72}
73
74func (b *Backend) makePath(key string) string {
75 path := fmt.Sprintf("%s/%s", b.PathPrefix, key)
76 return path
77}
78
79// List retrieves one or more items that match the specified key
sbarbari1e3e29c2019-11-05 10:06:50 -050080func (b *Backend) List(key string) (map[string]*kvstore.KVPair, error) {
Scott Baker2c1c4822019-10-16 11:02:41 -070081 b.Lock()
82 defer b.Unlock()
83
84 formattedPath := b.makePath(key)
sbarbari1e3e29c2019-11-05 10:06:50 -050085 log.Debugw("listing-key", log.Fields{"key": key, "path": formattedPath})
Scott Baker2c1c4822019-10-16 11:02:41 -070086
sbarbari1e3e29c2019-11-05 10:06:50 -050087 return b.Client.List(formattedPath, b.Timeout)
Scott Baker2c1c4822019-10-16 11:02:41 -070088}
89
90// Get retrieves an item that matches the specified key
sbarbari1e3e29c2019-11-05 10:06:50 -050091func (b *Backend) Get(key string) (*kvstore.KVPair, error) {
Scott Baker2c1c4822019-10-16 11:02:41 -070092 b.Lock()
93 defer b.Unlock()
94
95 formattedPath := b.makePath(key)
sbarbari1e3e29c2019-11-05 10:06:50 -050096 log.Debugw("getting-key", log.Fields{"key": key, "path": formattedPath})
Scott Baker2c1c4822019-10-16 11:02:41 -070097
sbarbari1e3e29c2019-11-05 10:06:50 -050098 return b.Client.Get(formattedPath, b.Timeout)
Scott Baker2c1c4822019-10-16 11:02:41 -070099}
100
101// Put stores an item value under the specifed key
sbarbari1e3e29c2019-11-05 10:06:50 -0500102func (b *Backend) Put(key string, value interface{}) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700103 b.Lock()
104 defer b.Unlock()
105
106 formattedPath := b.makePath(key)
sbarbari1e3e29c2019-11-05 10:06:50 -0500107 log.Debugw("putting-key", log.Fields{"key": key, "value": string(value.([]byte)), "path": formattedPath})
Scott Baker2c1c4822019-10-16 11:02:41 -0700108
sbarbari1e3e29c2019-11-05 10:06:50 -0500109 return b.Client.Put(formattedPath, value, b.Timeout)
Scott Baker2c1c4822019-10-16 11:02:41 -0700110}
111
112// Delete removes an item under the specified key
sbarbari1e3e29c2019-11-05 10:06:50 -0500113func (b *Backend) Delete(key string) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700114 b.Lock()
115 defer b.Unlock()
116
117 formattedPath := b.makePath(key)
sbarbari1e3e29c2019-11-05 10:06:50 -0500118 log.Debugw("deleting-key", log.Fields{"key": key, "path": formattedPath})
Scott Baker2c1c4822019-10-16 11:02:41 -0700119
sbarbari1e3e29c2019-11-05 10:06:50 -0500120 return b.Client.Delete(formattedPath, b.Timeout)
Scott Baker2c1c4822019-10-16 11:02:41 -0700121}
122
123// CreateWatch starts watching events for the specified key
124func (b *Backend) CreateWatch(key string) chan *kvstore.Event {
125 b.Lock()
126 defer b.Unlock()
127
128 formattedPath := b.makePath(key)
129 log.Debugw("creating-key-watch", log.Fields{"key": key, "path": formattedPath})
130
131 return b.Client.Watch(formattedPath)
132}
133
134// DeleteWatch stops watching events for the specified key
135func (b *Backend) DeleteWatch(key string, ch chan *kvstore.Event) {
136 b.Lock()
137 defer b.Unlock()
138
139 formattedPath := b.makePath(key)
140 log.Debugw("deleting-key-watch", log.Fields{"key": key, "path": formattedPath})
141
142 b.Client.CloseWatch(formattedPath, ch)
143}