diff options
author | holisticode <holistic.computing@gmail.com> | 2019-02-07 22:49:19 +0800 |
---|---|---|
committer | Rafael Matias <rafael@skyle.net> | 2019-02-19 20:06:13 +0800 |
commit | d1ace4f344616fb6fa8643872c1f9cac89f8549e (patch) | |
tree | 807c6d7af3875e3aedc5fe6b24c463205cffab19 /swarm/storage | |
parent | 637a75d61a13ee8a89a702a2eadb5ace3c79e7da (diff) | |
download | dexon-d1ace4f344616fb6fa8643872c1f9cac89f8549e.tar.gz dexon-d1ace4f344616fb6fa8643872c1f9cac89f8549e.tar.zst dexon-d1ace4f344616fb6fa8643872c1f9cac89f8549e.zip |
swarm: Debug API and HasChunks() API endpoint (#18980)
(cherry picked from commit 41597c2856d6ac7328baca1340c3e36ab0edd382)
Diffstat (limited to 'swarm/storage')
-rw-r--r-- | swarm/storage/common_test.go | 9 | ||||
-rw-r--r-- | swarm/storage/ldbstore.go | 12 | ||||
-rw-r--r-- | swarm/storage/localstore.go | 7 | ||||
-rw-r--r-- | swarm/storage/localstore_test.go | 33 | ||||
-rw-r--r-- | swarm/storage/memstore.go | 5 | ||||
-rw-r--r-- | swarm/storage/netstore.go | 7 | ||||
-rw-r--r-- | swarm/storage/types.go | 8 |
7 files changed, 80 insertions, 1 deletions
diff --git a/swarm/storage/common_test.go b/swarm/storage/common_test.go index bcc29d8cc..8ad95bfbc 100644 --- a/swarm/storage/common_test.go +++ b/swarm/storage/common_test.go @@ -266,6 +266,15 @@ func (m *MapChunkStore) Get(_ context.Context, ref Address) (Chunk, error) { return chunk, nil } +// Need to implement Has from SyncChunkStore +func (m *MapChunkStore) Has(ctx context.Context, ref Address) bool { + m.mu.RLock() + defer m.mu.RUnlock() + + _, has := m.chunks[ref.Hex()] + return has +} + func (m *MapChunkStore) Close() { } diff --git a/swarm/storage/ldbstore.go b/swarm/storage/ldbstore.go index 635d33429..a2f24eff0 100644 --- a/swarm/storage/ldbstore.go +++ b/swarm/storage/ldbstore.go @@ -969,6 +969,18 @@ func (s *LDBStore) Get(_ context.Context, addr Address) (chunk Chunk, err error) return s.get(addr) } +// Has 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) Has(_ context.Context, addr Address) bool { + s.lock.RLock() + defer s.lock.RUnlock() + + ikey := getIndexKey(addr) + _, err := s.db.Get(ikey) + + return err == nil +} + // 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) { if s.closed { diff --git a/swarm/storage/localstore.go b/swarm/storage/localstore.go index 956560902..eefb7565a 100644 --- a/swarm/storage/localstore.go +++ b/swarm/storage/localstore.go @@ -132,6 +132,13 @@ func (ls *LocalStore) Put(ctx context.Context, chunk Chunk) error { return err } +// Has 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) Has(ctx context.Context, addr Address) bool { + return ls.DbStore.Has(ctx, addr) +} + // Get(chunk *Chunk) looks up a chunk in the local stores // This method is blocking until the chunk is retrieved // so additional timeout may be needed to wrap this call if diff --git a/swarm/storage/localstore_test.go b/swarm/storage/localstore_test.go index 7a4162a47..ec69951c4 100644 --- a/swarm/storage/localstore_test.go +++ b/swarm/storage/localstore_test.go @@ -209,3 +209,36 @@ func setupLocalStore(t *testing.T, ldbCap int) (ls *LocalStore, cleanup func()) return store, cleanup } + +func TestHas(t *testing.T) { + ldbCap := defaultGCRatio + store, cleanup := setupLocalStore(t, ldbCap) + defer cleanup() + + nonStoredAddr := GenerateRandomChunk(128).Address() + + has := store.Has(context.Background(), nonStoredAddr) + if has { + t.Fatal("Expected Has() 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.Has(context.Background(), ch.Address()) + if !has { + t.Fatal("Expected Has() to return true, but returned false!") + } + } + + //let's be paranoic and test again that the non-existent chunk returns false + has = store.Has(context.Background(), nonStoredAddr) + if has { + t.Fatal("Expected Has() to return false, but returned true!") + } + +} diff --git a/swarm/storage/memstore.go b/swarm/storage/memstore.go index 86e5813d1..611ac3bc5 100644 --- a/swarm/storage/memstore.go +++ b/swarm/storage/memstore.go @@ -48,6 +48,11 @@ func NewMemStore(params *StoreParams, _ *LDBStore) (m *MemStore) { } } +// Has needed to implement SyncChunkStore +func (m *MemStore) Has(_ context.Context, addr Address) bool { + return m.cache.Contains(addr) +} + func (m *MemStore) Get(_ context.Context, addr Address) (Chunk, error) { if m.disabled { return nil, ErrChunkNotFound diff --git a/swarm/storage/netstore.go b/swarm/storage/netstore.go index 16bc48a9a..b24d08bc2 100644 --- a/swarm/storage/netstore.go +++ b/swarm/storage/netstore.go @@ -158,6 +158,13 @@ func (n *NetStore) get(ctx context.Context, ref Address) (Chunk, func(context.Co return chunk, nil, nil } +// Has is the storage layer entry point to query the underlying +// database to return if it has a chunk or not. +// Called from the DebugAPI +func (n *NetStore) Has(ctx context.Context, ref Address) bool { + return n.store.Has(ctx, ref) +} + // getOrCreateFetcher attempts at retrieving an existing fetchers // if none exists, creates one and saves it in the fetchers cache // caller must hold the lock diff --git a/swarm/storage/types.go b/swarm/storage/types.go index d79235225..7ec21328e 100644 --- a/swarm/storage/types.go +++ b/swarm/storage/types.go @@ -292,6 +292,7 @@ func (v *ContentAddressValidator) Validate(chunk Chunk) bool { type ChunkStore interface { Put(ctx context.Context, ch Chunk) (err error) Get(rctx context.Context, ref Address) (ch Chunk, err error) + Has(rctx context.Context, ref Address) bool Close() } @@ -314,7 +315,12 @@ func (f *FakeChunkStore) Put(_ context.Context, ch Chunk) error { return nil } -// Gut doesn't store anything it is just here to implement ChunkStore +// Has doesn't do anything it is just here to implement ChunkStore +func (f *FakeChunkStore) Has(_ 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) { panic("FakeChunkStore doesn't support Get") } |