2022-04-22 13:30:20 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2022-09-07 09:11:06 +00:00
|
|
|
"errors"
|
2022-04-22 13:30:20 +00:00
|
|
|
|
2022-07-26 09:48:55 +00:00
|
|
|
treeconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/tree"
|
2022-09-07 09:11:06 +00:00
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/pilorama"
|
2022-10-06 20:18:46 +00:00
|
|
|
containerClient "github.com/nspcc-dev/neofs-node/pkg/morph/client/container"
|
2022-09-07 09:11:06 +00:00
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/morph/event"
|
|
|
|
containerEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/container"
|
2022-10-06 20:18:46 +00:00
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/services/control"
|
2022-04-22 13:30:20 +00:00
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/services/tree"
|
2022-10-06 20:18:46 +00:00
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/util/logger"
|
2022-09-07 09:11:06 +00:00
|
|
|
"go.uber.org/zap"
|
2022-04-22 13:30:20 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func initTreeService(c *cfg) {
|
2022-07-26 09:48:55 +00:00
|
|
|
treeConfig := treeconfig.Tree(c.appCfg)
|
|
|
|
if !treeConfig.Enabled() {
|
2022-07-18 10:16:23 +00:00
|
|
|
c.log.Info("tree service is not enabled, skip initialization")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-05-16 16:31:50 +00:00
|
|
|
c.treeService = tree.New(
|
2022-04-22 13:30:20 +00:00
|
|
|
tree.WithContainerSource(c.cfgObject.cnrSource),
|
2022-09-08 12:44:27 +00:00
|
|
|
tree.WithEACLSource(c.cfgObject.eaclSource),
|
2022-04-22 13:30:20 +00:00
|
|
|
tree.WithNetmapSource(c.netMapSource),
|
|
|
|
tree.WithPrivateKey(&c.key.PrivateKey),
|
|
|
|
tree.WithLogger(c.log),
|
2022-07-19 08:03:13 +00:00
|
|
|
tree.WithStorage(c.cfgObject.cfgLocalStorage.localStorage),
|
2022-07-26 09:48:55 +00:00
|
|
|
tree.WithContainerCacheSize(treeConfig.CacheSize()),
|
|
|
|
tree.WithReplicationChannelCapacity(treeConfig.ReplicationChannelCapacity()),
|
|
|
|
tree.WithReplicationWorkerCount(treeConfig.ReplicationWorkerCount()))
|
2022-04-22 13:30:20 +00:00
|
|
|
|
2022-05-06 11:58:36 +00:00
|
|
|
for _, srv := range c.cfgGRPC.servers {
|
2022-05-16 16:31:50 +00:00
|
|
|
tree.RegisterTreeServiceServer(srv, c.treeService)
|
2022-05-06 11:58:36 +00:00
|
|
|
}
|
2022-04-22 13:30:20 +00:00
|
|
|
|
|
|
|
c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) {
|
2022-05-16 16:31:50 +00:00
|
|
|
c.treeService.Start(ctx)
|
2022-04-22 13:30:20 +00:00
|
|
|
}))
|
2022-05-06 11:58:36 +00:00
|
|
|
|
2022-10-06 20:18:46 +00:00
|
|
|
syncTreeFunc := func(ctx context.Context) {
|
|
|
|
syncTrees(ctx, c.treeService, c.shared.cnrClient, c.log)
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.cfgNetmap.state.controlNetmapStatus() == control.NetmapStatus_ONLINE {
|
|
|
|
c.workers = append(c.workers, newWorkerFromFunc(syncTreeFunc))
|
|
|
|
}
|
|
|
|
|
|
|
|
c.addOnlineStateHandler(syncTreeFunc)
|
|
|
|
|
2022-09-07 09:11:06 +00:00
|
|
|
subscribeToContainerRemoval(c, func(e event.Event) {
|
|
|
|
ev := e.(containerEvent.DeleteSuccess)
|
|
|
|
|
|
|
|
// This is executed asynchronously, so we don't care about the operation taking some time.
|
|
|
|
err := c.treeService.DropTree(context.Background(), ev.ID, "")
|
|
|
|
if err != nil && !errors.Is(err, pilorama.ErrTreeNotFound) {
|
|
|
|
// Ignore pilorama.ErrTreeNotFound but other errors, including shard.ErrReadOnly, should be logged.
|
|
|
|
c.log.Error("container removal event received, but trees weren't removed",
|
|
|
|
zap.Stringer("cid", ev.ID),
|
|
|
|
zap.String("error", err.Error()))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2022-05-16 16:31:50 +00:00
|
|
|
c.onShutdown(c.treeService.Shutdown)
|
2022-04-22 13:30:20 +00:00
|
|
|
}
|
2022-10-06 20:18:46 +00:00
|
|
|
|
|
|
|
func syncTrees(ctx context.Context, treeSvc *tree.Service, cnrCli *containerClient.Client, log *logger.Logger) {
|
|
|
|
log.Info("synchronizing trees...")
|
|
|
|
|
|
|
|
ids, err := cnrCli.List(nil)
|
|
|
|
if err != nil {
|
|
|
|
log.Error("trees are not synchronized", zap.Error(err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: #1902 fetch all the trees via a new tree RPC
|
|
|
|
wellKnownTrees := [...]string{"version", "system"}
|
|
|
|
|
|
|
|
for _, id := range ids {
|
|
|
|
for _, tID := range wellKnownTrees {
|
|
|
|
err = treeSvc.Synchronize(ctx, id, tID)
|
|
|
|
if err != nil && !errors.Is(err, tree.ErrNotInContainer) {
|
|
|
|
log.Warn(
|
|
|
|
"tree synchronization failed",
|
|
|
|
zap.Stringer("cid", id),
|
|
|
|
zap.String("tree_id", tID),
|
|
|
|
zap.Error(err),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Info("trees have been synchronized")
|
|
|
|
}
|