예제 #1
0
파일: service.go 프로젝트: gtfierro/giles2
func NewHandler(a *giles.Archiver, config *giles.BOSSWAVE) *BOSSWaveHandler {
	bwh := &BOSSWaveHandler{
		a:         a,
		bw:        bw.ConnectOrExit(config.Address),
		namespace: config.Namespace,
		stop:      make(chan bool),
		requests:  make(map[string]*ArchiveRequest),
	}
	bwh.bw.OverrideAutoChainTo(true)
	bwh.vk = bwh.bw.SetEntityFileOrExit(config.Entityfile)
	bwh.svc = bwh.bw.RegisterService(bwh.namespace, "s.giles")
	bwh.iface = bwh.svc.RegisterInterface("0", "i.archiver")
	queryChan, err := bwh.bw.Subscribe(&bw.SubscribeParams{
		URI: bwh.iface.SlotURI("query"),
	})
	if err != nil {
		log.Error(errors.Wrap(err, "Could not subscribe"))
	}
	log.Noticef("Listening on %s", bwh.iface.SlotURI("query"))
	log.Noticef("Listening on %s", bwh.iface.SlotURI("subscribe"))
	util.NewWorkerPool(queryChan, bwh.listenQueries, 1000).Start()

	bwh.iface.SubscribeSlot("subscribe", bwh.listenCQBS)

	v, e := views.CreateView(bwh.bw, views.Expression{
		NamespaceList: config.ListenNS,
		N:             &views.EqualsNode{Key: views.String("giles")},
	})
	if e != nil {
		log.Error(errors.Wrap(e, "Could not create view"))
	}

	go func() {
		for msg := range v.Subscribe() {
			go bwh.handleArchiveRequest(msg)
		}
	}()

	return bwh
}
예제 #2
0
파일: archive.go 프로젝트: gtfierro/giles2
func (uri *URIArchiver) Listen(a *giles.Archiver) {
	util.NewWorkerPool(uri.metadataChan, func(msg *bw.SimpleMessage) { a.AddData(uri.GetMetadata(msg)) }, 1000).Start()
	for msg := range uri.subscription {
		for _, po := range msg.POs {
			if !po.IsType(uri.PO, uri.PO) {
				continue
			}
			// for each of the major types, unmarshal it into some generic type
			// and apply the object builder stuff.
			// For now, assume it is msgpack
			var thing interface{}
			err := po.(bw.MsgPackPayloadObject).ValueInto(&thing)
			if err != nil {
				log.Error(errors.Wrap(err, "Could not unmarshal msgpack object"))
			}
			err = a.AddData(uri.GetSmapMessage(thing))
			if err != nil {
				log.Error(errors.Wrap(err, "Could not add data"))
			}
		}
	}
}
예제 #3
0
파일: manager.go 프로젝트: gtfierro/giles2
func (vm *ViewManager) subscribeNamespaces(expr Expression) {
	var (
		persistedMetadata chan *bw.SimpleMessage
	)
	for _, namespace := range expr.NamespaceList {
		// canonicalize the namespace
		uri := strings.TrimSuffix(namespace, "/") + "/*/!meta/+"
		// check if we are already subscribed to the namespace
		vm.nsL.RLock()
		_, found := vm.namespaceSubscriptions[namespace]
		vm.nsL.RUnlock()
		if found {
			continue
		}

		// if we are not subscribed to the namespace, we need to resolve the namespace into
		// its actual VK, because that is what will be in the URIs we receive on subscriptions.
		// We may actually end up getting the naked VK in the namespace, but it is more likely
		// that we will receive an alias which we will have to resolve.

		// resolve namespace
		ro, _, err := vm.client.ResolveRegistry(namespace)
		if err != nil {
			log.Fatal(errors.Wrapf(err, "Could not resolve namespace %s", namespace))
		}
		// OKAY so the issue here is that bw2's objects package is vendored, and runs into
		// conflict when used with the bw2bind package. So, we cannot import the objects
		// package. We only need the objects package to get the *objects.Entity object from
		// the RoutingObject interface we get from calling ResolveRegistry. The reason why we
		// need an Entity object is so we can call its GetVK() method to get the namespace VK
		// that is mapped to by the alias we threw into ResolveRegistry.
		// Because the underlying object actually is an entity object, we can use the reflect
		// package to just call the method directly without having to import the objects
		// package to do the type conversion (e.g. ro.(*object.Entity).GetVK()).
		// The rest is just reflection crap: call the method using f.Call() using []reflect.Value
		// to indicate an empty arguments list. We use [0] to get the first (and only) result,
		// and call .Bytes() to return the underlying byte array returned by GetVK(). We
		// then interpret it using base64 urlsafe encoding to get the string value.
		f := reflect.ValueOf(ro).MethodByName("GetVK")
		nsvk := base64.URLEncoding.EncodeToString(f.Call([]reflect.Value{})[0].Bytes())
		vm.namespaceAliases[namespace] = nsvk
		log.Noticef("Resolved alias %s -> %s", namespace, nsvk)
		log.Noticef("Subscribe to %s", uri)

		// subscribe to all !meta tags on that namespace
		vm.namespaceSubscriptions[namespace], err = vm.client.Subscribe(&bw.SubscribeParams{
			URI: uri,
		})
		if err != nil {
			log.Fatal(errors.Wrapf(err, "Could not subscribe to namespace %s", uri))
		}
		log.Debugf("Subscribed to namespace %s", uri)
		// handle the subscriptions
		sub := vm.namespaceSubscriptions[namespace]
		util.NewWorkerPool(sub, func(msg *bw.SimpleMessage) {
			for _, rec := range GetRecords(msg) {
				if err := vm.db.Insert(rec); err != nil {
					log.Error(errors.Wrap(err, "Could not insert record"))
				}
			}
			vm.checkViews()
		}, 1000).Start()
		// Subscriptions only give us metadata messages that appear AFTER the subscription begins,
		// so we execute a query to get all metadata messages that were there already
		persistedMetadata, err = vm.client.Query(&bw.QueryParams{
			URI: uri,
		})
		if err != nil {
			log.Fatal(errors.Wrapf(err, "Could not query namespace %s", uri))
		}
		util.NewWorkerPool(persistedMetadata, func(msg *bw.SimpleMessage) {
			for _, rec := range GetRecords(msg) {
				if err := vm.db.Insert(rec); err != nil {
					log.Error(errors.Wrap(err, "Could not insert record"))
				}
			}
			vm.checkViews()
		}, 1000).Start()
	}
}