main.go (1752B)
1 /* 2 Semfs is a semaphore file system. 3 The original idea is from this book ([Ballesteros 2006]). 4 5 You can mount this file system via 9P using 9pfuse for example. 6 The file system is initially empty, and you can make files on it. 7 Each file represents a semaphore length of which is the number of tickets. 8 To add tickets to an file, write the number of tickets to be added to the file. 9 To consume a ticket, read the file. 10 11 $ 9pfuse localhost:5640 /mnt 12 $ echo 1 > /mnt/sem 13 $ ls -l /mnt/sem 14 -rw-rw-rw- 1 kenji kenji 1 Jan 17 08:16 /mnt/sem 15 $ cat /mnt/sem 16 $ ls -l /mnt/sem 17 -rw-rw-rw- 1 kenji kenji 0 Jan 17 08:17 /mnt/sem 18 19 Reading a file with length 0 blocks until someone adds tickets to 20 the file. 21 22 $ ls -l /mnt/sem 23 -rw-rw-rw- 1 kenji kenji 0 Jan 17 08:17 /mnt/sem 24 $ (cat /mnt/sem; echo done) & sleep 1; echo write; echo 1 > /mnt/sem 25 [2] 42872 26 write 27 $ done 28 29 Usage: 30 31 semfs [-D] 32 33 The Flags are: 34 35 -D 36 print very chatty 9P conversation dialogue to the standard output. 37 38 [Ballesteros 2006]: http://doc.cat-v.org/plan_9/9.intro.pdf 39 */ 40 package main 41 42 import ( 43 "context" 44 "flag" 45 "fmt" 46 "log" 47 "net" 48 "os" 49 50 "git.mtkn.jp/lib9p" 51 ) 52 53 var dFlag = flag.Bool("D", false, "Prints chatty message to the stderr.") 54 55 func main() { 56 flag.Parse() 57 if flag.NArg() != 0 { 58 fmt.Fprintf(os.Stderr, "usage: %s [-D]\n", os.Args[0]) 59 os.Exit(1) 60 } 61 listener, err := net.Listen("tcp", "127.0.0.1:5640") 62 if err != nil { 63 log.Fatalf("listen tcp: %v", err) 64 } 65 fsys := &semFS{semfiles: make(map[int]*semFile)} 66 s := lib9p.NewServer(fsys) 67 if *dFlag { 68 s.Chatty() 69 } 70 for { 71 conn, err := listener.Accept() 72 if err != nil { 73 log.Printf("accept connection: %v", err) 74 continue 75 } 76 go func() { 77 defer conn.Close() 78 s.Serve(context.TODO(), conn, conn) 79 }() 80 } 81 }