mirror of
https://github.com/project-zot/zot.git
synced 2025-03-25 02:32:57 -05:00
pkg/api: use a rwlock when accessing storage
The original patch used a mutex, however, the workload patterns are likely to be read-heavy, so use a rwlock instead.
This commit is contained in:
parent
fe471a3c35
commit
2fd87b6a86
2 changed files with 20 additions and 10 deletions
|
@ -42,17 +42,27 @@ const (
|
||||||
|
|
||||||
type RouteHandler struct {
|
type RouteHandler struct {
|
||||||
c *Controller
|
c *Controller
|
||||||
blobLock sync.Mutex
|
blobLock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRouteHandler(c *Controller) *RouteHandler {
|
func NewRouteHandler(c *Controller) *RouteHandler {
|
||||||
rh := &RouteHandler{c: c, blobLock: sync.Mutex{}}
|
rh := &RouteHandler{c: c, blobLock: sync.RWMutex{}}
|
||||||
rh.SetupRoutes()
|
rh.SetupRoutes()
|
||||||
|
|
||||||
return rh
|
return rh
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rh *RouteHandler) blobLockWrapper(f func (w http.ResponseWriter, r *http.Request)) func (w http.ResponseWriter, r *http.Request) {
|
// blobRLockWrapper calls the real handler with read-lock held
|
||||||
|
func (rh *RouteHandler) blobRLockWrapper(f func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
rh.blobLock.RLock()
|
||||||
|
f(w, r)
|
||||||
|
rh.blobLock.RUnlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// blobLockWrapper calls the real handler with write-lock held
|
||||||
|
func (rh *RouteHandler) blobLockWrapper(f func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
rh.blobLock.Lock()
|
rh.blobLock.Lock()
|
||||||
f(w, r)
|
f(w, r)
|
||||||
|
@ -67,23 +77,23 @@ func (rh *RouteHandler) SetupRoutes() {
|
||||||
g.HandleFunc(fmt.Sprintf("/{name:%s}/tags/list", NameRegexp.String()),
|
g.HandleFunc(fmt.Sprintf("/{name:%s}/tags/list", NameRegexp.String()),
|
||||||
rh.ListTags).Methods("GET")
|
rh.ListTags).Methods("GET")
|
||||||
g.HandleFunc(fmt.Sprintf("/{name:%s}/manifests/{reference}", NameRegexp.String()),
|
g.HandleFunc(fmt.Sprintf("/{name:%s}/manifests/{reference}", NameRegexp.String()),
|
||||||
rh.CheckManifest).Methods("HEAD")
|
rh.blobRLockWrapper(rh.CheckManifest)).Methods("HEAD")
|
||||||
g.HandleFunc(fmt.Sprintf("/{name:%s}/manifests/{reference}", NameRegexp.String()),
|
g.HandleFunc(fmt.Sprintf("/{name:%s}/manifests/{reference}", NameRegexp.String()),
|
||||||
rh.GetManifest).Methods("GET")
|
rh.blobRLockWrapper(rh.GetManifest)).Methods("GET")
|
||||||
g.HandleFunc(fmt.Sprintf("/{name:%s}/manifests/{reference}", NameRegexp.String()),
|
g.HandleFunc(fmt.Sprintf("/{name:%s}/manifests/{reference}", NameRegexp.String()),
|
||||||
rh.blobLockWrapper(rh.UpdateManifest)).Methods("PUT")
|
rh.blobLockWrapper(rh.UpdateManifest)).Methods("PUT")
|
||||||
g.HandleFunc(fmt.Sprintf("/{name:%s}/manifests/{reference}", NameRegexp.String()),
|
g.HandleFunc(fmt.Sprintf("/{name:%s}/manifests/{reference}", NameRegexp.String()),
|
||||||
rh.blobLockWrapper(rh.DeleteManifest)).Methods("DELETE")
|
rh.blobLockWrapper(rh.DeleteManifest)).Methods("DELETE")
|
||||||
g.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/{digest}", NameRegexp.String()),
|
g.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/{digest}", NameRegexp.String()),
|
||||||
rh.CheckBlob).Methods("HEAD")
|
rh.blobRLockWrapper(rh.CheckBlob)).Methods("HEAD")
|
||||||
g.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/{digest}", NameRegexp.String()),
|
g.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/{digest}", NameRegexp.String()),
|
||||||
rh.GetBlob).Methods("GET")
|
rh.blobRLockWrapper(rh.GetBlob)).Methods("GET")
|
||||||
g.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/{digest}", NameRegexp.String()),
|
g.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/{digest}", NameRegexp.String()),
|
||||||
rh.blobLockWrapper(rh.DeleteBlob)).Methods("DELETE")
|
rh.blobLockWrapper(rh.DeleteBlob)).Methods("DELETE")
|
||||||
g.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/uploads/", NameRegexp.String()),
|
g.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/uploads/", NameRegexp.String()),
|
||||||
rh.blobLockWrapper(rh.CreateBlobUpload)).Methods("POST")
|
rh.blobLockWrapper(rh.CreateBlobUpload)).Methods("POST")
|
||||||
g.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/uploads/{session_id}", NameRegexp.String()),
|
g.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/uploads/{session_id}", NameRegexp.String()),
|
||||||
rh.GetBlobUpload).Methods("GET")
|
rh.blobRLockWrapper(rh.GetBlobUpload)).Methods("GET")
|
||||||
g.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/uploads/{session_id}", NameRegexp.String()),
|
g.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/uploads/{session_id}", NameRegexp.String()),
|
||||||
rh.blobLockWrapper(rh.PatchBlobUpload)).Methods("PATCH")
|
rh.blobLockWrapper(rh.PatchBlobUpload)).Methods("PATCH")
|
||||||
g.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/uploads/{session_id}", NameRegexp.String()),
|
g.HandleFunc(fmt.Sprintf("/{name:%s}/blobs/uploads/{session_id}", NameRegexp.String()),
|
||||||
|
|
|
@ -35,7 +35,7 @@ type BlobUpload struct {
|
||||||
// ImageStore provides the image storage operations.
|
// ImageStore provides the image storage operations.
|
||||||
type ImageStore struct {
|
type ImageStore struct {
|
||||||
rootDir string
|
rootDir string
|
||||||
lock *sync.Mutex
|
lock *sync.RWMutex
|
||||||
blobUploads map[string]BlobUpload
|
blobUploads map[string]BlobUpload
|
||||||
log zerolog.Logger
|
log zerolog.Logger
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ type ImageStore struct {
|
||||||
// NewImageStore returns a new image store backed by a file storage.
|
// NewImageStore returns a new image store backed by a file storage.
|
||||||
func NewImageStore(rootDir string, log zlog.Logger) *ImageStore {
|
func NewImageStore(rootDir string, log zlog.Logger) *ImageStore {
|
||||||
is := &ImageStore{rootDir: rootDir,
|
is := &ImageStore{rootDir: rootDir,
|
||||||
lock: &sync.Mutex{},
|
lock: &sync.RWMutex{},
|
||||||
blobUploads: make(map[string]BlobUpload),
|
blobUploads: make(map[string]BlobUpload),
|
||||||
log: log.With().Caller().Logger(),
|
log: log.With().Caller().Logger(),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue