Permalink
Browse files

added better logging facilities and did some code cleanup

  • Loading branch information...
1 parent 60be90f commit 13030362613cde2c5a24f79c8569a849e8c50fbf @jdp committed Nov 19, 2009
Showing with 132 additions and 45 deletions.
  1. +1 −2 .gitignore
  2. +18 −0 README
  3. +0 −21 main.go
  4. +3 −2 { → src}/Makefile
  5. +81 −0 src/main.go
  6. 0 { → src}/msgqueue.go
  7. +28 −20 { → src}/server.go
  8. +1 −0 test/speed.php
View
3 .gitignore
@@ -1,8 +1,7 @@
*.8
*.6
*.5
-goqueue
-lineupd
8.out
6.out
5.out
+bin
View
18 README
@@ -31,6 +31,23 @@ why?
that's not to say that lineupd is complete, not
to any degree.
+
+usage
+
+ run lineupd and it will listen on :9876, and
+ create a logfile lineupd.log and pidfile
+ lineupd.pid. if you want to explicitly set any
+ options, there are --port, --logfile, and
+ --pidfile command line options. there is also
+ the --timeout option, which sets the number of
+ seconds to wait to disconnect an idle client.
+
+bugs
+
+ - the --daemonize option doesn't work yet. most
+ of the code is there, but i can't find a
+ plain old fork() call in the go stdlib. help
+ here would be great.
credits
@@ -39,4 +56,5 @@ credits
redis http://code.google.com/p/redis
memcached http://memcached.org
beanstalkd http://kr.github.com/beanstalkd
+ suckless http://suckless.org
View
21 main.go
@@ -1,21 +0,0 @@
-package main
-
-import(
- //"fmt";
- "flag";
- . "./msgqueue";
- . "./server";
-)
-
-func main() {
- var port *int = flag.Int("port", 9876, "port to run server on");
- var daemon *bool = flag.Bool("daemonize", false, "whether or not to daemonize process");
- var timeout *int = flag.Int("timeout", 30, "number of seconds to wait disconnect inactive clients");
- flag.Parse();
- if *daemon {
- // daemonize
- }
- queue := NewMsgQueue(10);
- server := &Server{*port, *timeout, queue, 0, 0};
- server.Serve();
-}
View
5 Makefile → src/Makefile
@@ -7,12 +7,13 @@ OBJ = ${SRC:.go=.$O}
OUT = lineupd
$(OUT): $(OBJ)
- $(LD) -o $@ $(OBJ)
+ mkdir -p bin
+ $(LD) -o bin/$@ $(OBJ)
.go.$O:
$(GC) $<
clean:
- rm -f $(OBJ) $(OUT)
+ rm -f $(OBJ) bin/$(OUT)
.PHONY: clean
View
81 src/main.go
@@ -0,0 +1,81 @@
+package main
+
+import(
+ "fmt";
+ "flag";
+ "os";
+ "syscall";
+ "log";
+ . "./msgqueue";
+ . "./server";
+)
+
+func daemonize(server *Server) {
+ pid, err := os.ForkExec("lineupd", []string{}, []string{}, "/var/run", []*os.File{});
+ if err != nil {
+ server.Logger().Logf("couldn't fork: %s\n", err);
+ os.Exit(1);
+ }
+ server.Logger().Logf("%d->%d\n", os.Getpid(), pid);
+ if (pid < 0) {
+ os.Exit(1);
+ }
+ if (pid > 0) {
+ os.Exit(0);
+ }
+ syscall.Setsid();
+ for i := 0; i < 3; i++ {
+ syscall.Close(i);
+ }
+ for i := 0; i < 3; i++ {
+ syscall.Open("/dev/null", os.O_RDWR, 0644);
+ }
+ syscall.Umask(027);
+ syscall.Chdir("/var/run");
+}
+
+func makePidfile(server *Server, filename string) {
+ fp, err := os.Open(fmt.Sprintf("%s", filename), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666);
+ if err != nil {
+ server.Logger().Logf("couldn't open pidfile `%s': %s\n", filename, err);
+ os.Exit(1);
+ }
+ _, err = fp.WriteString(fmt.Sprintf("%d", os.Getpid()));
+ if err != nil {
+ server.Logger().Logf("couldn't write to pidfile `%s': %s\n", filename, err);
+ os.Exit(1);
+ }
+ fp.Close();
+}
+
+/* a ternary operator would make this function seem silly :) */
+func getLogger(logfile string, daemonized bool) (logger *log.Logger) {
+ logfp, err := os.Open(fmt.Sprintf("%s", logfile), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666);
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "couldn't open logfile `%s': %s\n", logfile, err);
+ os.Exit(1);
+ }
+ if daemonized {
+ logger = log.New(logfp, nil, "", log.Ldate|log.Ltime);
+ }
+ else {
+ logger = log.New(logfp, os.Stdout, "", log.Ldate|log.Ltime);
+ }
+ return;
+}
+
+func main() {
+ var port *int = flag.Int("port", 9876, "port to run server on");
+ var daemon *bool = flag.Bool("daemonize", false, "whether or not to daemonize process");
+ var timeout *int = flag.Int("timeout", 30, "number of seconds to wait disconnect inactive clients");
+ var logfile *string = flag.String("logfile", "lineupd.log", "filename of the log file to write to");
+ var pidfile *string = flag.String("pidfile", "lineupd.pid", "filename of the pid file to use");
+ flag.Parse();
+ queue := NewMsgQueue(10);
+ server := &Server{*port, *timeout, queue, getLogger(*logfile, *daemon), 0, 0};
+ if *daemon {
+ daemonize(server);
+ }
+ makePidfile(server, *pidfile);
+ server.Serve();
+}
View
0 msgqueue.go → src/msgqueue.go
File renamed without changes.
View
48 server.go → src/server.go
@@ -3,8 +3,8 @@ package server
import(
"os";
"fmt";
- "log";
"net";
+ "log";
"regexp";
"strings";
"bytes";
@@ -24,8 +24,9 @@ type Request struct {
*/
type Server struct {
port int; // Server port
- timeout int;
+ timeout int; // Number of seconds to wait to disconnect clients
mq *MsgQueue; // Message queue
+ log *log.Logger; // Logging interface
connections int; // Total current connections
totalConnections int; // Total lifetime connections
}
@@ -180,7 +181,7 @@ func (s *Server) handle(req *Request) {
case err == os.EAGAIN:
disconnected = true;
default:
- log.Stderrf("read error: %v\n", err);
+ s.log.Logf("read error: %v\n", err);
disconnected = true;
break;
}
@@ -192,74 +193,81 @@ func (s *Server) handle(req *Request) {
matches := giveCmd.MatchSlices(line);
priority, size := readInt(matches[1]), readInt(matches[2]);
if err := s.handleGiveCmd(req, buf, priority, size); err != nil {
- log.Stderrf("GIVE: failed (priority %d; size %d) from %s: %s\n", priority, size, req.conn.RemoteAddr(), err);
+ s.log.Logf("GIVE: failed (priority %d; size %d) from %s: %s\n", priority, size, req.conn.RemoteAddr(), err);
}
else {
- log.Stdoutf("GIVE: successful (priority %d; size %d) from %s; size: %d\n", priority, size, req.conn.RemoteAddr(), s.mq.Len());
+ s.log.Logf("GIVE: successful (priority %d; size %d) from %s; size: %d\n", priority, size, req.conn.RemoteAddr(), s.mq.Len());
}
// Handle the TAKE command
case takeCmd.Match(line):
if err := s.handleTakeCmd(req, buf); err != nil {
- log.Stderrf("TAKE: failed from %s: %s\n", req.conn.RemoteAddr(), err);
+ s.log.Logf("TAKE: failed from %s: %s\n", req.conn.RemoteAddr(), err);
}
else {
- log.Stdoutf("TAKE: successful from %s; size %d\n", req.conn.RemoteAddr(), s.mq.Len());
+ s.log.Logf("TAKE: successful from %s; size %d\n", req.conn.RemoteAddr(), s.mq.Len());
}
// Handle the PING command
case pingCmd.Match(line):
if err := s.handlePingCmd(req, buf); err != nil {
- log.Stderrf("PING: failed from %s: %s\n", req.conn.RemoteAddr(), err);
+ s.log.Logf("PING: failed from %s: %s\n", req.conn.RemoteAddr(), err);
}
else {
- log.Stdoutf("PING: successful from %s\n", req.conn.RemoteAddr());
+ s.log.Logf("PING: successful from %s\n", req.conn.RemoteAddr());
}
// Handle the EXIT command
case exitCmd.Match(line):
if err := s.handleExitCmd(req, buf); err != nil {
- log.Stderrf("EXIT: failed from %s: %s\n", req.conn.RemoteAddr(), err);
+ s.log.Logf("EXIT: failed from %s: %s\n", req.conn.RemoteAddr(), err);
}
else {
- log.Stdoutf("EXIT: successful from %s\n", req.conn.RemoteAddr());
+ s.log.Logf("EXIT: successful from %s\n", req.conn.RemoteAddr());
}
disconnected = true;
// No matching command to handle
default:
req.conn.Write(strings.Bytes("-INVALID_COMMAND\r\n"));
- log.Stderrf("invalid command from %s\n", req.conn.RemoteAddr());
+ s.log.Logf("invalid command from %s\n", req.conn.RemoteAddr());
}
}
if disconnected {
- log.Stdoutf("disconnected: %s\n", req.conn.RemoteAddr());
+ s.log.Logf("disconnected: %s\n", req.conn.RemoteAddr());
req.conn.Close();
s.connections--;
return;
}
}
}
+func (s *Server) Logger() *log.Logger {
+ return s.log;
+}
+
/*
* The actual server loop. Just chills out and accepts connections
* until it is sent a quit message.
*/
func (s *Server) Serve() {
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", s.port));
if err != nil {
- log.Exitf("could not start server: %s\n", err);
+ s.log.Logf("couldn't start server: %s\n", err);
+ os.Exit(1);
}
- log.Stdoutf("waiting for connections on %s\n", listener.Addr());
+ s.log.Logf("waiting for connections on %s\n", listener.Addr());
for {
conn, err := listener.Accept();
if err != nil {
- log.Exitf("couldn't accept: %s\n", err);
+ s.log.Logf("couldn't accept : %s\n", err);
+ }
+ else {
+ s.log.Logf("connected: %s\n", conn.RemoteAddr());
+ s.connections++;
+ s.totalConnections++;
+ go s.handle(&Request{conn});
}
- log.Stdoutf("connected: %s\n", conn.RemoteAddr());
- s.connections++;
- s.totalConnections++;
- go s.handle(&Request{conn});
}
}
View
1 test/speed.php
@@ -1,3 +1,4 @@
+#!/usr/bin/env php -q
<?php
include "lineup.php";

0 comments on commit 1303036

Please sign in to comment.