blob: 693ec02cdb4f99796addc056f06e43f58217d2ce [file] [log] [blame]
khenaidoobf6e7bb2018-08-14 22:27:29 -04001/*
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 */
Stephane Barbariedc5022d2018-11-19 15:21:44 -050016
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040017package model
18
19import (
20 "errors"
21 "fmt"
khenaidoob9203542018-09-17 22:56:37 -040022 "github.com/opencord/voltha-go/common/log"
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040023 "github.com/opencord/voltha-go/db/kvstore"
24 "strconv"
Stephane Barbariedc5022d2018-11-19 15:21:44 -050025 "sync"
Stephane Barbarieec0919b2018-09-05 14:14:29 -040026 "time"
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040027)
28
29//TODO: missing cache stuff
30//TODO: missing retry stuff
31//TODO: missing proper logging
32
Stephane Barbariedc5022d2018-11-19 15:21:44 -050033// Backend structure holds details for accessing the kv store
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040034type Backend struct {
Stephane Barbariedc5022d2018-11-19 15:21:44 -050035 sync.RWMutex
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040036 Client kvstore.Client
37 StoreType string
38 Host string
39 Port int
40 Timeout int
41 PathPrefix string
42}
43
Stephane Barbariedc5022d2018-11-19 15:21:44 -050044// NewBackend creates a new instance of a Backend structure
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040045func NewBackend(storeType string, host string, port int, timeout int, pathPrefix string) *Backend {
46 var err error
47
48 b := &Backend{
49 StoreType: storeType,
50 Host: host,
51 Port: port,
52 Timeout: timeout,
53 PathPrefix: pathPrefix,
54 }
55
56 address := host + ":" + strconv.Itoa(port)
57 if b.Client, err = b.newClient(address, timeout); err != nil {
Stephane Barbarieec0919b2018-09-05 14:14:29 -040058 log.Errorf("failed to create a new kv Client - %s", err.Error())
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040059 }
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 {
Stephane Barbarieec0919b2018-09-05 14:14:29 -040075 path := fmt.Sprintf("%s/%s", b.PathPrefix, key)
Stephane Barbarieec0919b2018-09-05 14:14:29 -040076 return path
77}
Stephane Barbariedc5022d2018-11-19 15:21:44 -050078
79// List retrieves one or more items that match the specified key
Stephane Barbarieec0919b2018-09-05 14:14:29 -040080func (b *Backend) List(key string) (map[string]*kvstore.KVPair, error) {
Stephane Barbariedc5022d2018-11-19 15:21:44 -050081 b.Lock()
82 defer b.Unlock()
83
84 formattedPath := b.makePath(key)
85 log.Debugf("List key: %s, path: %s", key, formattedPath)
86
87 return b.Client.List(formattedPath, b.Timeout)
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040088}
Stephane Barbariedc5022d2018-11-19 15:21:44 -050089
90// Get retrieves an item that matches the specified key
Stephane Barbarie4a2564d2018-07-26 11:02:58 -040091func (b *Backend) Get(key string) (*kvstore.KVPair, error) {
Stephane Barbariedc5022d2018-11-19 15:21:44 -050092 b.Lock()
93 defer b.Unlock()
94
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -040095 formattedPath := b.makePath(key)
96 log.Debugf("Get key: %s, path: %s", key, formattedPath)
Stephane Barbariedc5022d2018-11-19 15:21:44 -050097
Stephane Barbarieec0919b2018-09-05 14:14:29 -040098 start := time.Now()
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -040099 err, pair := b.Client.Get(formattedPath, b.Timeout)
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400100 stop := time.Now()
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500101
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400102 GetProfiling().AddToDatabaseRetrieveTime(stop.Sub(start).Seconds())
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500103
Stephane Barbarieec0919b2018-09-05 14:14:29 -0400104 return err, pair
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400105}
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500106
107// Put stores an item value under the specifed key
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400108func (b *Backend) Put(key string, value interface{}) error {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500109 b.Lock()
110 defer b.Unlock()
111
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400112 formattedPath := b.makePath(key)
113 log.Debugf("Put key: %s, value: %+v, path: %s", key, string(value.([]byte)), formattedPath)
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500114
Stephane Barbarie88fbe7f2018-09-25 12:25:23 -0400115 return b.Client.Put(formattedPath, value, b.Timeout)
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400116}
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500117
118// Delete removes an item under the specified key
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400119func (b *Backend) Delete(key string) error {
Stephane Barbariedc5022d2018-11-19 15:21:44 -0500120 b.Lock()
121 defer b.Unlock()
122
123 formattedPath := b.makePath(key)
124 log.Debugf("Delete key: %s, path: %s", key, formattedPath)
125
126 return b.Client.Delete(formattedPath, b.Timeout)
Stephane Barbarie4a2564d2018-07-26 11:02:58 -0400127}