mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
swarm: first version of HasChunk implementation
This commit is contained in:
parent
a89170cfb2
commit
b15960d933
13 changed files with 130 additions and 1 deletions
|
|
@ -80,6 +80,7 @@ const (
|
||||||
SWARM_ENV_STORE_CAPACITY = "SWARM_STORE_CAPACITY"
|
SWARM_ENV_STORE_CAPACITY = "SWARM_STORE_CAPACITY"
|
||||||
SWARM_ENV_STORE_CACHE_CAPACITY = "SWARM_STORE_CACHE_CAPACITY"
|
SWARM_ENV_STORE_CACHE_CAPACITY = "SWARM_STORE_CACHE_CAPACITY"
|
||||||
SWARM_ENV_BOOTNODE_MODE = "SWARM_BOOTNODE_MODE"
|
SWARM_ENV_BOOTNODE_MODE = "SWARM_BOOTNODE_MODE"
|
||||||
|
SWARM_ENV_DEBUG_API = "SWARM_DEBUG_API"
|
||||||
SWARM_ACCESS_PASSWORD = "SWARM_ACCESS_PASSWORD"
|
SWARM_ACCESS_PASSWORD = "SWARM_ACCESS_PASSWORD"
|
||||||
SWARM_AUTO_DEFAULTPATH = "SWARM_AUTO_DEFAULTPATH"
|
SWARM_AUTO_DEFAULTPATH = "SWARM_AUTO_DEFAULTPATH"
|
||||||
GETH_ENV_DATADIR = "GETH_DATADIR"
|
GETH_ENV_DATADIR = "GETH_DATADIR"
|
||||||
|
|
@ -262,6 +263,10 @@ func cmdLineOverride(currentConfig *bzzapi.Config, ctx *cli.Context) *bzzapi.Con
|
||||||
currentConfig.BootnodeMode = ctx.GlobalBool(SwarmBootnodeModeFlag.Name)
|
currentConfig.BootnodeMode = ctx.GlobalBool(SwarmBootnodeModeFlag.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ctx.GlobalIsSet(SwarmDebugAPIFlag.Name) {
|
||||||
|
currentConfig.DebugAPI = ctx.GlobalBool(SwarmDebugAPIFlag.Name)
|
||||||
|
}
|
||||||
|
|
||||||
return currentConfig
|
return currentConfig
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -375,6 +380,14 @@ func envVarsOverride(currentConfig *bzzapi.Config) (config *bzzapi.Config) {
|
||||||
currentConfig.BootnodeMode = bootnodeMode
|
currentConfig.BootnodeMode = bootnodeMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if debugAPIenable := os.Getenv(SWARM_ENV_DEBUG_API); debugAPIenable != "" {
|
||||||
|
debug, err := strconv.ParseBool(debugAPIenable)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("invalid environment variable %s: %v", SWARM_ENV_DEBUG_API, err)
|
||||||
|
}
|
||||||
|
currentConfig.DebugAPI = debug
|
||||||
|
}
|
||||||
|
|
||||||
return currentConfig
|
return currentConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -176,4 +176,8 @@ var (
|
||||||
Name: "user",
|
Name: "user",
|
||||||
Usage: "Indicates the user who updates the feed",
|
Usage: "Indicates the user who updates the feed",
|
||||||
}
|
}
|
||||||
|
SwarmDebugAPIFlag = cli.BoolFlag{
|
||||||
|
Name: "debug-api",
|
||||||
|
Usage: "Make debug APIs available",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,8 @@ func init() {
|
||||||
SwarmStorePath,
|
SwarmStorePath,
|
||||||
SwarmStoreCapacity,
|
SwarmStoreCapacity,
|
||||||
SwarmStoreCacheCapacity,
|
SwarmStoreCacheCapacity,
|
||||||
|
// provide debug API endpoints
|
||||||
|
SwarmDebugAPIFlag,
|
||||||
}
|
}
|
||||||
rpcFlags := []cli.Flag{
|
rpcFlags := []cli.Flag{
|
||||||
utils.WSEnabledFlag,
|
utils.WSEnabledFlag,
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ type Config struct {
|
||||||
BzzKey string
|
BzzKey string
|
||||||
NodeID string
|
NodeID string
|
||||||
NetworkID uint64
|
NetworkID uint64
|
||||||
|
DebugAPI bool
|
||||||
SwapEnabled bool
|
SwapEnabled bool
|
||||||
SyncEnabled bool
|
SyncEnabled bool
|
||||||
SyncingSkipCheck bool
|
SyncingSkipCheck bool
|
||||||
|
|
@ -90,6 +91,7 @@ func NewConfig() (c *Config) {
|
||||||
EnsAPIs: nil,
|
EnsAPIs: nil,
|
||||||
EnsRoot: ens.TestNetAddress,
|
EnsRoot: ens.TestNetAddress,
|
||||||
NetworkID: network.DefaultNetworkID,
|
NetworkID: network.DefaultNetworkID,
|
||||||
|
DebugAPI: false,
|
||||||
SwapEnabled: false,
|
SwapEnabled: false,
|
||||||
SyncEnabled: true,
|
SyncEnabled: true,
|
||||||
SyncingSkipCheck: false,
|
SyncingSkipCheck: false,
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,11 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/swarm/network"
|
"github.com/ethereum/go-ethereum/swarm/network"
|
||||||
|
"github.com/ethereum/go-ethereum/swarm/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Control struct {
|
type Control struct {
|
||||||
|
|
@ -32,3 +36,30 @@ func NewControl(api *API, hive *network.Hive) *Control {
|
||||||
func (c *Control) Hive() string {
|
func (c *Control) Hive() string {
|
||||||
return c.hive.String()
|
return c.hive.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DebugAPI struct {
|
||||||
|
netStore *storage.NetStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDebugAPI(nstore *storage.NetStore) *DebugAPI {
|
||||||
|
return &DebugAPI{
|
||||||
|
netStore: nstore,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dapi *DebugAPI) String() string {
|
||||||
|
return "debugapi"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dapi *DebugAPI) HasChunk(chunkAddress storage.Address) bool {
|
||||||
|
return dapi.netStore.HasChunk(context.Background(), chunkAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDebugAPIDesc(nstore *storage.NetStore) rpc.API {
|
||||||
|
return rpc.API{
|
||||||
|
Namespace: "debugapi",
|
||||||
|
Version: "1.0",
|
||||||
|
Service: NewDebugAPI(nstore),
|
||||||
|
Public: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -266,6 +266,14 @@ func (m *MapChunkStore) Get(_ context.Context, ref Address) (Chunk, error) {
|
||||||
return chunk, nil
|
return chunk, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MapChunkStore) HasChunk(ctx context.Context, ref Address) bool {
|
||||||
|
m.mu.RLock()
|
||||||
|
defer m.mu.RUnlock()
|
||||||
|
|
||||||
|
_, has := m.chunks[ref.Hex()]
|
||||||
|
return has
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MapChunkStore) Close() {
|
func (m *MapChunkStore) Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -969,6 +969,16 @@ func (s *LDBStore) Get(_ context.Context, addr Address) (chunk Chunk, err error)
|
||||||
return s.get(addr)
|
return s.get(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasChunk queries the underlying DB if a chunk with the given address is stored
|
||||||
|
// Returns true if the chunk is found, false if not
|
||||||
|
func (s *LDBStore) HasChunk(_ context.Context, addr Address) bool {
|
||||||
|
s.lock.RLock()
|
||||||
|
defer s.lock.RUnlock()
|
||||||
|
proximity := s.po(addr)
|
||||||
|
_, found := s.tryAccessIdx(addr, proximity)
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: To conform with other private methods of this object indices should not be updated
|
// TODO: To conform with other private methods of this object indices should not be updated
|
||||||
func (s *LDBStore) get(addr Address) (chunk *chunk, err error) {
|
func (s *LDBStore) get(addr Address) (chunk *chunk, err error) {
|
||||||
if s.closed {
|
if s.closed {
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,13 @@ func (ls *LocalStore) Put(ctx context.Context, chunk Chunk) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasChunk queries the underlying DbStore if a chunk with the given address
|
||||||
|
// is being stored there.
|
||||||
|
// Returns true if it is stored, false if not
|
||||||
|
func (ls *LocalStore) HasChunk(ctx context.Context, addr Address) bool {
|
||||||
|
return ls.DbStore.HasChunk(ctx, addr)
|
||||||
|
}
|
||||||
|
|
||||||
// Get(chunk *Chunk) looks up a chunk in the local stores
|
// Get(chunk *Chunk) looks up a chunk in the local stores
|
||||||
// This method is blocking until the chunk is retrieved
|
// This method is blocking until the chunk is retrieved
|
||||||
// so additional timeout may be needed to wrap this call if
|
// so additional timeout may be needed to wrap this call if
|
||||||
|
|
|
||||||
|
|
@ -209,3 +209,36 @@ func setupLocalStore(t *testing.T, ldbCap int) (ls *LocalStore, cleanup func())
|
||||||
|
|
||||||
return store, cleanup
|
return store, cleanup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHasChunk(t *testing.T) {
|
||||||
|
ldbCap := defaultGCRatio
|
||||||
|
store, cleanup := setupLocalStore(t, ldbCap)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
nonStoredAddr := GenerateRandomChunk(128).Address()
|
||||||
|
|
||||||
|
has := store.HasChunk(context.Background(), nonStoredAddr)
|
||||||
|
if has {
|
||||||
|
t.Fatal("Expected HasChunk() to return false, but returned true!")
|
||||||
|
}
|
||||||
|
|
||||||
|
storeChunks := GenerateRandomChunks(128, 3)
|
||||||
|
for _, ch := range storeChunks {
|
||||||
|
err := store.Put(context.Background(), ch)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Expected store to store chunk, but it failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
has := store.HasChunk(context.Background(), ch.Address())
|
||||||
|
if !has {
|
||||||
|
t.Fatal("Expected HasChunk() to return true, but returned false!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//let's be paranoic and test again that the non-existent chunk returns false
|
||||||
|
has = store.HasChunk(context.Background(), nonStoredAddr)
|
||||||
|
if has {
|
||||||
|
t.Fatal("Expected HasChunk() to return false, but returned true!")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,10 @@ func NewMemStore(params *StoreParams, _ *LDBStore) (m *MemStore) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MemStore) HasChunk(_ context.Context, addr Address) bool {
|
||||||
|
return m.cache.Contains(addr)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MemStore) Get(_ context.Context, addr Address) (Chunk, error) {
|
func (m *MemStore) Get(_ context.Context, addr Address) (Chunk, error) {
|
||||||
if m.disabled {
|
if m.disabled {
|
||||||
return nil, ErrChunkNotFound
|
return nil, ErrChunkNotFound
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,10 @@ func (n *NetStore) get(ctx context.Context, ref Address) (Chunk, func(context.Co
|
||||||
return chunk, nil, nil
|
return chunk, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *NetStore) HasChunk(ctx context.Context, ref Address) bool {
|
||||||
|
return n.store.HasChunk(ctx, ref)
|
||||||
|
}
|
||||||
|
|
||||||
// getOrCreateFetcher attempts at retrieving an existing fetchers
|
// getOrCreateFetcher attempts at retrieving an existing fetchers
|
||||||
// if none exists, creates one and saves it in the fetchers cache
|
// if none exists, creates one and saves it in the fetchers cache
|
||||||
// caller must hold the lock
|
// caller must hold the lock
|
||||||
|
|
|
||||||
|
|
@ -292,6 +292,7 @@ func (v *ContentAddressValidator) Validate(chunk Chunk) bool {
|
||||||
type ChunkStore interface {
|
type ChunkStore interface {
|
||||||
Put(ctx context.Context, ch Chunk) (err error)
|
Put(ctx context.Context, ch Chunk) (err error)
|
||||||
Get(rctx context.Context, ref Address) (ch Chunk, err error)
|
Get(rctx context.Context, ref Address) (ch Chunk, err error)
|
||||||
|
HasChunk(rctx context.Context, ref Address) bool
|
||||||
Close()
|
Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -314,7 +315,12 @@ func (f *FakeChunkStore) Put(_ context.Context, ch Chunk) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gut doesn't store anything it is just here to implement ChunkStore
|
// HasChunk doesn't do anything it is just here to implement ChunkStore
|
||||||
|
func (f *FakeChunkStore) HasChunk(_ context.Context, ref Address) bool {
|
||||||
|
panic("FakeChunkStore doesn't support HasChunk")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get doesn't store anything it is just here to implement ChunkStore
|
||||||
func (f *FakeChunkStore) Get(_ context.Context, ref Address) (Chunk, error) {
|
func (f *FakeChunkStore) Get(_ context.Context, ref Address) (Chunk, error) {
|
||||||
panic("FakeChunkStore doesn't support Get")
|
panic("FakeChunkStore doesn't support Get")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -514,6 +514,11 @@ func (self *Swarm) APIs() []rpc.API {
|
||||||
apis = append(apis, self.ps.APIs()...)
|
apis = append(apis, self.ps.APIs()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.config.DebugAPI {
|
||||||
|
log.Info("Running node with debug APIs attached")
|
||||||
|
apis = append(apis, api.GetDebugAPIDesc(self.netStore))
|
||||||
|
}
|
||||||
|
|
||||||
return apis
|
return apis
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue