Exemplo n.º 1
0
func MaybeCreateRoot(topology *server.Topology, conns map[common.RMId]paxos.Connection, cm *ConnectionManager, lc *client.LocalConnection) error {
	if topology.RootVarUUId != nil {
		return nil
	}
	requiredKnownRMs := int(topology.TwoFInc)
	if len(topology.AllRMs) < requiredKnownRMs {
		return nil
	}
	activeRMs := make([]common.RMId, 0, int(topology.FInc))
	passiveRMs := make([]common.RMId, 0, int(topology.F))
	for _, rmId := range topology.AllRMs[:requiredKnownRMs] {
		if _, found := conns[rmId]; found && len(activeRMs) < cap(activeRMs) {
			activeRMs = append(activeRMs, rmId)
		} else {
			passiveRMs = append(passiveRMs, rmId)
		}
	}
	if len(activeRMs) < cap(activeRMs) {
		return nil
	}

	server.Log("Creating Root. Actives:", activeRMs, "; Passives:", passiveRMs)
	for {
		seg := capn.NewBuffer(nil)
		txn := msgs.NewTxn(seg)
		txn.SetSubmitter(uint32(cm.RMId))
		txn.SetSubmitterBootCount(cm.BootCount)
		actions := msgs.NewActionList(seg, 1)
		txn.SetActions(actions)
		action := actions.At(0)
		vUUId := lc.NextVarUUId()
		action.SetVarId(vUUId[:])
		action.SetCreate()
		create := action.Create()
		positions := seg.NewUInt8List(int(topology.MaxRMCount))
		create.SetPositions(positions)
		for idx, l := 0, positions.Len(); idx < l; idx++ {
			positions.Set(idx, uint8(idx))
		}
		create.SetValue([]byte{})
		create.SetReferences(msgs.NewVarIdPosList(seg, 0))
		allocs := msgs.NewAllocationList(seg, requiredKnownRMs)
		txn.SetAllocations(allocs)
		idx := 0
		for listIdx, rmIds := range [][]common.RMId{activeRMs, passiveRMs} {
			for _, rmId := range rmIds {
				alloc := allocs.At(idx)
				idx++
				alloc.SetRmId(uint32(rmId))
				if listIdx == 0 {
					alloc.SetActive(conns[rmId].BootCount())
				} else {
					alloc.SetActive(0)
				}
				indices := seg.NewUInt16List(1)
				alloc.SetActionIndices(indices)
				indices.Set(0, 0)
			}
		}
		txn.SetFInc(topology.FInc)
		txn.SetTopologyVersion(topology.Version)
		result, err := lc.RunTransaction(&txn, true, activeRMs...)
		if err != nil {
			return err
		}
		if result == nil {
			return nil
		}
		if result.Which() == msgs.OUTCOME_COMMIT {
			server.Log("Root created in", vUUId)
			topology.RootVarUUId = vUUId
			topology.RootPositions = (*common.Positions)(&positions)
			return nil
		}
		abort := result.Abort()
		if abort.Which() == msgs.OUTCOMEABORT_RESUBMIT {
			continue
		}
		return fmt.Errorf("Internal error: creation of root gave rerun outcome")
	}
}