content: query active downloads and status
Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
parent
b6e446e7be
commit
9dea9654bd
2 changed files with 72 additions and 1 deletions
|
@ -41,7 +41,62 @@ func OpenContentStore(root string) (*ContentStore, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(stevvooe): Work out how we can export the status of an ongoing download.
|
type Status struct {
|
||||||
|
Ref string
|
||||||
|
Size int64
|
||||||
|
Meta interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *ContentStore) Stat(ref string) (Status, error) {
|
||||||
|
dfi, err := os.Stat(filepath.Join(cs.root, "ingest", ref, "data"))
|
||||||
|
if err != nil {
|
||||||
|
return Status{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status{
|
||||||
|
Ref: ref,
|
||||||
|
Size: dfi.Size(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *ContentStore) Active() ([]Status, error) {
|
||||||
|
ip := filepath.Join(cs.root, "ingest")
|
||||||
|
|
||||||
|
fp, err := os.Open(ip)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fis, err := fp.Readdir(-1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var active []Status
|
||||||
|
for _, fi := range fis {
|
||||||
|
stat, err := cs.Stat(fi.Name())
|
||||||
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(stevvooe): This is a common error if uploads are being
|
||||||
|
// completed while making this listing. Need to consider taking a
|
||||||
|
// lock on the whole store to coordinate this aspect.
|
||||||
|
//
|
||||||
|
// Another option is to cleanup downloads asynchronously and
|
||||||
|
// coordinate this method with the cleanup process.
|
||||||
|
//
|
||||||
|
// For now, we just skip them, as they really don't exist.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
active = append(active, stat)
|
||||||
|
}
|
||||||
|
|
||||||
|
return active, nil
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(stevvooe): Allow querying the set of blobs in the blob store.
|
// TODO(stevvooe): Allow querying the set of blobs in the blob store.
|
||||||
|
|
||||||
func (cs *ContentStore) GetPath(dgst digest.Digest) (string, error) {
|
func (cs *ContentStore) GetPath(dgst digest.Digest) (string, error) {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/distribution/digest"
|
"github.com/docker/distribution/digest"
|
||||||
|
@ -54,6 +55,21 @@ func TestContentWriter(t *testing.T) {
|
||||||
t.Fatal("no error on second resume")
|
t.Fatal("no error on second resume")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we should also see this as an active ingestion
|
||||||
|
ingestions, err := cs.Active()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(ingestions, []Status{
|
||||||
|
{
|
||||||
|
Ref: "myref",
|
||||||
|
Size: 0,
|
||||||
|
},
|
||||||
|
}) {
|
||||||
|
t.Fatalf("unexpected ingestion set: %v", ingestions)
|
||||||
|
}
|
||||||
|
|
||||||
p := make([]byte, 4<<20)
|
p := make([]byte, 4<<20)
|
||||||
if _, err := rand.Read(p); err != nil {
|
if _, err := rand.Read(p); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
Loading…
Reference in a new issue