util

package
v0.0.0-...-782cc26 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 11, 2018 License: MIT Imports: 13 Imported by: 1

Documentation

Overview

Various re-usable utility functions.

Various re-usable utility functions.

Various re-usable utility functions.

Various re-usable utility functions.

Index

Constants

This section is empty.

Variables

View Source
var BacklogFactor = 100

When the length of the backlog is N times the Backlog factor, the LogLevel is reduced by N.

View Source
var LogLevel = 0

Only messages with a level <= this number will be printed.

Functions

func AddTimestamp

func AddTimestamp(ts string, adder string) (string, error)

Takes a timestamp ts in the format produced by MakeTimestamp and adds to it an offset adder in the following format:

<integer>_seconds
<integer>_minutes
<integer>_hours
<integer>_days
<integer>_weeks
<integer>_months
<integer>_years

where <integer> is any integer (may be negative). Example: AddTimestamp("20170201120000", "-3_seconds")

returns "20170201115957"

If ts is invalid, time.Unix(0,0) is assumed and an error is logged (behavior of ParseTimestamp()). If adder is invalid, the timestamp is returned unchanged together with an error.

func AlmostJSON

func AlmostJSON(s string) []byte

Converts s to JSON. The format of s is illustrated by the following example:

key1: "string value\n2nd line. Embedded \"quotes\"."
"key2" = 42
key3: true
  # comment
key4: Hi, this works without "..."
key5: { "foo":"bar", "bla": 99
        key5: ["bla","fasel"] }

Compared to regular JSON you may optionally use the following shorthands:

  • The surrounding {...} around the whole structure may be omitted.
  • If a line starts with a key, the "..." surrouding the key may be omitted.
  • The character '=' may be used instead of ':'.
  • Everything following '#' (if not inside "...") is ignored till the end of line.
  • A ',' as last character of the line may be omitted.
  • If the first character after ':'/'=' is not one of -+.0123456789{[" and the first word does not start with "true", "false" or "null", then it is assumed to be a string that extends to the end of the line.

func Base64DecodeInPlace

func Base64DecodeInPlace(b64 []byte) (decoded []byte)

In-place decoder for base64 data. The decoded slice is always a sub-slice b64[0:n] of the input. See Base64DecodeString() for details about the decoder.

func Base64DecodeString

func Base64DecodeString(b64 string, carry *int) (decoded []byte)

Decodes the base64-encoded string b64 and returns the result. If the input is incomplete, *carry will be used to store partial data of the last 4-char block. By passing in this *carry to a future call, the decoding can be resumed.

If you pass carry==nil, the bytes from the last block will be output even if it is shorter than 4 chars. IOW the function will behave as if there were an appropriate number of "=".

Multiple base64-strings can be concatenated and passed together in one call. The decoded result will be the concatenation of the 2 decodings. Make sure that "=" terminators are used if necessary (see more info below).

After each 4-char block or "=" terminator the *carry will be 0 again, so that the next string can be fed into the decoder without having to explicitly reset the carry variable.

Non-alphabet characters are ignored. In particular the input string may contain arbitrary amounts of whitespace.

Due to the characteristics of base64, the output slice's length is always <=3/4 of the input length. The underlying array reserved by this function always has exactly (len(b64)>>2)*3 +3 bytes capacity, but the returned slice has the correct length.

The function can decode both standard encoding (using "+" and "/") and URL encoding (which uses "-" and "_").

The function doesn't care about the number of "=" characters. Each sequence of one or more "=" characters serves to flush the bytes from a partially decoded block. So if you want to concatenate multiple base64 strings you can always insert a "=" character between them to make sure that the first string doesn't influence the second, even if it is not properly padded (or corrupt). You can also feed the string "=" into this function to flush the carry.

func Base64EncodeInPlace

func Base64EncodeInPlace(data []byte, idx int) []byte

In-place base64 encoder. Encodes data[idx:] and writes the encoded base64 data (standard alphabet) to data[0:]. The value of idx must be at least (((len(data[idx:])+2)/3)<<2)-len(data[idx:]) or the result will be corrupted.

The function returns a subslice data[0:n] that contains the encoded data.

If idx is exactly the minimum value, then the returned subslice will be identical to data. If idx is larger than necessary, the returned subslice will be shorter.

The result is always padded with "=" to a multiple of 4 characters length.

func Base64EncodeString

func Base64EncodeString(data string) (encoded []byte)

Returns the base64 encoding (standard alphabet) of data. The result is always padded with "=" to a multiple of 4 characters.

func Counter

func Counter(start uint64) chan uint64

Returns a new channel that will return start as first item and then always the next number.

func DebVersionCompare

func DebVersionCompare(v1, v2 string) int

Returns -1, 0, +1 if v1 is less, equal, greater than v2 according to Debian version comparison rules.

See https://www.debian.org/doc/debian-policy/ch-controlfields.html
section "5.6.12 Version"

func DebVersionLess

func DebVersionLess(v1, v2 string) bool

Returns true if v1 is older than v2 according to Debian version comparison rules.

See https://www.debian.org/doc/debian-policy/ch-controlfields.html
section "5.6.12 Version"

func Log

func Log(level int, format string, args ...interface{})

Outputs a message to all loggers added by LoggerAdd() formatted as by fmt.Printf(). The level parameter assigns an importance to the message, where 0 is the most important (such as fatal errors) and increasing numbers mark messages of lesser importance. The idea is that a message of level N should only be printed when the program was started with N -v (i.e. verbose) switches. So level 0 marks messages that should always be logged. Level 1 are informative messages the user may not care about. Level 2 and above are typically used for debug messages, where level 2 are debug messages that may help the user pinpoint a problem and level 3 are debug messages only useful to developers. There is usually no need for higher levels.

func LogFile

func LogFile(fpath string) io.WriteCloser

Returns a io.WriteCloser that appends to the file fpath, checking on each write if fpath still refers to the same file and if it doesn't re-opens or re-creates the file fpath to append to. This behaviour is compatible with log-rotation without incurring the overhead of re-opening the file on every write.

NOTE: While closing the returned object will close the underlying file if it is open, it will not invalidate the object. The next write will open the file again (creating it if necessary) and will append to it.

func LoggerAdd

func LoggerAdd(w io.Writer)

Adds w to the beginning of the list of loggers. Note that any logger that blocks during Write() will prevent loggers later in the list from receiving data. No checking is done to see if w is already in the list. If w == nil, nothing happens.

The most efficient loggers are those that buffer data and support a Flush() or Sync() operation (e.g. os.File or bufio.Writer). The background task that writes to the loggers will call Flush()/Sync() whenever there is no backlog, so even if the logger has a large buffer, data will only be delayed if there is a backlog of messages.

func LoggerRemove

func LoggerRemove(w io.Writer)

Removes all loggers from the queue that are == to w (if any). If w == nil, nothing happens.

func LoggersCount

func LoggersCount() int

Returns the number of currently active loggers (not counting those suspended by LoggersSuspend())

func LoggersFlush

func LoggersFlush(maxwait time.Duration)

Does not return until all messages that have accrued up to this point have been processed and all loggers that are Flushable or Syncable have been flushed/synched. Messages that are logged while LoggersFlush() is executing are not guaranteed to be logged.

If you pass maxwait != 0, this function will return after at most this duration, even if the logs have not been flushed completely up to this point.

func LoggersRestore

func LoggersRestore()

Restores the loggers list at the most recent LoggersSuspend() call. Loggers that were deactivated by LoggersSuspend() are reactivated and all loggers added after that call are removed.

ATTENTION! If this function is called without LoggersSuspend() having been called first, all loggers will be removed.

func LoggersSuspend

func LoggersSuspend()

Disables all loggers currently in the list of loggers until LoggersRestore() is called. Loggers added later via LoggerAdd() are unaffected, so this call can be used to temporarily switch to a different set of loggers. Multiple LoggersSuspend()/LoggersRestore() pairs may be nested.

func MakeTimestamp

func MakeTimestamp(t time.Time) string

Converts t into a timestamp appropriate for use in siserver messages. The timestamp loses the time zone information of t. No time zone conversion will be performed. IOW "12:00 UTC" and "12:00 PDT" will both result in a timestamp that says "yyyymmdd1200ss".

func Md5sum

func Md5sum(s string) string

Returns the md5sum of its argument as a string of hex digits.

func ParseTimestamp

func ParseTimestamp(ts string) time.Time

Converts a timestamp as used in siserver messages into a time.Time. The returned time will be the time at which the server clock's current time converted with MakeTimestamp() is ts. The computation is based on the assumption that the server's time zone does not change EXCEPT for daylight savings time. IOW on a server running on local time in Berlin ParseTimestamp("20140101120000") gives 12:00 CET (winter time) and ParseTimestamp("20140601120000") gives 12:00 CEST (summer time).

ParseTimestamp() returns time.Unix(0,0) if the timestamp is invalid.

func ReadLn

func ReadLn(conn net.Conn, timeout time.Duration) (string, error)

Reads from the connection until \n is seen (or timeout or error) and returns the read data without any trailing \n or \r.

If timeout > 0, then reading will stop after at most this duration and the function will return with an error. If timeout <= 0 there will be no timeout (any pre-existing read deadline will be cleared).

If an error (or timeout) occurs before \n is seen, the data read up to the error is returned (without any trailing \r).

You should probably give special treatment to the case of an io.EOF error being returned. This happens when the last line of the connection is not terminated by \n. It often makes sense to not treat this as an error.

NOTE: This function reads individual bytes which means that data following the line read is still available for reading (in particular you can read subsequent lines by calling ReadLn() again). The drawback, however, is lower throughput compared to reading in chunks.

func Resolve

func Resolve(addr string, localip string) (string, error)

Takes either a HOST or a HOST:IP pair and replaces the HOST part with that machine's IP address (preferring an IPv4 address if there is one). If HOST is "localhost" or "::1", it will be replaced with "127.0.0.1". If HOST is already an IPv4 address, it will be kept. If there is only an IPv6 address available, it will be enclosed in "[...]" in the result (even if there is no port).

If localip != "" in the result "127.0.0.1" will be replaced with localip.

Returns the modified address or the original address with an error.

func SendLn

func SendLn(conn net.Conn, s string, timeout time.Duration) error

Sends strings via connection conn, followed by "\r\n" If timeout >= 0, then the send attempt will be aborted after at most this duration. Returns nil if sending was successful, an error otherwise. The error will also be sent to the log, so the caller does not have to log it.

func SendLnTo

func SendLnTo(target string, msg string, timeout time.Duration)

Opens a connection to target (e.g. "foo.example.com:20081"), sends msg followed by \r\n and then closes the connection. If timeout >= 0, then the connection will be terminated after at most this duration.

func WaitForDNS

func WaitForDNS(timeout time.Duration) bool

Waits until either the duration timeout has passed or DNS is available ON A NON-LOOPBACK INTERFACE (so this waits until external interfaces are up). If timeout == 0, wait forever if necessary. Returns true if DNS is available.

func WaitUntil

func WaitUntil(t time.Time)

Sleeps until time t. If clock is adjusted during the sleep, this will not cause more than 10 minutes extra sleep. In no case will this function return until time.Now() >= t.

func Wake

func Wake(macaddress string, host_or_net string) error

Sends a UDP wake-on-lan packet coded for the given macaddress to the broadcast address for the given host or network.

host_or_net can be:
  a) a host name (with or without ":<port>")
  b) a host's IP address from which the broadcast address will be
     derived by setting final byte to 255
  c) a network's broadcast IP address
If host_or_net includes a port that port will be used, otherwise the
default port 40000 is used.

func WithPanicHandler

func WithPanicHandler(g func())

Calls g wrapped in a panic handler that logs the panic and recovers from it. Example:

go util.WithPanicHandler(foobar)
go util.WithPanicHandler(func(){ Send_foreign_job_updates(server, jobs) })

func WriteAll

func WriteAll(w io.Writer, data []byte) (n int, err error)

Writes data to w, with automatic handling of short writes. A short write error will only be returned if multiple attempts failed in a row.

Types

type Flushable

type Flushable interface {
	Flush() error
}

type Syncable

type Syncable interface {
	Sync() error
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL