Пример #1
0
// Start fsm and create new pirates
func Start() {
	listener = make(chan gotocol.Message) // listener for fsm
	if archaius.Conf.Population < 2 {
		log.Fatal("fsm: can't create less than 2 pirates")
	}
	// create map of channels and a name index to select randoml nodes from
	noodles = make(map[string]chan gotocol.Message, archaius.Conf.Population)
	pnames = make([]string, archaius.Conf.Population) // indexable name list
	log.Println("fsm: population", archaius.Conf.Population, "pirates")
	for i := 1; i <= archaius.Conf.Population; i++ {
		name := names.Make(archaius.Conf.Arch, "atlantic", "bermuda", "blackbeard", "pirate", i)
		noodles[name] = make(chan gotocol.Message)
		go pirate.Start(noodles[name])
	}
	i := 0
	msgcount := 1
	start := time.Now()
	for name, noodle := range noodles {
		pnames[i] = name
		i++
		// tell the pirate it's name and how to talk back to it's fsm
		// this must be the first message the pirate sees
		noodle <- gotocol.Message{gotocol.Hello, listener, time.Now(), gotocol.NilContext, name}
		if edda.Logchan != nil {
			// tell the pirate to report itself and new edges to the logger
			noodle <- gotocol.Message{gotocol.Inform, edda.Logchan, time.Now(), gotocol.NilContext, ""}
			msgcount = 2
		}
	}
	log.Println("fsm: Talk amongst yourselves for", archaius.Conf.RunDuration)
	rand.Seed(int64(len(noodles)))
	for _, name := range pnames {
		// for each pirate tell them about two other random pirates
		noodle := noodles[name] // lookup the channel
		// pick a first random pirate to tell this one about
		talkto := pnames[rand.Intn(len(pnames))]
		noodle <- gotocol.Message{gotocol.NameDrop, noodles[talkto], time.Now(), gotocol.NewTrace(), talkto}
		// pick a second random pirate to tell this one about
		talkto = pnames[rand.Intn(len(pnames))]
		noodle <- gotocol.Message{gotocol.NameDrop, noodles[talkto], time.Now(), gotocol.NewTrace(), talkto}
		// anonymously send this pirate a random amount of GoldCoin up to 100
		gold := fmt.Sprintf("%d", rand.Intn(100))
		noodle <- gotocol.Message{gotocol.GoldCoin, nil, time.Now(), gotocol.NewTrace(), gold}
		// tell this pirate to start chatting with friends every 0.1 to 10 secs
		delay := fmt.Sprintf("%dms", 100+rand.Intn(9900))
		noodle <- gotocol.Message{gotocol.Chat, nil, time.Now(), gotocol.NewTrace(), delay}
	}
	msgcount += 4
	d := time.Since(start)
	log.Println("fsm: Delivered", msgcount*len(pnames), "messages in", d)
	shutdown()
}
Пример #2
0
// Reload the network from a file
func Reload(arch string) {
	listener = make(chan gotocol.Message) // listener for fsm
	log.Println("fsm reloading from " + arch + ".json")
	g := graphjson.ReadArch(arch)
	pop := 0
	// count how many nodes there are
	for _, element := range g.Graph {
		if element.Node != "" {
			pop++
		}
	}
	archaius.Conf.Population = pop
	// create the map of channels
	noodles = make(map[string]chan gotocol.Message, archaius.Conf.Population)
	// Start all the services
	for _, element := range g.Graph {
		if element.Node != "" && element.Service != "" {
			name := element.Node
			noodles[name] = make(chan gotocol.Message)
			// start the service and tell it it's name
			switch element.Service {
			case "pirate":
				go pirate.Start(noodles[name])
				noodles[name] <- gotocol.Message{gotocol.Hello, listener, time.Now(), gotocol.NilContext, name}
				if edda.Logchan != nil {
					// tell the pirate to report itself and new edges to the logger
					noodles[name] <- gotocol.Message{gotocol.Inform, edda.Logchan, time.Now(), gotocol.NilContext, ""}
				}
			default:
				log.Println("fsm: unknown service: " + element.Service)
			}
		}
	}
	// Make all the connections
	for _, element := range g.Graph {
		if element.Edge != "" && element.Source != "" && element.Target != "" {
			noodles[element.Source] <- gotocol.Message{gotocol.NameDrop, noodles[element.Target], time.Now(), gotocol.NewTrace(), element.Target}
			log.Println("Link " + element.Source + " > " + element.Target)
		}
	}
	// send money and start the pirates chatting
	for _, noodle := range noodles {
		// same as below for now, but will save and read back from file later
		// anonymously send this pirate a random amount of GoldCoin up to 100
		gold := fmt.Sprintf("%d", rand.Intn(100))
		noodle <- gotocol.Message{gotocol.GoldCoin, nil, time.Now(), gotocol.NewTrace(), gold}
		// tell this pirate to start chatting with friends every 0.1 to 10 secs
		delay := fmt.Sprintf("%dms", 100+rand.Intn(9900))
		noodle <- gotocol.Message{gotocol.Chat, nil, time.Now(), gotocol.NilContext, delay}
	}
	shutdown()
}
Пример #3
0
// Start a node using the named package, and connect it to any dependencies
func StartNode(name string, dependencies ...string) {
	if names.Package(name) == EurekaPkg {
		eurekachan[name] = make(chan gotocol.Message, archaius.Conf.Population/len(archaius.Conf.ZoneNames)) // buffer sized to a zone
		go eureka.Start(eurekachan[name], name)
		return
	} else {
		noodles[name] = make(chan gotocol.Message)
	}
	// start the service and tell it it's name
	switch names.Package(name) {
	case PiratePkg:
		go pirate.Start(noodles[name])
	case ElbPkg:
		go elb.Start(noodles[name])
	case DenominatorPkg:
		go denominator.Start(noodles[name])
	case ZuulPkg:
		go zuul.Start(noodles[name])
	case KaryonPkg:
		go karyon.Start(noodles[name])
	case MonolithPkg:
		go monolith.Start(noodles[name])
	case StaashPkg:
		go staash.Start(noodles[name])
	case RiakPkg:
		fallthrough // fake Riak using priamCassandra
	case PriamCassandraPkg:
		go priamCassandra.Start(noodles[name])
	case CachePkg:
		fallthrough // fake memcache using store
	case VolumePkg:
		fallthrough // fake disk volume using store
	case StorePkg:
		go store.Start(noodles[name])
	default:
		log.Fatal("asgard: unknown package: " + names.Package(name))
	}
	noodles[name] <- gotocol.Message{gotocol.Hello, listener, time.Now(), gotocol.NilContext, name}
	// there is a eureka service registry in each zone, so in-zone services just get to talk to their local registry
	// elb are cross zone, so need to see all registries in a region
	// denominator are cross region so need to see all registries globally
	// priamCassandra depends explicitly on eureka for cross region clusters
	crossregion := false
	for _, d := range dependencies {
		if d == "eureka" {
			crossregion = true
		}
	}
	for n, ch := range eurekachan {
		if names.Region(name) == "*" || crossregion {
			// need to know every eureka in all zones and regions
			gotocol.Send(noodles[name], gotocol.Message{gotocol.Inform, ch, time.Now(), gotocol.NilContext, n})
		} else {
			if names.Zone(name) == "*" && names.Region(name) == names.Region(n) {
				// need every eureka in my region
				gotocol.Send(noodles[name], gotocol.Message{gotocol.Inform, ch, time.Now(), gotocol.NilContext, n})
			} else {
				if names.RegionZone(name) == names.RegionZone(n) {
					// just the eureka in this specific zone
					gotocol.Send(noodles[name], gotocol.Message{gotocol.Inform, ch, time.Now(), gotocol.NilContext, n})
				}
			}
		}
	}
	//log.Println(dependencies)
	// pass on symbolic dependencies without channels that will be looked up in Eureka later
	for _, dep := range dependencies {
		if dep != "" && dep != "eureka" { // ignore special case of eureka in dependency list
			//log.Println(name + " depends on " + dep)
			gotocol.Send(noodles[name], gotocol.Message{gotocol.NameDrop, nil, time.Now(), gotocol.NilContext, dep})
		}
	}
}