... | ... |
@@ -65,7 +65,11 @@ func init() { |
65 | 65 |
|
66 | 66 |
// Create the "Server" |
67 | 67 |
srv := &Server{ |
68 |
- runtime: runtime, |
|
68 |
+ runtime: runtime, |
|
69 |
+ enableCors: false, |
|
70 |
+ lock: &sync.Mutex{}, |
|
71 |
+ pullingPool: make(map[string]struct{}), |
|
72 |
+ pushingPool: make(map[string]struct{}), |
|
69 | 73 |
} |
70 | 74 |
// Retrieve the Image |
71 | 75 |
if err := srv.ImagePull(unitTestImageName, "", "", os.Stdout, utils.NewStreamFormatter(false), nil); err != nil { |
... | ... |
@@ -15,6 +15,7 @@ import ( |
15 | 15 |
"path" |
16 | 16 |
"runtime" |
17 | 17 |
"strings" |
18 |
+ "sync" |
|
18 | 19 |
) |
19 | 20 |
|
20 | 21 |
func (srv *Server) DockerVersion() APIVersion { |
... | ... |
@@ -401,7 +402,47 @@ func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, local, re |
401 | 401 |
return nil |
402 | 402 |
} |
403 | 403 |
|
404 |
+func (srv *Server) poolAdd(kind, key string) error { |
|
405 |
+ srv.lock.Lock() |
|
406 |
+ defer srv.lock.Unlock() |
|
407 |
+ |
|
408 |
+ if _, exists := srv.pullingPool[key]; exists { |
|
409 |
+ return fmt.Errorf("%s %s is already in progress", key, kind) |
|
410 |
+ } |
|
411 |
+ |
|
412 |
+ switch kind { |
|
413 |
+ case "pull": |
|
414 |
+ srv.pullingPool[key] = struct{}{} |
|
415 |
+ break |
|
416 |
+ case "push": |
|
417 |
+ srv.pushingPool[key] = struct{}{} |
|
418 |
+ break |
|
419 |
+ default: |
|
420 |
+ return fmt.Errorf("Unkown pool type") |
|
421 |
+ } |
|
422 |
+ return nil |
|
423 |
+} |
|
424 |
+ |
|
425 |
+func (srv *Server) poolRemove(kind, key string) error { |
|
426 |
+ switch kind { |
|
427 |
+ case "pull": |
|
428 |
+ delete(srv.pullingPool, key) |
|
429 |
+ break |
|
430 |
+ case "push": |
|
431 |
+ delete(srv.pushingPool, key) |
|
432 |
+ break |
|
433 |
+ default: |
|
434 |
+ return fmt.Errorf("Unkown pool type") |
|
435 |
+ } |
|
436 |
+ return nil |
|
437 |
+} |
|
438 |
+ |
|
404 | 439 |
func (srv *Server) ImagePull(name, tag, endpoint string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig) error { |
440 |
+ if err := srv.poolAdd("pull", name+":"+tag); err != nil { |
|
441 |
+ return err |
|
442 |
+ } |
|
443 |
+ defer srv.poolRemove("pull", name+":"+tag) |
|
444 |
+ |
|
405 | 445 |
r := registry.NewRegistry(srv.runtime.root, authConfig) |
406 | 446 |
out = utils.NewWriteFlusher(out) |
407 | 447 |
if endpoint != "" { |
... | ... |
@@ -418,7 +459,6 @@ func (srv *Server) ImagePull(name, tag, endpoint string, out io.Writer, sf *util |
418 | 418 |
if err := srv.pullRepository(r, out, name, remote, tag, sf); err != nil { |
419 | 419 |
return err |
420 | 420 |
} |
421 |
- |
|
422 | 421 |
return nil |
423 | 422 |
} |
424 | 423 |
|
... | ... |
@@ -593,7 +633,13 @@ func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgId, |
593 | 593 |
return nil |
594 | 594 |
} |
595 | 595 |
|
596 |
+// FIXME: Allow to interupt current push when new push of same image is done. |
|
596 | 597 |
func (srv *Server) ImagePush(name, endpoint string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig) error { |
598 |
+ if err := srv.poolAdd("push", name); err != nil { |
|
599 |
+ return err |
|
600 |
+ } |
|
601 |
+ defer srv.poolRemove("push", name) |
|
602 |
+ |
|
597 | 603 |
out = utils.NewWriteFlusher(out) |
598 | 604 |
img, err := srv.runtime.graph.Get(name) |
599 | 605 |
r := registry.NewRegistry(srv.runtime.root, authConfig) |
... | ... |
@@ -991,14 +1037,20 @@ func NewServer(autoRestart, enableCors bool, dns ListOpts) (*Server, error) { |
991 | 991 |
return nil, err |
992 | 992 |
} |
993 | 993 |
srv := &Server{ |
994 |
- runtime: runtime, |
|
995 |
- enableCors: enableCors, |
|
994 |
+ runtime: runtime, |
|
995 |
+ enableCors: enableCors, |
|
996 |
+ lock: &sync.Mutex{}, |
|
997 |
+ pullingPool: make(map[string]struct{}), |
|
998 |
+ pushingPool: make(map[string]struct{}), |
|
996 | 999 |
} |
997 | 1000 |
runtime.srv = srv |
998 | 1001 |
return srv, nil |
999 | 1002 |
} |
1000 | 1003 |
|
1001 | 1004 |
type Server struct { |
1002 |
- runtime *Runtime |
|
1003 |
- enableCors bool |
|
1005 |
+ runtime *Runtime |
|
1006 |
+ enableCors bool |
|
1007 |
+ lock *sync.Mutex |
|
1008 |
+ pullingPool map[string]struct{} |
|
1009 |
+ pushingPool map[string]struct{} |
|
1004 | 1010 |
} |