Skip to content
This repository was archived by the owner on Dec 20, 2024. It is now read-only.

Commit 564290c

Browse files
committed
feature: add gc mgr for supernode
Signed-off-by: Starnop <[email protected]>
1 parent c476d46 commit 564290c

33 files changed

+756
-174
lines changed

cmd/supernode/app/root.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ func runSuperNode() error {
126126
// set up the CIDPrefix
127127
cfg.SetCIDPrefix(cfg.AdvertiseIP)
128128

129+
logrus.Debugf("get supernode config: %+v", cfg)
130+
129131
logrus.Info("start to run supernode")
130132

131133
d, err := daemon.New(cfg)

dfget/core/downloader/p2p_downloader/power_client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ func (pc *PowerClient) Run() error {
8181
pc.readCost.Seconds(), pc.total)
8282

8383
if err != nil {
84-
logrus.Errorf("read piece cont error:%v from dst:%s:%d, wait 20 ms",
85-
err, pc.pieceTask.PeerIP, pc.pieceTask.PeerPort)
84+
logrus.Errorf("failed to read piece cont(%s) from dst:%s:%d, wait 20 ms: %v",
85+
pc.pieceTask.Range, pc.pieceTask.PeerIP, pc.pieceTask.PeerPort, err)
8686
time.AfterFunc(time.Millisecond*20, func() {
8787
pc.queue.Put(pc.failPiece())
8888
})

pkg/syncmap/syncmap.go

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package syncmap
1919
import (
2020
"strconv"
2121
"sync"
22+
"time"
2223

2324
"github.com/dragonflyoss/Dragonfly/pkg/atomiccount"
2425
"github.com/dragonflyoss/Dragonfly/pkg/errortypes"
@@ -60,91 +61,119 @@ func (mmap *SyncMap) Get(key string) (interface{}, error) {
6061
return v, nil
6162
}
6263

63-
return nil, errors.Wrapf(errortypes.ErrDataNotFound, "key: %s", key)
64+
return nil, errors.Wrapf(errortypes.ErrDataNotFound, "failed to get key %s from map", key)
6465
}
6566

6667
// GetAsBitset returns result as *bitset.BitSet.
6768
// The ErrConvertFailed error will be returned if the assertion fails.
6869
func (mmap *SyncMap) GetAsBitset(key string) (*bitset.BitSet, error) {
6970
v, err := mmap.Get(key)
7071
if err != nil {
71-
return nil, errors.Wrapf(err, "key: %s", key)
72+
return nil, errors.Wrapf(err, "failed to get key %s from map", key)
7273
}
7374

7475
if value, ok := v.(*bitset.BitSet); ok {
7576
return value, nil
7677
}
77-
return nil, errors.Wrapf(errortypes.ErrConvertFailed, "key %s: %v", key, v)
78+
return nil, errors.Wrapf(errortypes.ErrConvertFailed, "failed to get key %s from map with value %s", key, v)
7879
}
7980

8081
// GetAsMap returns result as SyncMap.
8182
// The ErrConvertFailed error will be returned if the assertion fails.
8283
func (mmap *SyncMap) GetAsMap(key string) (*SyncMap, error) {
8384
v, err := mmap.Get(key)
8485
if err != nil {
85-
return nil, errors.Wrapf(err, "key: %s", key)
86+
return nil, errors.Wrapf(err, "failed to get key %s from map", key)
8687
}
8788

8889
if value, ok := v.(*SyncMap); ok {
8990
return value, nil
9091
}
91-
return nil, errors.Wrapf(errortypes.ErrConvertFailed, "key %s: %v", key, v)
92+
return nil, errors.Wrapf(errortypes.ErrConvertFailed, "failed to get key %s from map with value %s", key, v)
9293
}
9394

9495
// GetAsInt returns result as int.
9596
// The ErrConvertFailed error will be returned if the assertion fails.
9697
func (mmap *SyncMap) GetAsInt(key string) (int, error) {
9798
v, err := mmap.Get(key)
9899
if err != nil {
99-
return 0, errors.Wrapf(err, "key: %s", key)
100+
return 0, errors.Wrapf(err, "failed to get key %s from map", key)
100101
}
101102

102103
if value, ok := v.(int); ok {
103104
return value, nil
104105
}
105-
return 0, errors.Wrapf(errortypes.ErrConvertFailed, "key %s: %v", key, v)
106+
return 0, errors.Wrapf(errortypes.ErrConvertFailed, "failed to get key %s from map with value %s", key, v)
107+
}
108+
109+
// GetAsInt64 returns result as int64.
110+
// The ErrConvertFailed error will be returned if the assertion fails.
111+
func (mmap *SyncMap) GetAsInt64(key string) (int64, error) {
112+
v, err := mmap.Get(key)
113+
if err != nil {
114+
return 0, errors.Wrapf(err, "failed to get key %s from map", key)
115+
}
116+
117+
if value, ok := v.(int64); ok {
118+
return value, nil
119+
}
120+
return 0, errors.Wrapf(errortypes.ErrConvertFailed, "failed to get key %s from map with value %s", key, v)
106121
}
107122

108123
// GetAsString returns result as string.
109124
// The ErrConvertFailed error will be returned if the assertion fails.
110125
func (mmap *SyncMap) GetAsString(key string) (string, error) {
111126
v, err := mmap.Get(key)
112127
if err != nil {
113-
return "", errors.Wrapf(err, "key: %s", key)
128+
return "", errors.Wrapf(err, "failed to get key %s from map", key)
114129
}
115130

116131
if value, ok := v.(string); ok {
117132
return value, nil
118133
}
119-
return "", errors.Wrapf(errortypes.ErrConvertFailed, "key %s: %v", key, v)
134+
return "", errors.Wrapf(errortypes.ErrConvertFailed, "failed to get key %s from map with value %s", key, v)
120135
}
121136

122137
// GetAsBool returns result as bool.
123138
// The ErrConvertFailed error will be returned if the assertion fails.
124139
func (mmap *SyncMap) GetAsBool(key string) (bool, error) {
125140
v, err := mmap.Get(key)
126141
if err != nil {
127-
return false, errors.Wrapf(err, "key: %s", key)
142+
return false, errors.Wrapf(err, "failed to get key %s from map", key)
128143
}
129144

130145
if value, ok := v.(bool); ok {
131146
return value, nil
132147
}
133-
return false, errors.Wrapf(errortypes.ErrConvertFailed, "key %s: %v", key, v)
148+
return false, errors.Wrapf(errortypes.ErrConvertFailed, "failed to get key %s from map with value %s", key, v)
134149
}
135150

136151
// GetAsAtomicInt returns result as *AtomicInt.
137152
// The ErrConvertFailed error will be returned if the assertion fails.
138153
func (mmap *SyncMap) GetAsAtomicInt(key string) (*atomiccount.AtomicInt, error) {
139154
v, err := mmap.Get(key)
140155
if err != nil {
141-
return nil, errors.Wrapf(err, "key: %s", key)
156+
return nil, errors.Wrapf(err, "failed to get key %s from map", key)
142157
}
143158

144159
if value, ok := v.(*atomiccount.AtomicInt); ok {
145160
return value, nil
146161
}
147-
return nil, errors.Wrapf(errortypes.ErrConvertFailed, "key %s: %v", key, v)
162+
return nil, errors.Wrapf(errortypes.ErrConvertFailed, "failed to get key %s from map with value %s", key, v)
163+
}
164+
165+
// GetAsTime returns result as Time.
166+
// The ErrConvertFailed error will be returned if the assertion fails.
167+
func (mmap *SyncMap) GetAsTime(key string) (time.Time, error) {
168+
v, err := mmap.Get(key)
169+
if err != nil {
170+
return time.Now(), errors.Wrapf(err, "failed to get key %s from map", key)
171+
}
172+
173+
if value, ok := v.(time.Time); ok {
174+
return value, nil
175+
}
176+
return time.Now(), errors.Wrapf(errortypes.ErrConvertFailed, "failed to get key %s from map with value %s", key, v)
148177
}
149178

150179
// Remove deletes the key-value pair from the mmap.
@@ -156,7 +185,7 @@ func (mmap *SyncMap) Remove(key string) error {
156185
}
157186

158187
if _, ok := mmap.Load(key); !ok {
159-
return errors.Wrapf(errortypes.ErrDataNotFound, "key: %s", key)
188+
return errors.Wrapf(errortypes.ErrDataNotFound, "failed to get key %s from map", key)
160189
}
161190

162191
mmap.Delete(key)

supernode/config/config.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,11 @@ func NewBaseProperties() *BaseProperties {
102102
MaxBandwidth: 200,
103103
EnableProfiler: false,
104104
Debug: false,
105-
FailAccessInterval: 3,
105+
FailAccessInterval: DefaultFailAccessInterval,
106+
GCInitialDelay: DefaultGCInitialDelay,
107+
GCMetaInterval: DefaultGCMetaInterval,
108+
TaskExpireTime: DefaultTaskExpireTime,
109+
PeerGCDelay: DefaultPeerGCDelay,
106110
}
107111
}
108112

@@ -190,6 +194,19 @@ type BaseProperties struct {
190194
// default: 3
191195
FailAccessInterval time.Duration `yaml:"failAccessInterval"`
192196

197+
// GCInitialDelay is the delay time from the start to the first GC execution.
198+
GCInitialDelay time.Duration `yaml:"gcInitialDelay"`
199+
200+
// GCMetaInterval is the interval time to execute the GC meta.
201+
GCMetaInterval time.Duration `yaml:"gcMetaInterval"`
202+
203+
// TaskExpireTime when a task is not accessed within the taskExpireTime,
204+
// and it will be treated to be expired.
205+
TaskExpireTime time.Duration `yaml:"taskExpireTime"`
206+
207+
// PeerGCDelay is the delay time to execute the GC after the peer has reported the offline.
208+
PeerGCDelay time.Duration `yaml:"peerGCDelay"`
209+
193210
// cIDPrefix s a prefix string used to indicate that the CID is supernode.
194211
cIDPrefix string
195212

supernode/config/constants.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
package config
1818

19+
import (
20+
"time"
21+
)
22+
1923
const (
2024
// DefaultSupernodeConfigFilePath the default supernode config path.
2125
DefaultSupernodeConfigFilePath = "/etc/dragonfly/supernode.yml"
@@ -75,3 +79,21 @@ const (
7579
// SubsystemDfget represents metrics from dfget
7680
SubsystemDfget = "dfget"
7781
)
82+
83+
const (
84+
// DefaultFailAccessInterval is the interval time after failed to access the URL.
85+
DefaultFailAccessInterval = 3 * time.Minute
86+
87+
// DefaultGCInitialDelay is the delay time from the start to the first GC execution.
88+
DefaultGCInitialDelay = 6 * time.Second
89+
90+
// DefaultGCMetaInterval is the interval time to execute the GC meta.
91+
DefaultGCMetaInterval = 2 * time.Minute
92+
93+
// DefaultTaskExpireTime when a task is not accessed within the taskExpireTime,
94+
// and it will be treated to be expired.
95+
DefaultTaskExpireTime = 3 * time.Minute
96+
97+
// DefaultPeerGCDelay is the delay time to execute the GC after the peer has reported the offline.
98+
DefaultPeerGCDelay = 3 * time.Minute
99+
)

supernode/daemon/mgr/cdn/manager.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,13 @@ func (cm *Manager) GetStatus(ctx context.Context, taskID string) (cdnStatus stri
141141
return "", nil
142142
}
143143

144-
// Delete the file from disk with specified taskID.
145-
func (cm *Manager) Delete(ctx context.Context, taskID string) error {
144+
// Delete the cdn meta with specified taskID.
145+
func (cm *Manager) Delete(ctx context.Context, taskID string, force bool) error {
146+
if !force {
147+
return cm.pieceMD5Manager.removePieceMD5sByTaskID(taskID)
148+
}
149+
150+
// TODO: delete the file form disk.
146151
return nil
147152
}
148153

supernode/daemon/mgr/cdn/piece_md5_mgr.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,7 @@ func (pmm *pieceMD5Mgr) getPieceMD5sByTaskID(taskID string) (pieceMD5s []string,
7777
}
7878
return pieceMD5s, nil
7979
}
80+
81+
func (pmm *pieceMD5Mgr) removePieceMD5sByTaskID(taskID string) error {
82+
return pmm.taskPieceMD5s.Remove(taskID)
83+
}

supernode/daemon/mgr/cdn_mgr.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type CDNMgr interface {
4141
// GetStatus get the status of the file.
4242
GetStatus(ctx context.Context, taskID string) (cdnStatus string, err error)
4343

44-
// Delete the file from disk with specified taskID.
45-
Delete(ctx context.Context, taskID string) error
44+
// Delete the cdn meta with specified taskID.
45+
// The file on the disk will be deleted when the force is true.
46+
Delete(ctx context.Context, taskID string, force bool) error
4647
}

supernode/daemon/mgr/dfget_task_mgr.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ type DfgetTaskMgr interface {
3737
// GetCIDByPeerIDAndTaskID returns cid with specified peerID and taskID.
3838
GetCIDByPeerIDAndTaskID(ctx context.Context, peerID, taskID string) (string, error)
3939

40+
// GetCIDsByTaskID returns cids as a string slice with specified taskID.
41+
GetCIDsByTaskID(ctx context.Context, taskID string) ([]string, error)
42+
43+
// GetCIDAndTaskIDsByPeerID returns a cid<->taskID map by specified peerID.
44+
GetCIDAndTaskIDsByPeerID(ctx context.Context, peerID string) (map[string]string, error)
45+
4046
// List returns the list of dfgetTask.
4147
List(ctx context.Context, filter map[string]string) (dfgetTaskList []*types.DfGetTask, err error)
4248

supernode/daemon/mgr/dfgettask/manager.go

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package dfgettask
1919
import (
2020
"context"
2121
"fmt"
22+
"strings"
2223

2324
"github.com/dragonflyoss/Dragonfly/apis/types"
2425
"github.com/dragonflyoss/Dragonfly/pkg/errortypes"
@@ -31,10 +32,15 @@ import (
3132

3233
"github.com/pkg/errors"
3334
"github.com/prometheus/client_golang/prometheus"
35+
"github.com/sirupsen/logrus"
3436
)
3537

3638
var _ mgr.DfgetTaskMgr = &Manager{}
3739

40+
const (
41+
keyJoinChar = "@"
42+
)
43+
3844
type metrics struct {
3945
dfgetTasks *prometheus.GaugeVec
4046
dfgetTasksRegisterCount *prometheus.CounterVec
@@ -119,6 +125,62 @@ func (dtm *Manager) GetCIDByPeerIDAndTaskID(ctx context.Context, peerID, taskID
119125
return dtm.ptoc.GetAsString(generatePeerKey(peerID, taskID))
120126
}
121127

128+
// GetCIDsByTaskID returns cids as a string slice with specified taskID.
129+
func (dtm *Manager) GetCIDsByTaskID(ctx context.Context, taskID string) ([]string, error) {
130+
var result []string
131+
suffixString := keyJoinChar + taskID
132+
rangeFunc := func(k, v interface{}) bool {
133+
key, ok := k.(string)
134+
if !ok {
135+
return true
136+
}
137+
138+
if !strings.HasSuffix(key, suffixString) {
139+
return true
140+
}
141+
cid, err := dtm.ptoc.GetAsString(key)
142+
if err != nil {
143+
logrus.Warnf("failed to get cid from ptoc with key(%s): %v", key, err)
144+
return true
145+
}
146+
147+
result = append(result, cid)
148+
return true
149+
}
150+
dtm.ptoc.Range(rangeFunc)
151+
152+
return result, nil
153+
}
154+
155+
// GetCIDAndTaskIDsByPeerID returns a cid<->taskID map by specified peerID.
156+
func (dtm *Manager) GetCIDAndTaskIDsByPeerID(ctx context.Context, peerID string) (map[string]string, error) {
157+
var result = make(map[string]string)
158+
prefixStr := peerID + keyJoinChar
159+
rangeFunc := func(k, v interface{}) bool {
160+
key, ok := k.(string)
161+
if !ok {
162+
return true
163+
}
164+
165+
if !strings.HasPrefix(key, prefixStr) {
166+
return true
167+
}
168+
cid, err := dtm.ptoc.GetAsString(key)
169+
if err != nil {
170+
logrus.Warnf("failed to get cid from ptoc with key(%s): %v", key, err)
171+
return true
172+
}
173+
174+
// get TaskID from the key
175+
splitResult := strings.Split(key, keyJoinChar)
176+
result[cid] = splitResult[len(splitResult)-1]
177+
return true
178+
}
179+
dtm.ptoc.Range(rangeFunc)
180+
181+
return result, nil
182+
}
183+
122184
// List returns the list of dfgetTask.
123185
func (dtm *Manager) List(ctx context.Context, filter map[string]string) (dfgetTaskList []*types.DfGetTask, err error) {
124186
return nil, nil
@@ -189,9 +251,9 @@ func generateKey(cID, taskID string) (string, error) {
189251
return "", errors.Wrapf(errortypes.ErrEmptyValue, "taskID")
190252
}
191253

192-
return fmt.Sprintf("%s%s%s", cID, "@", taskID), nil
254+
return fmt.Sprintf("%s%s%s", cID, keyJoinChar, taskID), nil
193255
}
194256

195257
func generatePeerKey(peerID, taskID string) string {
196-
return fmt.Sprintf("%s@%s", peerID, taskID)
258+
return fmt.Sprintf("%s%s%s", peerID, keyJoinChar, taskID)
197259
}

0 commit comments

Comments
 (0)