// Copyright 2018 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // See the License for the specific language governing permissions and // limitations under the License. package store import ( "net/url" "strings" "github.com/pingcap/errors" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/logutil" "go.uber.org/zap" ) var stores = make(map[string]kv.Driver) // Register registers a kv storage with unique name and its associated Driver. func Register(name string, driver kv.Driver) error { name = strings.ToLower(name) if _, ok := stores[name]; ok { return errors.Errorf("%s is already registered", name) } stores[name] = driver return nil } // New creates a kv Storage with path. // // The path must be a URL format 'engine://path?params' like the one for // session.Open() but with the dbname cut off. // Examples: // // goleveldb://relative/path // boltdb:///absolute/path // // The engine should be registered before creating storage. func New(path string) (kv.Storage, error) { return newStoreWithRetry(path, util.DefaultMaxRetries) } func newStoreWithRetry(path string, maxRetries int) (kv.Storage, error) { storeURL, err := url.Parse(path) if err != nil { return nil, err } name := strings.ToLower(storeURL.Scheme) d, ok := stores[name] if !ok { return nil, errors.Errorf("invalid uri format, storage %s is not registered", name) } var s kv.Storage err = util.RunWithRetry(maxRetries, util.RetryInterval, func() (bool, error) { logutil.BgLogger().Info("new store", zap.String("path", path)) s, err = d.Open(path) return kv.IsTxnRetryableError(err), err }) if err == nil { logutil.BgLogger().Info("new store with retry success") } else { logutil.BgLogger().Warn("new store with retry failed", zap.Error(err)) } return s, errors.Trace(err) }