lib9p

Go 9P library.
Log | Files | Refs | LICENSE

main.go (2403B)


      1 // Diskfs exports the file system on the disk.
      2 //
      3 // Usage:
      4 // 	diskfs [-D] [-P profport] [-a addr] [-p port] root
      5 // Diskfs exports file system on the disk rooted at root.
      6 // By default it listens to 127.0.0.1:5640.
      7 // You can change the address and port number with -a and -p flags.
      8 // The -D flag enables very chatty log messages.
      9 // The -P flag enables the pprof web interface at the the port profport.
     10 // The address the pprof listens to is the same as addr (or 127.0.0.1 if
     11 // -a flag is not specified).
     12 package main
     13 
     14 import (
     15 	"context"
     16 	"flag"
     17 	"fmt"
     18 	"log"
     19 	"net"
     20 	"net/http"
     21 	_ "net/http/pprof"
     22 	"os"
     23 	"os/signal"
     24 	"runtime"
     25 	"sync"
     26 	"time"
     27 
     28 	"git.mtkn.jp/lib9p"
     29 	"git.mtkn.jp/lib9p/diskfs"
     30 )
     31 
     32 var dFlag = flag.Bool("D", false, "Prints chatty message to the stderr.")
     33 var aFlag = flag.String("a", "127.0.0.1", "Address the server listens to.")
     34 var pFlag = flag.Int("p", 5640, "Port number the server listens to.")
     35 var PFlag = flag.Int("P", 0, "Enables pprof over http on this port.")
     36 var gFlag = flag.Bool("g", false, "Prints goroutin count once per second.")
     37 
     38 func main() {
     39 	flag.Parse()
     40 	if flag.NArg() != 1 {
     41 		fmt.Fprintf(os.Stderr, "usage: %s [-D] [-P profport] [-a addr] [-p port] root\n", os.Args[0])
     42 		os.Exit(1)
     43 	}
     44 	if *gFlag {
     45 		go func() {
     46 			for {
     47 				log.Printf("num goroutine: %d", runtime.NumGoroutine())
     48 				time.Sleep(1 * time.Second)
     49 			}
     50 		}()
     51 	}
     52 	if *PFlag != 0 {
     53 		go func() {
     54 			log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%d", *aFlag, *PFlag), nil))
     55 		}()
     56 	}
     57 	listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", *aFlag, *pFlag))
     58 	if err != nil {
     59 		log.Fatalf("listen tcp: %v", err)
     60 	}
     61 	ctx := runSignalHandler()
     62 	go func() {
     63 		<-ctx.Done()
     64 		listener.Close()
     65 	}()
     66 	wg := new(sync.WaitGroup)
     67 	disk, err := diskfs.Open(flag.Arg(0))
     68 	if err != nil {
     69 		log.Fatalf("open file tree.")
     70 	}
     71 	s := lib9p.NewServer(disk)
     72 	if *dFlag {
     73 		s.Chatty()
     74 	}
     75 L:
     76 	for {
     77 		conn, err := listener.Accept()
     78 		if err != nil {
     79 			select {
     80 			case <-ctx.Done():
     81 				break L
     82 			default:
     83 				log.Printf("accept connection: %v", err)
     84 				continue L
     85 			}
     86 		}
     87 		wg.Add(1)
     88 		go func() {
     89 			defer conn.Close()
     90 			defer wg.Done()
     91 			s.Serve(ctx, conn, conn)
     92 		}()
     93 	}
     94 	wg.Wait()
     95 }
     96 
     97 func runSignalHandler() context.Context {
     98 	quit := make(chan os.Signal, 1)
     99 	signal.Notify(quit, os.Interrupt)
    100 	ctx, cancel := context.WithCancel(context.Background())
    101 	go func() {
    102 		<-quit
    103 		cancel()
    104 	}()
    105 	return ctx
    106 }