Add more command line docs + other cleanups
authorSimon J Mudd <sjmudd@pobox.com>
Mon, 15 Dec 2014 21:04:51 +0000 (22:04 +0100)
committerSimon J Mudd <sjmudd@pobox.com>
Mon, 15 Dec 2014 21:04:51 +0000 (22:04 +0100)
README.md
i_s/pl_by_user.go
i_s/processlist.go
key_value_cache/key_value_cache.go
main.go
version/version.go

index 44105b2..1bcf3b7 100644 (file)
--- a/README.md
+++ b/README.md
@@ -14,11 +14,23 @@ the actiity of those users.
 
 Install and update this go package with `go get -u github.com/sjmudd/pstop`
 
+### Dependencies
+
+The following Non-core Go dependencies are:
+* github.com/sjmudd/mysql_defaults_file for connecting to MySQL via
+a defaults file.
+* github.com/nsf/termbox-go a library for creating cross-platform
+text-based interfaces.
+
 ### Configuration
 
-Access to MySQL is currently via a defaults-file which is assumed
-to be `~/.my.cnf`.  Alternatively you can now provide
--defaults-file=/path/to/.my.cnf if needed.
+Access to MySQL can be made by one of the following methods:
+* Default: use a defaults-file named `~/.my.cnf`.
+* use an explicit defaults-file with `--defaults-file=/path/to/.my.cnf`.
+* connect to a host with `--host=somehost --port=999 --user=someuser --password=somepass`, or
+* connect via a socket with `--socket=/path/to/mysql.sock --user=someuser --password=somepass`
+
+The user if not specified will default to the contents of `$USER`.
 
 ### Grants
 
index 576045b..f5bd83f 100644 (file)
@@ -126,10 +126,6 @@ func (t pl_by_user_rows) Sort() {
        sort.Sort(ByRunTime(t))
 }
 
-func (r pl_by_user_row) Description() string {
-       return "no description"
-}
-
 func (t pl_by_user_rows) emptyRowContent() string {
        var r pl_by_user_row
        return r.row_content(r)
index 3c5c258..50d5e92 100644 (file)
@@ -70,7 +70,7 @@ func (t Processlist) RowContent(max_rows int) []string {
 
 func (t Processlist) Description() string {
        count := t.count_rows()
-       return fmt.Sprintf("User Information (processlist) %d rows", count)
+       return fmt.Sprintf("Activity by Username (processlist) %d rows", count)
 }
 
 func (t Processlist) count_rows() int {
index e5881b6..9b689a2 100644 (file)
@@ -1,3 +1,7 @@
+// key_value_cache provides an extremely simple string key to value cache.
+// This is used to reduce the number of lookups from MySQL filename
+// to the equivalent table or logical name given the conversion
+// routines to do this use many regexps and this is quite expensive.
 package key_value_cache
 
 import (
@@ -12,15 +16,14 @@ type KeyValueCache struct {
        read_requests, served_from_cache, write_requests int
 }
 
-// create a new KeyValueCache entry
+// Create a new KeyValueCache entry.
 func NewKeyValueCache() KeyValueCache {
        lib.Logger.Println("KeyValueCache()")
-       var kvc KeyValueCache
 
-       return kvc
+       return KeyValueCache {}
 }
 
-// return value if found
+// Given a lookup key return the value if found.
 func (kvc *KeyValueCache) Get(key string) (result string, err error) {
        lib.Logger.Println("KeyValueCache.Get(", key, ")")
        if kvc.cache == nil {
@@ -43,13 +46,15 @@ func (kvc *KeyValueCache) Get(key string) (result string, err error) {
        }
 }
 
-// write to cache and return value
+// Write to cache and return the value saved.
 func (kvc *KeyValueCache) Put(key, value string) string {
        lib.Logger.Println("KeyValueCache.Put(", key, ",", value, ")")
        kvc.cache[key] = value
        return value
 }
 
+// Provide some staticts on read and write requests and the number
+// of requests served from cache.
 func (kvc *KeyValueCache) Statistics() (int, int, int) {
        return kvc.read_requests, kvc.served_from_cache, kvc.write_requests
 }
diff --git a/main.go b/main.go
index 53960f2..94c0036 100644 (file)
--- a/main.go
+++ b/main.go
@@ -34,6 +34,11 @@ var (
        flag_debug         = flag.Bool("debug", false, "Enabling debug logging")
        flag_defaults_file = flag.String("defaults-file", "", "Provide a defaults-file to use to connect to MySQL")
        flag_help          = flag.Bool("help", false, "Provide some help for "+lib.MyName())
+       flag_host          = flag.String("host", "", "Provide the hostname of the MySQL to connect to")
+       flag_port          = flag.Int("port", 0 , "Provide the port number of the MySQL to connect to (default: 3306)") /* deliberately 0 here, defaults to 3306 elsewhere */
+       flag_socket        = flag.String("socket", "", "Provide the path to the local MySQL server to connect to")
+       flag_password      = flag.String("password", "", "Provide the password when connecting to the MySQL server")
+       flag_user          = flag.String("user", "", "Provide the username to connect with to MySQL (default: $USER)")
        flag_version       = flag.Bool("version", false, "Show the version of "+lib.MyName())
        cpuprofile         = flag.String("cpuprofile", "", "write cpu profile to file")
 
@@ -41,10 +46,10 @@ var (
 )
 
 // Connect to the database with the given defaults-file, or ~/.my.cnf if not provided.
-func get_db_handle( defaults_file string ) *sql.DB {
+func connect_by_defaults_file( defaults_file string ) *sql.DB {
        var err error
        var dbh *sql.DB
-       lib.Logger.Println("get_db_handle() connecting to database")
+       lib.Logger.Println("connect_by_defaults_file() connecting to database")
 
        dbh, err = mysql_defaults_file.OpenUsingDefaultsFile(sql_driver, defaults_file, "performance_schema")
        if err != nil {
@@ -57,6 +62,24 @@ func get_db_handle( defaults_file string ) *sql.DB {
        return dbh
 }
 
+// connect to MySQL using various component parts needed to make the dsn
+func connect_by_components( components map[string]string ) *sql.DB {
+       var err error
+       var dbh *sql.DB
+       lib.Logger.Println("connect_by_components() connecting to database")
+
+       new_dsn := mysql_defaults_file.BuildDSN(components, "performance_schema")
+       dbh, err = sql.Open(sql_driver, new_dsn)
+       if err != nil {
+               log.Fatal(err)
+       }
+       if err = dbh.Ping(); err != nil {
+               log.Fatal(err)
+       }
+
+       return dbh
+}
+
 // make chan for termbox events and run a poller to send events to the channel
 // - return the channel
 func new_tb_chan() chan termbox.Event {
@@ -78,9 +101,14 @@ func usage() {
        fmt.Println("Usage: " + lib.MyName() + " <options>")
        fmt.Println("")
        fmt.Println("Options:")
-       fmt.Println("-defaults-file=/path/to/defaults.file   Connect to MySQL using given defaults-file" )
-       fmt.Println("-help                                   show this help message")
-       fmt.Println("-version                                show the version")
+       fmt.Println("--defaults-file=/path/to/defaults.file   Connect to MySQL using given defaults-file" )
+       fmt.Println("--help                                   Show this help message")
+       fmt.Println("--version                                Show the version")
+       fmt.Println("--host=<hostname>                        MySQL host to connect to")
+       fmt.Println("--port=<port>                            MySQL port to connect to")
+       fmt.Println("--socket=<path>                          MySQL path of the socket to connect to")
+       fmt.Println("--user=<user>                            User to connect with")
+       fmt.Println("--password=<password>                    Password to use when connecting")
 }
 
 // pstop requires MySQL 5.6+ or MariaDB 10.0+. Check the version
@@ -149,11 +177,46 @@ func main() {
 
        lib.Logger.Println("Starting " + lib.MyName())
 
-       if flag_defaults_file != nil && *flag_defaults_file != "" {
-               defaults_file = *flag_defaults_file
+       var dbh *sql.DB
+
+       if *flag_host != "" || *flag_socket != "" {
+               lib.Logger.Println("--host= or --socket= defined")
+               var components = make(map[string]string)
+               if *flag_host != "" && *flag_socket != "" {
+                       fmt.Println(lib.MyName() + ": Do not specify --host and --socket together" )
+                       os.Exit(1)
+               }
+               if *flag_host != "" {
+                       components["host"] = *flag_host
+               }
+               if *flag_port != 0 {
+                       if *flag_socket == "" {
+                               components["port"] = fmt.Sprintf("%d", *flag_port)
+                       } else {
+                               fmt.Println(lib.MyName() + ": Do not specify --socket and --port together" )
+                               os.Exit(1)
+                       }
+               }
+               if *flag_socket != "" {
+                       components["socket"] = *flag_socket
+               }
+               if *flag_user != "" {
+                       components["user"] = *flag_user
+               }
+               if *flag_password != "" {
+                       components["password"] = *flag_password
+               }
+               dbh = connect_by_components( components )
+       } else {
+                if flag_defaults_file != nil && *flag_defaults_file != "" {
+                       lib.Logger.Println("--defaults-file defined")
+                       defaults_file = *flag_defaults_file
+               } else {
+                       lib.Logger.Println("connecting by implicit defaults file")
+               }
+               dbh = connect_by_defaults_file( defaults_file )
        }
 
-       dbh := get_db_handle( defaults_file )
        if err := validate_mysql_version(dbh); err != nil {
                log.Fatal(err)
        }
index be253eb..74ffa65 100644 (file)
@@ -1,8 +1,8 @@
-// package to return the package version
+// package to return the program version
 package version
 
 const (
-       version = "0.1.3"
+       version = "0.1.4"
 )
 
 // return the current application version