<commit_before>package rados

// #cgo LDFLAGS: -lrados
// #include <stdlib.h>
// #include <rados/librados.h>
import "C"

import (
	"bytes"
	"errors"
	"unsafe"
)

var (
	// ErrNotConnected is returned when functions are called without a RADOS connection
	ErrNotConnected = errors.New("RADOS not connected")
)

// ClusterStat represents Ceph cluster statistics.
type ClusterStat struct {
	Kb          uint64
	Kb_used     uint64
	Kb_avail    uint64
	Num_objects uint64
}

// Conn is a connection handle to a Ceph cluster.
type Conn struct {
	cluster   C.rados_t
	connected bool
}

// PingMonitor sends a ping to a monitor and returns the reply.
func (c *Conn) PingMonitor(id string) (string, error) {
	c_id := C.CString(id)
	defer C.free(unsafe.Pointer(c_id))

	var strlen C.size_t
	var strout *C.char

	ret := C.rados_ping_monitor(c.cluster, c_id, &strout, &strlen)
	defer C.rados_buffer_free(strout)

	if ret == 0 {
		reply := C.GoStringN(strout, (C.int)(strlen))
		return reply, nil
	}
	return "", RadosError(int(ret))
}

// Connect establishes a connection to a RADOS cluster. It returns an error,
// if any.
func (c *Conn) Connect() error {
	ret := C.rados_connect(c.cluster)
	if ret != 0 {
		return RadosError(int(ret))
	}
	c.connected = true
	return nil
}

// Shutdown disconnects from the cluster.
func (c *Conn) Shutdown() {
	if err := c.ensure_connected(); err != nil {
		return
	}
	freeConn(c)
}

// ReadConfigFile configures the connection using a Ceph configuration file.
func (c *Conn) ReadConfigFile(path string) error {
	c_path := C.CString(path)
	defer C.free(unsafe.Pointer(c_path))
	ret := C.rados_conf_read_file(c.cluster, c_path)
	return getRadosError(int(ret))
}

// ReadDefaultConfigFile configures the connection using a Ceph configuration
// file located at default locations.
func (c *Conn) ReadDefaultConfigFile() error {
	ret := C.rados_conf_read_file(c.cluster, nil)
	return getRadosError(int(ret))
}

// OpenIOContext creates and returns a new IOContext for the given pool.
//
// Implements:
//  int rados_ioctx_create(rados_t cluster, const char *pool_name,
//                         rados_ioctx_t *ioctx);
func (c *Conn) OpenIOContext(pool string) (*IOContext, error) {
	c_pool := C.CString(pool)
	defer C.free(unsafe.Pointer(c_pool))
	ioctx := &IOContext{}
	ret := C.rados_ioctx_create(c.cluster, c_pool, &ioctx.ioctx)
	if ret == 0 {
		return ioctx, nil
	}
	return nil, RadosError(int(ret))
}

// ListPools returns the names of all existing pools.
func (c *Conn) ListPools() (names []string, err error) {
	buf := make([]byte, 4096)
	for {
		ret := int(C.rados_pool_list(c.cluster,
			(*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))))
		if ret < 0 {
			return nil, RadosError(int(ret))
		}

		if ret > len(buf) {
			buf = make([]byte, ret)
			continue
		}

		tmp := bytes.SplitAfter(buf[:ret-1], []byte{0})
		for _, s := range tmp {
			if len(s) > 0 {
				name := C.GoString((*C.char)(unsafe.Pointer(&s[0])))
				names = append(names, name)
			}
		}

		return names, nil
	}
}

// SetConfigOption sets the value of the configuration option identified by
// the given name.
func (c *Conn) SetConfigOption(option, value string) error {
	c_opt, c_val := C.CString(option), C.CString(value)
	defer C.free(unsafe.Pointer(c_opt))
	defer C.free(unsafe.Pointer(c_val))
	ret := C.rados_conf_set(c.cluster, c_opt, c_val)
	return getRadosError(int(ret))
}

// GetConfigOption returns the value of the Ceph configuration option
// identified by the given name.
func (c *Conn) GetConfigOption(name string) (value string, err error) {
	buf := make([]byte, 4096)
	c_name := C.CString(name)
	defer C.free(unsafe.Pointer(c_name))
	ret := int(C.rados_conf_get(c.cluster, c_name,
		(*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))))
	// FIXME: ret may be -ENAMETOOLONG if the buffer is not large enough. We
	// can handle this case, but we need a reliable way to test for
	// -ENAMETOOLONG constant. Will the syscall/Errno stuff in Go help?
	if ret == 0 {
		value = C.GoString((*C.char)(unsafe.Pointer(&buf[0])))
		return value, nil
	}
	return "", RadosError(ret)
}

// WaitForLatestOSDMap blocks the caller until the latest OSD map has been
// retrieved.
func (c *Conn) WaitForLatestOSDMap() error {
	ret := C.rados_wait_for_latest_osdmap(c.cluster)
	return getRadosError(int(ret))
}

func (c *Conn) ensure_connected() error {
	if c.connected {
		return nil
	}
	return ErrNotConnected
}

// GetClusterStats returns statistics about the cluster associated with the
// connection.
func (c *Conn) GetClusterStats() (stat ClusterStat, err error) {
	if err := c.ensure_connected(); err != nil {
		return ClusterStat{}, err
	}
	c_stat := C.struct_rados_cluster_stat_t{}
	ret := C.rados_cluster_stat(c.cluster, &c_stat)
	if ret < 0 {
		return ClusterStat{}, RadosError(int(ret))
	}
	return ClusterStat{
		Kb:          uint64(c_stat.kb),
		Kb_used:     uint64(c_stat.kb_used),
		Kb_avail:    uint64(c_stat.kb_avail),
		Num_objects: uint64(c_stat.num_objects),
	}, nil
}

// ParseCmdLineArgs configures the connection from command line arguments.
func (c *Conn) ParseCmdLineArgs(args []string) error {
	// add an empty element 0 -- Ceph treats the array as the actual contents
	// of argv and skips the first element (the executable name)
	argc := C.int(len(args) + 1)
	argv := make([]*C.char, argc)

	// make the first element a string just in case it is ever examined
	argv[0] = C.CString("placeholder")
	defer C.free(unsafe.Pointer(argv[0]))

	for i, arg := range args {
		argv[i+1] = C.CString(arg)
		defer C.free(unsafe.Pointer(argv[i+1]))
	}

	ret := C.rados_conf_parse_argv(c.cluster, argc, &argv[0])
	return getRadosError(int(ret))
}

// ParseDefaultConfigEnv configures the connection from the default Ceph
// environment variable(s).
func (c *Conn) ParseDefaultConfigEnv() error {
	ret := C.rados_conf_parse_env(c.cluster, nil)
	return getRadosError(int(ret))
}

// GetFSID returns the fsid of the cluster as a hexadecimal string. The fsid
// is a unique identifier of an entire Ceph cluster.
func (c *Conn) GetFSID() (fsid string, err error) {
	buf := make([]byte, 37)
	ret := int(C.rados_cluster_fsid(c.cluster,
		(*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))))
	// FIXME: the success case isn't documented correctly in librados.h
	if ret == 36 {
		fsid = C.GoString((*C.char)(unsafe.Pointer(&buf[0])))
		return fsid, nil
	}
	return "", RadosError(int(ret))
}

// GetInstanceID returns a globally unique identifier for the cluster
// connection instance.
func (c *Conn) GetInstanceID() uint64 {
	// FIXME: are there any error cases for this?
	return uint64(C.rados_get_instance_id(c.cluster))
}

// MakePool creates a new pool with default settings.
func (c *Conn) MakePool(name string) error {
	c_name := C.CString(name)
	defer C.free(unsafe.Pointer(c_name))
	ret := int(C.rados_pool_create(c.cluster, c_name))
	return getRadosError(int(ret))
}

// DeletePool deletes a pool and all the data inside the pool.
func (c *Conn) DeletePool(name string) error {
	if err := c.ensure_connected(); err != nil {
		return err
	}
	c_name := C.CString(name)
	defer C.free(unsafe.Pointer(c_name))
	ret := int(C.rados_pool_delete(c.cluster, c_name))
	return getRadosError(int(ret))
}

// GetPoolByName returns the ID of the pool with a given name.
func (c *Conn) GetPoolByName(name string) (int64, error) {
	if err := c.ensure_connected(); err != nil {
		return 0, err
	}
	c_name := C.CString(name)
	defer C.free(unsafe.Pointer(c_name))
	ret := int64(C.rados_pool_lookup(c.cluster, c_name))
	if ret < 0 {
		return 0, RadosError(ret)
	}
	return ret, nil
}

// GetPoolByID returns the name of a pool by a given ID.
func (c *Conn) GetPoolByID(id int64) (string, error) {
	buf := make([]byte, 4096)
	if err := c.ensure_connected(); err != nil {
		return "", err
	}
	c_id := C.int64_t(id)
	ret := int(C.rados_pool_reverse_lookup(c.cluster, c_id, (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))))
	if ret < 0 {
		return "", RadosError(ret)
	}
	return C.GoString((*C.char)(unsafe.Pointer(&buf[0]))), nil
}

// MonCommand sends a command to one of the monitors
func (c *Conn) MonCommand(args []byte) (buffer []byte, info string, err error) {
	return c.monCommand(args, nil)
}

// MonCommandWithInputBuffer sends a command to one of the monitors, with an input buffer
func (c *Conn) MonCommandWithInputBuffer(args, inputBuffer []byte) (buffer []byte, info string, err error) {
	return c.monCommand(args, inputBuffer)
}

func (c *Conn) monCommand(args, inputBuffer []byte) (buffer []byte, info string, err error) {
	argv := C.CString(string(args))
	defer C.free(unsafe.Pointer(argv))

	var (
		outs, outbuf       *C.char
		outslen, outbuflen C.size_t
	)
	inbuf := C.CString(string(inputBuffer))
	inbufLen := len(inputBuffer)
	defer C.free(unsafe.Pointer(inbuf))

	ret := C.rados_mon_command(c.cluster,
		&argv, 1,
		inbuf,              // bulk input (e.g. crush map)
		C.size_t(inbufLen), // length inbuf
		&outbuf,            // buffer
		&outbuflen,         // buffer length
		&outs,              // status string
		&outslen)

	if outslen > 0 {
		info = C.GoStringN(outs, C.int(outslen))
		C.free(unsafe.Pointer(outs))
	}
	if outbuflen > 0 {
		buffer = C.GoBytes(unsafe.Pointer(outbuf), C.int(outbuflen))
		C.free(unsafe.Pointer(outbuf))
	}
	if ret != 0 {
		err = RadosError(int(ret))
		return nil, info, err
	}

	return
}

// PGCommand sends a command to one of the PGs
func (c *Conn) PGCommand(pgid []byte, args [][]byte) (buffer []byte, info string, err error) {
	return c.pgCommand(pgid, args, nil)
}

// PGCommand sends a command to one of the PGs, with an input buffer
func (c *Conn) PGCommandWithInputBuffer(pgid []byte, args [][]byte, inputBuffer []byte) (buffer []byte, info string, err error) {
	return c.pgCommand(pgid, args, inputBuffer)
}

func (c *Conn) pgCommand(pgid []byte, args [][]byte, inputBuffer []byte) (buffer []byte, info string, err error) {
	name := C.CString(string(pgid))
	defer C.free(unsafe.Pointer(name))

	argc := len(args)
	argv := make([]*C.char, argc)

	for i, arg := range args {
		argv[i] = C.CString(string(arg))
		defer C.free(unsafe.Pointer(argv[i]))
	}

	var (
		outs, outbuf       *C.char
		outslen, outbuflen C.size_t
	)
	inbuf := C.CString(string(inputBuffer))
	inbufLen := len(inputBuffer)
	defer C.free(unsafe.Pointer(inbuf))

	ret := C.rados_pg_command(c.cluster,
		name,
		&argv[0],
		C.size_t(argc),
		inbuf,              // bulk input
		C.size_t(inbufLen), // length inbuf
		&outbuf,            // buffer
		&outbuflen,         // buffer length
		&outs,              // status string
		&outslen)

	if outslen > 0 {
		info = C.GoStringN(outs, C.int(outslen))
		C.free(unsafe.Pointer(outs))
	}
	if outbuflen > 0 {
		buffer = C.GoBytes(unsafe.Pointer(outbuf), C.int(outbuflen))
		C.free(unsafe.Pointer(outbuf))
	}
	if ret != 0 {
		err = RadosError(int(ret))
		return nil, info, err
	}

	return
}
<commit_msg>rados: fix and update doc comments for PGCommand funcs<commit_after>package rados

// #cgo LDFLAGS: -lrados
// #include <stdlib.h>
// #include <rados/librados.h>
import "C"

import (
	"bytes"
	"errors"
	"unsafe"
)

var (
	// ErrNotConnected is returned when functions are called without a RADOS connection
	ErrNotConnected = errors.New("RADOS not connected")
)

// ClusterStat represents Ceph cluster statistics.
type ClusterStat struct {
	Kb          uint64
	Kb_used     uint64
	Kb_avail    uint64
	Num_objects uint64
}

// Conn is a connection handle to a Ceph cluster.
type Conn struct {
	cluster   C.rados_t
	connected bool
}

// PingMonitor sends a ping to a monitor and returns the reply.
func (c *Conn) PingMonitor(id string) (string, error) {
	c_id := C.CString(id)
	defer C.free(unsafe.Pointer(c_id))

	var strlen C.size_t
	var strout *C.char

	ret := C.rados_ping_monitor(c.cluster, c_id, &strout, &strlen)
	defer C.rados_buffer_free(strout)

	if ret == 0 {
		reply := C.GoStringN(strout, (C.int)(strlen))
		return reply, nil
	}
	return "", RadosError(int(ret))
}

// Connect establishes a connection to a RADOS cluster. It returns an error,
// if any.
func (c *Conn) Connect() error {
	ret := C.rados_connect(c.cluster)
	if ret != 0 {
		return RadosError(int(ret))
	}
	c.connected = true
	return nil
}

// Shutdown disconnects from the cluster.
func (c *Conn) Shutdown() {
	if err := c.ensure_connected(); err != nil {
		return
	}
	freeConn(c)
}

// ReadConfigFile configures the connection using a Ceph configuration file.
func (c *Conn) ReadConfigFile(path string) error {
	c_path := C.CString(path)
	defer C.free(unsafe.Pointer(c_path))
	ret := C.rados_conf_read_file(c.cluster, c_path)
	return getRadosError(int(ret))
}

// ReadDefaultConfigFile configures the connection using a Ceph configuration
// file located at default locations.
func (c *Conn) ReadDefaultConfigFile() error {
	ret := C.rados_conf_read_file(c.cluster, nil)
	return getRadosError(int(ret))
}

// OpenIOContext creates and returns a new IOContext for the given pool.
//
// Implements:
//  int rados_ioctx_create(rados_t cluster, const char *pool_name,
//                         rados_ioctx_t *ioctx);
func (c *Conn) OpenIOContext(pool string) (*IOContext, error) {
	c_pool := C.CString(pool)
	defer C.free(unsafe.Pointer(c_pool))
	ioctx := &IOContext{}
	ret := C.rados_ioctx_create(c.cluster, c_pool, &ioctx.ioctx)
	if ret == 0 {
		return ioctx, nil
	}
	return nil, RadosError(int(ret))
}

// ListPools returns the names of all existing pools.
func (c *Conn) ListPools() (names []string, err error) {
	buf := make([]byte, 4096)
	for {
		ret := int(C.rados_pool_list(c.cluster,
			(*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))))
		if ret < 0 {
			return nil, RadosError(int(ret))
		}

		if ret > len(buf) {
			buf = make([]byte, ret)
			continue
		}

		tmp := bytes.SplitAfter(buf[:ret-1], []byte{0})
		for _, s := range tmp {
			if len(s) > 0 {
				name := C.GoString((*C.char)(unsafe.Pointer(&s[0])))
				names = append(names, name)
			}
		}

		return names, nil
	}
}

// SetConfigOption sets the value of the configuration option identified by
// the given name.
func (c *Conn) SetConfigOption(option, value string) error {
	c_opt, c_val := C.CString(option), C.CString(value)
	defer C.free(unsafe.Pointer(c_opt))
	defer C.free(unsafe.Pointer(c_val))
	ret := C.rados_conf_set(c.cluster, c_opt, c_val)
	return getRadosError(int(ret))
}

// GetConfigOption returns the value of the Ceph configuration option
// identified by the given name.
func (c *Conn) GetConfigOption(name string) (value string, err error) {
	buf := make([]byte, 4096)
	c_name := C.CString(name)
	defer C.free(unsafe.Pointer(c_name))
	ret := int(C.rados_conf_get(c.cluster, c_name,
		(*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))))
	// FIXME: ret may be -ENAMETOOLONG if the buffer is not large enough. We
	// can handle this case, but we need a reliable way to test for
	// -ENAMETOOLONG constant. Will the syscall/Errno stuff in Go help?
	if ret == 0 {
		value = C.GoString((*C.char)(unsafe.Pointer(&buf[0])))
		return value, nil
	}
	return "", RadosError(ret)
}

// WaitForLatestOSDMap blocks the caller until the latest OSD map has been
// retrieved.
func (c *Conn) WaitForLatestOSDMap() error {
	ret := C.rados_wait_for_latest_osdmap(c.cluster)
	return getRadosError(int(ret))
}

func (c *Conn) ensure_connected() error {
	if c.connected {
		return nil
	}
	return ErrNotConnected
}

// GetClusterStats returns statistics about the cluster associated with the
// connection.
func (c *Conn) GetClusterStats() (stat ClusterStat, err error) {
	if err := c.ensure_connected(); err != nil {
		return ClusterStat{}, err
	}
	c_stat := C.struct_rados_cluster_stat_t{}
	ret := C.rados_cluster_stat(c.cluster, &c_stat)
	if ret < 0 {
		return ClusterStat{}, RadosError(int(ret))
	}
	return ClusterStat{
		Kb:          uint64(c_stat.kb),
		Kb_used:     uint64(c_stat.kb_used),
		Kb_avail:    uint64(c_stat.kb_avail),
		Num_objects: uint64(c_stat.num_objects),
	}, nil
}

// ParseCmdLineArgs configures the connection from command line arguments.
func (c *Conn) ParseCmdLineArgs(args []string) error {
	// add an empty element 0 -- Ceph treats the array as the actual contents
	// of argv and skips the first element (the executable name)
	argc := C.int(len(args) + 1)
	argv := make([]*C.char, argc)

	// make the first element a string just in case it is ever examined
	argv[0] = C.CString("placeholder")
	defer C.free(unsafe.Pointer(argv[0]))

	for i, arg := range args {
		argv[i+1] = C.CString(arg)
		defer C.free(unsafe.Pointer(argv[i+1]))
	}

	ret := C.rados_conf_parse_argv(c.cluster, argc, &argv[0])
	return getRadosError(int(ret))
}

// ParseDefaultConfigEnv configures the connection from the default Ceph
// environment variable(s).
func (c *Conn) ParseDefaultConfigEnv() error {
	ret := C.rados_conf_parse_env(c.cluster, nil)
	return getRadosError(int(ret))
}

// GetFSID returns the fsid of the cluster as a hexadecimal string. The fsid
// is a unique identifier of an entire Ceph cluster.
func (c *Conn) GetFSID() (fsid string, err error) {
	buf := make([]byte, 37)
	ret := int(C.rados_cluster_fsid(c.cluster,
		(*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))))
	// FIXME: the success case isn't documented correctly in librados.h
	if ret == 36 {
		fsid = C.GoString((*C.char)(unsafe.Pointer(&buf[0])))
		return fsid, nil
	}
	return "", RadosError(int(ret))
}

// GetInstanceID returns a globally unique identifier for the cluster
// connection instance.
func (c *Conn) GetInstanceID() uint64 {
	// FIXME: are there any error cases for this?
	return uint64(C.rados_get_instance_id(c.cluster))
}

// MakePool creates a new pool with default settings.
func (c *Conn) MakePool(name string) error {
	c_name := C.CString(name)
	defer C.free(unsafe.Pointer(c_name))
	ret := int(C.rados_pool_create(c.cluster, c_name))
	return getRadosError(int(ret))
}

// DeletePool deletes a pool and all the data inside the pool.
func (c *Conn) DeletePool(name string) error {
	if err := c.ensure_connected(); err != nil {
		return err
	}
	c_name := C.CString(name)
	defer C.free(unsafe.Pointer(c_name))
	ret := int(C.rados_pool_delete(c.cluster, c_name))
	return getRadosError(int(ret))
}

// GetPoolByName returns the ID of the pool with a given name.
func (c *Conn) GetPoolByName(name string) (int64, error) {
	if err := c.ensure_connected(); err != nil {
		return 0, err
	}
	c_name := C.CString(name)
	defer C.free(unsafe.Pointer(c_name))
	ret := int64(C.rados_pool_lookup(c.cluster, c_name))
	if ret < 0 {
		return 0, RadosError(ret)
	}
	return ret, nil
}

// GetPoolByID returns the name of a pool by a given ID.
func (c *Conn) GetPoolByID(id int64) (string, error) {
	buf := make([]byte, 4096)
	if err := c.ensure_connected(); err != nil {
		return "", err
	}
	c_id := C.int64_t(id)
	ret := int(C.rados_pool_reverse_lookup(c.cluster, c_id, (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))))
	if ret < 0 {
		return "", RadosError(ret)
	}
	return C.GoString((*C.char)(unsafe.Pointer(&buf[0]))), nil
}

// MonCommand sends a command to one of the monitors
func (c *Conn) MonCommand(args []byte) (buffer []byte, info string, err error) {
	return c.monCommand(args, nil)
}

// MonCommandWithInputBuffer sends a command to one of the monitors, with an input buffer
func (c *Conn) MonCommandWithInputBuffer(args, inputBuffer []byte) (buffer []byte, info string, err error) {
	return c.monCommand(args, inputBuffer)
}

func (c *Conn) monCommand(args, inputBuffer []byte) (buffer []byte, info string, err error) {
	argv := C.CString(string(args))
	defer C.free(unsafe.Pointer(argv))

	var (
		outs, outbuf       *C.char
		outslen, outbuflen C.size_t
	)
	inbuf := C.CString(string(inputBuffer))
	inbufLen := len(inputBuffer)
	defer C.free(unsafe.Pointer(inbuf))

	ret := C.rados_mon_command(c.cluster,
		&argv, 1,
		inbuf,              // bulk input (e.g. crush map)
		C.size_t(inbufLen), // length inbuf
		&outbuf,            // buffer
		&outbuflen,         // buffer length
		&outs,              // status string
		&outslen)

	if outslen > 0 {
		info = C.GoStringN(outs, C.int(outslen))
		C.free(unsafe.Pointer(outs))
	}
	if outbuflen > 0 {
		buffer = C.GoBytes(unsafe.Pointer(outbuf), C.int(outbuflen))
		C.free(unsafe.Pointer(outbuf))
	}
	if ret != 0 {
		err = RadosError(int(ret))
		return nil, info, err
	}

	return
}

// PGCommand sends a command to one of the PGs
//
// Implements:
//  int rados_pg_command(rados_t cluster, const char *pgstr,
//                       const char **cmd, size_t cmdlen,
//                       const char *inbuf, size_t inbuflen,
//                       char **outbuf, size_t *outbuflen,
//                       char **outs, size_t *outslen);
func (c *Conn) PGCommand(pgid []byte, args [][]byte) (buffer []byte, info string, err error) {
	return c.pgCommand(pgid, args, nil)
}

// PGCommandWithInputBuffer sends a command to one of the PGs, with an input buffer
//
// Implements:
//  int rados_pg_command(rados_t cluster, const char *pgstr,
//                       const char **cmd, size_t cmdlen,
//                       const char *inbuf, size_t inbuflen,
//                       char **outbuf, size_t *outbuflen,
//                       char **outs, size_t *outslen);
func (c *Conn) PGCommandWithInputBuffer(pgid []byte, args [][]byte, inputBuffer []byte) (buffer []byte, info string, err error) {
	return c.pgCommand(pgid, args, inputBuffer)
}

func (c *Conn) pgCommand(pgid []byte, args [][]byte, inputBuffer []byte) (buffer []byte, info string, err error) {
	name := C.CString(string(pgid))
	defer C.free(unsafe.Pointer(name))

	argc := len(args)
	argv := make([]*C.char, argc)

	for i, arg := range args {
		argv[i] = C.CString(string(arg))
		defer C.free(unsafe.Pointer(argv[i]))
	}

	var (
		outs, outbuf       *C.char
		outslen, outbuflen C.size_t
	)
	inbuf := C.CString(string(inputBuffer))
	inbufLen := len(inputBuffer)
	defer C.free(unsafe.Pointer(inbuf))

	ret := C.rados_pg_command(c.cluster,
		name,
		&argv[0],
		C.size_t(argc),
		inbuf,              // bulk input
		C.size_t(inbufLen), // length inbuf
		&outbuf,            // buffer
		&outbuflen,         // buffer length
		&outs,              // status string
		&outslen)

	if outslen > 0 {
		info = C.GoStringN(outs, C.int(outslen))
		C.free(unsafe.Pointer(outs))
	}
	if outbuflen > 0 {
		buffer = C.GoBytes(unsafe.Pointer(outbuf), C.int(outbuflen))
		C.free(unsafe.Pointer(outbuf))
	}
	if ret != 0 {
		err = RadosError(int(ret))
		return nil, info, err
	}

	return
}
<|endoftext|>


<commit_before>package main

import (
	"container/list"
	"math"
	"time"

	"github.com/coreos/go-raft"
)

type runtimeStats struct {
}

type raftServerStats struct {
	State                 string
	StartTime             time.Time
	Leader                string
	leaderStartTime       time.Time
	LeaderUptime          string
	RecvAppendRequestCnt  uint64
	SendAppendRequestCnt  uint64
	SendAppendReqeustRate uint64
	sendRateQueue         *list.List
	SendingRate           float64
}

func (ss *raftServerStats) RecvAppendReq(leaderName string) {
	ss.State = raft.Follower
	if leaderName != ss.Leader {
		ss.Leader = leaderName
		ss.leaderStartTime = time.Now()
	}

	ss.RecvAppendRequestCnt++
}

func (ss *raftServerStats) SendAppendReq() {
	now := time.Now()
	if ss.State != raft.Leader {
		ss.State = raft.Leader
		ss.Leader = r.Name()
		ss.leaderStartTime = now
	}

	if ss.sendRateQueue.Len() < 200 {
		ss.sendRateQueue.PushBack(now)
	} else {
		ss.sendRateQueue.PushBack(now)
		ss.sendRateQueue.Remove(ss.sendRateQueue.Front())
	}

	ss.SendAppendRequestCnt++
}

type raftPeerStats struct {
	Latency          float64 `json:"latency"`
	AvgLatency       float64 `json:"averageLatency"`
	avgLatencySquare float64
	SdvLatency       float64 `json:"sdvLatency"`
	MinLatency       float64 `json:"minLatency"`
	MaxLatency       float64 `json:"maxLatency"`
	FailCnt          uint64  `json:"failsCount"`
	SuccCnt          uint64  `json:"successCount"`
}

func (ps *raftPeerStats) Fail() {
	ps.FailCnt++
}

func (ps *raftPeerStats) Succ(d time.Duration) {

	total := float64(ps.SuccCnt) * ps.AvgLatency
	totalSquare := float64(ps.SuccCnt) * ps.avgLatencySquare

	ps.SuccCnt++

	ps.Latency = float64(d) / (1000000.0)

	if ps.Latency > ps.MaxLatency {
		ps.MaxLatency = ps.Latency
	}

	if ps.Latency < ps.MinLatency {
		ps.MinLatency = ps.Latency
	}

	ps.AvgLatency = (total + ps.Latency) / float64(ps.SuccCnt)
	ps.avgLatencySquare = (totalSquare + ps.Latency*ps.Latency) / float64(ps.SuccCnt)

	// sdv = sqrt(avg(x^2) - avg(x)^2)
	ps.SdvLatency = math.Sqrt(ps.avgLatencySquare - ps.AvgLatency*ps.AvgLatency)
}
<commit_msg>make a better array cyc-queue<commit_after>package main

import (
	"container/list"
	"math"
	"time"

	"github.com/coreos/go-raft"
)

const (
	queueCapacity = 200
)

type runtimeStats struct {
}

type packageStats struct {
	sendingTime time.Time
	size        uint64
}

type raftServerStats struct {
	State                 string
	StartTime             time.Time
	Leader                string
	leaderStartTime       time.Time
	LeaderUptime          string
	RecvAppendRequestCnt  uint64
	SendAppendRequestCnt  uint64
	SendAppendReqeustRate uint64
	sendRateQueue         *list.List
	recvRateQueue         *list.List
	SendingRate           float64
}

func (ss *raftServerStats) RecvAppendReq(leaderName string) {
	ss.State = raft.Follower
	if leaderName != ss.Leader {
		ss.Leader = leaderName
		ss.leaderStartTime = time.Now()
	}

	ss.RecvAppendRequestCnt++
}

func (ss *raftServerStats) SendAppendReq() {
	now := time.Now()
	if ss.State != raft.Leader {
		ss.State = raft.Leader
		ss.Leader = r.Name()
		ss.leaderStartTime = now
	}

	if ss.sendRateQueue.Len() < 200 {
		ss.sendRateQueue.PushBack(now)
	} else {
		ss.sendRateQueue.PushBack(now)
		ss.sendRateQueue.Remove(ss.sendRateQueue.Front())
	}

	ss.SendAppendRequestCnt++
}

type raftPeerStats struct {
	Latency          float64 `json:"latency"`
	AvgLatency       float64 `json:"averageLatency"`
	avgLatencySquare float64
	SdvLatency       float64 `json:"sdvLatency"`
	MinLatency       float64 `json:"minLatency"`
	MaxLatency       float64 `json:"maxLatency"`
	FailCnt          uint64  `json:"failsCount"`
	SuccCnt          uint64  `json:"successCount"`
}

func (ps *raftPeerStats) Fail() {
	ps.FailCnt++
}

func (ps *raftPeerStats) Succ(d time.Duration) {

	total := float64(ps.SuccCnt) * ps.AvgLatency
	totalSquare := float64(ps.SuccCnt) * ps.avgLatencySquare

	ps.SuccCnt++

	ps.Latency = float64(d) / (1000000.0)

	if ps.Latency > ps.MaxLatency {
		ps.MaxLatency = ps.Latency
	}

	if ps.Latency < ps.MinLatency {
		ps.MinLatency = ps.Latency
	}

	ps.AvgLatency = (total + ps.Latency) / float64(ps.SuccCnt)
	ps.avgLatencySquare = (totalSquare + ps.Latency*ps.Latency) / float64(ps.SuccCnt)

	// sdv = sqrt(avg(x^2) - avg(x)^2)
	ps.SdvLatency = math.Sqrt(ps.avgLatencySquare - ps.AvgLatency*ps.AvgLatency)
}

type statsQueue struct {
	items [queueCapacity]*packageStats
	size  int
	front int
	back  int
}

func (q *statsQueue) Len() int {
	return q.size
}

func (q *statsQueue) Front() *packageStats {
	if q.size != 0 {
		return q.items[q.front]
	}
	return nil
}

func (q *statsQueue) Back() *packageStats {
	if q.size != 0 {
		return q.items[q.back]
	}
	return nil
}

func (q *statsQueue) Insert(p *packageStats) {
	q.back = (q.back + 1) % queueCapacity
	q.items[q.back] = p
	if q.size == queueCapacity {
		q.front = (q.back + 1) % queueCapacity
	} else {
		q.size++
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

// Package beacon implements a GA4GH Beacon API (https://github.com/ga4gh-beacon/specification/blob/master/beacon.md).
package beacon

import (
	"encoding/xml"
	"fmt"
	"html/template"
	"net/http"
	"strconv"

	"github.com/googlegenomics/beacon-go/internal/variants"
	"google.golang.org/appengine"
)

const beaconAPIVersion = "v0.0.1"

var (
	aboutTemplate = template.Must(template.ParseFiles("about.xml"))
)

// Server provides handlers for Beacon API requests.
type Server struct {
	// ProjectID is the GCloud project ID.
	ProjectID string
	// TableID is the ID of the allele BigQuery table to query.
	// Must be provided in the following format: bigquery-project.dataset.table.
	TableID string
}

// Export registers the beacon API endpoint with mux.
func (server *Server) Export(mux *http.ServeMux) {
	mux.Handle("/", forwardOrigin(server.About))
	mux.Handle("/query", forwardOrigin(server.Query))
}

// About retrieves all the necessary information on the beacon and the API.
func (api *Server) About(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, fmt.Sprintf("HTTP method %s not supported", r.Method), http.StatusBadRequest)
		return
	}
	w.Header().Set("Content-Type", "application/xml")
	aboutTemplate.Execute(w, map[string]string{
		"APIVersion": beaconAPIVersion,
		"TableID":    api.TableID,
	})
}

// Query retrieves whether the requested allele exists in the dataset.
func (api *Server) Query(w http.ResponseWriter, r *http.Request) {
	query, err := parseInput(r)
	if err != nil {
		http.Error(w, fmt.Sprintf("parsing input: %v", err), http.StatusBadRequest)
		return
	}

	if err := query.ValidateInput(); err != nil {
		http.Error(w, fmt.Sprintf("validating input: %v", err), http.StatusBadRequest)
		return
	}

	ctx := appengine.NewContext(r)
	exists, err := query.Execute(ctx, api.ProjectID, api.TableID)
	if err != nil {
		http.Error(w, fmt.Sprintf("computing result: %v", err), http.StatusInternalServerError)
		return
	}
	writeResponse(w, exists)
}

func parseInput(r *http.Request) (*variants.Query, error) {
	var query variants.Query
	query.RefName = r.FormValue("chromosome")
	query.Allele = r.FormValue("allele")

	coord, err := getFormValueInt(r, "coordinate")
	if err != nil {
		return nil, fmt.Errorf("parsing coordinate: %v", err)
	}
	query.Coord = coord

	return &query, nil
}

func getFormValueInt(r *http.Request, key string) (*int64, error) {
	str := r.FormValue(key)
	if str == "" {
		return nil, nil
	}
	value, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		return nil, fmt.Errorf("parsing value as integer: %v", err)
	}
	return &value, nil
}

func writeResponse(w http.ResponseWriter, exists bool) {
	type beaconResponse struct {
		XMLName struct{} `xml:"BEACONResponse"`
		Exists  bool     `xml:"exists"`
	}
	var resp beaconResponse
	resp.Exists = exists

	w.Header().Set("Content-Type", "application/xml")
	enc := xml.NewEncoder(w)
	enc.Indent("", "  ")
	enc.Encode(resp)
}

type forwardOrigin func(w http.ResponseWriter, req *http.Request)

func (f forwardOrigin) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if origin := req.Header.Get("Origin"); origin != "" {
		w.Header().Set("Access-Control-Allow-Origin", origin)
	}
	f(w, req)
}
<commit_msg> Added support to query through POST HTTP method (#11)<commit_after>/*
 * Copyright (C) 2015 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

// Package beacon implements a GA4GH Beacon API (https://github.com/ga4gh-beacon/specification/blob/master/beacon.md).
package beacon

import (
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"strconv"

	"github.com/googlegenomics/beacon-go/internal/variants"
	"google.golang.org/appengine"
)

const beaconAPIVersion = "v0.0.1"

var (
	aboutTemplate = template.Must(template.ParseFiles("about.xml"))
)

// Server provides handlers for Beacon API requests.
type Server struct {
	// ProjectID is the GCloud project ID.
	ProjectID string
	// TableID is the ID of the allele BigQuery table to query.
	// Must be provided in the following format: bigquery-project.dataset.table.
	TableID string
}

// Export registers the beacon API endpoint with mux.
func (server *Server) Export(mux *http.ServeMux) {
	mux.Handle("/", forwardOrigin(server.About))
	mux.Handle("/query", forwardOrigin(server.Query))
}

// About retrieves all the necessary information on the beacon and the API.
func (api *Server) About(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, fmt.Sprintf("HTTP method %s not supported", r.Method), http.StatusBadRequest)
		return
	}
	w.Header().Set("Content-Type", "application/xml")
	aboutTemplate.Execute(w, map[string]string{
		"APIVersion": beaconAPIVersion,
		"TableID":    api.TableID,
	})
}

// Query retrieves whether the requested allele exists in the dataset.
func (api *Server) Query(w http.ResponseWriter, r *http.Request) {
	query, err := parseInput(r)
	if err != nil {
		http.Error(w, fmt.Sprintf("parsing input: %v", err), http.StatusBadRequest)
		return
	}

	if err := query.ValidateInput(); err != nil {
		http.Error(w, fmt.Sprintf("validating input: %v", err), http.StatusBadRequest)
		return
	}

	ctx := appengine.NewContext(r)
	exists, err := query.Execute(ctx, api.ProjectID, api.TableID)
	if err != nil {
		http.Error(w, fmt.Sprintf("computing result: %v", err), http.StatusInternalServerError)
		return
	}
	writeResponse(w, exists)
}

func parseInput(r *http.Request) (*variants.Query, error) {

	switch r.Method {
	case "GET":
		var query variants.Query
		query.RefName = r.FormValue("chromosome")
		query.Allele = r.FormValue("allele")

		coord, err := getFormValueInt(r, "coordinate")
		if err != nil {
			return nil, fmt.Errorf("parsing coordinate: %v", err)
		}
		query.Coord = coord

		return &query, nil
	case "POST":
		var params struct {
			RefName string `json:"chromosome"`
			Allele  string `json:"allele"`
			Coord   *int64 `json:"coordinate"`
		}
		body, _ := ioutil.ReadAll(r.Body)
		if err := json.Unmarshal(body, &params); err != nil {
			return nil, fmt.Errorf("decoding request body: %v", err)
		}
		return &variants.Query{
			RefName: params.RefName,
			Allele:  params.Allele,
			Coord:   params.Coord,
		}, nil
	default:
		return nil, errors.New(fmt.Sprintf("HTTP method %s not supported", r.Method))
	}
}

func getFormValueInt(r *http.Request, key string) (*int64, error) {
	str := r.FormValue(key)
	if str == "" {
		return nil, nil
	}
	value, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		return nil, fmt.Errorf("parsing value as integer: %v", err)
	}
	return &value, nil
}

func writeResponse(w http.ResponseWriter, exists bool) {
	type beaconResponse struct {
		XMLName struct{} `xml:"BEACONResponse"`
		Exists  bool     `xml:"exists"`
	}
	var resp beaconResponse
	resp.Exists = exists

	w.Header().Set("Content-Type", "application/xml")
	enc := xml.NewEncoder(w)
	enc.Indent("", "  ")
	enc.Encode(resp)
}

type forwardOrigin func(w http.ResponseWriter, req *http.Request)

func (f forwardOrigin) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if origin := req.Header.Get("Origin"); origin != "" {
		w.Header().Set("Access-Control-Allow-Origin", origin)
	}
	f(w, req)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"net/url"
	"os"
	"path"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/ovh/cds/sdk"
	"github.com/ovh/cds/sdk/log"
)

func runArtifactDownload(w *currentWorker) BuiltInAction {
	if w.currentJob.wJob == nil {
		return func(ctx context.Context, a *sdk.Action, buildID int64, params *[]sdk.Parameter, sendLog LoggerFunc) sdk.Result {
			res := sdk.Result{Status: sdk.StatusSuccess.String()}

			project := sdk.ParameterValue(*params, "cds.project")
			environment := sdk.ParameterValue(*params, "cds.environment")
			enabled := sdk.ParameterValue(*params, "enabled") != "false"

			application := sdk.ParameterValue(a.Parameters, "application")
			pipeline := sdk.ParameterValue(a.Parameters, "pipeline")
			path := sdk.ParameterValue(a.Parameters, "path")
			tag := sdk.ParameterValue(a.Parameters, "tag")
			pattern := sdk.ParameterValue(a.Parameters, "pattern")

			if pattern != "" {
				sendLog("pattern variable can be only used with CDS Workflow - ignored.")
			}

			if !enabled {
				sendLog("Artifact Download is disabled.")
				return res
			}

			if path == "" {
				path = "."
			}

			if tag == "" {
				res.Status = sdk.StatusFail.String()
				res.Reason = fmt.Sprintf("tag variable is empty. aborting")
				sendLog(res.Reason)
				return res
			}
			tag = strings.Replace(tag, "/", "-", -1)
			tag = url.QueryEscape(tag)

			if pipeline == "" {
				res.Status = sdk.StatusFail.String()
				res.Reason = fmt.Sprintf("pipeline variable is empty. aborting\n")
				sendLog(res.Reason)
				return res
			}

			sendLog(fmt.Sprintf("Downloading artifacts from into '%s'...", path))
			if err := sdk.DownloadArtifacts(project, application, pipeline, tag, path, environment); err != nil {
				res.Status = sdk.StatusFail.String()
				res.Reason = err.Error()
				log.Warning("Cannot download artifacts: %s", err)
				sendLog(res.Reason)
				return res
			}

			return res
		}
	}

	return func(ctx context.Context, a *sdk.Action, buildID int64, params *[]sdk.Parameter, sendLog LoggerFunc) sdk.Result {
		res := &sdk.Result{Status: sdk.StatusSuccess.String()}

		project := sdk.ParameterValue(*params, "cds.project")
		workflow := sdk.ParameterValue(*params, "cds.workflow")
		number := sdk.ParameterValue(*params, "cds.run.number")
		enabled := sdk.ParameterValue(*params, "enabled") != "false"
		pattern := sdk.ParameterValue(a.Parameters, "pattern")

		destPath := sdk.ParameterValue(a.Parameters, "path")
		tag := sdk.ParameterValue(a.Parameters, "tag")

		if destPath == "" {
			destPath = "."
		}

		if !enabled {
			sendLog("Artifact Download is disabled.")
			return *res
		}

		if err := os.MkdirAll(destPath, os.FileMode(0744)); err != nil {
			res.Status = sdk.StatusFail.String()
			res.Reason = fmt.Sprintf("Unable to create %s: %v", destPath, err)
			sendLog(res.Reason)
			return *res
		}

		if tag != "" {
			sendLog("tag variable can not be used with CDS Workflow - ignored.")
		}

		sendLog(fmt.Sprintf("Downloading artifacts from workflow into '%s'...", destPath))

		n, err := strconv.ParseInt(number, 10, 64)
		if err != nil {
			res.Status = sdk.StatusFail.String()
			res.Reason = fmt.Sprintf("cds.run.number variable is not valid. aborting")
			sendLog(res.Reason)
			return *res
		}
		artifacts, err := w.client.WorkflowRunArtifacts(project, workflow, n)
		if err != nil {
			res.Status = sdk.StatusFail.String()
			res.Reason = err.Error()
			log.Warning("Cannot download artifacts: %s", err)
			sendLog(res.Reason)
			return *res
		}

		regexp := regexp.MustCompile(pattern)
		wg := new(sync.WaitGroup)
		wg.Add(len(artifacts))

		for i := range artifacts {
			a := &artifacts[i]
			go func(a *sdk.WorkflowNodeRunArtifact) {
				defer wg.Done()

				if pattern != "" && !regexp.MatchString(a.Name) {
					sendLog(fmt.Sprintf("%s does not match pattern %s - skipped", a.Name, pattern))
					return
				}
				destFile := path.Join(destPath, a.Name)
				f, err := os.OpenFile(destFile, os.O_RDWR|os.O_CREATE, os.FileMode(a.Perm))
				if err != nil {
					res.Status = sdk.StatusFail.String()
					res.Reason = err.Error()
					log.Warning("Cannot download artifact (OpenFile) %s: %s", destFile, err)
					sendLog(res.Reason)
					return
				}
				sendLog(fmt.Sprintf("downloading artifact %s from workflow %s/%s on run %d...", destFile, project, workflow, n))
				if err := w.client.WorkflowNodeRunArtifactDownload(project, workflow, *a, f); err != nil {
					res.Status = sdk.StatusFail.String()
					res.Reason = err.Error()
					log.Warning("Cannot download artifact %s: %s", destFile, err)
					sendLog(res.Reason)
					return
				}
				if err := f.Close(); err != nil {
					res.Status = sdk.StatusFail.String()
					res.Reason = err.Error()
					log.Warning("Cannot download artifact %s: %s", destFile, err)
					sendLog(res.Reason)
					return
				}
			}(a)
			if len(artifacts) > 1 {
				time.Sleep(3 * time.Second)
			}
		}

		wg.Wait()
		return *res
	}
}
<commit_msg>feat (api): use tag on workflow artifact download (#1774)<commit_after>package main

import (
	"context"
	"fmt"
	"net/url"
	"os"
	"path"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/ovh/cds/sdk"
	"github.com/ovh/cds/sdk/log"
)

func runArtifactDownload(w *currentWorker) BuiltInAction {
	if w.currentJob.wJob == nil {
		return func(ctx context.Context, a *sdk.Action, buildID int64, params *[]sdk.Parameter, sendLog LoggerFunc) sdk.Result {
			res := sdk.Result{Status: sdk.StatusSuccess.String()}

			project := sdk.ParameterValue(*params, "cds.project")
			environment := sdk.ParameterValue(*params, "cds.environment")
			enabled := sdk.ParameterValue(*params, "enabled") != "false"

			application := sdk.ParameterValue(a.Parameters, "application")
			pipeline := sdk.ParameterValue(a.Parameters, "pipeline")
			path := sdk.ParameterValue(a.Parameters, "path")
			tag := sdk.ParameterValue(a.Parameters, "tag")
			pattern := sdk.ParameterValue(a.Parameters, "pattern")

			if pattern != "" {
				sendLog("pattern variable can be only used with CDS Workflow - ignored.")
			}

			if !enabled {
				sendLog("Artifact Download is disabled.")
				return res
			}

			if path == "" {
				path = "."
			}

			if tag == "" {
				res.Status = sdk.StatusFail.String()
				res.Reason = fmt.Sprintf("tag variable is empty. aborting")
				sendLog(res.Reason)
				return res
			}
			tag = strings.Replace(tag, "/", "-", -1)
			tag = url.QueryEscape(tag)

			if pipeline == "" {
				res.Status = sdk.StatusFail.String()
				res.Reason = fmt.Sprintf("pipeline variable is empty. aborting\n")
				sendLog(res.Reason)
				return res
			}

			sendLog(fmt.Sprintf("Downloading artifacts from into '%s'...", path))
			if err := sdk.DownloadArtifacts(project, application, pipeline, tag, path, environment); err != nil {
				res.Status = sdk.StatusFail.String()
				res.Reason = err.Error()
				log.Warning("Cannot download artifacts: %s", err)
				sendLog(res.Reason)
				return res
			}

			return res
		}
	}

	return func(ctx context.Context, a *sdk.Action, buildID int64, params *[]sdk.Parameter, sendLog LoggerFunc) sdk.Result {
		res := &sdk.Result{Status: sdk.StatusSuccess.String()}

		project := sdk.ParameterValue(*params, "cds.project")
		workflow := sdk.ParameterValue(*params, "cds.workflow")
		number := sdk.ParameterValue(*params, "cds.run.number")
		enabled := sdk.ParameterValue(*params, "enabled") != "false"
		pattern := sdk.ParameterValue(a.Parameters, "pattern")

		destPath := sdk.ParameterValue(a.Parameters, "path")
		tag := sdk.ParameterValue(a.Parameters, "tag")

		if destPath == "" {
			destPath = "."
		}

		if !enabled {
			sendLog("Artifact Download is disabled.")
			return *res
		}

		if err := os.MkdirAll(destPath, os.FileMode(0744)); err != nil {
			res.Status = sdk.StatusFail.String()
			res.Reason = fmt.Sprintf("Unable to create %s: %v", destPath, err)
			sendLog(res.Reason)
			return *res
		}

		sendLog(fmt.Sprintf("Downloading artifacts from workflow into '%s'...", destPath))

		n, err := strconv.ParseInt(number, 10, 64)
		if err != nil {
			res.Status = sdk.StatusFail.String()
			res.Reason = fmt.Sprintf("cds.run.number variable is not valid. aborting")
			sendLog(res.Reason)
			return *res
		}
		artifacts, err := w.client.WorkflowRunArtifacts(project, workflow, n)
		if err != nil {
			res.Status = sdk.StatusFail.String()
			res.Reason = err.Error()
			log.Warning("Cannot download artifacts: %s", err)
			sendLog(res.Reason)
			return *res
		}

		regexp := regexp.MustCompile(pattern)
		wg := new(sync.WaitGroup)
		wg.Add(len(artifacts))

		for i := range artifacts {
			a := &artifacts[i]
			go func(a *sdk.WorkflowNodeRunArtifact) {
				defer wg.Done()

				if pattern != "" && !regexp.MatchString(a.Name) {
					sendLog(fmt.Sprintf("%s does not match pattern %s - skipped", a.Name, pattern))
					return
				}

				if tag != "" && a.Tag != tag {
					sendLog(fmt.Sprintf("%s does not match tag %s - skipped", a.Name, tag))
					return
				}

				destFile := path.Join(destPath, a.Name)
				f, err := os.OpenFile(destFile, os.O_RDWR|os.O_CREATE, os.FileMode(a.Perm))
				if err != nil {
					res.Status = sdk.StatusFail.String()
					res.Reason = err.Error()
					log.Warning("Cannot download artifact (OpenFile) %s: %s", destFile, err)
					sendLog(res.Reason)
					return
				}
				sendLog(fmt.Sprintf("downloading artifact %s from workflow %s/%s on run %d...", destFile, project, workflow, n))
				if err := w.client.WorkflowNodeRunArtifactDownload(project, workflow, *a, f); err != nil {
					res.Status = sdk.StatusFail.String()
					res.Reason = err.Error()
					log.Warning("Cannot download artifact %s: %s", destFile, err)
					sendLog(res.Reason)
					return
				}
				if err := f.Close(); err != nil {
					res.Status = sdk.StatusFail.String()
					res.Reason = err.Error()
					log.Warning("Cannot download artifact %s: %s", destFile, err)
					sendLog(res.Reason)
					return
				}
			}(a)
			if len(artifacts) > 1 {
				time.Sleep(3 * time.Second)
			}
		}

		wg.Wait()
		return *res
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 - The Event Horizon authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package mongodb

import (
	"context"
	"fmt"
	"log"
	"os"
	"sort"
	"sync"
	"testing"
	"time"

	"github.com/google/uuid"
	eh "github.com/looplab/eventhorizon"
	"github.com/looplab/eventhorizon/commandhandler/bus"
	eventbus "github.com/looplab/eventhorizon/eventbus/local"
	eventstore "github.com/looplab/eventhorizon/eventstore/mongodb"
	"github.com/looplab/eventhorizon/examples/guestlist/domains/guestlist"
	repo "github.com/looplab/eventhorizon/repo/mongodb"
	"github.com/looplab/eventhorizon/repo/version"
)

func ExampleIntegration() {
	if testing.Short() {
		os.Exit(0)
	}

	// Use MongoDB in Docker with fallback to localhost.
	addr := os.Getenv("MONGODB_ADDR")
	if addr == "" {
		addr = "localhost:27017"
	}
	url := "mongodb://" + addr

	// Create the event store.
	eventStore, err := eventstore.NewEventStore(url, "demo")
	if err != nil {
		log.Fatalf("could not create event store: %s", err)
	}

	// Create the event bus that distributes events.
	eventBus := eventbus.NewEventBus()
	go func() {
		for e := range eventBus.Errors() {
			log.Printf("eventbus: %s", e.Error())
		}
	}()

	// Create the command bus.
	commandBus := bus.NewCommandHandler()

	// Create the read repositories.
	invitationRepo, err := repo.NewRepo(url, "demo", "invitations")
	if err != nil {
		log.Fatalf("could not create invitation repository: %s", err)
	}
	invitationRepo.SetEntityFactory(func() eh.Entity { return &guestlist.Invitation{} })
	// A version repo is needed for the projector to handle eventual consistency.
	invitationVersionRepo := version.NewRepo(invitationRepo)
	guestListRepo, err := repo.NewRepo(url, "demo", "guest_lists")
	if err != nil {
		log.Fatalf("could not create guest list repository: %s", err)
	}
	guestListRepo.SetEntityFactory(func() eh.Entity { return &guestlist.GuestList{} })

	// Set the namespace to use.
	ctx, cancel := context.WithCancel(
		eh.NewContextWithNamespace(context.Background(), "mongodb"),
	)

	// Setup a test utility waiter that waits for all 11 events to occur before
	// evaluating results.
	var wg sync.WaitGroup
	wg.Add(11)
	eventBus.AddHandler(ctx, eh.MatchAll{}, eh.EventHandlerFunc(
		func(ctx context.Context, e eh.Event) error {
			wg.Done()
			return nil
		},
	))

	// Setup the guestlist.
	eventID := uuid.New()
	guestlist.Setup(
		ctx,
		eventStore,
		eventBus,
		commandBus,
		invitationVersionRepo, guestListRepo,
		eventID,
	)

	// Clear DB collections.
	eventStore.Clear(ctx)
	invitationRepo.Clear(ctx)
	guestListRepo.Clear(ctx)

	// --- Execute commands on the domain --------------------------------------

	// IDs for all the guests.
	athenaID := uuid.New()
	hadesID := uuid.New()
	zeusID := uuid.New()
	poseidonID := uuid.New()

	// Issue some invitations and responses. Error checking omitted here.
	if err := commandBus.HandleCommand(ctx, &guestlist.CreateInvite{ID: athenaID, Name: "Athena", Age: 42}); err != nil {
		log.Println("error:", err)
	}
	if err := commandBus.HandleCommand(ctx, &guestlist.CreateInvite{ID: hadesID, Name: "Hades"}); err != nil {
		log.Println("error:", err)
	}
	if err := commandBus.HandleCommand(ctx, &guestlist.CreateInvite{ID: zeusID, Name: "Zeus"}); err != nil {
		log.Println("error:", err)
	}
	if err := commandBus.HandleCommand(ctx, &guestlist.CreateInvite{ID: poseidonID, Name: "Poseidon"}); err != nil {
		log.Println("error:", err)
	}

	// The invited guests accept and decline the event.
	// Note that Athena tries to decline the event after first accepting, but
	// that is not allowed by the domain logic in InvitationAggregate. The
	// result is that she is still accepted.
	if err := commandBus.HandleCommand(ctx, &guestlist.AcceptInvite{ID: athenaID}); err != nil {
		log.Println("error:", err)
	}
	if err = commandBus.HandleCommand(ctx, &guestlist.DeclineInvite{ID: athenaID}); err != nil {
		// NOTE: This error is supposed to be printed!
		log.Println("error:", err)
	}
	if err := commandBus.HandleCommand(ctx, &guestlist.AcceptInvite{ID: hadesID}); err != nil {
		log.Println("error:", err)
	}
	if err := commandBus.HandleCommand(ctx, &guestlist.DeclineInvite{ID: zeusID}); err != nil {
		log.Println("error:", err)
	}

	// Poseidon is a bit late to the party, will not be accepted...
	if err := commandBus.HandleCommand(ctx, &guestlist.AcceptInvite{ID: poseidonID}); err != nil {
		log.Println("error:", err)
	}

	// Wait for simulated eventual consistency before reading.
	wg.Wait()
	time.Sleep(1000 * time.Millisecond)

	// Read all invites.
	invitationStrs := []string{}
	invitations, err := invitationRepo.FindAll(ctx)
	if err != nil {
		log.Println("error:", err)
	}
	for _, i := range invitations {
		if i, ok := i.(*guestlist.Invitation); ok {
			invitationStrs = append(invitationStrs, fmt.Sprintf("%s - %s", i.Name, i.Status))
		}
	}

	// Sort the output to be able to compare test results.
	sort.Strings(invitationStrs)
	for _, s := range invitationStrs {
		log.Printf("invitation: %s\n", s)
		fmt.Printf("invitation: %s\n", s)
	}

	// Read the guest list.
	l, err := guestListRepo.Find(ctx, eventID)
	if err != nil {
		log.Println("error:", err)
	}
	if l, ok := l.(*guestlist.GuestList); ok {
		log.Printf("guest list: %d invited - %d accepted, %d declined - %d confirmed, %d denied\n",
			l.NumGuests, l.NumAccepted, l.NumDeclined, l.NumConfirmed, l.NumDenied)
		fmt.Printf("guest list: %d invited - %d accepted, %d declined - %d confirmed, %d denied\n",
			l.NumGuests, l.NumAccepted, l.NumDeclined, l.NumConfirmed, l.NumDenied)
	}

	// Cancel all handlers and wait.
	cancel()
	eventBus.Wait()

	// Output:
	// invitation: Athena - confirmed
	// invitation: Hades - confirmed
	// invitation: Poseidon - denied
	// invitation: Zeus - declined
	// guest list: 4 invited - 3 accepted, 1 declined - 2 confirmed, 1 denied
}
<commit_msg>test: Ignore integration example test<commit_after>// Copyright (c) 2014 - The Event Horizon authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package mongodb

import (
	"context"
	"fmt"
	"log"
	"os"
	"sort"
	"sync"
	"testing"
	"time"

	"github.com/google/uuid"
	eh "github.com/looplab/eventhorizon"
	"github.com/looplab/eventhorizon/commandhandler/bus"
	eventbus "github.com/looplab/eventhorizon/eventbus/local"
	eventstore "github.com/looplab/eventhorizon/eventstore/mongodb"
	"github.com/looplab/eventhorizon/examples/guestlist/domains/guestlist"
	repo "github.com/looplab/eventhorizon/repo/mongodb"
	"github.com/looplab/eventhorizon/repo/version"
)

func ExampleIntegration() {
	if testing.Short() {
		// Skip test when not running integration, fake success by printing.
		fmt.Println(`invitation: Athena - confirmed
invitation: Hades - confirmed
invitation: Poseidon - denied
invitation: Zeus - declined
guest list: 4 invited - 3 accepted, 1 declined - 2 confirmed, 1 denied`)
		return
	}

	// Use MongoDB in Docker with fallback to localhost.
	addr := os.Getenv("MONGODB_ADDR")
	if addr == "" {
		addr = "localhost:27017"
	}
	url := "mongodb://" + addr

	// Create the event store.
	eventStore, err := eventstore.NewEventStore(url, "demo")
	if err != nil {
		log.Fatalf("could not create event store: %s", err)
	}

	// Create the event bus that distributes events.
	eventBus := eventbus.NewEventBus()
	go func() {
		for e := range eventBus.Errors() {
			log.Printf("eventbus: %s", e.Error())
		}
	}()

	// Create the command bus.
	commandBus := bus.NewCommandHandler()

	// Create the read repositories.
	invitationRepo, err := repo.NewRepo(url, "demo", "invitations")
	if err != nil {
		log.Fatalf("could not create invitation repository: %s", err)
	}
	invitationRepo.SetEntityFactory(func() eh.Entity { return &guestlist.Invitation{} })
	// A version repo is needed for the projector to handle eventual consistency.
	invitationVersionRepo := version.NewRepo(invitationRepo)
	guestListRepo, err := repo.NewRepo(url, "demo", "guest_lists")
	if err != nil {
		log.Fatalf("could not create guest list repository: %s", err)
	}
	guestListRepo.SetEntityFactory(func() eh.Entity { return &guestlist.GuestList{} })

	// Set the namespace to use.
	ctx, cancel := context.WithCancel(
		eh.NewContextWithNamespace(context.Background(), "mongodb"),
	)

	// Setup a test utility waiter that waits for all 11 events to occur before
	// evaluating results.
	var wg sync.WaitGroup
	wg.Add(11)
	eventBus.AddHandler(ctx, eh.MatchAll{}, eh.EventHandlerFunc(
		func(ctx context.Context, e eh.Event) error {
			wg.Done()
			return nil
		},
	))

	// Setup the guestlist.
	eventID := uuid.New()
	guestlist.Setup(
		ctx,
		eventStore,
		eventBus,
		commandBus,
		invitationVersionRepo, guestListRepo,
		eventID,
	)

	// Clear DB collections.
	eventStore.Clear(ctx)
	invitationRepo.Clear(ctx)
	guestListRepo.Clear(ctx)

	// --- Execute commands on the domain --------------------------------------

	// IDs for all the guests.
	athenaID := uuid.New()
	hadesID := uuid.New()
	zeusID := uuid.New()
	poseidonID := uuid.New()

	// Issue some invitations and responses. Error checking omitted here.
	if err := commandBus.HandleCommand(ctx, &guestlist.CreateInvite{ID: athenaID, Name: "Athena", Age: 42}); err != nil {
		log.Println("error:", err)
	}
	if err := commandBus.HandleCommand(ctx, &guestlist.CreateInvite{ID: hadesID, Name: "Hades"}); err != nil {
		log.Println("error:", err)
	}
	if err := commandBus.HandleCommand(ctx, &guestlist.CreateInvite{ID: zeusID, Name: "Zeus"}); err != nil {
		log.Println("error:", err)
	}
	if err := commandBus.HandleCommand(ctx, &guestlist.CreateInvite{ID: poseidonID, Name: "Poseidon"}); err != nil {
		log.Println("error:", err)
	}

	// The invited guests accept and decline the event.
	// Note that Athena tries to decline the event after first accepting, but
	// that is not allowed by the domain logic in InvitationAggregate. The
	// result is that she is still accepted.
	if err := commandBus.HandleCommand(ctx, &guestlist.AcceptInvite{ID: athenaID}); err != nil {
		log.Println("error:", err)
	}
	if err = commandBus.HandleCommand(ctx, &guestlist.DeclineInvite{ID: athenaID}); err != nil {
		// NOTE: This error is supposed to be printed!
		log.Println("error:", err)
	}
	if err := commandBus.HandleCommand(ctx, &guestlist.AcceptInvite{ID: hadesID}); err != nil {
		log.Println("error:", err)
	}
	if err := commandBus.HandleCommand(ctx, &guestlist.DeclineInvite{ID: zeusID}); err != nil {
		log.Println("error:", err)
	}

	// Poseidon is a bit late to the party, will not be accepted...
	if err := commandBus.HandleCommand(ctx, &guestlist.AcceptInvite{ID: poseidonID}); err != nil {
		log.Println("error:", err)
	}

	// Wait for simulated eventual consistency before reading.
	wg.Wait()
	time.Sleep(1000 * time.Millisecond)

	// Read all invites.
	invitationStrs := []string{}
	invitations, err := invitationRepo.FindAll(ctx)
	if err != nil {
		log.Println("error:", err)
	}
	for _, i := range invitations {
		if i, ok := i.(*guestlist.Invitation); ok {
			invitationStrs = append(invitationStrs, fmt.Sprintf("%s - %s", i.Name, i.Status))
		}
	}

	// Sort the output to be able to compare test results.
	sort.Strings(invitationStrs)
	for _, s := range invitationStrs {
		log.Printf("invitation: %s\n", s)
		fmt.Printf("invitation: %s\n", s)
	}

	// Read the guest list.
	l, err := guestListRepo.Find(ctx, eventID)
	if err != nil {
		log.Println("error:", err)
	}
	if l, ok := l.(*guestlist.GuestList); ok {
		log.Printf("guest list: %d invited - %d accepted, %d declined - %d confirmed, %d denied\n",
			l.NumGuests, l.NumAccepted, l.NumDeclined, l.NumConfirmed, l.NumDenied)
		fmt.Printf("guest list: %d invited - %d accepted, %d declined - %d confirmed, %d denied\n",
			l.NumGuests, l.NumAccepted, l.NumDeclined, l.NumConfirmed, l.NumDenied)
	}

	// Cancel all handlers and wait.
	cancel()
	eventBus.Wait()

	// Output:
	// invitation: Athena - confirmed
	// invitation: Hades - confirmed
	// invitation: Poseidon - denied
	// invitation: Zeus - declined
	// guest list: 4 invited - 3 accepted, 1 declined - 2 confirmed, 1 denied
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// Package main implements a server for Greeter service.
package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"net"

	"google.golang.org/grpc"
	pb "google.golang.org/grpc/examples/helloworld/helloworld"
)

var (
	port = flag.Int("port", 50051, "The server port")
)

// server is used to implement helloworld.GreeterServer.
type server struct {
	pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	log.Printf("Received: %v", in.GetName())
	return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
	flag.Parse()
	lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", *port))
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &server{})
	log.Printf("server listening at %v", lis.Addr())
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}
<commit_msg>Let helloworld example listen to all hosts (#5089)<commit_after>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// Package main implements a server for Greeter service.
package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"net"

	"google.golang.org/grpc"
	pb "google.golang.org/grpc/examples/helloworld/helloworld"
)

var (
	port = flag.Int("port", 50051, "The server port")
)

// server is used to implement helloworld.GreeterServer.
type server struct {
	pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	log.Printf("Received: %v", in.GetName())
	return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
	flag.Parse()
	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &server{})
	log.Printf("server listening at %v", lis.Addr())
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"os"
	"os/exec"

	runtime "github.com/micro/micro/v3/proto/runtime"
	"github.com/micro/micro/v3/service"
	"github.com/micro/micro/v3/service/client"
	"github.com/micro/micro/v3/service/context"
	"github.com/micro/micro/v3/service/logger"
)

func main() {
	// setup the client
	srv := service.New()
	cli := runtime.NewBuildService("runtime", srv.Client())

	// get the name and version of the service, these are injected by the runtime manager
	name := getEnv("MICRO_SERVICE_NAME")
	version := getEnv("MICRO_SERVICE_VERSION")

	// stream the binary from the runtime
	logger.Infof("Downloading service %v:%v", name, version)
	svc := &runtime.Service{Name: name, Version: version}
	stream, err := cli.Read(context.DefaultContext, svc, client.WithAuthToken())
	if err != nil {
		logger.Fatalf("Error starting stream: %v", err)
	}

	// create a file to write the result into
	file, err := os.Create("service")
	if err != nil {
		logger.Fatalf("Error creating output file: %v", err)
	}
	if err := os.Chmod("service", 744); err != nil {
		logger.Fatalf("Error setting output file permissions: %v", err)
	}

	// write the build to the local file
	for {
		req, err := stream.Recv()
		if err == io.EOF {
			break
		} else if err != nil {
			logger.Fatalf("Error reading from the stream: %v", err)
		}

		// write the bytes to the buffer
		if _, err := file.Write(req.Data); err != nil {
			logger.Fatalf("Error writing data to the file: %v", err)
		}
	}
	if err := file.Close(); err != nil {
		logger.Fatalf("Error closing the file: %v", err)
	}

	// execute the binary
	logger.Info("Starting service")
	cmd := exec.Command("./service")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Start(); err != nil {
		logger.Fatalf("Error starting service: %v", err)
	}

	if err = cmd.Wait(); err != nil {
		logger.Fatalf("Service exited: %v", err)
	} else {
		logger.Fatalf("Service finished")
	}
}

func getEnv(key string) string {
	val := os.Getenv(key)
	if len(val) == 0 {
		logger.Fatalf("Missing required env var: %v", key)
	}
	return val
}
<commit_msg>in the event of kill signals pass from loader to child process (#1718)<commit_after>package main

import (
	"io"
	"os"
	"os/exec"
	"os/signal"
	"syscall"

	runtime "github.com/micro/micro/v3/proto/runtime"
	"github.com/micro/micro/v3/service"
	"github.com/micro/micro/v3/service/client"
	"github.com/micro/micro/v3/service/context"
	"github.com/micro/micro/v3/service/logger"
)

func main() {
	// setup the client
	srv := service.New()
	cli := runtime.NewBuildService("runtime", srv.Client())

	// get the name and version of the service, these are injected by the runtime manager
	name := getEnv("MICRO_SERVICE_NAME")
	version := getEnv("MICRO_SERVICE_VERSION")

	// stream the binary from the runtime
	logger.Infof("Downloading service %v:%v", name, version)
	svc := &runtime.Service{Name: name, Version: version}
	stream, err := cli.Read(context.DefaultContext, svc, client.WithAuthToken())
	if err != nil {
		logger.Fatalf("Error starting stream: %v", err)
	}

	// create a file to write the result into
	file, err := os.Create("service")
	if err != nil {
		logger.Fatalf("Error creating output file: %v", err)
	}
	if err := os.Chmod("service", 744); err != nil {
		logger.Fatalf("Error setting output file permissions: %v", err)
	}

	// write the build to the local file
	for {
		req, err := stream.Recv()
		if err == io.EOF {
			break
		} else if err != nil {
			logger.Fatalf("Error reading from the stream: %v", err)
		}

		// write the bytes to the buffer
		if _, err := file.Write(req.Data); err != nil {
			logger.Fatalf("Error writing data to the file: %v", err)
		}
	}
	if err := file.Close(); err != nil {
		logger.Fatalf("Error closing the file: %v", err)
	}

	// be notified of kill signals
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL)

	// execute the binary
	logger.Info("Starting service")
	cmd := exec.Command("./service")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	if err := cmd.Start(); err != nil {
		logger.Fatalf("Error starting service: %v", err)
	}

	// kill the service if we receive a kill signal
	go func() {
		sig := <-sigChan
		if cmd.Process != nil {
			cmd.Process.Signal(sig)
		}
	}()

	if err = cmd.Wait(); err != nil {
		logger.Fatalf("Service exited: %v", err)
	} else {
		logger.Fatalf("Service finished")
	}
}

func getEnv(key string) string {
	val := os.Getenv(key)
	if len(val) == 0 {
		logger.Fatalf("Missing required env var: %v", key)
	}
	return val
}
<|endoftext|>


<commit_before>package instancecommands

import (
	"fmt"
	"os"

	"github.com/codegangsta/cli"
	"github.com/fatih/structs"
	"github.com/jrperritt/rack/auth"
	"github.com/jrperritt/rack/output"
	"github.com/jrperritt/rack/util"
	"github.com/olekukonko/tablewriter"
	"github.com/rackspace/gophercloud/rackspace/compute/v2/servers"
)

var get = cli.Command{
	Name:        "get",
	Usage:       fmt.Sprintf("%s %s get %s [optional flags]", util.Name, commandPrefix, idOrNameUsage),
	Description: "Retrieves an existing server",
	Action:      commandGet,
	Flags:       util.CommandFlags(flagsGet),
	BashComplete: func(c *cli.Context) {
		util.CompleteFlags(util.CommandFlags(flagsGet))
	},
}

func flagsGet() []cli.Flag {
	return idAndNameFlags
}

func commandGet(c *cli.Context) {
	util.CheckArgNum(c, 0)
	client := auth.NewClient("compute")
	serverID := idOrName(c, client)
	o, err := servers.Get(client, serverID).Extract()
	if err != nil {
		fmt.Printf("Error retrieving server (%s): %s\n", serverID, err)
		os.Exit(1)
	}
	output.Print(c, o, tableGet)
}

func tableGet(c *cli.Context, i interface{}) {
	m := structs.Map(i)
	t := tablewriter.NewWriter(c.App.Writer)
	t.SetAlignment(tablewriter.ALIGN_LEFT)
	t.SetHeader([]string{"property", "value"})
	keys := []string{"ID", "Name", "Status", "Created", "Updated", "Image", "Flavor", "Public IPv4", "Public IPv6", "Private IPv4", "KeyName"}
	for _, key := range keys {
		tmp := ""
		switch key {
		case "Public IPv4":
			tmp = fmt.Sprint(m["AccessIPv4"])
		case "Public IPv6":
			tmp = fmt.Sprint(m["AccessIPv6"])
		case "Private IPv4":
			i, ok := m["Addresses"].(map[string]interface{})
			if !ok {
				tmp = ""
				break
			}
			j, ok := i["private"].([]interface{})
			if !ok || len(j) == 0 {
				tmp = ""
				break
			}
			i, ok = j[0].(map[string]interface{})
			if !ok {
				tmp = ""
				break
			}
			tmp = fmt.Sprint(i["addr"])
		case "Image":
			i, ok := m["Image"].(map[string]interface{})
			if !ok {
				tmp = ""
				break
			}
			tmp = fmt.Sprint(i["id"])
		case "Flavor":
			i, ok := m["Flavor"].(map[string]interface{})
			if !ok {
				tmp = ""
				break
			}
			tmp = fmt.Sprint(i["id"])
		default:
			tmp = fmt.Sprint(m[key])
		}
		if tmp == "<nil>" {
			tmp = ""
		}
		t.Append([]string{key, tmp})
	}
	t.Render()
}
<commit_msg>Simplify map creation.<commit_after>package instancecommands

import (
	"fmt"
	"os"

	"github.com/codegangsta/cli"
	"github.com/fatih/structs"
	"github.com/jrperritt/rack/auth"
	"github.com/jrperritt/rack/output"
	"github.com/jrperritt/rack/util"
	"github.com/olekukonko/tablewriter"
	"github.com/rackspace/gophercloud/rackspace/compute/v2/servers"
)

var get = cli.Command{
	Name:        "get",
	Usage:       fmt.Sprintf("%s %s get %s [optional flags]", util.Name, commandPrefix, idOrNameUsage),
	Description: "Retrieves an existing server",
	Action:      commandGet,
	Flags:       util.CommandFlags(flagsGet),
	BashComplete: func(c *cli.Context) {
		util.CompleteFlags(util.CommandFlags(flagsGet))
	},
}

func flagsGet() []cli.Flag {
	return idAndNameFlags
}

func commandGet(c *cli.Context) {
	util.CheckArgNum(c, 0)
	client := auth.NewClient("compute")
	serverID := idOrName(c, client)
	o, err := servers.Get(client, serverID).Extract()
	if err != nil {
		fmt.Printf("Error retrieving server (%s): %s\n", serverID, err)
		os.Exit(1)
	}
	output.Print(c, o, tableGet)
}

func tableGet(c *cli.Context, i interface{}) {
	m := structs.Map(i)
	t := tablewriter.NewWriter(c.App.Writer)
	t.SetAlignment(tablewriter.ALIGN_LEFT)
	t.SetHeader([]string{"property", "value"})
	keys := []string{"ID", "Name", "Status", "Created", "Updated", "Image", "Flavor", "Public IPv4", "Public IPv6", "Private IPv4", "KeyName"}

	m["Public IPv4"] = m["AccessIPv4"]
	m["Public IPv6"] = m["AccessIPv6"]

	// Private IPv4 case
	// Nested m["Addresses"]["private"][0]
	addrs, ok := m["Addresses"].(map[string]interface{})
	if ok {
		ips, ok := addrs["private"].([]interface{})
		if ok || len(ips) > 0 {
			priv, ok := ips[0].(map[string]interface{})
			if ok {
				m["Private IPv4"] = priv["addr"]
			}
		}
	}
	if !ok { // if any were not ok, set the field to blank
		m["Private IPv4"] = ""
	}

	flavor, ok := m["Flavor"].(map[string]interface{})
	if ok {
		m["Flavor"] = flavor["id"]
	} else {
		m["Flavor"] = ""
	}
	image, ok := m["Image"].(map[string]interface{})
	if ok {
		m["Image"] = image["id"]
	} else {
		m["Image"] = ""
	}

	for _, key := range keys {
		t.Append([]string{key, fmt.Sprint(m[key])})
	}
	t.Render()
}
<|endoftext|>


<commit_before>// Copyright 2015 The DER ASCII Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"encoding/hex"
	"fmt"
	"strconv"
	"unicode"

	"github.com/google/der-ascii/lib"
)

type writer struct {
	out    string
	indent int
}

func (w *writer) String() string {
	return w.out
}

func (w *writer) SetIndent(indent int) {
	w.indent = indent
}

func (w *writer) Indent() int {
	return w.indent
}

func (w *writer) AddIndent(v int) {
	w.indent += v
}

func (w *writer) WriteLine(line string) {
	for i := 0; i < w.indent; i++ {
		w.out += "  "
	}
	w.out += line
	w.out += "\n"
}

// isMadeOfElements returns true if bytes can be parsed as a series of DER
// elements with no trailing data and false otherwise.
func isMadeOfElements(bytes []byte) bool {
	var indefiniteCount int
	for len(bytes) != 0 {
		if indefiniteCount > 0 && len(bytes) >= 2 && bytes[0] == 0 && bytes[1] == 0 {
			bytes = bytes[2:]
			indefiniteCount--
			continue
		}

		_, _, indefinite, rest, ok := parseElement(bytes)
		if !ok {
			return false
		}
		bytes = rest
		if indefinite {
			indefiniteCount++
		}
	}
	return indefiniteCount == 0
}

func classToString(class lib.Class) string {
	switch class {
	case lib.ClassUniversal:
		return "UNIVERSAL"
	case lib.ClassApplication:
		return "APPLICATION"
	case lib.ClassContextSpecific:
		panic("should not be called")
	case lib.ClassPrivate:
		return "PRIVATE"
	default:
		panic(class)
	}
}

func tagToString(tag lib.Tag) string {
	// Write a short name if possible.
	name, toggleConstructed, ok := tag.GetAlias()
	if ok {
		if !toggleConstructed {
			return name
		}
		constructed := "PRIMITIVE"
		if tag.Constructed {
			constructed = "CONSTRUCTED"
		}
		return fmt.Sprintf("[%s %s]", name, constructed)
	}

	out := "["
	if tag.Class != lib.ClassContextSpecific {
		out += fmt.Sprintf("%s ", classToString(tag.Class))
	}
	out += fmt.Sprintf("%d", tag.Number)
	if !tag.Constructed {
		out += " PRIMITIVE"
	}
	out += "]"
	return out
}

func bytesToString(bytes []byte) string {
	if len(bytes) == 0 {
		return ""
	}

	var asciiCount int
	for _, b := range bytes {
		if b < 0x80 && (b == '\n' || unicode.IsPrint(rune(b))) {
			asciiCount++
		}
	}

	if float64(asciiCount)/float64(len(bytes)) > 0.85 {
		return bytesToQuotedString(bytes)
	} else {
		return bytesToHexString(bytes)
	}
}

func bytesToHexString(bytes []byte) string {
	return fmt.Sprintf("`%s`", hex.EncodeToString(bytes))
}

func bytesToQuotedString(bytes []byte) string {
	out := `"`
	for _, b := range bytes {
		if b == '\n' {
			out += `\n`
		} else if b == '"' {
			out += `\"`
		} else if b == '\\' {
			out += `\\`
		} else if b >= 0x80 || !unicode.IsPrint(rune(b)) {
			out += fmt.Sprintf(`\x%02x`, b)
		} else {
			out += string([]byte{b})
		}
	}
	out += `"`
	return out
}

func integerToString(bytes []byte) string {
	v, ok := decodeInteger(bytes)
	if ok && -100000 <= v && v <= 100000 {
		return strconv.FormatInt(v, 10)
	}
	return bytesToHexString(bytes)
}

func objectIdentifierToString(bytes []byte) string {
	oid, ok := decodeObjectIdentifier(bytes)
	if !ok {
		return bytesToHexString(bytes)
	}
	var out string
	for i, v := range oid {
		if i != 0 {
			out += "."
		}
		out += strconv.FormatUint(uint64(v), 10)
	}
	return out
}

func derToASCIIImpl(w *writer, bytes []byte, stopAtEOC bool) []byte {
	for len(bytes) != 0 {
		if stopAtEOC && len(bytes) >= 2 && bytes[0] == 0 && bytes[1] == 0 {
			// Emit a `0000` in lieu of a closing base.
			w.AddIndent(-1)
			w.WriteLine(bytesToString(bytes[:2]))
			return bytes[2:]
		}

		tag, body, indefinite, rest, ok := parseElement(bytes)
		if !ok {
			// Nothing more to encode. Write the rest as bytes.
			w.WriteLine(bytesToString(bytes))
			return nil
		}
		bytes = rest

		if indefinite {
			// Emit a `80` in lieu of an open brace.
			w.WriteLine(fmt.Sprintf("%s `80`", tagToString(tag)))
			indent := w.Indent()
			w.AddIndent(1)
			bytes = derToASCIIImpl(w, bytes, true)
			// If EOC was missing, the indent may not have been
			// restored correctly.
			w.SetIndent(indent)
			continue
		}

		if len(body) == 0 {
			// If the body is empty, skip the newlines.
			w.WriteLine(fmt.Sprintf("%s {}", tagToString(tag)))
			continue
		}

		if tag.Constructed {
			// If the element is constructed, recurse.
			w.WriteLine(fmt.Sprintf("%s {", tagToString(tag)))
			w.AddIndent(1)
			derToASCIIImpl(w, body, false)
			w.AddIndent(-1)
			w.WriteLine("}")
		} else {
			// The element is primitive. By default, emit the body
			// on the same line as curly braces. However, in some
			// cases, we heuristically decode the body as DER too.
			// In this case, the newlines are inserted as in the
			// constructed case.

			// If ok is false, name will be empty. There is also no
			// need to check toggleConstructed as we already know
			// the tag is primitive.
			name, _, _ := tag.GetAlias()
			switch name {
			case "INTEGER":
				w.WriteLine(fmt.Sprintf("%s { %s }", tagToString(tag), integerToString(body)))
			case "OBJECT_IDENTIFIER":
				w.WriteLine(fmt.Sprintf("%s { %s }", tagToString(tag), objectIdentifierToString(body)))
			case "BIT_STRING":
				// X.509 encodes signatures and SPKIs in BIT
				// STRINGs, so there is a 0 phase byte followed
				// by the potentially DER-encoded structure.
				if len(body) > 1 && body[0] == 0 && isMadeOfElements(body[1:]) {
					w.WriteLine(fmt.Sprintf("%s {", tagToString(tag)))
					w.AddIndent(1)
					// Emit the phase byte.
					w.WriteLine(bytesToString(body[:1]))
					// Emit the remaining as a DER element.
					derToASCIIImpl(w, body[1:], false) // Adds a trailing newline.
					w.AddIndent(-1)
					w.WriteLine("}")
				} else {
					w.WriteLine(fmt.Sprintf("%s { %s }", tagToString(tag), bytesToString(body)))
				}
			default:
				// Keep parsing if the body looks like ASN.1.
				if isMadeOfElements(body) {
					w.WriteLine(fmt.Sprintf("%s {", tagToString(tag)))
					w.AddIndent(1)
					derToASCIIImpl(w, body, false)
					w.AddIndent(-1)
					w.WriteLine("}")
				} else {
					w.WriteLine(fmt.Sprintf("%s { %s }", tagToString(tag), bytesToString(body)))
				}
			}
		}
	}
	return nil
}

func derToASCII(bytes []byte) string {
	var w writer
	derToASCIIImpl(&w, bytes, false)
	return w.String()
}
<commit_msg>Use bytes.Buffer rather than string concatenation in helper functions.<commit_after>// Copyright 2015 The DER ASCII Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"strconv"
	"unicode"

	"github.com/google/der-ascii/lib"
)

type writer struct {
	out    string
	indent int
}

func (w *writer) String() string {
	return w.out
}

func (w *writer) SetIndent(indent int) {
	w.indent = indent
}

func (w *writer) Indent() int {
	return w.indent
}

func (w *writer) AddIndent(v int) {
	w.indent += v
}

func (w *writer) WriteLine(line string) {
	for i := 0; i < w.indent; i++ {
		w.out += "  "
	}
	w.out += line
	w.out += "\n"
}

// isMadeOfElements returns true if bytes can be parsed as a series of DER
// elements with no trailing data and false otherwise.
func isMadeOfElements(bytes []byte) bool {
	var indefiniteCount int
	for len(bytes) != 0 {
		if indefiniteCount > 0 && len(bytes) >= 2 && bytes[0] == 0 && bytes[1] == 0 {
			bytes = bytes[2:]
			indefiniteCount--
			continue
		}

		_, _, indefinite, rest, ok := parseElement(bytes)
		if !ok {
			return false
		}
		bytes = rest
		if indefinite {
			indefiniteCount++
		}
	}
	return indefiniteCount == 0
}

func classToString(class lib.Class) string {
	switch class {
	case lib.ClassUniversal:
		return "UNIVERSAL"
	case lib.ClassApplication:
		return "APPLICATION"
	case lib.ClassContextSpecific:
		panic("should not be called")
	case lib.ClassPrivate:
		return "PRIVATE"
	default:
		panic(class)
	}
}

func tagToString(tag lib.Tag) string {
	// Write a short name if possible.
	name, toggleConstructed, ok := tag.GetAlias()
	if ok {
		if !toggleConstructed {
			return name
		}
		constructed := "PRIMITIVE"
		if tag.Constructed {
			constructed = "CONSTRUCTED"
		}
		return fmt.Sprintf("[%s %s]", name, constructed)
	}

	out := "["
	if tag.Class != lib.ClassContextSpecific {
		out += fmt.Sprintf("%s ", classToString(tag.Class))
	}
	out += fmt.Sprintf("%d", tag.Number)
	if !tag.Constructed {
		out += " PRIMITIVE"
	}
	out += "]"
	return out
}

func bytesToString(bytes []byte) string {
	if len(bytes) == 0 {
		return ""
	}

	var asciiCount int
	for _, b := range bytes {
		if b < 0x80 && (b == '\n' || unicode.IsPrint(rune(b))) {
			asciiCount++
		}
	}

	if float64(asciiCount)/float64(len(bytes)) > 0.85 {
		return bytesToQuotedString(bytes)
	} else {
		return bytesToHexString(bytes)
	}
}

func bytesToHexString(bytes []byte) string {
	return fmt.Sprintf("`%s`", hex.EncodeToString(bytes))
}

func bytesToQuotedString(in []byte) string {
	var out bytes.Buffer
	out.WriteString(`"`)
	for _, b := range in {
		if b == '\n' {
			out.WriteString(`\n`)
		} else if b == '"' {
			out.WriteString(`\"`)
		} else if b == '\\' {
			out.WriteString(`\\`)
		} else if b >= 0x80 || !unicode.IsPrint(rune(b)) {
			fmt.Fprintf(&out, `\x%02x`, b)
		} else {
			out.WriteByte(b)
		}
	}
	out.WriteString(`"`)
	return out.String()
}

func integerToString(bytes []byte) string {
	v, ok := decodeInteger(bytes)
	if ok && -100000 <= v && v <= 100000 {
		return strconv.FormatInt(v, 10)
	}
	return bytesToHexString(bytes)
}

func objectIdentifierToString(in []byte) string {
	oid, ok := decodeObjectIdentifier(in)
	if !ok {
		return bytesToHexString(in)
	}
	var out bytes.Buffer
	for i, v := range oid {
		if i != 0 {
			out.WriteString(".")
		}
		out.WriteString(strconv.FormatUint(uint64(v), 10))
	}
	return out.String()
}

func derToASCIIImpl(w *writer, bytes []byte, stopAtEOC bool) []byte {
	for len(bytes) != 0 {
		if stopAtEOC && len(bytes) >= 2 && bytes[0] == 0 && bytes[1] == 0 {
			// Emit a `0000` in lieu of a closing base.
			w.AddIndent(-1)
			w.WriteLine(bytesToString(bytes[:2]))
			return bytes[2:]
		}

		tag, body, indefinite, rest, ok := parseElement(bytes)
		if !ok {
			// Nothing more to encode. Write the rest as bytes.
			w.WriteLine(bytesToString(bytes))
			return nil
		}
		bytes = rest

		if indefinite {
			// Emit a `80` in lieu of an open brace.
			w.WriteLine(fmt.Sprintf("%s `80`", tagToString(tag)))
			indent := w.Indent()
			w.AddIndent(1)
			bytes = derToASCIIImpl(w, bytes, true)
			// If EOC was missing, the indent may not have been
			// restored correctly.
			w.SetIndent(indent)
			continue
		}

		if len(body) == 0 {
			// If the body is empty, skip the newlines.
			w.WriteLine(fmt.Sprintf("%s {}", tagToString(tag)))
			continue
		}

		if tag.Constructed {
			// If the element is constructed, recurse.
			w.WriteLine(fmt.Sprintf("%s {", tagToString(tag)))
			w.AddIndent(1)
			derToASCIIImpl(w, body, false)
			w.AddIndent(-1)
			w.WriteLine("}")
		} else {
			// The element is primitive. By default, emit the body
			// on the same line as curly braces. However, in some
			// cases, we heuristically decode the body as DER too.
			// In this case, the newlines are inserted as in the
			// constructed case.

			// If ok is false, name will be empty. There is also no
			// need to check toggleConstructed as we already know
			// the tag is primitive.
			name, _, _ := tag.GetAlias()
			switch name {
			case "INTEGER":
				w.WriteLine(fmt.Sprintf("%s { %s }", tagToString(tag), integerToString(body)))
			case "OBJECT_IDENTIFIER":
				w.WriteLine(fmt.Sprintf("%s { %s }", tagToString(tag), objectIdentifierToString(body)))
			case "BIT_STRING":
				// X.509 encodes signatures and SPKIs in BIT
				// STRINGs, so there is a 0 phase byte followed
				// by the potentially DER-encoded structure.
				if len(body) > 1 && body[0] == 0 && isMadeOfElements(body[1:]) {
					w.WriteLine(fmt.Sprintf("%s {", tagToString(tag)))
					w.AddIndent(1)
					// Emit the phase byte.
					w.WriteLine(bytesToString(body[:1]))
					// Emit the remaining as a DER element.
					derToASCIIImpl(w, body[1:], false) // Adds a trailing newline.
					w.AddIndent(-1)
					w.WriteLine("}")
				} else {
					w.WriteLine(fmt.Sprintf("%s { %s }", tagToString(tag), bytesToString(body)))
				}
			default:
				// Keep parsing if the body looks like ASN.1.
				if isMadeOfElements(body) {
					w.WriteLine(fmt.Sprintf("%s {", tagToString(tag)))
					w.AddIndent(1)
					derToASCIIImpl(w, body, false)
					w.AddIndent(-1)
					w.WriteLine("}")
				} else {
					w.WriteLine(fmt.Sprintf("%s { %s }", tagToString(tag), bytesToString(body)))
				}
			}
		}
	}
	return nil
}

func derToASCII(bytes []byte) string {
	var w writer
	derToASCIIImpl(&w, bytes, false)
	return w.String()
}
<|endoftext|>


<commit_before>package navigate

type NavigateType string

const (
	Left   NavigateType = `left`
	Top    NavigateType = `top`
	Right  NavigateType = `right`
	Bottom NavigateType = `bottom`
)

func NewCollection(baseProject string) *Collection {
	return &Collection{
		Backend: &ProjectNavigates{
			Navigates:   &Navigates{},
			baseProject: baseProject,
			projects:    map[string]*Navigates{},
		},
		Frontend: &Navigates{},
	}
}

type ProjectNavigates struct {
	*Navigates
	baseProject string
	projects    map[string]*Navigates
}

func (p *ProjectNavigates) Project(project string) *Navigates {
	if p.baseProject == project {
		return p.Navigates
	}
	nav, ok := p.projects[project]
	if !ok {
		nav = &Navigates{}
		p.projects[project] = nav
	}
	return nav
}

type Collection struct {
	Backend  *ProjectNavigates
	Frontend *Navigates
}

type Navigates map[NavigateType]*List

func (n *Navigates) Add(typ NavigateType, nav *List) {
	(*n)[typ] = nav
}

func (n *Navigates) AddItems(typ NavigateType, index int, items ...*Item) {
	nav := n.Get(typ)
	if nav == nil {
		nav = &List{}
		(*n)[typ] = nav
	}
	nav.Add(index, items...)
}

func (n *Navigates) AddTopItems(index int, items ...*Item) {
	n.AddItems(Top, index, items...)
}

func (n *Navigates) AddLeftItems(index int, items ...*Item) {
	n.AddItems(Left, index, items...)
}

func (n *Navigates) AddRightItems(index int, items ...*Item) {
	n.AddItems(Right, index, items...)
}

func (n *Navigates) AddBottomItems(index int, items ...*Item) {
	n.AddItems(Bottom, index, items...)
}

func (n *Navigates) Get(typ NavigateType) (nav *List) {
	nav = (*n)[typ]
	return
}

func (n *Navigates) GetTop() *List {
	return n.Get(Top)
}

func (n *Navigates) GetLeft() *List {
	return n.Get(Left)
}

func (n *Navigates) GetRight() *List {
	return n.Get(Right)
}

func (n *Navigates) GetBottom() *List {
	return n.Get(Bottom)
}

func (n *Navigates) Remove(typ NavigateType) bool {
	_, ok := (*n)[typ]
	if ok {
		delete(*n, typ)
	}
	return ok
}
<commit_msg>update<commit_after>package navigate

type NavigateType string

const (
	Left   NavigateType = `left`
	Top    NavigateType = `top`
	Right  NavigateType = `right`
	Bottom NavigateType = `bottom`
)

func NewCollection(baseProject string) *Collection {
	return &Collection{
		Backend: &ProjectNavigates{
			Navigates:   &Navigates{},
			baseProject: baseProject,
			projects:    map[string]*Navigates{},
		},
		Frontend: &Navigates{},
	}
}

type ProjectNavigates struct {
	*Navigates
	baseProject string
	projects    map[string]*Navigates
}

func (p *ProjectNavigates) Project(project string) *Navigates {
	if p.baseProject == project {
		return p.Navigates
	}
	nav, ok := p.projects[project]
	if !ok {
		nav = &Navigates{}
		p.projects[project] = nav
	}
	return nav
}

func (p *ProjectNavigates) RemoveProject(project string) {
	delete(p.projects, project)
}

type Collection struct {
	Backend  *ProjectNavigates
	Frontend *Navigates
}

type Navigates map[NavigateType]*List

func (n *Navigates) Add(typ NavigateType, nav *List) {
	(*n)[typ] = nav
}

func (n *Navigates) AddItems(typ NavigateType, index int, items ...*Item) {
	nav := n.Get(typ)
	if nav == nil {
		nav = &List{}
		(*n)[typ] = nav
	}
	nav.Add(index, items...)
}

func (n *Navigates) AddTopItems(index int, items ...*Item) {
	n.AddItems(Top, index, items...)
}

func (n *Navigates) AddLeftItems(index int, items ...*Item) {
	n.AddItems(Left, index, items...)
}

func (n *Navigates) AddRightItems(index int, items ...*Item) {
	n.AddItems(Right, index, items...)
}

func (n *Navigates) AddBottomItems(index int, items ...*Item) {
	n.AddItems(Bottom, index, items...)
}

func (n *Navigates) Get(typ NavigateType) (nav *List) {
	nav = (*n)[typ]
	return
}

func (n *Navigates) GetTop() *List {
	return n.Get(Top)
}

func (n *Navigates) GetLeft() *List {
	return n.Get(Left)
}

func (n *Navigates) GetRight() *List {
	return n.Get(Right)
}

func (n *Navigates) GetBottom() *List {
	return n.Get(Bottom)
}

func (n *Navigates) Remove(typ NavigateType) bool {
	_, ok := (*n)[typ]
	if ok {
		delete(*n, typ)
	}
	return ok
}
<|endoftext|>


<commit_before>package server

import (
	"bytes"
	"encoding/json"
	"sync"

	"veyron.io/wspr/veyron/services/wsprd/lib"
	"veyron.io/wspr/veyron/services/wsprd/signature"

	"veyron.io/veyron/veyron2/ipc"
	"veyron.io/veyron/veyron2/security"
	"veyron.io/veyron/veyron2/verror2"
	"veyron.io/veyron/veyron2/vlog"
)

type flowFactory interface {
	createFlow() *Flow
	cleanupFlow(id int64)
}

type invokerFactory interface {
	createInvoker(handle int64, signature signature.JSONServiceSignature, label security.Label) (ipc.Invoker, error)
}

type authFactory interface {
	createAuthorizer(handle int64, hasAuthorizer bool) (security.Authorizer, error)
}

type lookupReply struct {
	Handle        int64
	HasAuthorizer bool
	Label         security.Label
	Signature     signature.JSONServiceSignature
	Err           *verror2.Standard
}

type dispatcherRequest struct {
	ServerID uint64 `json:"serverId"`
	Suffix   string `json:"suffix"`
	Method   string `json:"method"`
}

// dispatcher holds the invoker and the authorizer to be used for lookup.
type dispatcher struct {
	mu                 sync.Mutex
	serverID           uint64
	flowFactory        flowFactory
	invokerFactory     invokerFactory
	authFactory        authFactory
	logger             vlog.Logger
	outstandingLookups map[int64]chan lookupReply
}

var _ ipc.Dispatcher = (*dispatcher)(nil)

// newDispatcher is a dispatcher factory.
func newDispatcher(serverID uint64, flowFactory flowFactory, invokerFactory invokerFactory, authFactory authFactory, logger vlog.Logger) *dispatcher {
	return &dispatcher{
		serverID:           serverID,
		flowFactory:        flowFactory,
		invokerFactory:     invokerFactory,
		authFactory:        authFactory,
		logger:             logger,
		outstandingLookups: make(map[int64]chan lookupReply),
	}
}

// Lookup implements dispatcher interface Lookup.
func (d *dispatcher) Lookup(suffix, method string) (ipc.Invoker, security.Authorizer, error) {
	flow := d.flowFactory.createFlow()
	d.mu.Lock()
	ch := make(chan lookupReply, 1)
	d.outstandingLookups[flow.ID] = ch
	d.mu.Unlock()

	message := dispatcherRequest{
		ServerID: d.serverID,
		Suffix:   suffix,
		Method:   lib.LowercaseFirstCharacter(method),
	}
	if err := flow.Writer.Send(lib.ResponseDispatcherLookup, message); err != nil {
		ch <- lookupReply{Err: verror2.Convert(verror2.Internal, nil, err).(*verror2.Standard)}
	}
	request := <-ch

	d.mu.Lock()
	delete(d.outstandingLookups, flow.ID)
	d.mu.Unlock()

	d.flowFactory.cleanupFlow(flow.ID)

	if request.Err != nil {
		return nil, nil, request.Err
	}

	if request.Handle < 0 {
		return nil, nil, verror2.Make(verror2.NoExist, nil, "Dispatcher", suffix)
	}

	invoker, err := d.invokerFactory.createInvoker(request.Handle, request.Signature, request.Label)
	if err != nil {
		return nil, nil, err
	}

	auth, err := d.authFactory.createAuthorizer(request.Handle, request.HasAuthorizer)

	return invoker, auth, err
}

func (d *dispatcher) handleLookupResponse(id int64, data string) {
	d.mu.Lock()
	ch := d.outstandingLookups[id]
	d.mu.Unlock()

	if ch == nil {
		d.flowFactory.cleanupFlow(id)
		d.logger.Errorf("unknown invoke request for flow: %d", id)
		return
	}

	var request lookupReply
	decoder := json.NewDecoder(bytes.NewBufferString(data))
	if err := decoder.Decode(&request); err != nil {
		request = lookupReply{Err: verror2.Convert(verror2.Internal, nil, err).(*verror2.Standard)}
		d.logger.Errorf("unmarshaling invoke request failed: %v, %s", err, data)
	}
	ch <- request
}

// StopServing implements dispatcher StopServing.
func (*dispatcher) StopServing() {
}
<commit_msg>ipc.Dispatcher.Lookup: signature change for CL 6254<commit_after>package server

import (
	"bytes"
	"encoding/json"
	"sync"

	"veyron.io/wspr/veyron/services/wsprd/lib"
	"veyron.io/wspr/veyron/services/wsprd/signature"

	"veyron.io/veyron/veyron2/ipc"
	"veyron.io/veyron/veyron2/security"
	"veyron.io/veyron/veyron2/verror2"
	"veyron.io/veyron/veyron2/vlog"
)

type flowFactory interface {
	createFlow() *Flow
	cleanupFlow(id int64)
}

type invokerFactory interface {
	createInvoker(handle int64, signature signature.JSONServiceSignature, label security.Label) (ipc.Invoker, error)
}

type authFactory interface {
	createAuthorizer(handle int64, hasAuthorizer bool) (security.Authorizer, error)
}

type lookupReply struct {
	Handle        int64
	HasAuthorizer bool
	Label         security.Label
	Signature     signature.JSONServiceSignature
	Err           *verror2.Standard
}

type dispatcherRequest struct {
	ServerID uint64 `json:"serverId"`
	Suffix   string `json:"suffix"`
	Method   string `json:"method"`
}

// dispatcher holds the invoker and the authorizer to be used for lookup.
type dispatcher struct {
	mu                 sync.Mutex
	serverID           uint64
	flowFactory        flowFactory
	invokerFactory     invokerFactory
	authFactory        authFactory
	logger             vlog.Logger
	outstandingLookups map[int64]chan lookupReply
}

var _ ipc.Dispatcher = (*dispatcher)(nil)

// newDispatcher is a dispatcher factory.
func newDispatcher(serverID uint64, flowFactory flowFactory, invokerFactory invokerFactory, authFactory authFactory, logger vlog.Logger) *dispatcher {
	return &dispatcher{
		serverID:           serverID,
		flowFactory:        flowFactory,
		invokerFactory:     invokerFactory,
		authFactory:        authFactory,
		logger:             logger,
		outstandingLookups: make(map[int64]chan lookupReply),
	}
}

// Lookup implements dispatcher interface Lookup.
func (d *dispatcher) Lookup(suffix, method string) (interface{}, security.Authorizer, error) {
	flow := d.flowFactory.createFlow()
	d.mu.Lock()
	ch := make(chan lookupReply, 1)
	d.outstandingLookups[flow.ID] = ch
	d.mu.Unlock()

	message := dispatcherRequest{
		ServerID: d.serverID,
		Suffix:   suffix,
		Method:   lib.LowercaseFirstCharacter(method),
	}
	if err := flow.Writer.Send(lib.ResponseDispatcherLookup, message); err != nil {
		ch <- lookupReply{Err: verror2.Convert(verror2.Internal, nil, err).(*verror2.Standard)}
	}
	request := <-ch

	d.mu.Lock()
	delete(d.outstandingLookups, flow.ID)
	d.mu.Unlock()

	d.flowFactory.cleanupFlow(flow.ID)

	if request.Err != nil {
		return nil, nil, request.Err
	}

	if request.Handle < 0 {
		return nil, nil, verror2.Make(verror2.NoExist, nil, "Dispatcher", suffix)
	}

	invoker, err := d.invokerFactory.createInvoker(request.Handle, request.Signature, request.Label)
	if err != nil {
		return nil, nil, err
	}

	auth, err := d.authFactory.createAuthorizer(request.Handle, request.HasAuthorizer)

	return invoker, auth, err
}

func (d *dispatcher) handleLookupResponse(id int64, data string) {
	d.mu.Lock()
	ch := d.outstandingLookups[id]
	d.mu.Unlock()

	if ch == nil {
		d.flowFactory.cleanupFlow(id)
		d.logger.Errorf("unknown invoke request for flow: %d", id)
		return
	}

	var request lookupReply
	decoder := json.NewDecoder(bytes.NewBufferString(data))
	if err := decoder.Decode(&request); err != nil {
		request = lookupReply{Err: verror2.Convert(verror2.Internal, nil, err).(*verror2.Standard)}
		d.logger.Errorf("unmarshaling invoke request failed: %v, %s", err, data)
	}
	ch <- request
}

// StopServing implements dispatcher StopServing.
func (*dispatcher) StopServing() {
}
<|endoftext|>


<commit_before>package generator

import (
	"socialapi/workers/helper"
	"socialapi/workers/sitemap/common"

	"github.com/koding/redis"
)

type FileSelector interface {
	Select() (string, error)
}

type SimpleFileSelector struct{}

func (s SimpleFileSelector) Select() (string, error) {
	return "sitemap", nil
}

type CachedFileSelector struct{}

func (s CachedFileSelector) Select() (string, error) {
	redisConn := helper.MustGetRedisConn()

	item, err := redisConn.PopSetMember(common.PrepareCurrentFileNameCacheKey())

	if err != redis.ErrNil {
		return "", err
	}

	return item, err
}
<commit_msg>Sitemap: Fix sitemap items are not generated bug<commit_after>package generator

import (
	"socialapi/workers/helper"
	"socialapi/workers/sitemap/common"
)

type FileSelector interface {
	Select() (string, error)
}

type SimpleFileSelector struct{}

func (s SimpleFileSelector) Select() (string, error) {
	return "sitemap", nil
}

type CachedFileSelector struct{}

func (s CachedFileSelector) Select() (string, error) {
	redisConn := helper.MustGetRedisConn()

	item, err := redisConn.PopSetMember(common.PrepareCurrentFileNameCacheKey())

	if err != nil {
		return "", err
	}

	return item, nil
}
<|endoftext|>