/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"github.com/jmhodges/levigo"
	"net"
	"org/apache/htrace/common"
	"org/apache/htrace/conf"
	"os"
	"runtime"
	"strings"
	"time"
)

var RELEASE_VERSION string
var GIT_VERSION string

const USAGE = `htraced: the HTrace server daemon.

htraced receives trace spans sent from HTrace clients.  It exposes a REST
interface which others can query.  It also runs a web server with a graphical
user interface.  htraced stores its span data in levelDB files on the local
disks.

Usage:
--help: this help message

-Dk=v: set configuration key 'k' to value 'v'
For example -Dweb.address=127.0.0.1:8080 sets the web address to localhost,
port 8080.

-Dk: set configuration key 'k' to 'true'

Normally, configuration options should be set in the ` + conf.CONFIG_FILE_NAME + `
configuration file.  We find this file by searching the paths in the 
` + conf.HTRACED_CONF_DIR + `. The command-line options are just an alternate way
of setting configuration when launching the daemon.
`

func main() {
	for idx := range os.Args {
		arg := os.Args[idx]
		if strings.HasPrefix(arg, "--h") || strings.HasPrefix(arg, "-h") {
			fmt.Fprintf(os.Stderr, USAGE)
			os.Exit(0)
		}
	}

	// Load the htraced configuration.
	cnf, cnfLog := conf.LoadApplicationConfig("htraced.")

	// Open the HTTP port.
	// We want to do this first, before initializing the datastore or setting up
	// logging.  That way, if someone accidentally starts two daemons with the
	// same config file, the second invocation will exit with a "port in use"
	// error rather than potentially disrupting the first invocation.
	rstListener, listenErr := net.Listen("tcp", cnf.Get(conf.HTRACE_WEB_ADDRESS))
	if listenErr != nil {
		fmt.Fprintf(os.Stderr, "Error opening HTTP port: %s\n",
			listenErr.Error())
		os.Exit(1)
	}

	// Print out the startup banner and information about the daemon
	// configuration.
	lg := common.NewLogger("main", cnf)
	defer lg.Close()
	lg.Infof("*** Starting htraced %s [%s]***\n", RELEASE_VERSION, GIT_VERSION)
	scanner := bufio.NewScanner(cnfLog)
	for scanner.Scan() {
		lg.Infof(scanner.Text() + "\n")
	}
	common.InstallSignalHandlers(cnf)
	if runtime.GOMAXPROCS(0) == 1 {
		ncpu := runtime.NumCPU()
		runtime.GOMAXPROCS(ncpu)
		lg.Infof("setting GOMAXPROCS=%d\n", ncpu)
	} else {
		lg.Infof("GOMAXPROCS=%d\n", runtime.GOMAXPROCS(0))
	}
	lg.Infof("leveldb version=%d.%d\n",
		levigo.GetLevelDBMajorVersion(), levigo.GetLevelDBMinorVersion())

	// Initialize the datastore.
	store, err := CreateDataStore(cnf, nil)
	if err != nil {
		lg.Errorf("Error creating datastore: %s\n", err.Error())
		os.Exit(1)
	}
	var rsv *RestServer
	rsv, err = CreateRestServer(cnf, store, rstListener)
	if err != nil {
		lg.Errorf("Error creating REST server: %s\n", err.Error())
		os.Exit(1)
	}
	var hsv *HrpcServer
	if cnf.Get(conf.HTRACE_HRPC_ADDRESS) != "" {
		hsv, err = CreateHrpcServer(cnf, store, nil)
		if err != nil {
			lg.Errorf("Error creating HRPC server: %s\n", err.Error())
			os.Exit(1)
		}
	} else {
		lg.Infof("Not starting HRPC server because no value was given for %s.\n",
			conf.HTRACE_HRPC_ADDRESS)
	}
	naddr := cnf.Get(conf.HTRACE_STARTUP_NOTIFICATION_ADDRESS)
	if naddr != "" {
		notif := StartupNotification{
			HttpAddr:  rsv.Addr().String(),
			ProcessId: os.Getpid(),
		}
		if hsv != nil {
			notif.HrpcAddr = hsv.Addr().String()
		}
		err = sendStartupNotification(naddr, &notif)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Failed to send startup notification: "+
				"%s\n", err.Error())
			os.Exit(1)
		}
	}
	for {
		time.Sleep(time.Duration(10) * time.Hour)
	}
}

// A startup notification message that we optionally send on startup.
// Used by unit tests.
type StartupNotification struct {
	HttpAddr  string
	HrpcAddr  string
	ProcessId int
}

func sendStartupNotification(naddr string, notif *StartupNotification) error {
	conn, err := net.Dial("tcp", naddr)
	if err != nil {
		return err
	}
	defer func() {
		if conn != nil {
			conn.Close()
		}
	}()
	var buf []byte
	buf, err = json.Marshal(notif)
	if err != nil {
		return err
	}
	_, err = conn.Write(buf)
	conn.Close()
	conn = nil
	return nil
}
