diff --git a/asink/client.go b/asink/client.go index 1a1d2ac..94d6249 100644 --- a/asink/client.go +++ b/asink/client.go @@ -8,6 +8,7 @@ import ( "asink" "asink/util" "code.google.com/p/goconf/conf" + "errors" "flag" "fmt" "io/ioutil" @@ -124,6 +125,9 @@ func StartClient(args []string) { } func ProcessLocalEvent(globals AsinkGlobals, event *asink.Event) { + StatStartLocalUpdate() + defer StatStopLocalUpdate() + //make the path relative before we save/send it anywhere var err error absolutePath := event.Path @@ -190,7 +194,9 @@ func ProcessLocalEvent(globals AsinkGlobals, event *asink.Event) { } //upload file to remote storage + StatStartUpload() err = globals.storage.Put(cachedFilename, event.Hash) + StatStopUpload() if err != nil { panic(err) } @@ -217,6 +223,8 @@ func ProcessLocalEvents(globals AsinkGlobals, eventChan chan *asink.Event) { } func ProcessRemoteEvent(globals AsinkGlobals, event *asink.Event) { + StatStartRemoteUpdate() + defer StatStopRemoteUpdate() latestLocal := LockPath(event.Path, true) defer UnlockPath(event) @@ -248,7 +256,9 @@ func ProcessRemoteEvent(globals AsinkGlobals, event *asink.Event) { } tmpfilename := outfile.Name() outfile.Close() + StatStartDownload() err = globals.storage.Get(tmpfilename, event.Hash) + StatStopDownload() if err != nil { panic(err) //TODO handle sensibly } @@ -307,7 +317,7 @@ func ProcessRemoteEvents(globals AsinkGlobals, eventChan chan *asink.Event) { } } -func StopClient(args []string) { +func getSocketFromArgs(args []string) (string, error) { const config_usage = "Config File to use" userHomeDir := "~" @@ -323,20 +333,46 @@ func StopClient(args []string) { config, err := conf.ReadConfigFile(globals.configFileName) if err != nil { - fmt.Println(err) - fmt.Println("Error reading config file at ", globals.configFileName, ". Does it exist?") - return + return "", err } - rpcSock, err := config.GetString("local", "socket") //TODO make sure this exists + rpcSock, err := config.GetString("local", "socket") if err != nil { - fmt.Println("Error reading local.socket from config file at ", globals.configFileName) + return "", errors.New("Error reading local.socket from config file at " + globals.configFileName) + } + + return rpcSock, nil +} + +func StopClient(args []string) { + rpcSock, err := getSocketFromArgs(args) + if err != nil { + fmt.Println(err) + return } i := 99 returnCode := 0 - err = asink.RPCCall(rpcSock, "ClientStopper.StopClient", &returnCode, &i) + err = asink.RPCCall(rpcSock, "ClientAdmin.StopClient", &i, &returnCode) if err != nil { panic(err) } } + +func GetStatus(args []string) { + var status string + + rpcSock, err := getSocketFromArgs(args) + if err != nil { + fmt.Println(err) + return + } + + i := 99 + err = asink.RPCCall(rpcSock, "ClientAdmin.GetClientStatus", &i, &status) + if err != nil { + panic(err) + } + + fmt.Println(status) +} diff --git a/asink/main.go b/asink/main.go index ca1ec17..e72a690 100644 --- a/asink/main.go +++ b/asink/main.go @@ -27,17 +27,16 @@ var commands []Command = []Command{ fn: StopClient, explanation: "Stop the client daemon", }, + Command{ + cmd: "status", + fn: GetStatus, + explanation: "Get a summary of the client's status", + }, Command{ cmd: "version", fn: PrintVersion, explanation: "Display the current version", }, - /* Command{ - cmd: "status", - fn: GetStatus, - explanation: "Get a summary of the client's status", - }, - */ } func main() { diff --git a/asink/rpc_server.go b/asink/rpc_server.go index 31b141a..b12acc5 100644 --- a/asink/rpc_server.go +++ b/asink/rpc_server.go @@ -11,19 +11,24 @@ import ( "net/rpc" ) -type ClientStopper int +type ClientAdmin int -func (c *ClientStopper) StopClient(code *int, result *int) error { +func (c *ClientAdmin) StopClient(code *int, result *int) error { asink.Exit(*code) *result = 0 return nil } +func (c *ClientAdmin) GetClientStatus(code *int, result *string) error { + *result = GetStats() + return nil +} + func StartRPC(sock string, tornDown chan int) { defer func() { tornDown <- 0 }() //the main thread waits for this to ensure the socket is closed - clientstop := new(ClientStopper) - rpc.Register(clientstop) + clientadmin := new(ClientAdmin) + rpc.Register(clientadmin) rpc.HandleHTTP() l, err := net.Listen("unix", sock) diff --git a/asink/status.go b/asink/status.go new file mode 100644 index 0000000..7dbb5a4 --- /dev/null +++ b/asink/status.go @@ -0,0 +1,52 @@ +/* + Copyright (C) 2013 Aaron Lindsay +*/ + +package main + +import ( + "fmt" + "sync/atomic" +) + +var localUpdates int32 = 0 +var remoteUpdates int32 = 0 +var fileUploads int32 = 0 +var fileDownloads int32 = 0 + +func GetStats() string { + local := atomic.LoadInt32(&localUpdates) + remote := atomic.LoadInt32(&remoteUpdates) + uploads := atomic.LoadInt32(&fileUploads) + downloads := atomic.LoadInt32(&fileDownloads) + + return fmt.Sprintf(`Asink client statistics: + Processing %d file updates (%d local, %d remote) + Uploading %d files + Downloading %d files`, local + remote, local, remote, uploads, downloads) +} + +func StatStartLocalUpdate() { + atomic.AddInt32(&localUpdates, 1) +} +func StatStopLocalUpdate() { + atomic.AddInt32(&localUpdates, -1) +} +func StatStartRemoteUpdate() { + atomic.AddInt32(&remoteUpdates, 1) +} +func StatStopRemoteUpdate() { + atomic.AddInt32(&remoteUpdates, -1) +} +func StatStartUpload() { + atomic.AddInt32(&fileUploads, 1) +} +func StatStopUpload() { + atomic.AddInt32(&fileUploads, -1) +} +func StatStartDownload() { + atomic.AddInt32(&fileDownloads, 1) +} +func StatStopDownload() { + atomic.AddInt32(&fileDownloads, -1) +}