github.com/portworx/kvdb@v0.0.0-20241107215734-a185a966f535/kvdb_mgr.go (about) 1 package kvdb 2 3 import ( 4 "fmt" 5 "sync" 6 ) 7 8 var ( 9 instance Kvdb 10 datastores = make(map[string]DatastoreInit) 11 datastoreVersions = make(map[string]DatastoreVersion) 12 wrappers = make(map[WrapperName]WrapperInit) 13 lock sync.RWMutex 14 ) 15 16 // Instance returns instance set via SetInstance, nil if none was set. 17 func Instance() Kvdb { 18 return instance 19 } 20 21 // SetInstance sets the singleton instance. 22 func SetInstance(kvdb Kvdb) error { 23 instance = kvdb 24 return nil 25 } 26 27 // New return a new instance of KVDB as specified by datastore name. 28 // If domain is set all requests to KVDB are prefixed by domain. 29 // options is interpreted by backend KVDB. 30 func New( 31 name string, 32 domain string, 33 machines []string, 34 options map[string]string, 35 errorCB FatalErrorCB, 36 ) (Kvdb, error) { 37 lock.RLock() 38 defer lock.RUnlock() 39 if dsInit, exists := datastores[name]; exists { 40 return dsInit(domain, machines, options, errorCB) 41 } 42 return nil, ErrNotSupported 43 } 44 45 // AddWrapper adds wrapper is it is not already added 46 func AddWrapper( 47 wrapper WrapperName, 48 kvdb Kvdb, 49 options map[string]string, 50 ) (Kvdb, error) { 51 lock.Lock() 52 defer lock.Unlock() 53 54 for w := kvdb; w != nil; w = w.WrappedKvdb() { 55 if w.WrapperName() == wrapper { 56 return kvdb, fmt.Errorf("wrapper %v already present in kvdb", 57 wrapper) 58 } 59 } 60 if initFn, ok := wrappers[wrapper]; !ok { 61 return kvdb, fmt.Errorf("wrapper %v not found", wrapper) 62 } else { 63 // keep log wrapper at the top if it exists 64 if kvdb.WrapperName() == Wrapper_Log { 65 newWrapper, err := initFn(kvdb.WrappedKvdb(), options) 66 if err == nil { 67 kvdb.SetWrappedKvdb(newWrapper) 68 return kvdb, nil 69 } else { 70 return kvdb, err 71 } 72 } 73 return initFn(kvdb, options) 74 } 75 } 76 77 // RemoveWrapper adds wrapper is it is not already added 78 func RemoveWrapper( 79 wrapper WrapperName, 80 kvdb Kvdb, 81 ) (Kvdb, error) { 82 var prevWrapper Kvdb 83 for w := kvdb; w != nil; w = w.WrappedKvdb() { 84 if w.WrapperName() == wrapper { 85 w.Removed() 86 if prevWrapper != nil { 87 prevWrapper.SetWrappedKvdb(w.WrappedKvdb()) 88 return kvdb, nil 89 } else { 90 // removing the top-most wrapper 91 return w.WrappedKvdb(), nil 92 } 93 } 94 prevWrapper = w 95 } 96 return kvdb, nil // did not find the wrapper to remove 97 } 98 99 // Register adds specified datastore backend to the list of options. 100 func Register(name string, dsInit DatastoreInit, dsVersion DatastoreVersion) error { 101 lock.Lock() 102 defer lock.Unlock() 103 if _, exists := datastores[name]; exists { 104 return fmt.Errorf("Datastore provider %q is already registered", name) 105 } 106 datastores[name] = dsInit 107 108 if _, exists := datastoreVersions[name]; exists { 109 return fmt.Errorf("Datastore provider's %q version function already registered", name) 110 } 111 datastoreVersions[name] = dsVersion 112 return nil 113 } 114 115 // Register wrapper 116 func RegisterWrapper(name WrapperName, initFn WrapperInit) error { 117 lock.Lock() 118 defer lock.Unlock() 119 wrappers[name] = initFn 120 return nil 121 } 122 123 // Version returns the supported version for the provided kvdb endpoint. 124 func Version(name string, url string, kvdbOptions map[string]string) (string, error) { 125 lock.RLock() 126 defer lock.RUnlock() 127 128 if dsVersion, exists := datastoreVersions[name]; exists { 129 return dsVersion(url, kvdbOptions) 130 } 131 return "", ErrNotSupported 132 }