swarm/api, swarm/storage: Fullstack contexts

This commit is contained in:
lash 2018-01-24 02:44:50 +01:00
parent 4a7b5b862a
commit add8971467
4 changed files with 45 additions and 48 deletions

View file

@ -17,6 +17,7 @@
package api
import (
"context"
"fmt"
"io"
"net/http"
@ -365,21 +366,21 @@ func (self *Api) BuildDirectoryTree(mhash string, nameresolver bool) (key storag
}
// Look up mutable resource updates at specific periods and versions
func (self *Api) ResourceLookup(name string, period uint32, version uint32) (storage.Key, []byte, error) {
func (self *Api) ResourceLookup(ctx context.Context, name string, period uint32, version uint32) (storage.Key, []byte, error) {
var err error
if version != 0 {
if period == 0 {
currentblocknumber, err := self.resource.GetBlock()
currentblocknumber, err := self.resource.GetBlock(ctx)
if err != nil {
return nil, nil, fmt.Errorf("Could not determine latest block: %v", err)
}
period = self.resource.BlockToPeriod(name, currentblocknumber)
}
_, err = self.resource.LookupVersionByName(name, period, version, true)
_, err = self.resource.LookupVersionByName(ctx, name, period, version, true)
} else if period != 0 {
_, err = self.resource.LookupHistoricalByName(name, period, true)
_, err = self.resource.LookupHistoricalByName(ctx, name, period, true)
} else {
_, err = self.resource.LookupLatestByName(name, true)
_, err = self.resource.LookupLatestByName(ctx, name, true)
}
if err != nil {
return nil, nil, err
@ -387,8 +388,8 @@ func (self *Api) ResourceLookup(name string, period uint32, version uint32) (sto
return self.resource.GetContent(name)
}
func (self *Api) ResourceCreate(name string, frequency uint64) (storage.Key, error) {
rsrc, err := self.resource.NewResource(name, frequency)
func (self *Api) ResourceCreate(ctx context.Context, name string, frequency uint64) (storage.Key, error) {
rsrc, err := self.resource.NewResource(ctx, name, frequency)
if err != nil {
return nil, err
}
@ -396,8 +397,8 @@ func (self *Api) ResourceCreate(name string, frequency uint64) (storage.Key, err
return storage.Key(h[:]), nil
}
func (self *Api) ResourceUpdate(name string, data []byte) (storage.Key, uint32, uint32, error) {
key, err := self.resource.Update(name, data)
func (self *Api) ResourceUpdate(ctx context.Context, name string, data []byte) (storage.Key, uint32, uint32, error) {
key, err := self.resource.Update(ctx, name, data)
period, _ := self.resource.GetLastPeriod(name)
version, _ := self.resource.GetVersion(name)
return key, period, version, err

View file

@ -299,7 +299,7 @@ func (s *Server) HandlePostResource(w http.ResponseWriter, r *Request) {
s.BadRequest(w, r, fmt.Sprintf("Cannot parse frequency parameter: %v", err))
return
}
key, err := s.api.ResourceCreate(r.uri.Addr, frequency)
key, err := s.api.ResourceCreate(r.Context(), r.uri.Addr, frequency)
if err != nil {
s.Error(w, r, fmt.Errorf("Resource creation failed: %v", err))
return
@ -312,7 +312,7 @@ func (s *Server) HandlePostResource(w http.ResponseWriter, r *Request) {
s.Error(w, r, err)
return
}
_, _, _, err = s.api.ResourceUpdate(r.uri.Addr, data)
_, _, _, err = s.api.ResourceUpdate(r.Context(), r.uri.Addr, data)
if err != nil {
s.Error(w, r, fmt.Errorf("Update resource failed: %v", err))
return
@ -350,7 +350,7 @@ func (s *Server) handleGetResource(w http.ResponseWriter, r *Request, name strin
log.Debug("handlegetdb", "name", name)
switch len(params) {
case 0:
updateKey, data, err = s.api.ResourceLookup(name, 0, 0)
updateKey, data, err = s.api.ResourceLookup(r.Context(), name, 0, 0)
case 2:
version, err = strconv.ParseUint(params[1], 10, 32)
if err != nil {
@ -360,13 +360,13 @@ func (s *Server) handleGetResource(w http.ResponseWriter, r *Request, name strin
if err != nil {
break
}
updateKey, data, err = s.api.ResourceLookup(name, uint32(period), uint32(version))
updateKey, data, err = s.api.ResourceLookup(r.Context(), name, uint32(period), uint32(version))
case 1:
period, err = strconv.ParseUint(params[0], 10, 32)
if err != nil {
break
}
updateKey, data, err = s.api.ResourceLookup(name, uint32(period), uint32(version))
updateKey, data, err = s.api.ResourceLookup(r.Context(), name, uint32(period), uint32(version))
default:
s.BadRequest(w, r, "Invalid mutable resource request")
return

View file

@ -130,8 +130,6 @@ type ethApi interface {
// TODO: Include modtime in chunk data + signature
type ResourceHandler struct {
ChunkStore
ctx context.Context // base for new contexts passed to storage layer and ethapi, to ensure teardown when Close() is called
cancelFunc func()
validator ResourceValidator
ethClient ethApi
resources map[string]*resource
@ -158,15 +156,12 @@ func NewResourceHandler(datadir string, cloudStore CloudStore, ethClient ethApi,
DbStore: dbStore,
}
ctx, cancel := context.WithCancel(context.Background())
rh := &ResourceHandler{
ChunkStore: newResourceChunkStore(path, hashfunc, localStore, cloudStore),
ethClient: ethClient,
resources: make(map[string]*resource),
validator: validator,
storeTimeout: defaultStoreTimeout,
ctx: ctx,
cancelFunc: cancel,
hashPool: sync.Pool{
New: func() interface{} {
return MakeHashFunc(SHA3Hash)()
@ -241,7 +236,7 @@ func (self *ResourceHandler) chunkSize() int64 {
// The signature data should match the hash of the idna-converted name by the validator's namehash function, NOT the raw name bytes.
//
// The start block of the resource update will be the actual current block height of the connected network.
func (self *ResourceHandler) NewResource(name string, frequency uint64) (*resource, error) {
func (self *ResourceHandler) NewResource(ctx context.Context, name string, frequency uint64) (*resource, error) {
// frequency 0 is invalid
if frequency == 0 {
@ -272,7 +267,7 @@ func (self *ResourceHandler) NewResource(name string, frequency uint64) (*resour
}
// get our blockheight at this time
currentblock, err := self.GetBlock()
currentblock, err := self.GetBlock(ctx)
if err != nil {
return nil, err
}
@ -312,11 +307,11 @@ func (self *ResourceHandler) NewResource(name string, frequency uint64) (*resour
// update root data was retrieved externally, it typically doesn't)
//
//
func (self *ResourceHandler) LookupVersionByName(name string, period uint32, version uint32, refresh bool) (*resource, error) {
return self.LookupVersion(self.nameHash(name), name, period, version, refresh)
func (self *ResourceHandler) LookupVersionByName(ctx context.Context, name string, period uint32, version uint32, refresh bool) (*resource, error) {
return self.LookupVersion(ctx, self.nameHash(name), name, period, version, refresh)
}
func (self *ResourceHandler) LookupVersion(nameHash common.Hash, name string, period uint32, version uint32, refresh bool) (*resource, error) {
func (self *ResourceHandler) LookupVersion(ctx context.Context, nameHash common.Hash, name string, period uint32, version uint32, refresh bool) (*resource, error) {
rsrc, err := self.loadResource(nameHash, name, refresh)
if err != nil {
return nil, err
@ -332,11 +327,11 @@ func (self *ResourceHandler) LookupVersion(nameHash common.Hash, name string, pe
// and returned.
//
// See also (*ResourceHandler).LookupVersion
func (self *ResourceHandler) LookupHistoricalByName(name string, period uint32, refresh bool) (*resource, error) {
return self.LookupHistorical(self.nameHash(name), name, period, refresh)
func (self *ResourceHandler) LookupHistoricalByName(ctx context.Context, name string, period uint32, refresh bool) (*resource, error) {
return self.LookupHistorical(ctx, self.nameHash(name), name, period, refresh)
}
func (self *ResourceHandler) LookupHistorical(nameHash common.Hash, name string, period uint32, refresh bool) (*resource, error) {
func (self *ResourceHandler) LookupHistorical(ctx context.Context, nameHash common.Hash, name string, period uint32, refresh bool) (*resource, error) {
rsrc, err := self.loadResource(nameHash, name, refresh)
if err != nil {
return nil, err
@ -354,18 +349,18 @@ func (self *ResourceHandler) LookupHistorical(nameHash common.Hash, name string,
// Version iteration is done as in (*ResourceHandler).LookupHistorical
//
// See also (*ResourceHandler).LookupHistorical
func (self *ResourceHandler) LookupLatestByName(name string, refresh bool) (*resource, error) {
return self.LookupLatest(self.nameHash(name), name, refresh)
func (self *ResourceHandler) LookupLatestByName(ctx context.Context, name string, refresh bool) (*resource, error) {
return self.LookupLatest(ctx, self.nameHash(name), name, refresh)
}
func (self *ResourceHandler) LookupLatest(nameHash common.Hash, name string, refresh bool) (*resource, error) {
func (self *ResourceHandler) LookupLatest(ctx context.Context, nameHash common.Hash, name string, refresh bool) (*resource, error) {
// get our blockheight at this time and the next block of the update period
rsrc, err := self.loadResource(nameHash, name, refresh)
if err != nil {
return nil, err
}
currentblock, err := self.GetBlock()
currentblock, err := self.GetBlock(ctx)
if err != nil {
return nil, err
}
@ -532,7 +527,7 @@ func (self *ResourceHandler) parseUpdate(chunkdata []byte) (*Signature, uint32,
// It is the caller's responsibility to make sure that this data is not stale.
//
// A resource update cannot span chunks, and thus has max length 4096
func (self *ResourceHandler) Update(name string, data []byte) (Key, error) {
func (self *ResourceHandler) Update(ctx context.Context, name string, data []byte) (Key, error) {
var signaturelength int
if self.validator != nil {
@ -555,7 +550,7 @@ func (self *ResourceHandler) Update(name string, data []byte) (Key, error) {
}
// get our blockheight at this time and the next block of the update period
currentblock, err := self.GetBlock()
currentblock, err := self.GetBlock(ctx)
if err != nil {
return nil, err
}
@ -620,13 +615,10 @@ func (self *ResourceHandler) Update(name string, data []byte) (Key, error) {
// Closes the datastore.
// Always call this at shutdown to avoid data corruption.
func (self *ResourceHandler) Close() {
self.cancelFunc()
self.ChunkStore.Close()
}
func (self *ResourceHandler) GetBlock() (uint64, error) {
ctx, cancel := context.WithCancel(self.ctx)
defer cancel()
func (self *ResourceHandler) GetBlock(ctx context.Context) (uint64, error) {
blockheader, err := self.ethClient.HeaderByNumber(ctx, nil)
if err != nil {
return 0, err

View file

@ -157,7 +157,9 @@ func TestResourceHandler(t *testing.T) {
defer teardownTest()
// create a new resource
_, err = rh.NewResource(safeName, resourceFrequency)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
_, err = rh.NewResource(ctx, safeName, resourceFrequency)
if err != nil {
t.Fatal(err)
}
@ -183,7 +185,7 @@ func TestResourceHandler(t *testing.T) {
resourcekey := make(map[string]Key)
fwdBlocks(int(resourceFrequency/2), backend)
data := []byte("blinky")
resourcekey["blinky"], err = rh.Update(safeName, data)
resourcekey["blinky"], err = rh.Update(ctx, safeName, data)
if err != nil {
t.Fatal(err)
}
@ -191,7 +193,7 @@ func TestResourceHandler(t *testing.T) {
// update on first period
fwdBlocks(int(resourceFrequency/2), backend)
data = []byte("pinky")
resourcekey["pinky"], err = rh.Update(safeName, data)
resourcekey["pinky"], err = rh.Update(ctx, safeName, data)
if err != nil {
t.Fatal(err)
}
@ -199,7 +201,7 @@ func TestResourceHandler(t *testing.T) {
// update on second period
fwdBlocks(int(resourceFrequency), backend)
data = []byte("inky")
resourcekey["inky"], err = rh.Update(safeName, data)
resourcekey["inky"], err = rh.Update(ctx, safeName, data)
if err != nil {
t.Fatal(err)
}
@ -207,7 +209,7 @@ func TestResourceHandler(t *testing.T) {
// update just after second period
fwdBlocks(1, backend)
data = []byte("clyde")
resourcekey["clyde"], err = rh.Update(safeName, data)
resourcekey["clyde"], err = rh.Update(ctx, safeName, data)
if err != nil {
t.Fatal(err)
}
@ -219,7 +221,7 @@ func TestResourceHandler(t *testing.T) {
fwdBlocks(int(resourceFrequency*2)-1, backend)
rh2, err := NewResourceHandler(datadir, &testCloudStore{}, rh.ethClient, nil)
_, err = rh2.LookupLatestByName(safeName, true)
_, err = rh2.LookupLatestByName(ctx, safeName, true)
if err != nil {
t.Fatal(err)
}
@ -237,7 +239,7 @@ func TestResourceHandler(t *testing.T) {
log.Debug("Latest lookup", "period", rh2.resources[safeName].lastPeriod, "version", rh2.resources[safeName].version, "data", rh2.resources[safeName].data)
// specific block, latest version
rsrc, err := rh2.LookupHistoricalByName(safeName, 3, true)
rsrc, err := rh2.LookupHistoricalByName(ctx, safeName, 3, true)
if err != nil {
t.Fatal(err)
}
@ -248,7 +250,7 @@ func TestResourceHandler(t *testing.T) {
log.Debug("Historical lookup", "period", rh2.resources[safeName].lastPeriod, "version", rh2.resources[safeName].version, "data", rh2.resources[safeName].data)
// specific block, specific version
rsrc, err = rh2.LookupVersionByName(safeName, 3, 1, true)
rsrc, err = rh2.LookupVersionByName(ctx, safeName, 3, 1, true)
if err != nil {
t.Fatal(err)
}
@ -293,14 +295,16 @@ func TestResourceENSOwner(t *testing.T) {
defer teardownTest()
// create new resource when we are owner = ok
_, err = rh.NewResource(safeName, resourceFrequency)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
_, err = rh.NewResource(ctx, safeName, resourceFrequency)
if err != nil {
t.Fatalf("Create resource fail: %v", err)
}
data := []byte("foo")
// update resource when we are owner = ok
_, err = rh.Update(safeName, data)
_, err = rh.Update(ctx, safeName, data)
if err != nil {
t.Fatalf("Update resource fail: %v", err)
}
@ -311,7 +315,7 @@ func TestResourceENSOwner(t *testing.T) {
t.Fatal(err)
}
rh.validator.(*ENSValidator).signFunc = signertwo.signContent
_, err = rh.Update(safeName, data)
_, err = rh.Update(ctx, safeName, data)
if err == nil {
t.Fatalf("Expected resource update fail due to owner mismatch")
}