Ejemplo n.º 1
0
// main entry point for data writer
func main() {
	var err error
	var writerSocket *zmq4.Socket
	var eventSubSocket *zmq4.Socket

	fog.Info("program starts")

	if writerSocket, err = createWriterSocket(); err != nil {
		fog.Critical("createWriterSocket %s", err)
	}
	defer writerSocket.Close()

	fog.Info("binding writer socket to %s", dataWriterAddress)
	if err = writerSocket.Bind(dataWriterAddress); err != nil {
		fog.Critical("Bind(%s) %s", dataWriterAddress, err)
	}

	if eventSubSocket, err = createEventSubSocket(); err != nil {
		fog.Critical("createEventSubSocket %s", err)
	}
	defer eventSubSocket.Close()

	fog.Info("connecting event sub socket to %s", eventAggregatorPubAddress)
	if err = eventSubSocket.Connect(eventAggregatorPubAddress); err != nil {
		fog.Critical("Connect(%s) %s", eventAggregatorPubAddress, err)
	}

	messageChan := NewMessageHandler()

	reactor := zmq4.NewReactor()
	reactor.AddChannel(tools.NewSignalWatcher(), 1, tools.SigtermHandler)
	reactor.AddSocket(writerSocket, zmq4.POLLIN,
		NewWriterSocketHandler(writerSocket, messageChan))
	reactor.AddSocket(eventSubSocket, zmq4.POLLIN,
		NewEventSubSocketHandler(eventSubSocket))

	fog.Debug("starting reactor.Run")
	reactor.SetVerbose(true)
	err = reactor.Run(reactorPollingInterval)
	if err == tools.SigtermError {
		fog.Info("program terminates normally due to SIGTERM")
	} else if errno, ok := err.(syscall.Errno); ok {
		// we can get 'interrupted system call' if we get SIGTERM while
		// a socket is waiting on a read. That's not too bad.
		if errno == syscall.EINTR {
			fog.Warn("reactor.Run returns '%s' assuming SIGTERM", errno)
		} else {
			fog.Error("reactor.Run returns %T '%s'", errno, errno)
		}
	} else {
		fog.Error("reactor.Run returns %T %s", err, err)
	}
}
Ejemplo n.º 2
0
func testPOST(serviceDomain string, useTLS bool) {
	var contentLength uint64 = 1024 * 1024 * 1024
	fog.Debug("start post %dmb", contentLength/(1024*1024))

	client, scheme := getClient(useTLS)

	url := fmt.Sprintf("%s://%s/admin", scheme, serviceDomain)
	bodyReader := tools.NewSizeReader(contentLength)
	request, err := http.NewRequest("POST", url, bodyReader)
	if err != nil {
		fog.Critical("NewRequest (POST) failed %s", err)
	}
	request.TransferEncoding = []string{"identity"}
	request.Header.Add("Content-Type", "text/plain")
	request.Header.Add("Content-Length", fmt.Sprintf("%s", contentLength))
	request.ContentLength = int64(contentLength)
	response, err := client.Do(request)
	if err != nil {
		fog.Error("post %s", err)
		return
	}
	tools.ReadAndDiscard(response.Body)
	response.Body.Close()

	fog.Debug("finished post %s", response.Status)
}
Ejemplo n.º 3
0
// NewEventSubSocketHandler returns a function that handles event notifications
func NewEventSubSocketHandler(eventSubSocket *zmq4.Socket) func(zmq4.State) error {
	var nodeIDMap map[string]uint32
	var err error

	if nodeIDMap, err = centraldb.GetNodeIDMap(); err != nil {
		fog.Critical("centraldb.GetNodeIDMap() failed %s", err)
	}

	return func(_ zmq4.State) error {
		var err error
		var ok bool
		var webWriterStart msg.WebWriterStart
		var timestamp time.Time
		var sourceNodeID uint32

		marshalledMessage, err := eventSubSocket.RecvMessage(0)
		if err != nil {
			return fmt.Errorf("RecvMessage %s", err)
		}

		// the 0th part should be the topic, we skip that

		err = json.Unmarshal([]byte(marshalledMessage[1]), &webWriterStart)
		if err != nil {
			return fmt.Errorf("Unmarshal %s", err)
		}

		if webWriterStart.MessageType != "web-writer-start" {
			return fmt.Errorf("unknown message type '%s'",
				webWriterStart.MessageType)
		}

		timestamp, err = tools.ParseTimestampRepr(webWriterStart.TimestampRepr)
		if err != nil {
			return fmt.Errorf("unable to parse %s %s",
				webWriterStart.TimestampRepr, err)
		}

		sourceNodeID, ok = nodeIDMap[webWriterStart.SourceNodeName]
		if !ok {
			return fmt.Errorf("unknown source_node_name %s",
				webWriterStart.SourceNodeName)
		}

		fog.Debug("cancel-segments-from-node %s", webWriterStart.SourceNodeName)

		// cancel all all segment rows
		//    * from a specifiic source node
		//    * are in active status
		//    * with a timestamp earlier than the specified time.
		// This is triggered by a web server restart
		stmt := nodedb.Stmts["cancel-segments-from-node"]
		if _, err = stmt.Exec(sourceNodeID, timestamp); err != nil {
			return fmt.Errorf("cancel-segments-from-node %s", err)
		}

		return nil
	}
}
Ejemplo n.º 4
0
func NewMessageHandler() chan<- types.Message {
	var nimbusioWriter writer.NimbusioWriter
	var replyChan chan<- *reply.ReplyMessage
	var err error

	messageChan := make(chan types.Message, messageChanCapacity)

	if err = nodedb.Initialize(); err != nil {
		fog.Critical("NewMessageHandler: nodedb.Initialize failed %s", err)
	}

	if nimbusioWriter, err = writer.NewNimbusioWriter(); err != nil {
		fog.Critical("NewMessageHandler: NewNimbusioWriter() failed %s", err)
	}

	replyChan = reply.NewReplyHandler()

	dispatchTable := map[string]messageHandler{
		"archive-key-entire":       handleArchiveKeyEntire,
		"archive-key-start":        handleArchiveKeyStart,
		"archive-key-next":         handleArchiveKeyNext,
		"archive-key-final":        handleArchiveKeyFinal,
		"archive-key-cancel":       handleArchiveKeyCancel,
		"destroy-key":              handleDestroyKey,
		"start-conjoined-archive":  handleStartConjoinedArchive,
		"abort-conjoined-archive":  handleAbortConjoinedArchive,
		"finish-conjoined-archive": handleFinishConjoinedArchive}

	go func() {
		for message := range messageChan {
			handler, ok := dispatchTable[message.Type]
			if !ok {
				fog.Error("Unknown message type %s %s",
					message.Type, message.Marshalled)
				continue
			}
			go handler(message, nimbusioWriter, replyChan)
		}
	}()

	return messageChan
}
Ejemplo n.º 5
0
func init() {
	destHashKey = make([]byte, keySize)

	keyPath := os.Getenv("NIMBUSIO_URL_DEST_HASH_KEY")
	if keyPath != "" {
		file, err := os.Open(keyPath)
		if err != nil {
			fog.Critical("No valid file at NIMBUSIO_URL_DEST_HASH_KEY %s %s",
				keyPath, err)
		}
		defer file.Close()
		_, err = file.Read(destHashKey)
		if err != nil {
			fog.Critical("Error reading file at NIMBUSIO_URL_DEST_HASH_KEY %s %s",
				keyPath, err)
		}
	} else {
		_, err := rand.Read(destHashKey)
		if err != nil {
			fog.Critical("Error reading destHashKey rand.Read %s", err)
		}
	}
}
Ejemplo n.º 6
0
func init() {
	maxValueFileSizeStr := os.Getenv("NIMBUS_IO_MAX_VALUE_FILE_SIZE")
	if maxValueFileSizeStr == "" {
		MaxValueFileSize = uint64(1024 * 1024 * 1024)
	} else {
		var intSize int
		var err error
		intSize, err = strconv.Atoi(maxValueFileSizeStr)
		if err != nil {
			fog.Critical("invalid NIMBUS_IO_MAX_VALUE_FILE_SIZE '%s'",
				maxValueFileSizeStr)
		}
		MaxValueFileSize = uint64(intSize)
	}
}
Ejemplo n.º 7
0
func testGET(serviceDomain string, useTLS bool) {

	fog.Debug("start get")

	client, scheme := getClient(useTLS)

	url := fmt.Sprintf("%s://%s/admin", scheme, serviceDomain)
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		fog.Critical("NewRequest (GET) failed %s", err)
	}
	response, err := client.Do(request)
	if err != nil {
		fog.Error("get %s", err)
		return
	}

	fog.Debug("reading GET response body")
	tools.ReadAndDiscard(response.Body)
	response.Body.Close()

	fog.Debug("finished get %s", response.Status)
}
Ejemplo n.º 8
0
// Critical prepends literal 'CRITICAL' to log message
// program terminates
func (l logData) Critical(text string, args ...interface{}) {
	fog.Critical(l.prefix()+text, args...)
}
Ejemplo n.º 9
0
// main entry point for webdirector
func main() {
	var err error

	fog.Info("program starts")

	// set up a signal handling channel
	signalChannel := make(chan os.Signal)
	signal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM)

	if profilePath := os.Getenv("WEBDIRECTOR_CPU_PROFILE_PATH"); profilePath != "" {
		profileFile, err := os.Create(profilePath)
		if err != nil {
			fog.Critical("os.Create(%s) failed %s", profilePath, err)
		}
		fog.Info("writing CPU profile data to %s", profilePath)
		pprof.StartCPUProfile(profileFile)
		defer pprof.StopCPUProfile()
	}

	useTLS := os.Getenv("NIMBUS_IO_SERVICE_SSL") == "1"
	fog.Info("TLS = %t", useTLS)

	listenAddress, err := getListenAddress()
	if err != nil {
		fog.Critical("error getListenAddress %s", err)
	}
	fog.Info("webdirector listens to %s", listenAddress)

	var listener net.Listener
	if useTLS {
		if listener, err = getTLSListener(listenAddress); err != nil {
			fog.Critical("Unable to create TLS listener: %s", err)
		}
	} else {
		if listener, err = getTCPListener(listenAddress); err != nil {
			fog.Critical("Unable to create TCP listener: %s", err)
		}
	}

	managmentAPIDests, err := mgmtapi.NewManagementAPIDestinations()
	if err != nil {
		fog.Critical("NewManagementAPIDestinations: %s", err)
	}

	centralDB := centraldb.NewCentralDB()

	availableHosts, err := avail.NewAvailability()
	if err != nil {
		fog.Critical("NewAvailability: %s", err)
	}

	router := routing.NewRouter(managmentAPIDests, centralDB, availableHosts)

	fog.Info("NIMBUS_IO_SERVICE_DOMAIN = '%s'",
		os.Getenv("NIMBUS_IO_SERVICE_DOMAIN"))
	fog.Info("NIMBUSIO_WEB_PUBLIC_READER_PORT = '%s'",
		os.Getenv("NIMBUSIO_WEB_PUBLIC_READER_PORT"))
	fog.Info("NIMBUSIO_WEB_WRITER_PORT = '%s'",
		os.Getenv("NIMBUSIO_WEB_WRITER_PORT"))

	listenerChan := make(chan net.Conn, listenerChanCapacity)
	go func() {
		for {
			connection, err := listener.Accept()
			if err != nil {
				fog.Error("listener.Accept() %s", err)
				close(listenerChan)
				break
			}
			listenerChan <- connection
		}
	}()

	for running := true; running; {
		select {
		case signal := <-signalChannel:
			fog.Info("terminated by signal: %v", signal)
			running = false
		case conn, ok := <-listenerChan:
			if ok {
				fog.Info("connection from %s", conn.RemoteAddr().String())
				go handleConnection(router, conn)
			} else {
				running = false
			}
		}
	}
	listener.Close()

	fog.Info("program terminates")
}