Пример #1
0
// Dispatch handles all incoming rpc requests for this object.
func (this *Election) Dispatch(header *msgpb.Header, data []byte) error {
	request := header.GetRequest()
	objectID := request.GetObjectId()

	// Dispatch classic paxos rpcs to the paxos instances.
	if objectID != this.uid {
		if this.IsPaxosUID(objectID) {
			return this.DispatchPaxos(header, data)
		}
		this.Errorf("rpc request %s doesn't belong to this instance", header)
		return errs.ErrInvalid
	}

	message := thispb.ElectionMessage{}
	if err := proto.Unmarshal(data, &message); err != nil {
		this.Errorf("could not parse incoming message %s", header)
		return err
	}

	switch {
	case message.ElectRequest != nil:
		return this.ElectRPC(header, message.GetElectRequest())

	case message.StatusRequest != nil:
		return this.StatusRPC(header, message.GetStatusRequest())

	default:
		this.Errorf("unknown/invalid rpc reqest %s", header)
		return errs.ErrInvalid
	}
}
Пример #2
0
// DispatchPaxos handles incoming rpc requests for the paxos instances.
func (this *Election) DispatchPaxos(header *msgpb.Header, data []byte) error {
	request := header.GetRequest()
	objectID := request.GetObjectId()

	instance, errGet := this.GetPaxosInstance(objectID)
	if errGet != nil {
		this.Errorf("could not get paxos instance with object id %s", objectID)
		return errGet
	}

	return instance.Dispatch(header, data)
}
Пример #3
0
Файл: util.go Проект: bvk/ascent
// RequestTimeout returns the pending time left to complete the operations
// represented by the request header. Timeout is measured from the creation
// timestamp if the request header is created locally; otherwise, timeout is
// measured from the time this request is received from the socket (optionally,
// removing any transfer latency if available.)
func RequestTimeout(header *msgpb.Header) time.Duration {
	if header.Request == nil {
		// This is not a request.
		return 0
	}
	start := header.GetCreateTimestampNsecs()
	if header.ReceiverTimestampNsecs != nil {
		start = header.GetReceiverTimestampNsecs()
	}
	request := header.GetRequest()
	timeout := time.Duration(request.GetTimeoutNsecs())
	elapsed := time.Now().UnixNano() - start
	return timeout - time.Duration(elapsed)
}
Пример #4
0
// Dispatch implements the msg.Handler interface for Paxos objects.
//
// header: Message header for an incoming request.
//
// data: User data in the message.
//
// Returns the result of perform the incoming request.
func (this *Paxos) Dispatch(header *msgpb.Header, data []byte) error {
	request := header.GetRequest()
	if request == nil {
		this.Error("rpc message %s is not a request", header)
		return errs.ErrInvalid
	}

	if request.GetObjectId() != this.uid {
		this.Errorf("rpc request [%s] doesn't belong to this paxos instance %s",
			header, this.uid)
		return errs.ErrInvalid
	}

	message := &thispb.PaxosMessage{}
	if err := proto.Unmarshal(data, message); err != nil {
		this.Errorf("could not parse message [%s]: %v", header, err)
		return err
	}

	switch {
	case message.ProposeRequest != nil:
		if !this.IsProposer() {
			return errs.ErrInvalid
		}
		return this.ProposeRPC(header, message.ProposeRequest)

	case message.Phase1Request != nil:
		if !this.IsAcceptor() {
			return errs.ErrInvalid
		}
		return this.Phase1RPC(header, message.Phase1Request)

	case message.Phase2Request != nil:
		if !this.IsAcceptor() {
			return errs.ErrInvalid
		}
		return this.Phase2RPC(header, message.Phase2Request)

	case message.LearnRequest != nil:
		if !this.IsLearner() {
			return errs.ErrInvalid
		}
		return this.LearnRPC(header, message.LearnRequest)

	default:
		this.Errorf("rpc request [%s] has no request parameters", header)
		return errs.ErrInvalid
	}
}
Пример #5
0
// DispatchRequest invokes the target (exported) function identified in the
// request message.
//
// header: Message header for the request.
//
// data: User data in the request.
//
// Returns dispatch operation status and the handler status.
func (this *Messenger) DispatchRequest(header *msgpb.Header,
	data []byte) (msnStatus, appStatus error) {

	defer func() {
		if msnStatus != nil || appStatus != nil {
			failure := this.NewResponse(header)
			if msnStatus != nil {
				failure.Response.MessengerStatus = errs.MakeProtoFromError(msnStatus)
			} else {
				failure.Response.HandlerStatus = errs.MakeProtoFromError(appStatus)
			}

			sourceID := header.GetMessengerId()
			if err := this.Send(sourceID, failure, nil); err != nil {
				this.Errorf("could not reply failure %s for %s from %s (ignored)",
					failure, header, sourceID)
			}
		}
	}()

	lock, errLock := this.ctlr.Lock("this.exportMap")
	if errLock != nil {
		return errLock, nil
	}
	defer lock.Unlock()

	request := header.GetRequest()
	classID := request.GetClassId()
	methodName := request.GetMethodName()
	if len(classID) == 0 || len(methodName) == 0 {
		this.Errorf("header %s is invalid because class id and/or method name "+
			"are empty", header)
		msnStatus = errs.NewErrInvalid("class id and/or method name cannot be " +
			"empty")
		return msnStatus, nil
	}

	methodMap, found := this.exportMap[classID]
	if !found {
		this.Errorf("no class with id %s was registered", classID)
		msnStatus = errs.NewErrNotExist("no class with id %s was registered",
			classID)
		return msnStatus, nil
	}

	handler, found := methodMap[methodName]
	if !found {
		this.Errorf("class %s has no method named %s", classID, methodName)
		msnStatus = errs.NewErrNotExist("class %s has no method named %s", classID,
			methodName)
		return msnStatus, nil
	}

	// Close the lock early to release the resources.
	lock.Unlock()

	appStatus = handler.Dispatch(header, data)
	if appStatus != nil {
		this.Warningf("request %s failed with status %v", header, appStatus)
	}
	return nil, appStatus
}