Initial import of pstop v0.0.10
[pstop.git] / lib / common.go
diff --git a/lib/common.go b/lib/common.go
new file mode 100644 (file)
index 0000000..c04aab9
--- /dev/null
@@ -0,0 +1,162 @@
+// package lib - common routines for pstop
+package lib
+
+import (
+       "fmt"
+       _ "github.com/go-sql-driver/mysql"
+       _ "github.com/sjmudd/pstop/version"
+       "strconv"
+)
+
+const (
+       myname = "pstop"
+       copyright = "Copyright (C) 2014 Simon J Mudd <sjmudd@pobox.com>"
+)
+
+// myround converts this floating value to the right width etc.
+// There must be a function in Go to do this. Find it.
+func myround(f float64, width, decimals int) string {
+       format := "%" + fmt.Sprintf("%d", width) + "." + fmt.Sprintf("%d", decimals) + "f"
+       return fmt.Sprintf(format, f)
+}
+
+// MyName returns the program's name.
+func MyName() string {
+       return myname
+}
+
+// Copyright provides a copyright message for pstop
+func Copyright() string {
+       return copyright
+}
+
+// sec_to_time() converts a number of hours, minutes and seconds into hh:mm:ss format.
+// e.g. 7384 = 2h 3m 4s, 7200 + 180 + 4
+func sec_to_time(d int) string {
+       hours := d / 3600                // integer value
+       minutes := (d - hours*3600) / 60 // integer value
+       seconds := d - hours*3600 - minutes*60
+
+       return fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
+}
+
+// FormatTime is based on sys.format_time. It 
+// formats to 10 characters including space and suffix.
+// All values have 2 decimal places. Zero is returned as
+// an empty string.
+func FormatTime(picoseconds int) string {
+       if picoseconds == 0 {
+               return ""
+       }
+       if picoseconds >= 3600000000000000 {
+               return myround(float64(picoseconds)/3600000000000000, 8, 2) + " h"
+       }
+       if picoseconds >= 60000000000000 {
+               return sec_to_time(picoseconds / 1000000000000)
+       }
+       if picoseconds >= 1000000000000 {
+               return myround(float64(picoseconds)/1000000000000, 8, 2) + " s"
+       }
+       if picoseconds >= 1000000000 {
+               return myround(float64(picoseconds)/1000000000, 7, 2) + " ms"
+       }
+       if picoseconds >= 1000000 {
+               return myround(float64(picoseconds)/1000000, 7, 2) + " us"
+       }
+       if picoseconds >= 1000 {
+               return myround(float64(picoseconds)/1000, 7, 2) + " ns"
+       }
+       return strconv.Itoa(int(picoseconds)) + " ps"
+}
+
+// FormatPct() formats a floating point number as a percentage
+// including the trailing % sign. Print the value as a %5.1f with
+// a % suffix if there's a value.
+// If the value is 0 print as 6 spaces.
+// if the value is > 999.9 then show +++.+% to indicate an overflow.
+func FormatPct(pct float64) string {
+       var s string
+       if pct < 0.0001 {
+               s = "      "
+       } else if pct > 999.9 {
+               s = "+++.+%" // too large to fit! (probably a bug as we don't expect this value to be > 100.00)
+       } else {
+               s = fmt.Sprintf("%5.1f", 100.0*pct) + "%"
+       }
+
+       return s
+}
+
+// FormatAmount() convert numbers to k = 1024 , M = 1024 x 1024, G = 1024 x 1024 x 1024, P = 1024x1024x1024x1024.
+// For values = 0 return an empty string.
+// For values < 1000 show 6,2 decimal places.
+// For values >= 1000 show 6,1 decimal place.
+func FormatAmount(amount int) string {
+       var suffix string
+       var formatted string
+       var decimal_amount float64
+
+       if amount == 0 {
+               return ""
+       }
+       if amount <= 1024 {
+               return strconv.Itoa(amount)
+       }
+
+       if amount > (1024 * 1024 * 1024 * 1024) {
+               suffix = "P"
+               decimal_amount = float64(amount) / 1024 / 1024 / 1024 / 1024
+       } else if amount > (1024 * 1024 * 1024) {
+               suffix = "G"
+               decimal_amount = float64(amount) / 1024 / 1024 / 1024
+       } else if amount > (1024 * 1024) {
+               suffix = "M"
+               decimal_amount = float64(amount) / 1024 / 1024
+       } else if amount > 1024 {
+               suffix = "k"
+               decimal_amount = float64(amount) / 1024
+       }
+
+       if decimal_amount > 1000.0 {
+               formatted = fmt.Sprintf("%6.1f %s", decimal_amount, suffix)
+       } else {
+               formatted = fmt.Sprintf("%6.2f %s", decimal_amount, suffix)
+       }
+       return formatted
+}
+
+// MyDivide() divides a by b except if b is 0 in which case we return 0.
+func MyDivide(a int, b int) float64 {
+       if b == 0 {
+               return float64(0)
+       } else {
+               return float64(a) / float64(b)
+       }
+}
+
+// Uptime() provides a  usable form of uptime.
+// Note: this doesn't return a string of a fixed size!
+// Minimum value: 1s.
+// Maximum value: 100d 23h 59m 59s (sort of).
+func Uptime(uptime int) string {
+       var result string
+
+       days := uptime / 24 / 60 / 60
+       hours := (uptime - days*86400) / 3600
+       minutes := (uptime - days*86400 - hours*3600) / 60
+       seconds := uptime - days*86400 - hours*3600 - minutes*60
+
+       result = strconv.Itoa(seconds) + "s"
+
+       if minutes > 0 {
+               result = strconv.Itoa(minutes) + "m " + result
+       }
+       if hours > 0 {
+               result = strconv.Itoa(hours) + "h " + result
+       }
+       if days > 0 {
+               result = strconv.Itoa(days) + "d " + result
+       }
+
+       return result
+}