Example #1
0
func TestClientHandling(t *testing.T) {
	conf := config.New()
	conf.ConfigPath = "../test/testconfig.conf"
	conf.MappingPath = "../test/testmapping.json"
	mapp, err := conf.Load()
	if err != nil {
		t.Error("Expected config loading without error, got", err.Error())
	}
	channel := make(chan Record, conf.Connections)
	repository := storage.New(conf, mapp)
	go ProcessClient(channel, repository)

	// make pipe connections for testing
	// connIn will ready to write into by function ProcessClient
	connIn, connOut := net.Pipe()
	defer connIn.Close()
	defer connOut.Close()
	newClient := Record{Conn: connIn}

	// prepare query for ProcessClient
	newClient.Query = []byte("google.com")

	// send it into channel
	channel <- newClient

	// just read answer from channel pipe
	buffer := make([]byte, 256)
	numBytes, err := connOut.Read(buffer)
	if err != nil {
		t.Error("Network communication error", err.Error())
	}
	if numBytes == 0 || len(buffer) == 0 {
		t.Error("Expexted some data read, got", string(buffer))
	}
	partAnswer := "Updated Date: 2014-05-19T04:00:17Z"
	if !strings.Contains(string(buffer), partAnswer) {
		t.Error("Expexted that contains", partAnswer, ", got", string(buffer))
	}
}
Example #2
0
// Run or manage the service
func (service *Record) Run() (string, error) {

	// if received any kind of command, do it
	if len(os.Args) > 1 {
		command := os.Args[1]
		switch command {
		case "install":
			return service.Install()
		case "remove":
			return service.Remove()
		case "start":
			return service.Start()
		case "stop":
			return service.Stop()
		case "status":
			return service.Status()
		}
	}

	// Load configuration and get mapping
	mapp, err := service.Config.Load()
	if err != nil {
		return "Loading mapping file was unsuccessful", err
	}

	// Logs for what is host&port used
	serviceHostPort := fmt.Sprintf("%s:%d", service.Config.Host, service.Config.Port)
	log.Printf("%s started on %s\n", service.Name, serviceHostPort)
	log.Printf("Used storage %s on %s:%d\n",
		service.Config.Storage.StorageType,
		service.Config.Storage.Host,
		service.Config.Storage.Port,
	)

	// Set up listener for defined host and port
	listener, err := net.Listen("tcp", serviceHostPort)
	if err != nil {
		return "Possibly was a problem with the port binding", err
	}

	// set up channel to collect client queries
	channel := make(chan client.Record, service.Config.Connections)

	// set up current storage
	repository := storage.New(service.Config, mapp)

	// init workers
	for i := 0; i < service.Config.Workers; i++ {
		go client.ProcessClient(channel, repository)
	}

	// This block is for testing purpose only
	if service.Config.TestMode == true {
		// make pipe connections for testing
		// connIn will ready to write into by function ProcessClient
		connIn, connOut := net.Pipe()
		defer connIn.Close()
		defer connOut.Close()
		newClient := client.Record{Conn: connIn}

		// prepare query for ProcessClient
		newClient.Query = []byte(service.Config.TestQuery)

		// send it into channel
		channel <- newClient
		// just read answer from channel pipe
		buffer := make([]byte, 4096)
		numBytes, err := connOut.Read(buffer)
		log.Println("Read bytes:", numBytes)
		return string(buffer), err
	}

	// Set up channel on which to send signal notifications.
	// We must use a buffered channel or risk missing the signal
	// if we're not ready to receive when the signal is sent.
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM)

	// set up channel on which to send accepted connections
	listen := make(chan net.Conn, service.Config.Connections)
	go acceptConnection(listener, listen)

	// loop work cycle with accept connections or interrupt
	// by system signal
	for {
		select {
		case conn := <-listen:
			newClient := client.Record{Conn: conn}
			go newClient.HandleClient(channel)
		case killSignal := <-interrupt:
			log.Println("Got signal:", killSignal)
			log.Println("Stoping listening on ", listener.Addr())
			listener.Close()
			if killSignal == os.Interrupt {
				return "Daemon was interruped by system signal", nil
			}
			return "Daemon was killed", nil
		}
	}

	// never happen, but need to complete code
	return "If you see that, you are lucky bastard", nil
}