github.com/braveheart12/just@v0.8.7/ledger/artifactmanager/handler.go (about)

     1  /*
     2   *    Copyright 2019 Insolar Technologies
     3   *
     4   *    Licensed under the Apache License, Version 2.0 (the "License");
     5   *    you may not use this file except in compliance with the License.
     6   *    You may obtain a copy of the License at
     7   *
     8   *        http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   *    Unless required by applicable law or agreed to in writing, software
    11   *    distributed under the License is distributed on an "AS IS" BASIS,
    12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   *    See the License for the specific language governing permissions and
    14   *    limitations under the License.
    15   */
    16  
    17  package artifactmanager
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"fmt"
    23  	"time"
    24  
    25  	"github.com/insolar/insolar/core/delegationtoken"
    26  	"github.com/insolar/insolar/ledger/storage/nodes"
    27  	"github.com/pkg/errors"
    28  	"go.opencensus.io/stats"
    29  	"go.opencensus.io/tag"
    30  
    31  	"github.com/insolar/insolar/instrumentation/inslogger"
    32  	"github.com/insolar/insolar/instrumentation/insmetrics"
    33  	"github.com/insolar/insolar/ledger/recentstorage"
    34  	"github.com/insolar/insolar/ledger/storage/jet"
    35  
    36  	"github.com/insolar/insolar/configuration"
    37  	"github.com/insolar/insolar/core"
    38  	"github.com/insolar/insolar/core/message"
    39  	"github.com/insolar/insolar/core/reply"
    40  	"github.com/insolar/insolar/instrumentation/hack"
    41  	"github.com/insolar/insolar/ledger/storage"
    42  	"github.com/insolar/insolar/ledger/storage/index"
    43  	"github.com/insolar/insolar/ledger/storage/record"
    44  )
    45  
    46  // MessageHandler processes messages for local storage interaction.
    47  type MessageHandler struct {
    48  	RecentStorageProvider      recentstorage.Provider          `inject:""`
    49  	Bus                        core.MessageBus                 `inject:""`
    50  	PlatformCryptographyScheme core.PlatformCryptographyScheme `inject:""`
    51  	JetCoordinator             core.JetCoordinator             `inject:""`
    52  	CryptographyService        core.CryptographyService        `inject:""`
    53  	DelegationTokenFactory     core.DelegationTokenFactory     `inject:""`
    54  	HeavySync                  core.HeavySync                  `inject:""`
    55  	PulseStorage               core.PulseStorage               `inject:""`
    56  	JetStorage                 storage.JetStorage              `inject:""`
    57  	DropStorage                storage.DropStorage             `inject:""`
    58  	ObjectStorage              storage.ObjectStorage           `inject:""`
    59  	Nodes                      nodes.Accessor                  `inject:""`
    60  	PulseTracker               storage.PulseTracker            `inject:""`
    61  	DBContext                  storage.DBContext               `inject:""`
    62  	HotDataWaiter              HotDataWaiter                   `inject:""`
    63  
    64  	certificate    core.Certificate
    65  	replayHandlers map[core.MessageType]core.MessageHandler
    66  	conf           *configuration.Ledger
    67  	middleware     *middleware
    68  	jetTreeUpdater *jetTreeUpdater
    69  	isHeavy        bool
    70  }
    71  
    72  // NewMessageHandler creates new handler.
    73  func NewMessageHandler(conf *configuration.Ledger, certificate core.Certificate) *MessageHandler {
    74  	return &MessageHandler{
    75  		certificate:    certificate,
    76  		replayHandlers: map[core.MessageType]core.MessageHandler{},
    77  		conf:           conf,
    78  	}
    79  }
    80  
    81  func instrumentHandler(name string) Handler {
    82  	return func(handler core.MessageHandler) core.MessageHandler {
    83  		return func(ctx context.Context, p core.Parcel) (core.Reply, error) {
    84  			// TODO: add tags to log
    85  			inslog := inslogger.FromContext(ctx)
    86  			start := time.Now()
    87  			code := "2xx"
    88  			ctx = insmetrics.InsertTag(ctx, tagMethod, name)
    89  
    90  			repl, err := handler(ctx, p)
    91  
    92  			latency := time.Since(start)
    93  			if err != nil {
    94  				code = "5xx"
    95  				inslog.Errorf("AM's handler %v returns error: %v", name, err)
    96  			}
    97  			inslog.Debugf("measured time of AM method %v is %v", name, latency)
    98  
    99  			ctx = insmetrics.ChangeTags(
   100  				ctx,
   101  				tag.Insert(tagMethod, name),
   102  				tag.Insert(tagResult, code),
   103  			)
   104  			stats.Record(ctx, statCalls.M(1), statLatency.M(latency.Nanoseconds()/1e6))
   105  
   106  			return repl, err
   107  		}
   108  	}
   109  }
   110  
   111  // Init initializes handlers and middleware.
   112  func (h *MessageHandler) Init(ctx context.Context) error {
   113  	m := newMiddleware(h)
   114  	h.middleware = m
   115  
   116  	h.jetTreeUpdater = newJetTreeUpdater(h.Nodes, h.JetStorage, h.Bus, h.JetCoordinator)
   117  
   118  	h.isHeavy = h.certificate.GetRole() == core.StaticRoleHeavyMaterial
   119  
   120  	// core.StaticRoleUnknown - genesis
   121  	if h.certificate.GetRole() == core.StaticRoleLightMaterial || h.certificate.GetRole() == core.StaticRoleUnknown {
   122  		h.setHandlersForLight(m)
   123  		h.setReplayHandlers(m)
   124  	}
   125  
   126  	if h.isHeavy {
   127  		h.setHandlersForHeavy(m)
   128  	}
   129  
   130  	return nil
   131  }
   132  
   133  func (h *MessageHandler) setHandlersForLight(m *middleware) {
   134  	// Generic.
   135  	h.Bus.MustRegister(core.TypeGetCode, BuildMiddleware(h.handleGetCode))
   136  
   137  	h.Bus.MustRegister(core.TypeGetObject,
   138  		BuildMiddleware(h.handleGetObject,
   139  			instrumentHandler("handleGetObject"),
   140  			m.addFieldsToLogger,
   141  			m.checkJet,
   142  			m.waitForHotData))
   143  
   144  	h.Bus.MustRegister(core.TypeGetDelegate,
   145  		BuildMiddleware(h.handleGetDelegate,
   146  			instrumentHandler("handleGetDelegate"),
   147  			m.addFieldsToLogger,
   148  			m.checkJet,
   149  			m.waitForHotData))
   150  
   151  	h.Bus.MustRegister(core.TypeGetChildren,
   152  		BuildMiddleware(h.handleGetChildren,
   153  			instrumentHandler("handleGetChildren"),
   154  			m.addFieldsToLogger,
   155  			m.checkJet,
   156  			m.waitForHotData))
   157  
   158  	h.Bus.MustRegister(core.TypeSetRecord,
   159  		BuildMiddleware(h.handleSetRecord,
   160  			instrumentHandler("handleSetRecord"),
   161  			m.addFieldsToLogger,
   162  			m.checkJet,
   163  			m.waitForHotData))
   164  
   165  	h.Bus.MustRegister(core.TypeUpdateObject,
   166  		BuildMiddleware(h.handleUpdateObject,
   167  			instrumentHandler("handleUpdateObject"),
   168  			m.addFieldsToLogger,
   169  			m.checkJet,
   170  			m.waitForHotData))
   171  
   172  	h.Bus.MustRegister(core.TypeRegisterChild,
   173  		BuildMiddleware(h.handleRegisterChild,
   174  			instrumentHandler("handleRegisterChild"),
   175  			m.addFieldsToLogger,
   176  			m.checkJet,
   177  			m.waitForHotData))
   178  
   179  	h.Bus.MustRegister(core.TypeSetBlob,
   180  		BuildMiddleware(h.handleSetBlob,
   181  			instrumentHandler("handleSetBlob"),
   182  			m.addFieldsToLogger,
   183  			m.checkJet,
   184  			m.waitForHotData))
   185  
   186  	h.Bus.MustRegister(core.TypeGetObjectIndex,
   187  		BuildMiddleware(h.handleGetObjectIndex,
   188  			instrumentHandler("handleGetObjectIndex"),
   189  			m.addFieldsToLogger,
   190  			m.checkJet,
   191  			m.waitForHotData))
   192  
   193  	h.Bus.MustRegister(core.TypeGetPendingRequests,
   194  		BuildMiddleware(h.handleHasPendingRequests,
   195  			instrumentHandler("handleHasPendingRequests"),
   196  			m.addFieldsToLogger,
   197  			m.checkJet,
   198  			m.waitForHotData))
   199  
   200  	h.Bus.MustRegister(core.TypeGetJet,
   201  		BuildMiddleware(h.handleGetJet,
   202  			instrumentHandler("handleGetJet")))
   203  
   204  	h.Bus.MustRegister(core.TypeHotRecords,
   205  		BuildMiddleware(h.handleHotRecords,
   206  			instrumentHandler("handleHotRecords"),
   207  			m.releaseHotDataWaiters))
   208  
   209  	h.Bus.MustRegister(
   210  		core.TypeGetRequest,
   211  		BuildMiddleware(
   212  			h.handleGetRequest,
   213  			instrumentHandler("handleGetRequest"),
   214  			m.checkJet,
   215  		),
   216  	)
   217  
   218  	h.Bus.MustRegister(
   219  		core.TypeGetPendingRequestID,
   220  		BuildMiddleware(
   221  			h.handleGetPendingRequestID,
   222  			instrumentHandler("handleGetPendingRequestID"),
   223  			m.checkJet,
   224  		),
   225  	)
   226  
   227  	// Validation.
   228  	h.Bus.MustRegister(core.TypeValidateRecord,
   229  		BuildMiddleware(h.handleValidateRecord,
   230  			m.addFieldsToLogger,
   231  			m.checkJet))
   232  
   233  	h.Bus.MustRegister(core.TypeValidationCheck,
   234  		BuildMiddleware(h.handleValidationCheck,
   235  			m.addFieldsToLogger,
   236  			m.checkJet))
   237  
   238  	h.Bus.MustRegister(core.TypeJetDrop,
   239  		BuildMiddleware(h.handleJetDrop,
   240  			m.addFieldsToLogger,
   241  			m.checkJet))
   242  }
   243  func (h *MessageHandler) setReplayHandlers(m *middleware) {
   244  	// Generic.
   245  	h.replayHandlers[core.TypeGetCode] = BuildMiddleware(h.handleGetCode, m.addFieldsToLogger)
   246  	h.replayHandlers[core.TypeGetObject] = BuildMiddleware(h.handleGetObject, m.addFieldsToLogger, m.checkJet)
   247  	h.replayHandlers[core.TypeGetDelegate] = BuildMiddleware(h.handleGetDelegate, m.addFieldsToLogger, m.checkJet)
   248  	h.replayHandlers[core.TypeGetChildren] = BuildMiddleware(h.handleGetChildren, m.addFieldsToLogger, m.checkJet)
   249  	h.replayHandlers[core.TypeSetRecord] = BuildMiddleware(h.handleSetRecord, m.addFieldsToLogger, m.checkJet)
   250  	h.replayHandlers[core.TypeUpdateObject] = BuildMiddleware(h.handleUpdateObject, m.addFieldsToLogger, m.checkJet)
   251  	h.replayHandlers[core.TypeRegisterChild] = BuildMiddleware(h.handleRegisterChild, m.addFieldsToLogger, m.checkJet)
   252  	h.replayHandlers[core.TypeSetBlob] = BuildMiddleware(h.handleSetBlob, m.addFieldsToLogger, m.checkJet)
   253  	h.replayHandlers[core.TypeGetObjectIndex] = BuildMiddleware(h.handleGetObjectIndex, m.addFieldsToLogger, m.checkJet)
   254  	h.replayHandlers[core.TypeGetPendingRequests] = BuildMiddleware(h.handleHasPendingRequests, m.addFieldsToLogger, m.checkJet)
   255  	h.replayHandlers[core.TypeGetJet] = BuildMiddleware(h.handleGetJet)
   256  
   257  	// Validation.
   258  	h.replayHandlers[core.TypeValidateRecord] = BuildMiddleware(h.handleValidateRecord, m.addFieldsToLogger, m.checkJet)
   259  	h.replayHandlers[core.TypeValidationCheck] = BuildMiddleware(h.handleValidationCheck, m.addFieldsToLogger, m.checkJet)
   260  }
   261  func (h *MessageHandler) setHandlersForHeavy(m *middleware) {
   262  	// Heavy.
   263  	h.Bus.MustRegister(core.TypeHeavyStartStop,
   264  		BuildMiddleware(h.handleHeavyStartStop,
   265  			instrumentHandler("handleHeavyStartStop")))
   266  
   267  	h.Bus.MustRegister(core.TypeHeavyReset,
   268  		BuildMiddleware(h.handleHeavyReset,
   269  			instrumentHandler("handleHeavyReset")))
   270  
   271  	h.Bus.MustRegister(core.TypeHeavyPayload,
   272  		BuildMiddleware(h.handleHeavyPayload,
   273  			instrumentHandler("handleHeavyPayload")))
   274  
   275  	// Generic.
   276  	h.Bus.MustRegister(core.TypeGetCode,
   277  		BuildMiddleware(h.handleGetCode))
   278  
   279  	h.Bus.MustRegister(core.TypeGetObject,
   280  		BuildMiddleware(h.handleGetObject,
   281  			instrumentHandler("handleGetObject"),
   282  			m.zeroJetForHeavy))
   283  
   284  	h.Bus.MustRegister(core.TypeGetDelegate,
   285  		BuildMiddleware(h.handleGetDelegate,
   286  			instrumentHandler("handleGetDelegate"),
   287  			m.zeroJetForHeavy))
   288  
   289  	h.Bus.MustRegister(core.TypeGetChildren,
   290  		BuildMiddleware(h.handleGetChildren,
   291  			instrumentHandler("handleGetChildren"),
   292  			m.zeroJetForHeavy))
   293  
   294  	h.Bus.MustRegister(core.TypeGetObjectIndex,
   295  		BuildMiddleware(h.handleGetObjectIndex,
   296  			instrumentHandler("handleGetObjectIndex"),
   297  			m.zeroJetForHeavy))
   298  
   299  	h.Bus.MustRegister(
   300  		core.TypeGetRequest,
   301  		BuildMiddleware(h.handleGetRequest,
   302  			instrumentHandler("handleGetRequest"),
   303  			m.zeroJetForHeavy))
   304  }
   305  
   306  func (h *MessageHandler) handleSetRecord(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
   307  	if h.isHeavy {
   308  		return nil, errors.New("heavy updates are forbidden")
   309  	}
   310  
   311  	msg := parcel.Message().(*message.SetRecord)
   312  	rec := record.DeserializeRecord(msg.Record)
   313  	jetID := jetFromContext(ctx)
   314  
   315  	calculatedID := record.NewRecordIDFromRecord(h.PlatformCryptographyScheme, parcel.Pulse(), rec)
   316  
   317  	switch r := rec.(type) {
   318  	case record.Request:
   319  		if h.RecentStorageProvider.Count() > h.conf.PendingRequestsLimit {
   320  			return &reply.Error{ErrType: reply.ErrTooManyPendingRequests}, nil
   321  		}
   322  		recentStorage := h.RecentStorageProvider.GetPendingStorage(ctx, jetID)
   323  		recentStorage.AddPendingRequest(ctx, r.GetObject(), *calculatedID)
   324  	case *record.ResultRecord:
   325  		recentStorage := h.RecentStorageProvider.GetPendingStorage(ctx, jetID)
   326  		recentStorage.RemovePendingRequest(ctx, r.Object, *r.Request.Record())
   327  	}
   328  
   329  	id, err := h.ObjectStorage.SetRecord(ctx, jetID, parcel.Pulse(), rec)
   330  	if err == storage.ErrOverride {
   331  		inslogger.FromContext(ctx).WithField("type", fmt.Sprintf("%T", rec)).Warn("set record override")
   332  		id = calculatedID
   333  	} else if err != nil {
   334  		return nil, err
   335  	}
   336  
   337  	return &reply.ID{ID: *id}, nil
   338  }
   339  
   340  func (h *MessageHandler) handleSetBlob(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
   341  	if h.isHeavy {
   342  		return nil, errors.New("heavy updates are forbidden")
   343  	}
   344  
   345  	msg := parcel.Message().(*message.SetBlob)
   346  	jetID := jetFromContext(ctx)
   347  	calculatedID := record.CalculateIDForBlob(h.PlatformCryptographyScheme, parcel.Pulse(), msg.Memory)
   348  
   349  	_, err := h.ObjectStorage.GetBlob(ctx, jetID, calculatedID)
   350  	if err == nil {
   351  		return &reply.ID{ID: *calculatedID}, nil
   352  	}
   353  	if err != nil && err != core.ErrNotFound {
   354  		return nil, err
   355  	}
   356  
   357  	id, err := h.ObjectStorage.SetBlob(ctx, jetID, parcel.Pulse(), msg.Memory)
   358  	if err == nil {
   359  		return &reply.ID{ID: *id}, nil
   360  	}
   361  	if err == storage.ErrOverride {
   362  		return &reply.ID{ID: *calculatedID}, nil
   363  	}
   364  	return nil, err
   365  }
   366  
   367  func (h *MessageHandler) handleGetCode(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
   368  	msg := parcel.Message().(*message.GetCode)
   369  	jetID := *jet.NewID(0, nil)
   370  
   371  	codeRec, err := h.getCode(ctx, msg.Code.Record())
   372  	if err == core.ErrNotFound {
   373  		// We don't have code record. Must be on another node.
   374  		node, err := h.JetCoordinator.NodeForJet(ctx, jetID, parcel.Pulse(), msg.Code.Record().Pulse())
   375  		if err != nil {
   376  			return nil, err
   377  		}
   378  		return reply.NewGetCodeRedirect(h.DelegationTokenFactory, parcel, node)
   379  	}
   380  	if err != nil {
   381  		return nil, err
   382  	}
   383  	code, err := h.ObjectStorage.GetBlob(ctx, jetID, codeRec.Code)
   384  	if err != nil {
   385  		return nil, err
   386  	}
   387  
   388  	rep := reply.Code{
   389  		Code:        code,
   390  		MachineType: codeRec.MachineType,
   391  	}
   392  
   393  	return &rep, nil
   394  }
   395  
   396  func (h *MessageHandler) handleGetObject(
   397  	ctx context.Context, parcel core.Parcel,
   398  ) (core.Reply, error) {
   399  	msg := parcel.Message().(*message.GetObject)
   400  	jetID := jetFromContext(ctx)
   401  	logger := inslogger.FromContext(ctx).WithFields(map[string]interface{}{
   402  		"object": msg.Head.Record().DebugString(),
   403  		"pulse":  parcel.Pulse(),
   404  	})
   405  
   406  	if !h.isHeavy {
   407  		h.RecentStorageProvider.GetIndexStorage(ctx, jetID).AddObject(ctx, *msg.Head.Record())
   408  	}
   409  
   410  	// Fetch object index. If not found redirect.
   411  	idx, err := h.ObjectStorage.GetObjectIndex(ctx, jetID, msg.Head.Record(), false)
   412  	if err == core.ErrNotFound {
   413  		if h.isHeavy {
   414  			return nil, fmt.Errorf("failed to fetch index for %s", msg.Head.Record().String())
   415  		}
   416  
   417  		logger.Debug("failed to fetch index (fetching from heavy)")
   418  		node, err := h.JetCoordinator.Heavy(ctx, parcel.Pulse())
   419  		if err != nil {
   420  			return nil, err
   421  		}
   422  		idx, err = h.saveIndexFromHeavy(ctx, jetID, msg.Head, node)
   423  		if err != nil {
   424  			return nil, errors.Wrap(err, "failed to fetch index from heavy")
   425  		}
   426  	} else if err != nil {
   427  		return nil, errors.Wrapf(err, "failed to fetch object index %s", msg.Head.Record().String())
   428  	}
   429  
   430  	// Determine object state id.
   431  	var stateID *core.RecordID
   432  	if msg.State != nil {
   433  		stateID = msg.State
   434  	} else {
   435  		if msg.Approved {
   436  			stateID = idx.LatestStateApproved
   437  		} else {
   438  			stateID = idx.LatestState
   439  		}
   440  	}
   441  	if stateID == nil {
   442  		return &reply.Error{ErrType: reply.ErrStateNotAvailable}, nil
   443  	}
   444  
   445  	var (
   446  		stateJet *core.RecordID
   447  	)
   448  	if h.isHeavy {
   449  		stateJet = &jetID
   450  	} else {
   451  		var actual bool
   452  		onHeavy, err := h.JetCoordinator.IsBeyondLimit(ctx, parcel.Pulse(), stateID.Pulse())
   453  		if err != nil {
   454  			return nil, err
   455  		}
   456  		if onHeavy {
   457  			node, err := h.JetCoordinator.Heavy(ctx, parcel.Pulse())
   458  			if err != nil {
   459  				return nil, err
   460  			}
   461  			logger.WithFields(map[string]interface{}{
   462  				"state":    stateID.DebugString(),
   463  				"going_to": node.String(),
   464  			}).Debug("fetching object (on heavy)")
   465  
   466  			obj, err := h.fetchObject(ctx, msg.Head, *node, stateID)
   467  			if err != nil {
   468  				if err == core.ErrDeactivated {
   469  					return &reply.Error{ErrType: reply.ErrDeactivated}, nil
   470  				}
   471  				return nil, err
   472  			}
   473  
   474  			return &reply.Object{
   475  				Head:         msg.Head,
   476  				State:        *stateID,
   477  				Prototype:    obj.Prototype,
   478  				IsPrototype:  obj.IsPrototype,
   479  				ChildPointer: idx.ChildPointer,
   480  				Parent:       idx.Parent,
   481  				Memory:       obj.Memory,
   482  			}, nil
   483  		}
   484  
   485  		stateJet, actual = h.JetStorage.FindJet(ctx, stateID.Pulse(), *msg.Head.Record())
   486  		if !actual {
   487  			actualJet, err := h.jetTreeUpdater.fetchJet(ctx, *msg.Head.Record(), stateID.Pulse())
   488  			if err != nil {
   489  				return nil, err
   490  			}
   491  			stateJet = actualJet
   492  		}
   493  	}
   494  
   495  	// Fetch state record.
   496  	rec, err := h.ObjectStorage.GetRecord(ctx, *stateJet, stateID)
   497  	if err == core.ErrNotFound {
   498  		if h.isHeavy {
   499  			return nil, fmt.Errorf("failed to fetch state for %v. jet: %v, state: %v", msg.Head.Record(), stateJet.DebugString(), stateID.DebugString())
   500  		}
   501  		// The record wasn't found on the current node. Return redirect to the node that contains it.
   502  		// We get Jet tree for pulse when given state was added.
   503  		node, err := h.JetCoordinator.NodeForJet(ctx, *stateJet, parcel.Pulse(), stateID.Pulse())
   504  		if err != nil {
   505  			return nil, err
   506  		}
   507  		logger.WithFields(map[string]interface{}{
   508  			"state":    stateID.DebugString(),
   509  			"going_to": node.String(),
   510  		}).Debug("fetching object (record not found)")
   511  
   512  		obj, err := h.fetchObject(ctx, msg.Head, *node, stateID)
   513  		if err != nil {
   514  			if err == core.ErrDeactivated {
   515  				return &reply.Error{ErrType: reply.ErrDeactivated}, nil
   516  			}
   517  			return nil, err
   518  		}
   519  
   520  		return &reply.Object{
   521  			Head:         msg.Head,
   522  			State:        *stateID,
   523  			Prototype:    obj.Prototype,
   524  			IsPrototype:  obj.IsPrototype,
   525  			ChildPointer: idx.ChildPointer,
   526  			Parent:       idx.Parent,
   527  			Memory:       obj.Memory,
   528  		}, nil
   529  	}
   530  	if err != nil {
   531  		return nil, err
   532  	}
   533  	state, ok := rec.(record.ObjectState)
   534  	if !ok {
   535  		return nil, errors.New("invalid object record")
   536  	}
   537  	if state.State() == record.StateDeactivation {
   538  		return &reply.Error{ErrType: reply.ErrDeactivated}, nil
   539  	}
   540  
   541  	var childPointer *core.RecordID
   542  	if idx.ChildPointer != nil {
   543  		childPointer = idx.ChildPointer
   544  	}
   545  	rep := reply.Object{
   546  		Head:         msg.Head,
   547  		State:        *stateID,
   548  		Prototype:    state.GetImage(),
   549  		IsPrototype:  state.GetIsPrototype(),
   550  		ChildPointer: childPointer,
   551  		Parent:       idx.Parent,
   552  	}
   553  
   554  	if state.GetMemory() != nil {
   555  		rep.Memory, err = h.ObjectStorage.GetBlob(ctx, *stateJet, state.GetMemory())
   556  		if err != nil {
   557  			return nil, errors.Wrap(err, "failed to fetch blob")
   558  		}
   559  	}
   560  
   561  	return &rep, nil
   562  }
   563  
   564  func (h *MessageHandler) handleHasPendingRequests(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
   565  	msg := parcel.Message().(*message.GetPendingRequests)
   566  	jetID := jetFromContext(ctx)
   567  
   568  	for _, reqID := range h.RecentStorageProvider.GetPendingStorage(ctx, jetID).GetRequestsForObject(*msg.Object.Record()) {
   569  		if reqID.Pulse() < parcel.Pulse() {
   570  			return &reply.HasPendingRequests{Has: true}, nil
   571  		}
   572  	}
   573  
   574  	return &reply.HasPendingRequests{Has: false}, nil
   575  }
   576  
   577  func (h *MessageHandler) handleGetJet(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
   578  	msg := parcel.Message().(*message.GetJet)
   579  
   580  	jetID, actual := h.JetStorage.FindJet(ctx, msg.Pulse, msg.Object)
   581  
   582  	return &reply.Jet{ID: *jetID, Actual: actual}, nil
   583  }
   584  
   585  func (h *MessageHandler) handleGetDelegate(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
   586  	msg := parcel.Message().(*message.GetDelegate)
   587  	jetID := jetFromContext(ctx)
   588  
   589  	if !h.isHeavy {
   590  		h.RecentStorageProvider.GetIndexStorage(ctx, jetID).AddObject(ctx, *msg.Head.Record())
   591  	}
   592  
   593  	idx, err := h.ObjectStorage.GetObjectIndex(ctx, jetID, msg.Head.Record(), false)
   594  	if err == core.ErrNotFound {
   595  		if h.isHeavy {
   596  			return nil, fmt.Errorf("failed to fetch index for %v", msg.Head.Record())
   597  		}
   598  
   599  		heavy, err := h.JetCoordinator.Heavy(ctx, parcel.Pulse())
   600  		if err != nil {
   601  			return nil, err
   602  		}
   603  		idx, err = h.saveIndexFromHeavy(ctx, jetID, msg.Head, heavy)
   604  		if err != nil {
   605  			return nil, errors.Wrap(err, "failed to fetch index from heavy")
   606  		}
   607  	} else if err != nil {
   608  		return nil, errors.Wrap(err, "failed to fetch object index")
   609  	}
   610  
   611  	delegateRef, ok := idx.Delegates[msg.AsType]
   612  	if !ok {
   613  		return nil, errors.New("the object has no delegate for this type")
   614  	}
   615  
   616  	rep := reply.Delegate{
   617  		Head: delegateRef,
   618  	}
   619  
   620  	return &rep, nil
   621  }
   622  
   623  func (h *MessageHandler) handleGetChildren(
   624  	ctx context.Context, parcel core.Parcel,
   625  ) (core.Reply, error) {
   626  	msg := parcel.Message().(*message.GetChildren)
   627  	jetID := jetFromContext(ctx)
   628  
   629  	if !h.isHeavy {
   630  		h.RecentStorageProvider.GetIndexStorage(ctx, jetID).AddObject(ctx, *msg.Parent.Record())
   631  	}
   632  
   633  	idx, err := h.ObjectStorage.GetObjectIndex(ctx, jetID, msg.Parent.Record(), false)
   634  	if err == core.ErrNotFound {
   635  		if h.isHeavy {
   636  			return nil, fmt.Errorf("failed to fetch index for %v", msg.Parent.Record())
   637  		}
   638  
   639  		heavy, err := h.JetCoordinator.Heavy(ctx, parcel.Pulse())
   640  		if err != nil {
   641  			return nil, err
   642  		}
   643  		idx, err = h.saveIndexFromHeavy(ctx, jetID, msg.Parent, heavy)
   644  		if err != nil {
   645  			return nil, errors.Wrap(err, "failed to fetch index from heavy")
   646  		}
   647  		if idx.ChildPointer == nil {
   648  			return &reply.Children{Refs: nil, NextFrom: nil}, nil
   649  		}
   650  	} else if err != nil {
   651  		return nil, errors.Wrap(err, "failed to fetch object index")
   652  	}
   653  
   654  	var (
   655  		refs         []core.RecordRef
   656  		currentChild *core.RecordID
   657  	)
   658  
   659  	// Counting from specified child or the latest.
   660  	if msg.FromChild != nil {
   661  		currentChild = msg.FromChild
   662  	} else {
   663  		currentChild = idx.ChildPointer
   664  	}
   665  
   666  	// The object has no children.
   667  	if currentChild == nil {
   668  		return &reply.Children{Refs: nil, NextFrom: nil}, nil
   669  	}
   670  
   671  	var childJet *core.RecordID
   672  	if h.isHeavy {
   673  		childJet = &jetID
   674  	} else {
   675  		var actual bool
   676  		onHeavy, err := h.JetCoordinator.IsBeyondLimit(ctx, parcel.Pulse(), currentChild.Pulse())
   677  		if err != nil {
   678  			return nil, err
   679  		}
   680  		if onHeavy {
   681  			node, err := h.JetCoordinator.Heavy(ctx, parcel.Pulse())
   682  			if err != nil {
   683  				return nil, err
   684  			}
   685  			return reply.NewGetChildrenRedirect(h.DelegationTokenFactory, parcel, node, *currentChild)
   686  		}
   687  
   688  		childJet, actual = h.JetStorage.FindJet(ctx, currentChild.Pulse(), *msg.Parent.Record())
   689  		if !actual {
   690  			actualJet, err := h.jetTreeUpdater.fetchJet(ctx, *msg.Parent.Record(), currentChild.Pulse())
   691  			if err != nil {
   692  				return nil, err
   693  			}
   694  			childJet = actualJet
   695  		}
   696  	}
   697  
   698  	// Try to fetch the first child.
   699  	_, err = h.ObjectStorage.GetRecord(ctx, *childJet, currentChild)
   700  	if err == core.ErrNotFound {
   701  		if h.isHeavy {
   702  			return nil, fmt.Errorf("failed to fetch child for %v. jet: %v, state: %v", msg.Parent.Record(), childJet.DebugString(), currentChild.DebugString())
   703  		}
   704  		node, err := h.JetCoordinator.NodeForJet(ctx, *childJet, parcel.Pulse(), currentChild.Pulse())
   705  		if err != nil {
   706  			return nil, err
   707  		}
   708  		return reply.NewGetChildrenRedirect(h.DelegationTokenFactory, parcel, node, *currentChild)
   709  	}
   710  
   711  	if err != nil {
   712  		return nil, errors.Wrap(err, "failed to fetch child")
   713  	}
   714  
   715  	counter := 0
   716  	for currentChild != nil {
   717  		// We have enough results.
   718  		if counter >= msg.Amount {
   719  			return &reply.Children{Refs: refs, NextFrom: currentChild}, nil
   720  		}
   721  		counter++
   722  
   723  		rec, err := h.ObjectStorage.GetRecord(ctx, *childJet, currentChild)
   724  		// We don't have this child reference. Return what was collected.
   725  		if err == core.ErrNotFound {
   726  			return &reply.Children{Refs: refs, NextFrom: currentChild}, nil
   727  		}
   728  		if err != nil {
   729  			return nil, errors.New("failed to retrieve children")
   730  		}
   731  
   732  		childRec, ok := rec.(*record.ChildRecord)
   733  		if !ok {
   734  			return nil, errors.New("failed to retrieve children")
   735  		}
   736  		currentChild = childRec.PrevChild
   737  
   738  		// Skip records later than specified pulse.
   739  		recPulse := childRec.Ref.Record().Pulse()
   740  		if msg.FromPulse != nil && recPulse > *msg.FromPulse {
   741  			continue
   742  		}
   743  		refs = append(refs, childRec.Ref)
   744  	}
   745  
   746  	return &reply.Children{Refs: refs, NextFrom: nil}, nil
   747  }
   748  
   749  func (h *MessageHandler) handleGetRequest(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
   750  	jetID := jetFromContext(ctx)
   751  	msg := parcel.Message().(*message.GetRequest)
   752  
   753  	rec, err := h.ObjectStorage.GetRecord(ctx, jetID, &msg.Request)
   754  	if err != nil {
   755  		return nil, errors.New("failed to fetch request")
   756  	}
   757  
   758  	req, ok := rec.(*record.RequestRecord)
   759  	if !ok {
   760  		return nil, errors.New("failed to decode request")
   761  	}
   762  
   763  	rep := reply.Request{
   764  		ID:     msg.Request,
   765  		Record: record.SerializeRecord(req),
   766  	}
   767  
   768  	return &rep, nil
   769  }
   770  
   771  func (h *MessageHandler) handleGetPendingRequestID(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
   772  	jetID := jetFromContext(ctx)
   773  	msg := parcel.Message().(*message.GetPendingRequestID)
   774  
   775  	requests := h.RecentStorageProvider.GetPendingStorage(ctx, jetID).GetRequestsForObject(msg.ObjectID)
   776  	if len(requests) == 0 {
   777  		return &reply.Error{ErrType: reply.ErrNoPendingRequests}, nil
   778  	}
   779  
   780  	rep := reply.ID{
   781  		ID: requests[0],
   782  	}
   783  
   784  	return &rep, nil
   785  }
   786  
   787  func (h *MessageHandler) handleUpdateObject(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
   788  	if h.isHeavy {
   789  		return nil, errors.New("heavy updates are forbidden")
   790  	}
   791  
   792  	msg := parcel.Message().(*message.UpdateObject)
   793  	jetID := jetFromContext(ctx)
   794  	logger := inslogger.FromContext(ctx).WithFields(map[string]interface{}{
   795  		"object": msg.Object.Record().DebugString(),
   796  		"pulse":  parcel.Pulse(),
   797  	})
   798  
   799  	rec := record.DeserializeRecord(msg.Record)
   800  	state, ok := rec.(record.ObjectState)
   801  	if !ok {
   802  		return nil, errors.New("wrong object state record")
   803  	}
   804  
   805  	h.RecentStorageProvider.GetIndexStorage(ctx, jetID).AddObject(ctx, *msg.Object.Record())
   806  
   807  	// FIXME: temporary fix. If we calculate blob id on the client, pulse can change before message sending and this
   808  	//  id will not match the one calculated on the server.
   809  	blobID, err := h.ObjectStorage.SetBlob(ctx, jetID, parcel.Pulse(), msg.Memory)
   810  	if err != nil {
   811  		return nil, errors.Wrap(err, "failed to set blob")
   812  	}
   813  
   814  	switch s := state.(type) {
   815  	case *record.ObjectActivateRecord:
   816  		s.Memory = blobID
   817  	case *record.ObjectAmendRecord:
   818  		s.Memory = blobID
   819  	}
   820  
   821  	var idx *index.ObjectLifeline
   822  	err = h.DBContext.Update(ctx, func(tx *storage.TransactionManager) error {
   823  		var err error
   824  		idx, err = tx.GetObjectIndex(ctx, jetID, msg.Object.Record(), true)
   825  		// No index on our node.
   826  		if err == core.ErrNotFound {
   827  			if state.State() == record.StateActivation {
   828  				// We are activating the object. There is no index for it anywhere.
   829  				idx = &index.ObjectLifeline{State: record.StateUndefined}
   830  			} else {
   831  				logger.Debug("failed to fetch index (fetching from heavy)")
   832  				// We are updating object. Index should be on the heavy executor.
   833  				heavy, err := h.JetCoordinator.Heavy(ctx, parcel.Pulse())
   834  				if err != nil {
   835  					return err
   836  				}
   837  				idx, err = h.saveIndexFromHeavy(ctx, jetID, msg.Object, heavy)
   838  				if err != nil {
   839  					return errors.Wrap(err, "failed to fetch index from heavy")
   840  				}
   841  			}
   842  		} else if err != nil {
   843  			return err
   844  		}
   845  
   846  		if err = validateState(idx.State, state.State()); err != nil {
   847  			return err
   848  		}
   849  
   850  		recID := record.NewRecordIDFromRecord(h.PlatformCryptographyScheme, parcel.Pulse(), rec)
   851  
   852  		// Index exists and latest record id does not match (preserving chain consistency).
   853  		// For the case when vm can't save or send result to another vm and it tries to update the same record again
   854  		if idx.LatestState != nil && !state.PrevStateID().Equal(idx.LatestState) && idx.LatestState != recID {
   855  			return errors.New("invalid state record")
   856  		}
   857  
   858  		id, err := tx.SetRecord(ctx, jetID, parcel.Pulse(), rec)
   859  		if err == storage.ErrOverride {
   860  			logger.WithField("type", fmt.Sprintf("%T", rec)).Warn("set record override (#1)")
   861  			id = recID
   862  		} else if err != nil {
   863  			return err
   864  		}
   865  		idx.LatestState = id
   866  		idx.State = state.State()
   867  		if state.State() == record.StateActivation {
   868  			idx.Parent = state.(*record.ObjectActivateRecord).Parent
   869  		}
   870  
   871  		idx.LatestUpdate = parcel.Pulse()
   872  		return tx.SetObjectIndex(ctx, jetID, msg.Object.Record(), idx)
   873  	})
   874  	if err != nil {
   875  		if err == ErrObjectDeactivated {
   876  			return &reply.Error{ErrType: reply.ErrDeactivated}, nil
   877  		}
   878  		return nil, err
   879  	}
   880  
   881  	logger.WithField("state", idx.LatestState.DebugString()).Debug("saved object")
   882  
   883  	rep := reply.Object{
   884  		Head:         msg.Object,
   885  		State:        *idx.LatestState,
   886  		Prototype:    state.GetImage(),
   887  		IsPrototype:  state.GetIsPrototype(),
   888  		ChildPointer: idx.ChildPointer,
   889  		Parent:       idx.Parent,
   890  	}
   891  	return &rep, nil
   892  }
   893  
   894  func (h *MessageHandler) handleRegisterChild(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
   895  	if h.isHeavy {
   896  		return nil, errors.New("heavy updates are forbidden")
   897  	}
   898  
   899  	logger := inslogger.FromContext(ctx)
   900  
   901  	msg := parcel.Message().(*message.RegisterChild)
   902  	jetID := jetFromContext(ctx)
   903  	rec := record.DeserializeRecord(msg.Record)
   904  	childRec, ok := rec.(*record.ChildRecord)
   905  	if !ok {
   906  		return nil, errors.New("wrong child record")
   907  	}
   908  
   909  	h.RecentStorageProvider.GetIndexStorage(ctx, jetID).AddObject(ctx, *msg.Parent.Record())
   910  
   911  	var child *core.RecordID
   912  	err := h.DBContext.Update(ctx, func(tx *storage.TransactionManager) error {
   913  		idx, err := h.ObjectStorage.GetObjectIndex(ctx, jetID, msg.Parent.Record(), false)
   914  		if err == core.ErrNotFound {
   915  			heavy, err := h.JetCoordinator.Heavy(ctx, parcel.Pulse())
   916  			if err != nil {
   917  				return err
   918  			}
   919  			idx, err = h.saveIndexFromHeavy(ctx, jetID, msg.Parent, heavy)
   920  			if err != nil {
   921  				return errors.Wrap(err, "failed to fetch index from heavy")
   922  			}
   923  		} else if err != nil {
   924  			return err
   925  		}
   926  
   927  		recID := record.NewRecordIDFromRecord(h.PlatformCryptographyScheme, parcel.Pulse(), childRec)
   928  
   929  		// Children exist and pointer does not match (preserving chain consistency).
   930  		// For the case when vm can't save or send result to another vm and it tries to update the same record again
   931  		if idx.ChildPointer != nil && !childRec.PrevChild.Equal(idx.ChildPointer) && idx.ChildPointer != recID {
   932  			return errors.New("invalid child record")
   933  		}
   934  
   935  		child, err = tx.SetRecord(ctx, jetID, parcel.Pulse(), childRec)
   936  		if err == storage.ErrOverride {
   937  			logger.WithField("type", fmt.Sprintf("%T", rec)).Warn("set record override (#2)")
   938  			child = recID
   939  		} else if err != nil {
   940  			return err
   941  		}
   942  
   943  		idx.ChildPointer = child
   944  		if msg.AsType != nil {
   945  			idx.Delegates[*msg.AsType] = msg.Child
   946  		}
   947  		idx.LatestUpdate = parcel.Pulse()
   948  		err = tx.SetObjectIndex(ctx, jetID, msg.Parent.Record(), idx)
   949  		if err != nil {
   950  			return err
   951  		}
   952  
   953  		return nil
   954  	})
   955  
   956  	if err != nil {
   957  		return nil, err
   958  	}
   959  
   960  	return &reply.ID{ID: *child}, nil
   961  }
   962  
   963  func (h *MessageHandler) handleJetDrop(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
   964  	msg := parcel.Message().(*message.JetDrop)
   965  
   966  	if !hack.SkipValidation(ctx) {
   967  		for _, parcelBuff := range msg.Messages {
   968  			jetDropMsg, err := message.Deserialize(bytes.NewBuffer(parcelBuff))
   969  			if err != nil {
   970  				return nil, err
   971  			}
   972  			handler, ok := h.replayHandlers[jetDropMsg.Type()]
   973  			if !ok {
   974  				return nil, errors.New("unknown message type")
   975  			}
   976  
   977  			_, err = handler(ctx, &message.Parcel{Msg: jetDropMsg})
   978  			if err != nil {
   979  				return nil, err
   980  			}
   981  		}
   982  	}
   983  
   984  	err := h.JetStorage.AddJets(ctx, msg.JetID)
   985  	if err != nil {
   986  		return nil, err
   987  	}
   988  
   989  	h.JetStorage.UpdateJetTree(
   990  		ctx, parcel.Pulse(), true, msg.JetID,
   991  	)
   992  
   993  	return &reply.OK{}, nil
   994  }
   995  
   996  func (h *MessageHandler) handleValidateRecord(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
   997  	if h.isHeavy {
   998  		return nil, errors.New("heavy updates are forbidden")
   999  	}
  1000  
  1001  	msg := parcel.Message().(*message.ValidateRecord)
  1002  	jetID := jetFromContext(ctx)
  1003  
  1004  	err := h.DBContext.Update(ctx, func(tx *storage.TransactionManager) error {
  1005  		idx, err := tx.GetObjectIndex(ctx, jetID, msg.Object.Record(), true)
  1006  		if err == core.ErrNotFound {
  1007  			heavy, err := h.JetCoordinator.Heavy(ctx, parcel.Pulse())
  1008  			if err != nil {
  1009  				return err
  1010  			}
  1011  			idx, err = h.saveIndexFromHeavy(ctx, jetID, msg.Object, heavy)
  1012  			if err != nil {
  1013  				return errors.Wrap(err, "failed to fetch index from heavy")
  1014  			}
  1015  		} else if err != nil {
  1016  			return err
  1017  		}
  1018  
  1019  		// Find node that has this state.
  1020  		node, err := h.JetCoordinator.NodeForJet(ctx, jetID, parcel.Pulse(), msg.Object.Record().Pulse())
  1021  		if err != nil {
  1022  			return err
  1023  		}
  1024  
  1025  		// Send checking message.
  1026  		genericReply, err := h.Bus.Send(ctx, &message.ValidationCheck{
  1027  			Object:              msg.Object,
  1028  			ValidatedState:      msg.State,
  1029  			LatestStateApproved: idx.LatestStateApproved,
  1030  		}, &core.MessageSendOptions{
  1031  			Receiver: node,
  1032  		})
  1033  		if err != nil {
  1034  			return err
  1035  		}
  1036  		switch genericReply.(type) {
  1037  		case *reply.OK:
  1038  			if msg.IsValid {
  1039  				idx.LatestStateApproved = &msg.State
  1040  			} else {
  1041  				idx.LatestState = idx.LatestStateApproved
  1042  			}
  1043  			idx.LatestUpdate = parcel.Pulse()
  1044  			err = tx.SetObjectIndex(ctx, jetID, msg.Object.Record(), idx)
  1045  			if err != nil {
  1046  				return errors.Wrap(err, "failed to save object index")
  1047  			}
  1048  		case *reply.NotOK:
  1049  			return errors.New("validation sequence integrity failure")
  1050  		default:
  1051  			return errors.New("handleValidateRecord: unexpected reply")
  1052  		}
  1053  
  1054  		return nil
  1055  	})
  1056  	if err != nil {
  1057  		return nil, err
  1058  	}
  1059  
  1060  	return &reply.OK{}, nil
  1061  }
  1062  
  1063  func (h *MessageHandler) handleGetObjectIndex(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
  1064  	msg := parcel.Message().(*message.GetObjectIndex)
  1065  	jetID := jetFromContext(ctx)
  1066  
  1067  	idx, err := h.ObjectStorage.GetObjectIndex(ctx, jetID, msg.Object.Record(), true)
  1068  	if err != nil {
  1069  		return nil, errors.Wrap(err, "failed to fetch object index")
  1070  	}
  1071  
  1072  	buf, err := index.EncodeObjectLifeline(idx)
  1073  	if err != nil {
  1074  		return nil, errors.Wrap(err, "failed to serialize index")
  1075  	}
  1076  
  1077  	return &reply.ObjectIndex{Index: buf}, nil
  1078  }
  1079  
  1080  func (h *MessageHandler) handleValidationCheck(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
  1081  	msg := parcel.Message().(*message.ValidationCheck)
  1082  	jetID := jetFromContext(ctx)
  1083  
  1084  	rec, err := h.ObjectStorage.GetRecord(ctx, jetID, &msg.ValidatedState)
  1085  	if err != nil {
  1086  		return nil, errors.Wrap(err, "failed to fetch state record")
  1087  	}
  1088  	state, ok := rec.(record.ObjectState)
  1089  	if !ok {
  1090  		return nil, errors.New("failed to fetch state record")
  1091  	}
  1092  	approved := msg.LatestStateApproved
  1093  	validated := state.PrevStateID()
  1094  	if !approved.Equal(validated) && approved != nil && validated != nil {
  1095  		return &reply.NotOK{}, nil
  1096  	}
  1097  
  1098  	return &reply.OK{}, nil
  1099  }
  1100  
  1101  func (h *MessageHandler) getCode(ctx context.Context, id *core.RecordID) (*record.CodeRecord, error) {
  1102  	jetID := *jet.NewID(0, nil)
  1103  
  1104  	rec, err := h.ObjectStorage.GetRecord(ctx, jetID, id)
  1105  	if err != nil {
  1106  		return nil, err
  1107  	}
  1108  	codeRec, ok := rec.(*record.CodeRecord)
  1109  	if !ok {
  1110  		return nil, errors.Wrap(ErrInvalidRef, "failed to retrieve code record")
  1111  	}
  1112  
  1113  	return codeRec, nil
  1114  }
  1115  
  1116  func validateState(old record.State, new record.State) error {
  1117  	if old == record.StateDeactivation {
  1118  		return ErrObjectDeactivated
  1119  	}
  1120  	if old == record.StateUndefined && new != record.StateActivation {
  1121  		return errors.New("object is not activated")
  1122  	}
  1123  	if old != record.StateUndefined && new == record.StateActivation {
  1124  		return errors.New("object is already activated")
  1125  	}
  1126  	return nil
  1127  }
  1128  
  1129  func (h *MessageHandler) saveIndexFromHeavy(
  1130  	ctx context.Context, jetID core.RecordID, obj core.RecordRef, heavy *core.RecordRef,
  1131  ) (*index.ObjectLifeline, error) {
  1132  	genericReply, err := h.Bus.Send(ctx, &message.GetObjectIndex{
  1133  		Object: obj,
  1134  	}, &core.MessageSendOptions{
  1135  		Receiver: heavy,
  1136  	})
  1137  	if err != nil {
  1138  		return nil, errors.Wrap(err, "failed to send")
  1139  	}
  1140  	rep, ok := genericReply.(*reply.ObjectIndex)
  1141  	if !ok {
  1142  		return nil, fmt.Errorf("failed to fetch object index: unexpected reply type %T (reply=%+v)", genericReply, genericReply)
  1143  	}
  1144  	idx, err := index.DecodeObjectLifeline(rep.Index)
  1145  	if err != nil {
  1146  		return nil, errors.Wrap(err, "failed to decode")
  1147  	}
  1148  
  1149  	err = h.ObjectStorage.SetObjectIndex(ctx, jetID, obj.Record(), idx)
  1150  	if err != nil {
  1151  		return nil, errors.Wrap(err, "failed to save")
  1152  	}
  1153  	return idx, nil
  1154  }
  1155  
  1156  func (h *MessageHandler) fetchObject(
  1157  	ctx context.Context, obj core.RecordRef, node core.RecordRef, stateID *core.RecordID,
  1158  ) (*reply.Object, error) {
  1159  	sender := BuildSender(
  1160  		h.Bus.Send,
  1161  		followRedirectSender(h.Bus),
  1162  		retryJetSender(h.JetStorage),
  1163  	)
  1164  	genericReply, err := sender(
  1165  		ctx,
  1166  		&message.GetObject{
  1167  			Head:     obj,
  1168  			Approved: false,
  1169  			State:    stateID,
  1170  		},
  1171  		&core.MessageSendOptions{
  1172  			Receiver: &node,
  1173  			Token:    &delegationtoken.GetObjectRedirectToken{},
  1174  		},
  1175  	)
  1176  	if err != nil {
  1177  		return nil, errors.Wrap(err, "failed to fetch object state")
  1178  	}
  1179  	if rep, ok := genericReply.(*reply.Error); ok {
  1180  		return nil, rep.Error()
  1181  	}
  1182  
  1183  	rep, ok := genericReply.(*reply.Object)
  1184  	if !ok {
  1185  		return nil, fmt.Errorf("failed to fetch object state: unexpected reply type %T (reply=%+v)", genericReply, genericReply)
  1186  	}
  1187  	return rep, nil
  1188  }
  1189  
  1190  func (h *MessageHandler) handleHotRecords(ctx context.Context, parcel core.Parcel) (core.Reply, error) {
  1191  	if h.isHeavy {
  1192  		return nil, errors.New("heavy updates are forbidden")
  1193  	}
  1194  
  1195  	logger := inslogger.FromContext(ctx)
  1196  
  1197  	msg := parcel.Message().(*message.HotData)
  1198  	// FIXME: check split signatures.
  1199  	jetID := *msg.Jet.Record()
  1200  
  1201  	logger.WithFields(map[string]interface{}{
  1202  		"jet": jetID.DebugString(),
  1203  	}).Info("received hot data")
  1204  
  1205  	err := h.DropStorage.SetDrop(ctx, msg.DropJet, &msg.Drop)
  1206  	if err == storage.ErrOverride {
  1207  		err = nil
  1208  	}
  1209  	if err != nil {
  1210  		return nil, errors.Wrapf(err, "[jet]: drop error (pulse: %v)", msg.Drop.Pulse)
  1211  	}
  1212  
  1213  	err = h.DropStorage.SetDropSizeHistory(ctx, msg.DropJet, msg.JetDropSizeHistory)
  1214  	if err != nil {
  1215  		return nil, errors.Wrap(err, "[ handleHotRecords ] Can't SetDropSizeHistory")
  1216  	}
  1217  
  1218  	pendingStorage := h.RecentStorageProvider.GetPendingStorage(ctx, jetID)
  1219  	logger.Debugf("received %d pending requests", len(msg.PendingRequests))
  1220  
  1221  	var notificationList []core.RecordID
  1222  	for objID, objContext := range msg.PendingRequests {
  1223  		if !objContext.Active {
  1224  			notificationList = append(notificationList, objID)
  1225  		}
  1226  
  1227  		objContext.Active = false
  1228  		pendingStorage.SetContextToObject(ctx, objID, objContext)
  1229  	}
  1230  
  1231  	go func() {
  1232  		for _, objID := range notificationList {
  1233  			go func(objID core.RecordID) {
  1234  				rep, err := h.Bus.Send(ctx, &message.AbandonedRequestsNotification{
  1235  					Object: objID,
  1236  				}, nil)
  1237  
  1238  				if err != nil {
  1239  					logger.Error("failed to notify about pending requests")
  1240  					return
  1241  				}
  1242  				if _, ok := rep.(*reply.OK); !ok {
  1243  					logger.Error("received unexpected reply on pending notification")
  1244  				}
  1245  			}(objID)
  1246  		}
  1247  	}()
  1248  
  1249  	indexStorage := h.RecentStorageProvider.GetIndexStorage(ctx, jetID)
  1250  	for id, meta := range msg.RecentObjects {
  1251  		decodedIndex, err := index.DecodeObjectLifeline(meta.Index)
  1252  		if err != nil {
  1253  			logger.Error(err)
  1254  			continue
  1255  		}
  1256  
  1257  		err = h.ObjectStorage.SetObjectIndex(ctx, jetID, &id, decodedIndex)
  1258  		if err != nil {
  1259  			logger.Error(err)
  1260  			continue
  1261  		}
  1262  
  1263  		indexStorage.AddObjectWithTLL(ctx, id, meta.TTL)
  1264  	}
  1265  
  1266  	h.JetStorage.UpdateJetTree(
  1267  		ctx, msg.PulseNumber, true, jetID,
  1268  	)
  1269  
  1270  	h.jetTreeUpdater.releaseJet(ctx, jetID, msg.PulseNumber)
  1271  
  1272  	err = h.JetStorage.AddJets(ctx, jetID)
  1273  	if err != nil {
  1274  		logger.Error(errors.Wrap(err, "couldn't add jet"))
  1275  		return nil, err
  1276  	}
  1277  
  1278  	return &reply.OK{}, nil
  1279  }