mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
replace individual endpoint_cnt read from store with 1 bulk read
getNetworksFromStore reads networks and endpoint_cnt from the kvstores. endpoint_cnt especially is read in a for-loop for each network and that causes a lot of stress in poorly performing KV-Stores. This fix eases the load on the kvstore by fetching all the endpoint_cnt in a single read and the operation is performed on it. Signed-off-by: Madhu Venugopal <madhu@docker.com>
This commit is contained in:
parent
58744967be
commit
71fff44c0b
2 changed files with 50 additions and 16 deletions
|
@ -40,6 +40,8 @@ type DataStore interface {
|
||||||
// key. The caller must pass a KVObject of the same type as
|
// key. The caller must pass a KVObject of the same type as
|
||||||
// the objects that need to be listed
|
// the objects that need to be listed
|
||||||
List(string, KVObject) ([]KVObject, error)
|
List(string, KVObject) ([]KVObject, error)
|
||||||
|
// Map returns a Map of KVObjects
|
||||||
|
Map(key string, kvObject KVObject) (map[string]KVObject, error)
|
||||||
// Scope returns the scope of the store
|
// Scope returns the scope of the store
|
||||||
Scope() string
|
Scope() string
|
||||||
// KVStore returns access to the KV Store
|
// KVStore returns access to the KV Store
|
||||||
|
@ -512,23 +514,34 @@ func (ds *datastore) List(key string, kvObject KVObject) ([]KVObject, error) {
|
||||||
return ds.cache.list(kvObject)
|
return ds.cache.list(kvObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var kvol []KVObject
|
||||||
|
cb := func(key string, val KVObject) {
|
||||||
|
kvol = append(kvol, val)
|
||||||
|
}
|
||||||
|
err := ds.iterateKVPairsFromStore(key, kvObject, cb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return kvol, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *datastore) iterateKVPairsFromStore(key string, kvObject KVObject, callback func(string, KVObject)) error {
|
||||||
// Bail out right away if the kvObject does not implement KVConstructor
|
// Bail out right away if the kvObject does not implement KVConstructor
|
||||||
ctor, ok := kvObject.(KVConstructor)
|
ctor, ok := kvObject.(KVConstructor)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error listing objects, object does not implement KVConstructor interface")
|
return fmt.Errorf("error listing objects, object does not implement KVConstructor interface")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the parent key exists
|
// Make sure the parent key exists
|
||||||
if err := ds.ensureParent(key); err != nil {
|
if err := ds.ensureParent(key); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
kvList, err := ds.store.List(key)
|
kvList, err := ds.store.List(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var kvol []KVObject
|
|
||||||
for _, kvPair := range kvList {
|
for _, kvPair := range kvList {
|
||||||
if len(kvPair.Value) == 0 {
|
if len(kvPair.Value) == 0 {
|
||||||
continue
|
continue
|
||||||
|
@ -536,16 +549,33 @@ func (ds *datastore) List(key string, kvObject KVObject) ([]KVObject, error) {
|
||||||
|
|
||||||
dstO := ctor.New()
|
dstO := ctor.New()
|
||||||
if err := dstO.SetValue(kvPair.Value); err != nil {
|
if err := dstO.SetValue(kvPair.Value); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the object has a correct view of the DB index in
|
// Make sure the object has a correct view of the DB index in
|
||||||
// case we need to modify it and update the DB.
|
// case we need to modify it and update the DB.
|
||||||
dstO.SetIndex(kvPair.LastIndex)
|
dstO.SetIndex(kvPair.LastIndex)
|
||||||
|
callback(kvPair.Key, dstO)
|
||||||
kvol = append(kvol, dstO)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *datastore) Map(key string, kvObject KVObject) (map[string]KVObject, error) {
|
||||||
|
if ds.sequential {
|
||||||
|
ds.Lock()
|
||||||
|
defer ds.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
kvol := make(map[string]KVObject)
|
||||||
|
cb := func(key string, val KVObject) {
|
||||||
|
// Trim the leading & trailing "/" to make it consistent across all stores
|
||||||
|
kvol[strings.Trim(key, "/")] = val
|
||||||
|
}
|
||||||
|
err := ds.iterateKVPairsFromStore(key, kvObject, cb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return kvol, nil
|
return kvol, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package libnetwork
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/libkv/store/boltdb"
|
"github.com/docker/libkv/store/boltdb"
|
||||||
|
@ -152,21 +153,24 @@ func (c *controller) getNetworksFromStore() ([]*network, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kvep, err := store.Map(datastore.Key(epCntKeyPrefix), &endpointCnt{})
|
||||||
|
if err != nil {
|
||||||
|
if err != datastore.ErrKeyNotFound {
|
||||||
|
logrus.Warnf("failed to get endpoint_count map for scope %s: %v", store.Scope(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, kvo := range kvol {
|
for _, kvo := range kvol {
|
||||||
n := kvo.(*network)
|
n := kvo.(*network)
|
||||||
n.Lock()
|
n.Lock()
|
||||||
n.ctrlr = c
|
n.ctrlr = c
|
||||||
n.Unlock()
|
|
||||||
|
|
||||||
ec := &endpointCnt{n: n}
|
ec := &endpointCnt{n: n}
|
||||||
err = store.GetObject(datastore.Key(ec.Key()...), ec)
|
// Trim the leading & trailing "/" to make it consistent across all stores
|
||||||
if err != nil && !n.inDelete {
|
if val, ok := kvep[strings.Trim(datastore.Key(ec.Key()...), "/")]; ok {
|
||||||
logrus.Warnf("could not find endpoint count key %s for network %s while listing: %v", datastore.Key(ec.Key()...), n.Name(), err)
|
ec = val.(*endpointCnt)
|
||||||
continue
|
ec.n = n
|
||||||
|
n.epCnt = ec
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Lock()
|
|
||||||
n.epCnt = ec
|
|
||||||
n.scope = store.Scope()
|
n.scope = store.Scope()
|
||||||
n.Unlock()
|
n.Unlock()
|
||||||
nl = append(nl, n)
|
nl = append(nl, n)
|
||||||
|
|
Loading…
Add table
Reference in a new issue