forked from TrueCloudLab/distribution
6ab228f798
This changeset integrates the layer info cache with the registry webapp and storage backend. The main benefit is to cache immutable layer meta data, reducing backend roundtrips. The cache can be configured to use either redis or an inmemory cache. This provides massive performance benefits for HEAD http checks on layer blobs and manifest verification. Signed-off-by: Stephen J Day <stephen.day@docker.com>
117 lines
3.3 KiB
Go
117 lines
3.3 KiB
Go
package storage
|
|
|
|
import (
|
|
"github.com/docker/distribution"
|
|
"github.com/docker/distribution/registry/api/v2"
|
|
"github.com/docker/distribution/registry/storage/cache"
|
|
storagedriver "github.com/docker/distribution/registry/storage/driver"
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
// registry is the top-level implementation of Registry for use in the storage
|
|
// package. All instances should descend from this object.
|
|
type registry struct {
|
|
driver storagedriver.StorageDriver
|
|
pm *pathMapper
|
|
blobStore *blobStore
|
|
layerInfoCache cache.LayerInfoCache
|
|
}
|
|
|
|
// NewRegistryWithDriver creates a new registry instance from the provided
|
|
// driver. The resulting registry may be shared by multiple goroutines but is
|
|
// cheap to allocate.
|
|
func NewRegistryWithDriver(driver storagedriver.StorageDriver, layerInfoCache cache.LayerInfoCache) distribution.Registry {
|
|
bs := &blobStore{
|
|
driver: driver,
|
|
pm: defaultPathMapper,
|
|
}
|
|
|
|
return ®istry{
|
|
driver: driver,
|
|
blobStore: bs,
|
|
|
|
// TODO(sday): This should be configurable.
|
|
pm: defaultPathMapper,
|
|
layerInfoCache: layerInfoCache,
|
|
}
|
|
}
|
|
|
|
// Repository returns an instance of the repository tied to the registry.
|
|
// Instances should not be shared between goroutines but are cheap to
|
|
// allocate. In general, they should be request scoped.
|
|
func (reg *registry) Repository(ctx context.Context, name string) (distribution.Repository, error) {
|
|
if err := v2.ValidateRespositoryName(name); err != nil {
|
|
return nil, distribution.ErrRepositoryNameInvalid{
|
|
Name: name,
|
|
Reason: err,
|
|
}
|
|
}
|
|
|
|
return &repository{
|
|
ctx: ctx,
|
|
registry: reg,
|
|
name: name,
|
|
}, nil
|
|
}
|
|
|
|
// repository provides name-scoped access to various services.
|
|
type repository struct {
|
|
*registry
|
|
ctx context.Context
|
|
name string
|
|
}
|
|
|
|
// Name returns the name of the repository.
|
|
func (repo *repository) Name() string {
|
|
return repo.name
|
|
}
|
|
|
|
// Manifests returns an instance of ManifestService. Instantiation is cheap and
|
|
// may be context sensitive in the future. The instance should be used similar
|
|
// to a request local.
|
|
func (repo *repository) Manifests() distribution.ManifestService {
|
|
return &manifestStore{
|
|
repository: repo,
|
|
revisionStore: &revisionStore{
|
|
repository: repo,
|
|
},
|
|
tagStore: &tagStore{
|
|
repository: repo,
|
|
},
|
|
}
|
|
}
|
|
|
|
// Layers returns an instance of the LayerService. Instantiation is cheap and
|
|
// may be context sensitive in the future. The instance should be used similar
|
|
// to a request local.
|
|
func (repo *repository) Layers() distribution.LayerService {
|
|
ls := &layerStore{
|
|
repository: repo,
|
|
}
|
|
|
|
if repo.registry.layerInfoCache != nil {
|
|
// TODO(stevvooe): This is not the best place to setup a cache. We would
|
|
// really like to decouple the cache from the backend but also have the
|
|
// manifeset service use the layer service cache. For now, we can simply
|
|
// integrate the cache directly. The main issue is that we have layer
|
|
// access and layer data coupled in a single object. Work is already under
|
|
// way to decouple this.
|
|
|
|
return &cachedLayerService{
|
|
LayerService: ls,
|
|
repository: repo,
|
|
ctx: repo.ctx,
|
|
driver: repo.driver,
|
|
blobStore: repo.blobStore,
|
|
cache: repo.registry.layerInfoCache,
|
|
}
|
|
}
|
|
|
|
return ls
|
|
}
|
|
|
|
func (repo *repository) Signatures() distribution.SignatureService {
|
|
return &signatureStore{
|
|
repository: repo,
|
|
}
|
|
}
|