コード例 #1
0
ファイル: instance.go プロジェクト: subnr01/epaxos
// 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("")
	}
}
コード例 #2
0
ファイル: instance.go プロジェクト: subnr01/epaxos
// 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("")
	}
}
コード例 #3
0
ファイル: instance.go プロジェクト: subnr01/epaxos
// 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("")
	}
}
コード例 #4
0
ファイル: instance.go プロジェクト: subnr01/epaxos
// 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("")
	}
}