예제 #1
0
파일: paxos.go 프로젝트: pombredanne/qlease
func (r *Replica) handleForward(fwd *paxosproto.Forward) {
	if state.IsRead(&fwd.Command) {
		if r.maintainReadStats {
			r.readStats.AddRead(fwd.Command.K, fwd.ReplicaId)
		}
		//make sure that the channel is not going to be full,
		//because this may cause the consumer to block when trying to
		//put request back
		for len(r.fwdReadsChannel) >= READ_CHAN_SIZE-10000 {
			time.Sleep(1000)
		}
		r.fwdReadsChannel <- fwd
	} else {
		// the forward is a write
		r.handlePropose(&genericsmr.Propose{&genericsmrproto.Propose{0, fwd.Command, 0}, fwd.ReplicaId, fwd.PropId, nil, nil})
	}
}
예제 #2
0
파일: paxos.go 프로젝트: pombredanne/qlease
func (r *Replica) handlePropose(propose *genericsmr.Propose) {

	batches := make(map[int64][]state.Command, 10)
	proposals := make(map[int64][]*genericsmr.Propose, 10)

	haveWrites := false

	totalLen := len(r.ProposeChan) + 1

	if totalLen > MAX_BATCH {
		totalLen = MAX_BATCH
	}

	for i := 0; i < totalLen; i++ {
		if state.IsRead(&propose.Command) && (r.IsLeader || r.isKeyGranted(propose.Command.K)) {
			reads++
			//make sure that the channel is not going to be full,
			//because this may cause the consumer to block when trying to
			//put request back
			for len(r.readsChannel) >= READ_CHAN_SIZE-10000 {
				time.Sleep(1000)
			}
			r.readsChannel <- propose
		} else if !r.IsLeader {
			if state.IsRead(&propose.Command) {
				reads++
			}
			r.fwdId++
			r.fwdPropMap[r.fwdId] = propose
			r.SendMsg(r.leaderId, r.forwardRPC, &paxosproto.Forward{r.Id, r.fwdId, propose.Command})
		} else {
			q := quorumToInt64(r.getLeaseQuorumForKey(propose.Command.K, r.Id))
			var cmds []state.Command
			var present bool
			var props []*genericsmr.Propose
			props = proposals[q]
			if cmds, present = batches[q]; !present {
				cmds = make([]state.Command, 0, totalLen/2+1)
				props = make([]*genericsmr.Propose, 0, totalLen/2+1)
			}
			cmds = append(cmds, propose.Command)
			batches[q] = cmds
			props = append(props, propose)
			proposals[q] = props
			haveWrites = true
		}
		if i < totalLen-1 {
			propose = <-r.ProposeChan
		}
	}

	if !haveWrites {
		return
	}

	/*    if !r.IsLeader {
	      preply := &genericsmrproto.ProposeReplyTS{FALSE, -1, state.NIL, 0}
	      r.ReplyProposeTS(preply, propose)
	      return
	  }*/

	for r.instanceSpace[r.crtInstance] != nil {
		r.crtInstance++
	}

	//dlog.Printf("Batched %d\n", batchSize)

	status := PREPARING
	ballot := r.makeUniqueBallot(0)

	if r.defaultBallot > -1 {
		status = PREPARED
		ballot = r.defaultBallot
	}

	for q, cmds := range batches {
		if len(cmds) == 0 {
			continue
		}
		//log.Printf("Batching %d\n", len(cmds))
		props := proposals[q]
		r.instanceSpace[r.crtInstance] = &Instance{
			cmds,
			ballot,
			status,
			&LeaderBookkeeping{props, 0, 0, 0, 0, 0},
			0, false}
		if status == PREPARING {
			r.bcastPrepare(r.crtInstance, ballot, true)
			dlog.Printf("Classic round for instance %d\n", r.crtInstance)
		} else {
			r.recordInstanceMetadata(r.instanceSpace[r.crtInstance])
			r.recordCommands(cmds)
			r.sync()

			if r.crtInstance > r.latestAcceptedInst {
				r.latestAcceptedInst = r.crtInstance
			}

			if props[0].FwdReplica >= 0 && props[0].FwdReplica != r.Id {
				r.addUpdatingKeys(cmds)
			}

			//TODO: make sure it supports Forwards
			r.instanceSpace[r.crtInstance].lb.acceptOKsToWait, _ = r.bcastAccept(r.crtInstance, ballot, cmds, props[0].FwdReplica, props[0].FwdId)
			dlog.Printf("Fast round for instance %d\n", r.crtInstance)
			if genericsmr.SendError {
				log.Println("BCAST ERROR")
				r.delayedInstances <- r.crtInstance
			}
		}
		r.crtInstance++
	}
}