Ejemplo n.º 1
0
func AddSelfToTopology(cm *ConnectionManager, conns map[common.RMId]paxos.Connection, topology *server.Topology, fInc int, active, passive []common.RMId, lc *client.LocalConnection) (*server.Topology, bool, error) {
	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)
	topologyAction := actions.At(0)
	topologyAction.SetVarId(server.TopologyVarUUId[:])
	topologyAction.SetReadwrite()
	rw := topologyAction.Readwrite()
	rw.SetVersion(topology.DBVersion[:])
	rw.SetValue(topology.Serialize())
	if topology.RootVarUUId == nil {
		rw.SetReferences(msgs.NewVarIdPosList(seg, 0))
	} else {
		refs := msgs.NewVarIdPosList(seg, 1)
		rw.SetReferences(refs)
		varIdPos := refs.At(0)
		varIdPos.SetId(topology.RootVarUUId[:])
		varIdPos.SetPositions((capn.UInt8List)(*topology.RootPositions))
	}

	allocs := msgs.NewAllocationList(seg, len(topology.AllRMs))
	txn.SetAllocations(allocs)
	idx := 0
	for listIdx, rmIds := range [][]common.RMId{active, passive} {
		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(uint8(fInc))
	txn.SetTopologyVersion(topology.Version)

	result, err := lc.RunTransaction(&txn, true, active...)
	if err != nil || result == nil {
		return nil, false, err
	}
	txnId := common.MakeTxnId(result.Txn().Id())
	if result.Which() == msgs.OUTCOME_COMMIT {
		topology.DBVersion = txnId
		server.Log("Topology Txn Committed ok with txnId", topology.DBVersion)
		return topology, false, nil
	}
	abort := result.Abort()
	server.Log("Topology Txn Aborted", txnId)
	if abort.Which() == msgs.OUTCOMEABORT_RESUBMIT {
		return nil, true, nil
	}
	abortUpdates := abort.Rerun()
	if abortUpdates.Len() != 1 {
		return nil, false, fmt.Errorf("Internal error: readwrite of topology gave %v updates (1 expected)", abortUpdates.Len())
	}
	update := abortUpdates.At(0)
	dbversion := common.MakeTxnId(update.TxnId())

	updateActions := update.Actions()
	if updateActions.Len() != 1 && updateActions.Len() != 2 {
		return nil, false, fmt.Errorf("Internal error: readwrite of topology gave multiple actions: %v", updateActions.Len())
	}
	var updateAction *msgs.Action
	for idx, l := 0, updateActions.Len(); idx < l; idx++ {
		action := updateActions.At(idx)
		if bytes.Equal(action.VarId(), server.TopologyVarUUId[:]) {
			updateAction = &action
			break
		}
	}

	if updateAction == nil {
		return nil, false, fmt.Errorf("Internal error: unable to find action for topology from readwrite")
	}
	if updateAction.Which() != msgs.ACTION_WRITE {
		return nil, false, fmt.Errorf("Internal error: readwrite of topology gave non-write action")
	}
	write := updateAction.Write()
	var rootVarPos *msgs.VarIdPos
	if refs := write.References(); refs.Len() == 1 {
		root := refs.At(0)
		rootVarPos = &root
	} else if refs.Len() > 1 {
		return nil, false, fmt.Errorf("Internal error: readwrite of topology had wrong references: %v", refs.Len())
	}
	topology, err = server.TopologyDeserialize(dbversion, rootVarPos, write.Value())
	if err != nil {
		return nil, false, err
	}
	found := false
	for _, rmId := range topology.AllRMs {
		if found = rmId == cm.RMId; found {
			server.Log("Topology Txn Aborted, but found self in topology.")
			return topology, false, nil
		}
	}
	return topology, true, nil
}
Ejemplo n.º 2
0
func GetTopologyFromLocalDatabase(cm *ConnectionManager, varDispatcher *eng.VarDispatcher, lc *client.LocalConnection) (*server.Topology, error) {
	if paxos.IsDatabaseClean(varDispatcher) {
		return nil, nil
	}

	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)
		action.SetVarId(server.TopologyVarUUId[:])
		action.SetRead()
		action.Read().SetVersion(common.VersionZero[:])
		allocs := msgs.NewAllocationList(seg, 1)
		txn.SetAllocations(allocs)
		alloc := allocs.At(0)
		alloc.SetRmId(uint32(cm.RMId))
		alloc.SetActive(cm.BootCount)
		indices := seg.NewUInt16List(1)
		alloc.SetActionIndices(indices)
		indices.Set(0, 0)
		txn.SetFInc(1)
		txn.SetTopologyVersion(0)

		result, err := lc.RunTransaction(&txn, true, cm.RMId)
		if err != nil {
			return nil, err
		}
		if result == nil {
			return nil, nil // shutting down
		}
		if result.Which() == msgs.OUTCOME_COMMIT {
			return nil, fmt.Errorf("Internal error: read of topology version 0 failed to abort")
		}
		abort := result.Abort()
		if abort.Which() == msgs.OUTCOMEABORT_RESUBMIT {
			continue
		}
		abortUpdates := abort.Rerun()
		if abortUpdates.Len() != 1 {
			return nil, fmt.Errorf("Internal error: read of topology version 0 gave multiple updates")
		}
		update := abortUpdates.At(0)
		dbversion := common.MakeTxnId(update.TxnId())
		updateActions := update.Actions()
		if updateActions.Len() != 1 && updateActions.Len() != 2 {
			return nil, fmt.Errorf("Internal error: read of topology version 0 gave multiple actions: %v", updateActions.Len())
		}
		var updateAction *msgs.Action
		for idx, l := 0, updateActions.Len(); idx < l; idx++ {
			action := updateActions.At(idx)
			if bytes.Equal(action.VarId(), server.TopologyVarUUId[:]) {
				updateAction = &action
				break
			}
		}
		if updateAction == nil {
			return nil, fmt.Errorf("Internal error: unable to find action for topology from read of topology version 0")
		}
		if updateAction.Which() != msgs.ACTION_WRITE {
			return nil, fmt.Errorf("Internal error: read of topology version 0 gave non-write action")
		}
		write := updateAction.Write()
		var rootPtr *msgs.VarIdPos
		if refs := write.References(); refs.Len() == 1 {
			root := refs.At(0)
			rootPtr = &root
		}
		return server.TopologyDeserialize(dbversion, rootPtr, write.Value())
	}
}
Ejemplo n.º 3
0
func (s *server) start() {
	procs := runtime.NumCPU()
	if procs < 2 {
		procs = 2
	}
	runtime.GOMAXPROCS(procs)

	disk, err := mdbs.NewMDBServer(s.dataDir, mdb.WRITEMAP, 0600, goshawk.OneTB, procs/2, time.Millisecond, db.DB)
	s.maybeShutdown(err)
	s.addOnShutdown(disk.Shutdown)

	cm, lc := network.NewConnectionManager(s.rmId, s.bootCount, procs, disk, s.passwordHash)
	s.connectionManager = cm
	s.addOnShutdown(cm.Shutdown)
	s.addOnShutdown(lc.Shutdown)

	s.Add(1)
	go s.signalHandler()

	topologyLocal, err := network.GetTopologyFromLocalDatabase(cm, cm.Dispatchers.VarDispatcher, lc)
	s.maybeShutdown(err)

	topology, err := s.chooseTopology(topologyLocal)
	s.maybeShutdown(err)

	if topologyLocal == nil {
		topologyTxnId, err := network.CreateTopologyZero(cm, topology, lc)
		s.maybeShutdown(err)
		topology.DBVersion = topologyTxnId
	}

	cm.SetTopology(topology)

	cm.Dispatchers.VarDispatcher.ApplyToVar(func(v *eng.Var, err error) {
		if err != nil {
			log.Println("Error trying to subscribe to topology:", err)
			return
		}
		emptyTxnId := common.MakeTxnId([]byte{})
		v.AddWriteSubscriber(emptyTxnId,
			func(v *eng.Var, value []byte, refs *msgs.VarIdPos_List, txn *eng.Txn) {
				var rootVarPosPtr *msgs.VarIdPos
				if refs.Len() == 1 {
					root := refs.At(0)
					rootVarPosPtr = &root
				}
				topology, err := goshawk.TopologyDeserialize(txn.Id, rootVarPosPtr, value)
				if err != nil {
					log.Println("Unable to deserialize new topology:", err)
				}
				cm.SetTopology(topology)
				disk.WithEnv(func(env *mdb.Env) (interface{}, error) {
					return nil, env.SetFlags(mdb.MAPASYNC, topology.AsyncFlush)
				})
			})
	}, false, goshawk.TopologyVarUUId)

	cm.AddSender(network.NewTopologyWriter(topology, lc, cm))

	localHost, remoteHosts, err := topology.LocalRemoteHosts(s.port)
	s.maybeShutdown(err)

	log.Printf(">==> We are %v (%v) <==<\n", localHost, s.rmId)

	listener, err := network.NewListener(s.port, cm)
	s.maybeShutdown(err)
	s.addOnShutdown(listener.Shutdown)

	cm.SetDesiredServers(localHost, remoteHosts)

	defer s.shutdown(nil)
	s.Wait()
}