Commit ea6c227a authored by Geoff Simmons's avatar Geoff Simmons

Add package vsm.

parent 3b321d6c
// +build e2e
/*-
* Copyright (c) 2018 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
// This test is only run if go test is invoked with a -tags option
// that includes "e2e". It requires that two instances of Varnish are
// running: a default instance (varnishd invoked without the -n
// option), and an instance named "gotest" (varnishd -n "gotest"). For
// the purposes of this test, it does not matter how either instance
// is configured, only that they are running.
package vsm
import (
"testing"
"time"
)
func TestNewDestroy(t *testing.T) {
v := New()
defer v.Destroy()
if v == nil {
t.Fatal("New() returned nil")
}
var n *VSM
if err := n.Destroy(); err == nil {
t.Error("expected nil.Destroy() to fail")
}
uninit := new(VSM)
if err := uninit.Destroy(); err == nil {
t.Error("expected uninitialized.Destroy() to fail")
}
}
const nilobjerr string = "VSM object is nil"
const uniniterr string = "VSM object was uninitialized via New()"
func TestError(t *testing.T) {
v := New()
defer v.Destroy()
s := v.Error()
if s == "" {
t.Error("Error() expected empty got: ", s)
}
var n *VSM
if err := n.Error(); err != nilobjerr {
t.Errorf("nil.Error() expected=\"%v\" got=\"%v\"",
nilobjerr, err)
}
uninit := new(VSM)
if err := uninit.Error(); err != uniniterr {
t.Errorf("uninitialized.Error() expected=\"%v\" got=\"%v\"",
uniniterr, err)
}
}
func TestAttach(t *testing.T) {
v := New()
defer v.Destroy()
if err := v.Attach(false); err != nil {
t.Fatal("Attach(false):", err)
}
var n *VSM
if err := n.Attach(false); err == nil {
t.Error("expected nil.Attach() to fail")
}
uninit := new(VSM)
if err := uninit.Attach(false); err == nil {
t.Error("expected uninitialized.Attach() to fail")
}
}
func TestAttachProgress(t *testing.T) {
v := New()
defer v.Destroy()
if err := v.Attach(true); err != nil {
t.Error("Attach(true):", err)
}
}
const zerosec = time.Duration(0)
func TestAttachTmo(t *testing.T) {
v := New()
defer v.Destroy()
for _, s := range []int{0, 1, -1, ^0, int(^uint(0) >> 1)} {
if e := v.AttachTmo(time.Duration(s) * time.Second); e != nil {
t.Error("AttachTmo():", e)
}
}
var n *VSM
if err := n.AttachTmo(zerosec); err == nil {
t.Error("expected nil.AttachTmo() to fail")
}
uninit := new(VSM)
if err := uninit.AttachTmo(zerosec); err == nil {
t.Error("expected uninitialized.AttachTmo() to fail")
}
}
func TestAttachInstance(t *testing.T) {
v := New()
defer v.Destroy()
if err := v.AttachInstance("gotest", false); err != nil {
t.Error("AttachInstance(\"gotest\"):", err)
}
f := New()
defer f.Destroy()
if err := f.AttachTmo(zerosec); err != nil {
t.Error("AttachTmo(0s):", err)
}
if err := f.AttachInstance("instanceDoesNotExist", false); err == nil {
t.Error("expected AttachInstance() to fail for a " +
"non-existent instance")
}
}
/*-
* Copyright (c) 2018 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
// Package vsm implements attachment to Varnish shared memory, to read
// logs, statistics and other information.
package vsm
/*
#cgo pkg-config: varnishapi
#include <stdint.h>
#include <vapi/vsm.h>
*/
import "C"
import (
"errors"
"strconv"
"time"
)
// An Attacher can attach to a running instance of Varnish. This means
// that it can obtain information from resources that are actively
// managed and updated by the live Varnish child process.
type Attacher interface {
// Set the timeout for attaching to a Varnish instance. If the
// Duration, rounded to seconds toward 0s, is >= 0s, then wait
// that many seconds to attach. If the Duration < 0s, wait
// indefinitely. By default, the Varnish default timeout holds
// (5s in recent Varnish versions).
AttachTmo(time.Duration) error
// Attach to the default instance of Varnish -- the instance
// of varnishd invoked without the -n option.
//
// If the bool argument is true, a dot ('.') is printed to
// standard output for each second waiting for the attach to
// succeed. If the attach fails after timeout, a newline is
// printed. If the argument is false, there is no such output.
Attach(bool) error
// Attach to a named instance of Varnish, where the string
// corresponds to the -n argument in the invocation of
// varnishd.
AttachInstance(string, bool) error
}
// VSM provides methods for attaching to Varnish shared memory.
type VSM struct {
vsm *C.struct_vsm
}
// New returns a new and initialied instance of VSM. Instances should
// only be created through this function, since it performs
// initializations for the native library that are required for the
// object methods.
//
// New may return nil in rare cases, usually in an out of memory
// condition.
func New() *VSM {
vsmp := C.VSM_New()
if vsmp == nil {
return nil
}
return &VSM{vsmp}
}
func (v *VSM) checkNil() error {
if v == nil {
return errors.New("VSM object is nil")
}
if v.vsm == nil {
return errors.New("VSM object was uninitialized via New()")
}
return nil
}
// Destroy releases native resources associated with this object. You
// should always call Destroy when you're done using with a VSM
// object, otherwise there is risk of resource leakage.
func (v *VSM) Destroy() error {
if err := v.checkNil(); err != nil {
return err
}
C.VSM_Destroy(&v.vsm)
return nil
}
// Error returns the most recent error message from the native
// library.
func (v *VSM) Error() string {
if err := v.checkNil(); err != nil {
return err.Error()
}
return C.GoString(C.VSM_Error(v.vsm))
}
// AttachTmo sets the timeout for attaching to a Varnish instance, as
// documented for the Attacher interface.
func (v *VSM) AttachTmo(tmo time.Duration) error {
if err := v.checkNil(); err != nil {
return err
}
arg := "off"
secs := tmo / time.Second
if secs >= 0 {
arg = strconv.FormatUint(uint64(secs), 10)
}
C.VSM_ResetError(v.vsm)
if C.VSM_Arg(v.vsm, 't', C.CString(arg)) != 1 {
return v
}
return nil
}
func (v *VSM) attach(progress bool) error {
if err := v.checkNil(); err != nil {
return err
}
prog := -1
if progress {
prog = 0
}
C.VSM_ResetError(v.vsm)
if C.VSM_Attach(v.vsm, C.int(prog)) != 0 {
return v
}
return nil
}
// Attach attaches to the default instance of Varnish, as documented
// for the Attacher interface.
func (v *VSM) Attach(progress bool) error {
return v.attach(progress)
}
// AttachInstance attaches to a named instance of Varnish, as
// documented for the Attacher interface.
func (v *VSM) AttachInstance(inst string, progress bool) error {
C.VSM_ResetError(v.vsm)
if C.VSM_Arg(v.vsm, 'n', C.CString(inst)) != 1 {
return v
}
return v.attach(progress)
}
/*
func (v *VSM) Get(class string, ident string) (string, error) {
var vf C.struct_vsm_fantom
if C.VSM_Get(v.vsm, &vf, C.CString(class), C.CString(ident)) == 0 {
return "", v
}
return C.GoStringN(vf.b, vf.e - vf.b), nil
}
*/
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment