Beispiel #1
0
// committed instance will
// - reject all request messages (pre-accept, accept),
// - handle prepare to help it find committed,
// - ignore others
func (i *Instance) committedProcess(m message.Message) (action uint8, msg message.Message) {
	defer i.checkStatus(committed)

	if !i.isAtStatus(committed) {
		panic("")
	}

	switch content := m.Content().(type) {
	case *message.PreAccept:
		return noAction, nil
	case *message.Accept:
		return noAction, nil
	case *message.Timeout:
		// here we ignore the timeout event instead of panic,
		// because sometimes timeout event
		// comes right after the instance becomes committed
		return noAction, nil
	case *message.Prepare:
		return i.handlePrepare(content)
	case *message.PreAcceptReply, *message.PreAcceptOk, *message.AcceptReply, *message.PrepareReply, *message.Commit:
		return noAction, nil // ignore stale replies
	default:
		panic("")
	}
}
Beispiel #2
0
// preparing instance could only acts as a sender.
// It handles most kinds of messages (in some conditions with larger ballot) and
// ignores all replies except prepare reply.
func (i *Instance) preparingProcess(m message.Message) (action uint8, msg message.Message) {
	defer i.checkStatus(preparing, preAccepted, accepted, committed, nilStatus)

	if !i.isAtStatus(preparing) || i.recoveryInfo == nil {
		panic("")
	}

	switch content := m.Content().(type) {
	case *message.PreAccept:
		if content.Ballot.Compare(i.ballot) < 0 {
			return noAction, nil
		}
		return i.handlePreAccept(content)
	case *message.Accept:
		if content.Ballot.Compare(i.ballot) < 0 {
			return noAction, nil
		}
		return i.handleAccept(content)
	case *message.Commit:
		return i.handleCommit(content)
	case *message.Timeout:
		return i.handleTimeout(content)
	case *message.Prepare:
		// the instance itself is the first one to have ballot of this
		// magnitude. It can't receive others having the same
		if content.Ballot.Compare(i.ballot) == 0 {
			panic("")
		}
		if content.Ballot.Compare(i.ballot) < 0 {
			return noAction, nil
		}
		return i.revertAndHandlePrepare(content)
	case *message.PrepareReply:
		if content.Ballot.Compare(i.ballot) < 0 {
			return noAction, nil
		}
		return i.handlePrepareReply(content)
	case *message.PreAcceptReply:
		if i.recoveryInfo.formerStatus < preAccepted {
			panic("")
		}
		return noAction, nil
	case *message.PreAcceptOk:
		if i.recoveryInfo.formerStatus < preAccepted {
			panic("")
		}
		return noAction, nil
	case *message.AcceptReply:
		if i.recoveryInfo.formerStatus < accepted {
			panic("")
		}
		// ignore delayed replies
		return noAction, nil
	default:
		panic("")
	}
}
Beispiel #3
0
// preaccepted instance
// - handles preaccept-ok/-reply, preaccept, accept, commit, and prepare.
func (i *Instance) preAcceptedProcess(m message.Message) (action uint8, msg message.Message) {
	defer i.checkStatus(preAccepted, accepted, committed, preparing)

	if !i.isAtStatus(preAccepted) {
		panic("")
	}

	switch content := m.Content().(type) {
	case *message.PreAccept:
		if content.Ballot.Compare(i.ballot) < 0 {
			return noAction, nil
		}
		return i.handlePreAccept(content)
	case *message.Accept:
		if content.Ballot.Compare(i.ballot) < 0 {
			return noAction, nil
		}
		return i.handleAccept(content)
	case *message.Commit:
		return i.handleCommit(content)
	case *message.Timeout:
		return i.handleTimeout(content)
	case *message.Prepare:
		if content.Ballot.Compare(i.ballot) < 0 {
			return noAction, nil
		}
		return i.handlePrepare(content)
	case *message.PreAcceptReply:
		if content.Ballot.Compare(i.ballot) < 0 {
			// ignore stale PreAcceptReply
			return noAction, nil
		}
		return i.handlePreAcceptReply(content)
	case *message.PreAcceptOk:
		if !i.ballot.IsInitialBallot() {
			return noAction, nil // ignore stale reply
		}
		return i.handlePreAcceptOk(content)
	case *message.AcceptReply:
		panic("")
	case *message.PrepareReply:
		if i.ballot.IsInitialBallot() {
			panic("")
		}
		return noAction, nil
	default:
		panic("")
	}
}
Beispiel #4
0
// NilStatus exists for:
// - the instance is newly created when
// - - received a proposal first time and only once. (sender)
// - - received pre-accept, accept, commit, prepare the first time. (receiver)
// - - required by commit dependencies and transitioning to preparing. (sender)
// - the instance is not newly created when
// - - after reverted back from `preparing`(sender -> receiver)
// - - received prepare and waiting for further message. (receiver)
func (i *Instance) nilStatusProcess(m message.Message) (action uint8, msg message.Message) {
	defer i.checkStatus(nilStatus, preAccepted, accepted, committed, preparing)

	if !i.isAtStatus(nilStatus) {
		panic("")
	}

	switch content := m.Content().(type) {
	case *message.Propose:
		return i.handlePropose(content)
	case *message.PreAccept:
		if content.Ballot.Compare(i.ballot) < 0 {
			return noAction, nil
		}
		return i.handlePreAccept(content)
	case *message.Accept:
		if content.Ballot.Compare(i.ballot) < 0 {
			// [*] this could happens when the instance revert from preparing
			return noAction, nil
		}
		return i.handleAccept(content)
	case *message.Commit:
		return i.handleCommit(content)
	case *message.Timeout:
		return i.handleTimeout(content)
	case *message.Prepare:
		if content.Ballot.Compare(i.ballot) < 0 {
			return noAction, nil
		}
		return i.handlePrepare(content)
	case *message.PrepareReply:
		if i.isNewBorn() || i.ballot.GetNumber() == 0 {
			panic("Never send prepare before but receive prepare reply")
		}
		return noAction, nil
	case *message.PreAcceptReply, *message.AcceptReply, *message.PreAcceptOk:
		panic("")
	default:
		panic("")
	}
}
Beispiel #5
0
// This function is responsible for communicating with instance processing.
func (r *Replica) dispatch(msg message.Message) {
	replicaId := msg.Replica()
	instanceId := msg.Instance()

	r.updateMaxInstanceNum(replicaId, instanceId)

	v1Log.Infof("Replica[%v]: recv message[%s], from Replica[%v]\n",
		r.Id, msg.String(), msg.Sender())
	if glog.V(0) {
		printDependencies(msg)
	}

	if instanceId <= conflictNotFound {
		panic("")
	}

	if r.InstanceMatrix[replicaId][instanceId] == nil {
		r.InstanceMatrix[replicaId][instanceId] = NewInstance(r, replicaId, instanceId)
		if p, ok := msg.(*message.Propose); ok {
			// send back a signal for this successfully creation
			close(p.Created)
		}
	}

	i := r.InstanceMatrix[replicaId][instanceId]
	i.touch() // update last touched timestamp

	v1Log.Infof("Replica[%v]: instance[%v][%v] status before = %v, ballot = [%v]\n",
		r.Id, replicaId, instanceId, i.StatusString(), i.ballot.String())
	v2Log.Infof("dependencies before: %v\n", i.Dependencies())

	var action uint8
	var rep message.Message

	switch i.status {
	case nilStatus:
		action, rep = i.nilStatusProcess(msg)
	case preAccepted:
		action, rep = i.preAcceptedProcess(msg)
	case accepted:
		action, rep = i.acceptedProcess(msg)
	case committed:
		action, rep = i.committedProcess(msg)
	case preparing:
		action, rep = i.preparingProcess(msg)
	default:
		panic("")
	}

	v2Log.Infof("dependencies after: %v\n", i.Dependencies())
	if action == noAction {
		v1Log.Infof("Replica[%v]: instance[%v][%v] status after = %v, ballot = [%v]\n\n\n",
			r.Id, replicaId, instanceId, i.StatusString(), i.ballot.String())
	} else {
		v1Log.Infof("Replica[%v]: instance[%v][%v] status after = %v, ballot = [%v]\n",
			r.Id, replicaId, instanceId, i.StatusString(), i.ballot.String())
	}

	if r.enablePersistent {
		r.StoreSingleInstance(i)
	}

	switch action {
	case noAction:
		return
	case replyAction:
		v1Log.Infof("Replica[%v]: send message[%s], to Replica[%v]\n\n\n",
			r.Id, rep.String(), msg.Sender())
		r.Transporter.Send(msg.Sender(), rep) // send back to the sender of the message
	case fastQuorumAction:
		v1Log.Infof("Replica[%v]: send message[%s], to FastQuorum\n\n\n",
			r.Id, rep.String())
		r.Transporter.MulticastFastquorum(rep)
	case broadcastAction:
		v1Log.Infof("Replica[%v]: send message[%s], to Everyone\n\n\n",
			r.Id, rep.String())
		r.Transporter.Broadcast(rep)
	default:
		panic("")
	}
}