mtsatellite/main.go
2014-08-23 18:05:40 +02:00

130 lines
2.6 KiB
Go

// Copyright 2014 by Sascha L. Teichmann
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.
package main
import (
"flag"
"fmt"
"log"
"net"
"os"
"os/signal"
"runtime"
"time"
"bitbucket.org/s_l_teichmann/mtredisalize/common"
)
const (
Version = "0.3"
GCDuration = "24h"
)
func main() {
var (
port int
host string
driver string
cacheSize int
version bool
interleaved bool
gcDuration string
)
flag.IntVar(&port, "port", 6379, "port to bind")
flag.StringVar(&driver, "driver", "leveldb", "type of database (leveldb, sqlite)")
flag.StringVar(&host, "host", "", "host to bind")
flag.IntVar(&cacheSize, "cache", 32, "cache size in MB")
flag.BoolVar(&version, "version", false, "Print version and exit.")
flag.BoolVar(&interleaved, "interleaved", false, "Backend stores key in interleaved form.")
flag.StringVar(&gcDuration, "gc-duration", GCDuration, "Duration between forced GCs.")
flag.Parse()
if version {
fmt.Printf("Version: %s\n", Version)
os.Exit(0)
}
args := flag.Args()
if len(args) < 1 {
log.Fatal("Missing path to world")
}
var (
err error
backend Backend
gcDur time.Duration
)
if gcDur, err = time.ParseDuration(gcDuration); err != nil {
log.Fatal(err)
}
if driver == "sqlite" {
if backend, err = NewSqliteBackend(args[0], interleaved); err != nil {
log.Fatal(err)
}
} else {
if backend, err = NewLeveDBBackend(
args[0],
common.IdentityTranscoder,
common.IdentityTranscoder,
cacheSize); err != nil {
log.Fatal(err)
}
}
defer backend.Shutdown()
var listener net.Listener
listener, err = net.Listen("tcp", fmt.Sprintf("%s:%d", host, port))
if err != nil {
log.Fatal(err)
}
defer listener.Close()
log.Printf("Server started at %s", listener.Addr())
connChan := make(chan net.Conn)
defer close(connChan)
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, os.Kill)
go func() {
for {
conn, err := listener.Accept()
if err != nil {
log.Fatal(err)
}
log.Printf("Client accepted from: %s", conn.RemoteAddr())
connChan <- conn
}
}()
log.Printf("Doing garbage collection every: %s", gcDur)
gcChan := time.Tick(gcDur)
for {
select {
case conn := <-connChan:
var session Session
if session, err = backend.NewSession(); err != nil {
log.Printf("Cannot create session: %s", err)
conn.Close()
} else {
go NewConnection(conn, session).Run()
}
case <-sigChan:
log.Println("Shutting down")
return
case <-gcChan:
log.Println("Starting garbage collection.")
runtime.GC()
log.Println("Garbage collection done.")
}
}
}