package main import ( "fmt" "io" "io/ioutil" "gopkg.in/src-d/go-git.v4/core" "github.com/aerospike/aerospike-client-go" ) // CREATE INDEX commits ON test.commit (url) STRING; // CREATE INDEX blobs ON test.blob (url) STRING; type AerospikeStorage struct { url string client *aerospike.Client os *AerospikeObjectStorage rs *AerospikeReferenceStorage } func NewAerospikeStorage(url string, client *aerospike.Client) *AerospikeStorage { return &AerospikeStorage{url: url, client: client} } func (s *AerospikeStorage) ObjectStorage() core.ObjectStorage { if s.os == nil { s.os = NewAerospikeObjectStorage(s.url, s.client) } return s.os } func (s *AerospikeStorage) ReferenceStorage() core.ReferenceStorage { if s.rs == nil { s.rs = NewAerospikeReferenceStorage(s.url, s.client) } return s.rs } type AerospikeObjectStorage struct { url string client *aerospike.Client } func NewAerospikeObjectStorage(url string, c *aerospike.Client) *AerospikeObjectStorage { return &AerospikeObjectStorage{url, c} } func (s *AerospikeObjectStorage) NewObject() core.Object { return &core.MemoryObject{} } func (o *AerospikeObjectStorage) Set(obj core.Object) (core.Hash, error) { key, err := aerospike.NewKey("test", obj.Type().String(), obj.Hash().String()) if err != nil { return obj.Hash(), err } r, err := obj.Reader() if err != nil { return obj.Hash(), err } c, err := ioutil.ReadAll(r) if err != nil { return obj.Hash(), err } bins := aerospike.BinMap{ "url": o.url, "hash": obj.Hash().String(), "type": obj.Type().String(), "blob": c, } err = o.client.Put(nil, key, bins) fmt.Println(err, key) return obj.Hash(), err } func (o *AerospikeObjectStorage) Get(h core.Hash) (core.Object, error) { key, err := keyFromObject(h) if err != nil { return nil, err } rec, err := o.client.Get(nil, key) if err != nil { return nil, err } fmt.Println(rec.Bins) return nil, core.ErrObjectNotFound } func (o *AerospikeObjectStorage) Iter(t core.ObjectType) (core.ObjectIter, error) { s := aerospike.NewStatement("test", t.String()) err := s.Addfilter(aerospike.NewEqualFilter("url", o.url)) rs, err := o.client.Query(nil, s) if err != nil { return nil, err } return &AerospikeObjectIter{t, rs.Records}, nil } func keyFromObject(h core.Hash) (*aerospike.Key, error) { return aerospike.NewKey("test", "objects", h.String()) } type AerospikeObjectIter struct { t core.ObjectType ch chan *aerospike.Record } func (i *AerospikeObjectIter) Next() (core.Object, error) { r := <-i.ch if r == nil { return nil, io.EOF } content := r.Bins["blob"].([]byte) o := &core.MemoryObject{} o.SetType(i.t) o.SetSize(int64(len(content))) _, err := o.Write(content) if err != nil { return nil, err } return o, nil } func (i *AerospikeObjectIter) Close() {} type AerospikeReferenceStorage struct { url string client *aerospike.Client } func NewAerospikeReferenceStorage(url string, c *aerospike.Client) *AerospikeReferenceStorage { return &AerospikeReferenceStorage{url, c} } // Set stores a reference. func (s *AerospikeReferenceStorage) Set(ref *core.Reference) error { key, err := aerospike.NewKey("test", "references", ref.Name().String()) if err != nil { return err } raw := ref.Strings() bins := aerospike.BinMap{ "url": s.url, "name": raw[0], "target": raw[1], } return s.client.Put(nil, key, bins) } // Get returns a stored reference with the given name func (s *AerospikeReferenceStorage) Get(n core.ReferenceName) (*core.Reference, error) { key, err := aerospike.NewKey("test", "references", n.String()) if err != nil { return nil, err } rec, err := s.client.Get(nil, key) if err != nil { return nil, err } return core.NewReferenceFromStrings( rec.Bins["name"].(string), rec.Bins["target"].(string), ), nil } // Iter returns a core.ReferenceIter func (s *AerospikeReferenceStorage) Iter() (core.ReferenceIter, error) { stmnt := aerospike.NewStatement("test", "references") err := stmnt.Addfilter(aerospike.NewEqualFilter("url", s.url)) if err != nil { return nil, err } rs, err := s.client.Query(nil, stmnt) if err != nil { return nil, err } var refs []*core.Reference for r := range rs.Records { refs = append(refs, core.NewReferenceFromStrings( r.Bins["name"].(string), r.Bins["target"].(string), )) } return core.NewReferenceSliceIter(refs), nil }