<commit_before>// Random odds and ends.

package fuse

import (
	"os"
	"fmt"
	"log"
	"math"
	"regexp"
	"sort"
	"syscall"
	"unsafe"
	"io/ioutil"
)

// Make a temporary directory securely.
func MakeTempDir() string {
	nm, err := ioutil.TempDir("", "go-fuse")
	if err != nil {
		panic("TempDir() failed: " + err.String())
	}
	return nm
}

// Convert os.Error back to Errno based errors.
func OsErrorToFuseError(err os.Error) Status {
	if err != nil {
		asErrno, ok := err.(os.Errno)
		if ok {
			return Status(asErrno)
		}

		asSyscallErr, ok := err.(*os.SyscallError)
		if ok {
			return Status(asSyscallErr.Errno)
		}

		asPathErr, ok := err.(*os.PathError)
		if ok {
			return OsErrorToFuseError(asPathErr.Error)
		}

		asLinkErr, ok := err.(*os.LinkError)
		if ok {
			return OsErrorToFuseError(asLinkErr.Error)
		}

		// Should not happen.  Should we log an error somewhere?
		log.Println("can't convert error type:", err)
		return ENOSYS
	}
	return OK
}

func replyString(opcode uint32, ptr unsafe.Pointer) string {
	switch opcode {
	case FUSE_LOOKUP:
		return fmt.Sprintf("%v", (*EntryOut)(ptr))
	}
	return ""
}

func operationName(opcode uint32) string {
	switch opcode {
	case FUSE_LOOKUP:
		return "FUSE_LOOKUP"
	case FUSE_FORGET:
		return "FUSE_FORGET"
	case FUSE_GETATTR:
		return "FUSE_GETATTR"
	case FUSE_SETATTR:
		return "FUSE_SETATTR"
	case FUSE_READLINK:
		return "FUSE_READLINK"
	case FUSE_SYMLINK:
		return "FUSE_SYMLINK"
	case FUSE_MKNOD:
		return "FUSE_MKNOD"
	case FUSE_MKDIR:
		return "FUSE_MKDIR"
	case FUSE_UNLINK:
		return "FUSE_UNLINK"
	case FUSE_RMDIR:
		return "FUSE_RMDIR"
	case FUSE_RENAME:
		return "FUSE_RENAME"
	case FUSE_LINK:
		return "FUSE_LINK"
	case FUSE_OPEN:
		return "FUSE_OPEN"
	case FUSE_READ:
		return "FUSE_READ"
	case FUSE_WRITE:
		return "FUSE_WRITE"
	case FUSE_STATFS:
		return "FUSE_STATFS"
	case FUSE_RELEASE:
		return "FUSE_RELEASE"
	case FUSE_FSYNC:
		return "FUSE_FSYNC"
	case FUSE_SETXATTR:
		return "FUSE_SETXATTR"
	case FUSE_GETXATTR:
		return "FUSE_GETXATTR"
	case FUSE_LISTXATTR:
		return "FUSE_LISTXATTR"
	case FUSE_REMOVEXATTR:
		return "FUSE_REMOVEXATTR"
	case FUSE_FLUSH:
		return "FUSE_FLUSH"
	case FUSE_INIT:
		return "FUSE_INIT"
	case FUSE_OPENDIR:
		return "FUSE_OPENDIR"
	case FUSE_READDIR:
		return "FUSE_READDIR"
	case FUSE_RELEASEDIR:
		return "FUSE_RELEASEDIR"
	case FUSE_FSYNCDIR:
		return "FUSE_FSYNCDIR"
	case FUSE_GETLK:
		return "FUSE_GETLK"
	case FUSE_SETLK:
		return "FUSE_SETLK"
	case FUSE_SETLKW:
		return "FUSE_SETLKW"
	case FUSE_ACCESS:
		return "FUSE_ACCESS"
	case FUSE_CREATE:
		return "FUSE_CREATE"
	case FUSE_INTERRUPT:
		return "FUSE_INTERRUPT"
	case FUSE_BMAP:
		return "FUSE_BMAP"
	case FUSE_DESTROY:
		return "FUSE_DESTROY"
	case FUSE_IOCTL:
		return "FUSE_IOCTL"
	case FUSE_POLL:
		return "FUSE_POLL"
	}
	return "UNKNOWN"
}

func (code Status) String() string {
	if code == OK {
		return "OK"
	}
	return fmt.Sprintf("%d=%v", int(code), os.Errno(code))
}

func SplitNs(time float64, secs *uint64, nsecs *uint32) {
	*nsecs = uint32(1e9 * (time - math.Trunc(time)))
	*secs = uint64(math.Trunc(time))
}

func CopyFileInfo(fi *os.FileInfo, attr *Attr) {
	attr.Ino = uint64(fi.Ino)
	attr.Size = uint64(fi.Size)
	attr.Blocks = uint64(fi.Blocks)

	attr.Atime = uint64(fi.Atime_ns / 1e9)
	attr.Atimensec = uint32(fi.Atime_ns % 1e9)

	attr.Mtime = uint64(fi.Mtime_ns / 1e9)
	attr.Mtimensec = uint32(fi.Mtime_ns % 1e9)

	attr.Ctime = uint64(fi.Ctime_ns / 1e9)
	attr.Ctimensec = uint32(fi.Ctime_ns % 1e9)

	attr.Mode = fi.Mode
	attr.Nlink = uint32(fi.Nlink)
	attr.Uid = uint32(fi.Uid)
	attr.Gid = uint32(fi.Gid)
	attr.Rdev = uint32(fi.Rdev)
	attr.Blksize = uint32(fi.Blksize)
}

func writev(fd int, iovecs *syscall.Iovec, cnt int) (n int, errno int) {
	n1, _, e1 := syscall.Syscall(
		syscall.SYS_WRITEV,
		uintptr(fd), uintptr(unsafe.Pointer(iovecs)), uintptr(cnt))
	return int(n1), int(e1)
}

func Writev(fd int, packet [][]byte) (n int, err os.Error) {
	iovecs := make([]syscall.Iovec, 0, len(packet))

	for _, v := range packet {
		if v == nil || len(v) == 0 {
			continue
		}
		vec := syscall.Iovec{
			Base: &v[0],
		}
		vec.SetLen(len(v))
		iovecs = append(iovecs, vec)
	}

	if len(iovecs) == 0 {
		return 0, nil
	}

	n, errno := writev(fd, &iovecs[0], len(iovecs))
	if errno != 0 {
		err = os.NewSyscallError("writev", errno)
	}
	return n, err
}

func CountCpus() int {
	var contents [10240]byte

	f, err := os.Open("/proc/stat")
	defer f.Close()
	if err != nil {
		return 1
	}
	n, _ := f.Read(contents[:])
	re, _ := regexp.Compile("\ncpu[0-9]")

	return len(re.FindAllString(string(contents[:n]), 100))
}

// Creates a return entry for a non-existent path.
func NegativeEntry(time float64) *EntryOut {
	out := new(EntryOut)
	out.NodeId = 0
	SplitNs(time, &out.EntryValid, &out.EntryValidNsec)
	return out
}

func ModeToType(mode uint32) uint32 {
	return (mode & 0170000) >> 12
}

func CheckSuccess(e os.Error) {
	if e != nil {
		panic(fmt.Sprintf("Unexpected error: %v", e))
	}
}

// For printing latency data.
func PrintMap(m map[string]float64) {
	keys := make([]string, len(m))
	for k, _ := range m {
		keys = append(keys, k)
	}

	sort.SortStrings(keys)
	for _, k := range keys {
		if m[k] > 0 {
			fmt.Println(k, m[k])
		}
	}
}

func MyPID() string {
	v, _ := os.Readlink("/proc/self")
	return v
}

var inputSizeMap map[int]int
var outputSizeMap map[int]int

func init() {
	inputSizeMap = map[int]int{
		FUSE_LOOKUP:      0,
		FUSE_FORGET:      unsafe.Sizeof(ForgetIn{}),
		FUSE_GETATTR:     unsafe.Sizeof(GetAttrIn{}),
		FUSE_SETATTR:     unsafe.Sizeof(SetAttrIn{}),
		FUSE_READLINK:    0,
		FUSE_SYMLINK:     0,
		FUSE_MKNOD:       unsafe.Sizeof(MknodIn{}),
		FUSE_MKDIR:       unsafe.Sizeof(MkdirIn{}),
		FUSE_UNLINK:      0,
		FUSE_RMDIR:       0,
		FUSE_RENAME:      unsafe.Sizeof(RenameIn{}),
		FUSE_LINK:        unsafe.Sizeof(LinkIn{}),
		FUSE_OPEN:        unsafe.Sizeof(OpenIn{}),
		FUSE_READ:        unsafe.Sizeof(ReadIn{}),
		FUSE_WRITE:       unsafe.Sizeof(WriteIn{}),
		FUSE_STATFS:      0,
		FUSE_RELEASE:     unsafe.Sizeof(ReleaseIn{}),
		FUSE_FSYNC:       unsafe.Sizeof(FsyncIn{}),
		FUSE_SETXATTR:    unsafe.Sizeof(SetXAttrIn{}),
		FUSE_GETXATTR:    unsafe.Sizeof(GetXAttrIn{}),
		FUSE_LISTXATTR:   unsafe.Sizeof(GetXAttrIn{}),
		FUSE_REMOVEXATTR: 0,
		FUSE_FLUSH:       unsafe.Sizeof(FlushIn{}),
		FUSE_INIT:        unsafe.Sizeof(InitIn{}),
		FUSE_OPENDIR:     unsafe.Sizeof(OpenIn{}),
		FUSE_READDIR:     unsafe.Sizeof(ReadIn{}),
		FUSE_RELEASEDIR:  unsafe.Sizeof(ReleaseIn{}),
		FUSE_FSYNCDIR:    unsafe.Sizeof(FsyncIn{}),
		FUSE_GETLK:       0,
		FUSE_SETLK:       0,
		FUSE_SETLKW:      0,
		FUSE_ACCESS:      unsafe.Sizeof(AccessIn{}),
		FUSE_CREATE:      unsafe.Sizeof(CreateIn{}),
		FUSE_INTERRUPT:   unsafe.Sizeof(InterruptIn{}),
		FUSE_BMAP:        unsafe.Sizeof(BmapIn{}),
		FUSE_DESTROY:     0,
		FUSE_IOCTL:       unsafe.Sizeof(IoctlIn{}),
		FUSE_POLL:        unsafe.Sizeof(PollIn{}),
	}

	outputSizeMap = map[int]int{
		FUSE_LOOKUP:      unsafe.Sizeof(EntryOut{}),
		FUSE_FORGET:      0,
		FUSE_GETATTR:     unsafe.Sizeof(AttrOut{}),
		FUSE_SETATTR:     unsafe.Sizeof(AttrOut{}),
		FUSE_READLINK:    0,
		FUSE_SYMLINK:     unsafe.Sizeof(EntryOut{}),
		FUSE_MKNOD:       unsafe.Sizeof(EntryOut{}),
		FUSE_MKDIR:       unsafe.Sizeof(EntryOut{}),
		FUSE_UNLINK:      0,
		FUSE_RMDIR:       0,
		FUSE_RENAME:      0,
		FUSE_LINK:        unsafe.Sizeof(EntryOut{}),
		FUSE_OPEN:        unsafe.Sizeof(OpenOut{}),
		FUSE_READ:        0,
		FUSE_WRITE:       unsafe.Sizeof(WriteOut{}),
		FUSE_STATFS:      unsafe.Sizeof(StatfsOut{}),
		FUSE_RELEASE:     0,
		FUSE_FSYNC:       0,
		FUSE_SETXATTR:    0,
		FUSE_GETXATTR:    unsafe.Sizeof(GetXAttrOut{}),
		FUSE_LISTXATTR:   unsafe.Sizeof(GetXAttrOut{}),
		FUSE_REMOVEXATTR: 0,
		FUSE_FLUSH:       0,
		FUSE_INIT:        unsafe.Sizeof(InitOut{}),
		FUSE_OPENDIR:     unsafe.Sizeof(OpenOut{}),
		FUSE_READDIR:     0,
		FUSE_RELEASEDIR:  0,
		FUSE_FSYNCDIR:    0,
		// TODO
		FUSE_GETLK:     0,
		FUSE_SETLK:     0,
		FUSE_SETLKW:    0,
		FUSE_ACCESS:    0,
		FUSE_CREATE:    unsafe.Sizeof(CreateOut{}),
		FUSE_INTERRUPT: 0,
		FUSE_BMAP:      unsafe.Sizeof(BmapOut{}),
		FUSE_DESTROY:   0,
		FUSE_IOCTL:     unsafe.Sizeof(IoctlOut{}),
		FUSE_POLL:      unsafe.Sizeof(PollOut{}),
	}
}
<commit_msg>Use type switch for OsErrorToFuseError().<commit_after>// Random odds and ends.

package fuse

import (
	"os"
	"fmt"
	"log"
	"math"
	"regexp"
	"sort"
	"syscall"
	"unsafe"
	"io/ioutil"
)

// Make a temporary directory securely.
func MakeTempDir() string {
	nm, err := ioutil.TempDir("", "go-fuse")
	if err != nil {
		panic("TempDir() failed: " + err.String())
	}
	return nm
}

// Convert os.Error back to Errno based errors.
func OsErrorToFuseError(err os.Error) Status {
	if err != nil {
		switch t := err.(type) {
		case os.Errno:
			return Status(t)
		case *os.SyscallError:
			return Status(t.Errno)
		case *os.PathError:
			return OsErrorToFuseError(t.Error)
		case *os.LinkError:
			return OsErrorToFuseError(t.Error)
		default:
			log.Println("can't convert error type:", err)
			return ENOSYS
		}
	}
	return OK
}

func replyString(opcode uint32, ptr unsafe.Pointer) string {
	switch opcode {
	case FUSE_LOOKUP:
		return fmt.Sprintf("%v", (*EntryOut)(ptr))
	}
	return ""
}

func operationName(opcode uint32) string {
	switch opcode {
	case FUSE_LOOKUP:
		return "FUSE_LOOKUP"
	case FUSE_FORGET:
		return "FUSE_FORGET"
	case FUSE_GETATTR:
		return "FUSE_GETATTR"
	case FUSE_SETATTR:
		return "FUSE_SETATTR"
	case FUSE_READLINK:
		return "FUSE_READLINK"
	case FUSE_SYMLINK:
		return "FUSE_SYMLINK"
	case FUSE_MKNOD:
		return "FUSE_MKNOD"
	case FUSE_MKDIR:
		return "FUSE_MKDIR"
	case FUSE_UNLINK:
		return "FUSE_UNLINK"
	case FUSE_RMDIR:
		return "FUSE_RMDIR"
	case FUSE_RENAME:
		return "FUSE_RENAME"
	case FUSE_LINK:
		return "FUSE_LINK"
	case FUSE_OPEN:
		return "FUSE_OPEN"
	case FUSE_READ:
		return "FUSE_READ"
	case FUSE_WRITE:
		return "FUSE_WRITE"
	case FUSE_STATFS:
		return "FUSE_STATFS"
	case FUSE_RELEASE:
		return "FUSE_RELEASE"
	case FUSE_FSYNC:
		return "FUSE_FSYNC"
	case FUSE_SETXATTR:
		return "FUSE_SETXATTR"
	case FUSE_GETXATTR:
		return "FUSE_GETXATTR"
	case FUSE_LISTXATTR:
		return "FUSE_LISTXATTR"
	case FUSE_REMOVEXATTR:
		return "FUSE_REMOVEXATTR"
	case FUSE_FLUSH:
		return "FUSE_FLUSH"
	case FUSE_INIT:
		return "FUSE_INIT"
	case FUSE_OPENDIR:
		return "FUSE_OPENDIR"
	case FUSE_READDIR:
		return "FUSE_READDIR"
	case FUSE_RELEASEDIR:
		return "FUSE_RELEASEDIR"
	case FUSE_FSYNCDIR:
		return "FUSE_FSYNCDIR"
	case FUSE_GETLK:
		return "FUSE_GETLK"
	case FUSE_SETLK:
		return "FUSE_SETLK"
	case FUSE_SETLKW:
		return "FUSE_SETLKW"
	case FUSE_ACCESS:
		return "FUSE_ACCESS"
	case FUSE_CREATE:
		return "FUSE_CREATE"
	case FUSE_INTERRUPT:
		return "FUSE_INTERRUPT"
	case FUSE_BMAP:
		return "FUSE_BMAP"
	case FUSE_DESTROY:
		return "FUSE_DESTROY"
	case FUSE_IOCTL:
		return "FUSE_IOCTL"
	case FUSE_POLL:
		return "FUSE_POLL"
	}
	return "UNKNOWN"
}

func (code Status) String() string {
	if code == OK {
		return "OK"
	}
	return fmt.Sprintf("%d=%v", int(code), os.Errno(code))
}

func SplitNs(time float64, secs *uint64, nsecs *uint32) {
	*nsecs = uint32(1e9 * (time - math.Trunc(time)))
	*secs = uint64(math.Trunc(time))
}

func CopyFileInfo(fi *os.FileInfo, attr *Attr) {
	attr.Ino = uint64(fi.Ino)
	attr.Size = uint64(fi.Size)
	attr.Blocks = uint64(fi.Blocks)

	attr.Atime = uint64(fi.Atime_ns / 1e9)
	attr.Atimensec = uint32(fi.Atime_ns % 1e9)

	attr.Mtime = uint64(fi.Mtime_ns / 1e9)
	attr.Mtimensec = uint32(fi.Mtime_ns % 1e9)

	attr.Ctime = uint64(fi.Ctime_ns / 1e9)
	attr.Ctimensec = uint32(fi.Ctime_ns % 1e9)

	attr.Mode = fi.Mode
	attr.Nlink = uint32(fi.Nlink)
	attr.Uid = uint32(fi.Uid)
	attr.Gid = uint32(fi.Gid)
	attr.Rdev = uint32(fi.Rdev)
	attr.Blksize = uint32(fi.Blksize)
}

func writev(fd int, iovecs *syscall.Iovec, cnt int) (n int, errno int) {
	n1, _, e1 := syscall.Syscall(
		syscall.SYS_WRITEV,
		uintptr(fd), uintptr(unsafe.Pointer(iovecs)), uintptr(cnt))
	return int(n1), int(e1)
}

func Writev(fd int, packet [][]byte) (n int, err os.Error) {
	iovecs := make([]syscall.Iovec, 0, len(packet))

	for _, v := range packet {
		if v == nil || len(v) == 0 {
			continue
		}
		vec := syscall.Iovec{
			Base: &v[0],
		}
		vec.SetLen(len(v))
		iovecs = append(iovecs, vec)
	}

	if len(iovecs) == 0 {
		return 0, nil
	}

	n, errno := writev(fd, &iovecs[0], len(iovecs))
	if errno != 0 {
		err = os.NewSyscallError("writev", errno)
	}
	return n, err
}

func CountCpus() int {
	var contents [10240]byte

	f, err := os.Open("/proc/stat")
	defer f.Close()
	if err != nil {
		return 1
	}
	n, _ := f.Read(contents[:])
	re, _ := regexp.Compile("\ncpu[0-9]")

	return len(re.FindAllString(string(contents[:n]), 100))
}

// Creates a return entry for a non-existent path.
func NegativeEntry(time float64) *EntryOut {
	out := new(EntryOut)
	out.NodeId = 0
	SplitNs(time, &out.EntryValid, &out.EntryValidNsec)
	return out
}

func ModeToType(mode uint32) uint32 {
	return (mode & 0170000) >> 12
}

func CheckSuccess(e os.Error) {
	if e != nil {
		panic(fmt.Sprintf("Unexpected error: %v", e))
	}
}

// For printing latency data.
func PrintMap(m map[string]float64) {
	keys := make([]string, len(m))
	for k, _ := range m {
		keys = append(keys, k)
	}

	sort.SortStrings(keys)
	for _, k := range keys {
		if m[k] > 0 {
			fmt.Println(k, m[k])
		}
	}
}

func MyPID() string {
	v, _ := os.Readlink("/proc/self")
	return v
}

var inputSizeMap map[int]int
var outputSizeMap map[int]int

func init() {
	inputSizeMap = map[int]int{
		FUSE_LOOKUP:      0,
		FUSE_FORGET:      unsafe.Sizeof(ForgetIn{}),
		FUSE_GETATTR:     unsafe.Sizeof(GetAttrIn{}),
		FUSE_SETATTR:     unsafe.Sizeof(SetAttrIn{}),
		FUSE_READLINK:    0,
		FUSE_SYMLINK:     0,
		FUSE_MKNOD:       unsafe.Sizeof(MknodIn{}),
		FUSE_MKDIR:       unsafe.Sizeof(MkdirIn{}),
		FUSE_UNLINK:      0,
		FUSE_RMDIR:       0,
		FUSE_RENAME:      unsafe.Sizeof(RenameIn{}),
		FUSE_LINK:        unsafe.Sizeof(LinkIn{}),
		FUSE_OPEN:        unsafe.Sizeof(OpenIn{}),
		FUSE_READ:        unsafe.Sizeof(ReadIn{}),
		FUSE_WRITE:       unsafe.Sizeof(WriteIn{}),
		FUSE_STATFS:      0,
		FUSE_RELEASE:     unsafe.Sizeof(ReleaseIn{}),
		FUSE_FSYNC:       unsafe.Sizeof(FsyncIn{}),
		FUSE_SETXATTR:    unsafe.Sizeof(SetXAttrIn{}),
		FUSE_GETXATTR:    unsafe.Sizeof(GetXAttrIn{}),
		FUSE_LISTXATTR:   unsafe.Sizeof(GetXAttrIn{}),
		FUSE_REMOVEXATTR: 0,
		FUSE_FLUSH:       unsafe.Sizeof(FlushIn{}),
		FUSE_INIT:        unsafe.Sizeof(InitIn{}),
		FUSE_OPENDIR:     unsafe.Sizeof(OpenIn{}),
		FUSE_READDIR:     unsafe.Sizeof(ReadIn{}),
		FUSE_RELEASEDIR:  unsafe.Sizeof(ReleaseIn{}),
		FUSE_FSYNCDIR:    unsafe.Sizeof(FsyncIn{}),
		FUSE_GETLK:       0,
		FUSE_SETLK:       0,
		FUSE_SETLKW:      0,
		FUSE_ACCESS:      unsafe.Sizeof(AccessIn{}),
		FUSE_CREATE:      unsafe.Sizeof(CreateIn{}),
		FUSE_INTERRUPT:   unsafe.Sizeof(InterruptIn{}),
		FUSE_BMAP:        unsafe.Sizeof(BmapIn{}),
		FUSE_DESTROY:     0,
		FUSE_IOCTL:       unsafe.Sizeof(IoctlIn{}),
		FUSE_POLL:        unsafe.Sizeof(PollIn{}),
	}

	outputSizeMap = map[int]int{
		FUSE_LOOKUP:      unsafe.Sizeof(EntryOut{}),
		FUSE_FORGET:      0,
		FUSE_GETATTR:     unsafe.Sizeof(AttrOut{}),
		FUSE_SETATTR:     unsafe.Sizeof(AttrOut{}),
		FUSE_READLINK:    0,
		FUSE_SYMLINK:     unsafe.Sizeof(EntryOut{}),
		FUSE_MKNOD:       unsafe.Sizeof(EntryOut{}),
		FUSE_MKDIR:       unsafe.Sizeof(EntryOut{}),
		FUSE_UNLINK:      0,
		FUSE_RMDIR:       0,
		FUSE_RENAME:      0,
		FUSE_LINK:        unsafe.Sizeof(EntryOut{}),
		FUSE_OPEN:        unsafe.Sizeof(OpenOut{}),
		FUSE_READ:        0,
		FUSE_WRITE:       unsafe.Sizeof(WriteOut{}),
		FUSE_STATFS:      unsafe.Sizeof(StatfsOut{}),
		FUSE_RELEASE:     0,
		FUSE_FSYNC:       0,
		FUSE_SETXATTR:    0,
		FUSE_GETXATTR:    unsafe.Sizeof(GetXAttrOut{}),
		FUSE_LISTXATTR:   unsafe.Sizeof(GetXAttrOut{}),
		FUSE_REMOVEXATTR: 0,
		FUSE_FLUSH:       0,
		FUSE_INIT:        unsafe.Sizeof(InitOut{}),
		FUSE_OPENDIR:     unsafe.Sizeof(OpenOut{}),
		FUSE_READDIR:     0,
		FUSE_RELEASEDIR:  0,
		FUSE_FSYNCDIR:    0,
		// TODO
		FUSE_GETLK:     0,
		FUSE_SETLK:     0,
		FUSE_SETLKW:    0,
		FUSE_ACCESS:    0,
		FUSE_CREATE:    unsafe.Sizeof(CreateOut{}),
		FUSE_INTERRUPT: 0,
		FUSE_BMAP:      unsafe.Sizeof(BmapOut{}),
		FUSE_DESTROY:   0,
		FUSE_IOCTL:     unsafe.Sizeof(IoctlOut{}),
		FUSE_POLL:      unsafe.Sizeof(PollOut{}),
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 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 data

import (
	"database/sql"
	"fmt"
	"github.com/30x/apid-core"
	"github.com/30x/apid-core/api"
	"github.com/30x/apid-core/data/wrap"
	"github.com/30x/apid-core/logger"
	"github.com/Sirupsen/logrus"
	"github.com/mattn/go-sqlite3"
	"os"
	"path"
	"runtime"
	"strings"
	"sync"
	"time"
)

const (
	configDataDriverKey    = "data_driver"
	configDataSourceKey    = "data_source"
	configDataPathKey      = "data_path"
	statCollectionInterval = 10
	commonDBID             = "common"
	commonDBVersion        = "base"

	defaultTraceLevel = "warn"
)

var log, dbTraceLog apid.LogService
var config apid.ConfigService

type dbMapInfo struct {
	db *sql.DB
	closed chan bool
}

var dbMap = make(map[string]*dbMapInfo)
var dbMapSync sync.RWMutex

func CreateDataService() apid.DataService {
	config = apid.Config()
	log = apid.Log().ForModule("data")

	// we don't want to trace normally
	config.SetDefault("DATA_TRACE_LOG_LEVEL", defaultTraceLevel)
	dbTraceLog = apid.Log().ForModule("data_trace")

	config.SetDefault(configDataDriverKey, "sqlite3")
	config.SetDefault(configDataSourceKey, "file:%s")
	config.SetDefault(configDataPathKey, "sqlite")

	return &dataService{}
}

type dataService struct {
}

func (d *dataService) DB() (apid.DB, error) {
	return d.dbVersionForID(commonDBID, commonDBVersion)
}

func (d *dataService) DBForID(id string) (apid.DB, error) {
	if id == commonDBID {
		return nil, fmt.Errorf("reserved ID: %s", id)
	}
	return d.dbVersionForID(id, commonDBVersion)
}

func (d *dataService) DBVersion(version string) (apid.DB, error) {
	if version == commonDBVersion {
		return nil, fmt.Errorf("reserved version: %s", version)
	}
	return d.dbVersionForID(commonDBID, version)
}

func (d *dataService) DBVersionForID(id, version string) (apid.DB, error) {
	if id == commonDBID {
		return nil, fmt.Errorf("reserved ID: %s", id)
	}
	if version == commonDBVersion {
		return nil, fmt.Errorf("reserved version: %s", version)
	}
	return d.dbVersionForID(id, version)
}

// will set DB to close and delete when no more references
func (d *dataService) ReleaseDB(id, version string) {
	versionedID := VersionedDBID(id, version)

	dbMapSync.Lock()
	defer dbMapSync.Unlock()

	dbm := dbMap[versionedID]
	if dbm.db != nil {
		if strings.EqualFold(config.GetString(logger.ConfigLevel), logrus.DebugLevel.String()) {
			dbm.closed <- true
		}
		log.Warn("SETTING FINALIZER")
		finalizer := Delete(versionedID)
		runtime.SetFinalizer(dbm.db, finalizer)
		dbMap[versionedID] = nil
	} else {
		log.Error("Cannot find DB handle for ver {%s} to release", version)
	}

	return
}

func (d *dataService) dbVersionForID(id, version string) (db *sql.DB, err error) {

	var stoplogchan chan bool
	versionedID := VersionedDBID(id, version)

	dbMapSync.RLock()
	dbm := dbMap[versionedID]
	dbMapSync.RUnlock()
	if dbm != nil && dbm.db != nil {
		return dbm.db, nil
	}

	dbMapSync.Lock()
	defer dbMapSync.Unlock()

	dataPath := DBPath(versionedID)

	if err = os.MkdirAll(path.Dir(dataPath), 0700); err != nil {
		return
	}

	log.Infof("LoadDB: %s", dataPath)
	source := fmt.Sprintf(config.GetString(configDataSourceKey), dataPath)

	wrappedDriverName := "dd:" + config.GetString(configDataDriverKey)
	driver := wrap.NewDriver(&sqlite3.SQLiteDriver{}, dbTraceLog)
	func() {
		// just ignore the "registered twice" panic
		defer func() {
			recover()
		}()
		sql.Register(wrappedDriverName, driver)
	}()

	db, err = sql.Open(wrappedDriverName, source)
	if err != nil {
		log.Errorf("error loading db: %s", err)
		return
	}

	err = db.Ping()
	if err != nil {
		log.Errorf("error pinging db: %s", err)
		return
	}

	sqlString := "PRAGMA journal_mode=WAL;"
	_, err = db.Exec(sqlString)
	if err != nil {
		log.Errorf("error setting journal_mode: %s", err)
		return
	}

	sqlString = "PRAGMA foreign_keys = ON;"
	_, err = db.Exec(sqlString)
	if err != nil {
		log.Errorf("error enabling foreign_keys: %s", err)
		return
	}
	if strings.EqualFold(config.GetString(logger.ConfigLevel),
			logrus.DebugLevel.String()) {
		stoplogchan = logDBInfo(versionedID, db)
	}

	db.SetMaxOpenConns(config.GetInt(api.ConfigDBMaxConns))
	db.SetMaxIdleConns(config.GetInt(api.ConfigDBIdleConns))
	db.SetConnMaxLifetime(time.Duration(config.GetInt(api.ConfigDBConnsTimeout)) * time.Second)
	dbInfo := dbMapInfo {db: db, closed: stoplogchan}
	dbMap[versionedID] = &dbInfo
	return
}

func Delete(versionedID string) interface{} {
	return func(db *sql.DB) {
		err := db.Close()
		if err != nil {
			log.Errorf("error closing DB: %v", err)
		}
		dataDir := path.Dir(DBPath(versionedID))
		err = os.RemoveAll(dataDir)
		if err != nil {
			log.Errorf("error removing DB files: %v", err)
		}
		delete(dbMap, versionedID)
	}
}

func VersionedDBID(id, version string) string {
	return path.Join(id, version)
}

func DBPath(id string) string {
	storagePath := config.GetString("local_storage_path")
	relativeDataPath := config.GetString(configDataPathKey)
	return path.Join(storagePath, relativeDataPath, id, "sqlite3")
}

func logDBInfo(versionedId string, db *sql.DB) chan bool {
	stop := make(chan bool)
	go func() {
		for {
			select {
			case <-time.After(time.Duration(statCollectionInterval * time.Second)):
				log.Debugf("Current number of open DB connections for ver {%s} is {%d}",
					versionedId, db.Stats().OpenConnections)
			case <-stop:
				log.Debugf("Stop DB conn. logging for ver {%s}", versionedId)
				return
			}
		}
	}()
	return stop
}

<commit_msg>gofmt.<commit_after>// Copyright 2017 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 data

import (
	"database/sql"
	"fmt"
	"github.com/30x/apid-core"
	"github.com/30x/apid-core/api"
	"github.com/30x/apid-core/data/wrap"
	"github.com/30x/apid-core/logger"
	"github.com/Sirupsen/logrus"
	"github.com/mattn/go-sqlite3"
	"os"
	"path"
	"runtime"
	"strings"
	"sync"
	"time"
)

const (
	configDataDriverKey    = "data_driver"
	configDataSourceKey    = "data_source"
	configDataPathKey      = "data_path"
	statCollectionInterval = 10
	commonDBID             = "common"
	commonDBVersion        = "base"

	defaultTraceLevel = "warn"
)

var log, dbTraceLog apid.LogService
var config apid.ConfigService

type dbMapInfo struct {
	db     *sql.DB
	closed chan bool
}

var dbMap = make(map[string]*dbMapInfo)
var dbMapSync sync.RWMutex

func CreateDataService() apid.DataService {
	config = apid.Config()
	log = apid.Log().ForModule("data")

	// we don't want to trace normally
	config.SetDefault("DATA_TRACE_LOG_LEVEL", defaultTraceLevel)
	dbTraceLog = apid.Log().ForModule("data_trace")

	config.SetDefault(configDataDriverKey, "sqlite3")
	config.SetDefault(configDataSourceKey, "file:%s")
	config.SetDefault(configDataPathKey, "sqlite")

	return &dataService{}
}

type dataService struct {
}

func (d *dataService) DB() (apid.DB, error) {
	return d.dbVersionForID(commonDBID, commonDBVersion)
}

func (d *dataService) DBForID(id string) (apid.DB, error) {
	if id == commonDBID {
		return nil, fmt.Errorf("reserved ID: %s", id)
	}
	return d.dbVersionForID(id, commonDBVersion)
}

func (d *dataService) DBVersion(version string) (apid.DB, error) {
	if version == commonDBVersion {
		return nil, fmt.Errorf("reserved version: %s", version)
	}
	return d.dbVersionForID(commonDBID, version)
}

func (d *dataService) DBVersionForID(id, version string) (apid.DB, error) {
	if id == commonDBID {
		return nil, fmt.Errorf("reserved ID: %s", id)
	}
	if version == commonDBVersion {
		return nil, fmt.Errorf("reserved version: %s", version)
	}
	return d.dbVersionForID(id, version)
}

// will set DB to close and delete when no more references
func (d *dataService) ReleaseDB(id, version string) {
	versionedID := VersionedDBID(id, version)

	dbMapSync.Lock()
	defer dbMapSync.Unlock()

	dbm := dbMap[versionedID]
	if dbm != nil && dbm.db != nil {
		if strings.EqualFold(config.GetString(logger.ConfigLevel), logrus.DebugLevel.String()) {
			dbm.closed <- true
		}
		log.Warn("SETTING FINALIZER")
		finalizer := Delete(versionedID)
		runtime.SetFinalizer(dbm.db, finalizer)
		dbMap[versionedID] = nil
	} else {
		log.Error("Cannot find DB handle for ver {%s} to release", version)
	}

	return
}

func (d *dataService) dbVersionForID(id, version string) (db *sql.DB, err error) {

	var stoplogchan chan bool
	versionedID := VersionedDBID(id, version)

	dbMapSync.RLock()
	dbm := dbMap[versionedID]
	dbMapSync.RUnlock()
	if dbm != nil && dbm.db != nil {
		return dbm.db, nil
	}

	dbMapSync.Lock()
	defer dbMapSync.Unlock()

	dataPath := DBPath(versionedID)

	if err = os.MkdirAll(path.Dir(dataPath), 0700); err != nil {
		return
	}

	log.Infof("LoadDB: %s", dataPath)
	source := fmt.Sprintf(config.GetString(configDataSourceKey), dataPath)

	wrappedDriverName := "dd:" + config.GetString(configDataDriverKey)
	driver := wrap.NewDriver(&sqlite3.SQLiteDriver{}, dbTraceLog)
	func() {
		// just ignore the "registered twice" panic
		defer func() {
			recover()
		}()
		sql.Register(wrappedDriverName, driver)
	}()

	db, err = sql.Open(wrappedDriverName, source)
	if err != nil {
		log.Errorf("error loading db: %s", err)
		return
	}

	err = db.Ping()
	if err != nil {
		log.Errorf("error pinging db: %s", err)
		return
	}

	sqlString := "PRAGMA journal_mode=WAL;"
	_, err = db.Exec(sqlString)
	if err != nil {
		log.Errorf("error setting journal_mode: %s", err)
		return
	}

	sqlString = "PRAGMA foreign_keys = ON;"
	_, err = db.Exec(sqlString)
	if err != nil {
		log.Errorf("error enabling foreign_keys: %s", err)
		return
	}
	if strings.EqualFold(config.GetString(logger.ConfigLevel),
		logrus.DebugLevel.String()) {
		stoplogchan = logDBInfo(versionedID, db)
	}

	db.SetMaxOpenConns(config.GetInt(api.ConfigDBMaxConns))
	db.SetMaxIdleConns(config.GetInt(api.ConfigDBIdleConns))
	db.SetConnMaxLifetime(time.Duration(config.GetInt(api.ConfigDBConnsTimeout)) * time.Second)
	dbInfo := dbMapInfo{db: db, closed: stoplogchan}
	dbMap[versionedID] = &dbInfo
	return
}

func Delete(versionedID string) interface{} {
	return func(db *sql.DB) {
		err := db.Close()
		if err != nil {
			log.Errorf("error closing DB: %v", err)
		}
		dataDir := path.Dir(DBPath(versionedID))
		err = os.RemoveAll(dataDir)
		if err != nil {
			log.Errorf("error removing DB files: %v", err)
		}
		delete(dbMap, versionedID)
	}
}

func VersionedDBID(id, version string) string {
	return path.Join(id, version)
}

func DBPath(id string) string {
	storagePath := config.GetString("local_storage_path")
	relativeDataPath := config.GetString(configDataPathKey)
	return path.Join(storagePath, relativeDataPath, id, "sqlite3")
}

func logDBInfo(versionedId string, db *sql.DB) chan bool {
	stop := make(chan bool)
	go func() {
		for {
			select {
			case <-time.After(time.Duration(statCollectionInterval * time.Second)):
				log.Debugf("Current number of open DB connections for ver {%s} is {%d}",
					versionedId, db.Stats().OpenConnections)
			case <-stop:
				log.Debugf("Stop DB conn. logging for ver {%s}", versionedId)
				return
			}
		}
	}()
	return stop
}
<|endoftext|>


<commit_before>// Copyright 2016 The Upspin Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package transports is a helper package that aggregates
// the key, store, and directory imports.
// It should be imported by client programs as a convenient
// way to link with all the transport implementations.
// It should not be imported by server programs.
package transports

import (
	"sync"

	"upspin.io/bind"
	"upspin.io/dir/inprocess"
	"upspin.io/upspin"

	_ "upspin.io/key/transports"
	_ "upspin.io/store/transports"

	_ "upspin.io/dir/remote"
	_ "upspin.io/dir/unassigned"
)

var bindOnce sync.Once

// Init initializes the transports for the given configuration.
// It is a no-op if passed a nil config or called more than once.
//
// It should be called only by client programs, directly after parsing a
// config. This handles the case where a config specifies an inprocess
// directory server and configures that server to talk to the specified store
// server.
func Init(cfg upspin.Config) {
	if cfg == nil {
		return
	}
	if cfg.DirEndpoint().Transport == upspin.InProcess {
		bindOnce.Do(func() {
			bind.RegisterDirServer(upspin.InProcess, inprocess.New(cfg))
		})
	}
}
<commit_msg>transports: fix doc comment<commit_after>// Copyright 2016 The Upspin Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package transports is a helper package that aggregates
// the key, store, and directory imports.
// It can be imported by Upspin programs as a convenient
// way to link with all the transport implementations.
package transports

import (
	"sync"

	"upspin.io/bind"
	"upspin.io/dir/inprocess"
	"upspin.io/upspin"

	_ "upspin.io/key/transports"
	_ "upspin.io/store/transports"

	_ "upspin.io/dir/remote"
	_ "upspin.io/dir/unassigned"
)

var bindOnce sync.Once

// Init initializes the transports for the given configuration.
// It is a no-op if passed a nil config or called more than once.
//
// It should be called only by client programs, directly after parsing a
// config. This handles the case where a config specifies an inprocess
// directory server and configures that server to talk to the specified store
// server.
func Init(cfg upspin.Config) {
	if cfg == nil {
		return
	}
	if cfg.DirEndpoint().Transport == upspin.InProcess {
		bindOnce.Do(func() {
			bind.RegisterDirServer(upspin.InProcess, inprocess.New(cfg))
		})
	}
}
<|endoftext|>


<commit_before>package check

import (
	"fmt"
	"testing"

	"github.com/alcortesm/queue"
)

func Seq(n int) []int {
	ret := make([]int, n)
	for i, _ := range ret {
		ret[i] = i
	}
	return ret
}

func error(t *testing.T, ctx string, msg string) {
	t.Errorf("context: %q\n %s", ctx, msg)
}

func Bounded(t *testing.T, q queue.Queue, expected bool, context string) {
	obtained := q.Bounded()
	if obtained != expected {
		msg := fmt.Sprintf("wrong bounded info: expected %t, got %t",
			expected, obtained)
		error(t, context, msg)
	}
}

func CapInfinite(t *testing.T, q queue.Queue, context string) {
	capacity, err := q.Cap()
	if err == nil {
		msg := fmt.Sprintf("nil error calling Cap, "+
			"ErrInfinite was expected, capacity was %d",
			capacity)
		error(t, context, msg)
	}
	if err != queue.ErrInfinite {
		t.Errorf("%swrong error calling Cap: %s", context, err)
	}
}

func CapBounded(t *testing.T, q queue.Queue, expected int, context string) {
	obtained, err := q.Cap()
	if err != nil {
		msg := fmt.Sprintf("unexpected error calling Cap: %q", err)
		error(t, context, msg)
	}
	if obtained != expected {
		msg := fmt.Sprintf("wrong capacity: expected %d, got %d",
			expected, obtained)
		error(t, context, msg)
	}
}

func Len(t *testing.T, q queue.Queue, expected int, context string) {
	obtained := q.Len()
	if obtained != expected {
		msg := fmt.Sprintf("wrong Len: expected %d, got %d",
			expected, obtained)
		error(t, context, msg)
	}
}

func Empty(t *testing.T, q queue.Queue, expected bool, context string) {
	obtained := q.Empty()
	if obtained != expected {
		msg := fmt.Sprintf("wrong Empty: expected %t, got %t",
			expected, obtained)
		error(t, context, msg)
	}
}

func Full(t *testing.T, q queue.Queue, expected bool, context string) {
	obtained := q.Full()
	if obtained != expected {
		msg := fmt.Sprintf("wrong Full: expected %t, got %t",
			expected, obtained)
		error(t, context, msg)
	}
}
<commit_msg>check: add check to fill queue and try to enqueue again<commit_after>package check

import (
	"fmt"
	"testing"

	"github.com/alcortesm/queue"
)

func Seq(n int) []int {
	ret := make([]int, n)
	for i, _ := range ret {
		ret[i] = i
	}
	return ret
}

func error(t *testing.T, ctx string, msg string) {
	t.Errorf("context: %q\n %s", ctx, msg)
}

func Bounded(t *testing.T, q queue.Queue, expected bool, context string) {
	obtained := q.Bounded()
	if obtained != expected {
		msg := fmt.Sprintf("wrong bounded info: expected %t, got %t",
			expected, obtained)
		error(t, context, msg)
	}
}

func CapInfinite(t *testing.T, q queue.Queue, context string) {
	capacity, err := q.Cap()
	if err == nil {
		msg := fmt.Sprintf("nil error calling Cap, "+
			"ErrInfinite was expected, capacity was %d",
			capacity)
		error(t, context, msg)
	}
	if err != queue.ErrInfinite {
		t.Errorf("%swrong error calling Cap: %s", context, err)
	}
}

func CapBounded(t *testing.T, q queue.Queue, expected int, context string) {
	obtained, err := q.Cap()
	if err != nil {
		msg := fmt.Sprintf("unexpected error calling Cap: %q", err)
		error(t, context, msg)
	}
	if obtained != expected {
		msg := fmt.Sprintf("wrong capacity: expected %d, got %d",
			expected, obtained)
		error(t, context, msg)
	}
}

func Len(t *testing.T, q queue.Queue, expected int, context string) {
	obtained := q.Len()
	if obtained != expected {
		msg := fmt.Sprintf("wrong Len: expected %d, got %d",
			expected, obtained)
		error(t, context, msg)
	}
}

func Empty(t *testing.T, q queue.Queue, expected bool, context string) {
	obtained := q.Empty()
	if obtained != expected {
		msg := fmt.Sprintf("wrong Empty: expected %t, got %t",
			expected, obtained)
		error(t, context, msg)
	}
}

func Full(t *testing.T, q queue.Queue, expected bool, context string) {
	obtained := q.Full()
	if obtained != expected {
		msg := fmt.Sprintf("wrong Full: expected %t, got %t",
			expected, obtained)
		error(t, context, msg)
	}
}

func ErrorWhenCapIsReached(t *testing.T, q queue.Queue, context string) {
	Bounded(t, q, true, context)
	Len(t, q, 0, context)
	capacity, err := q.Cap()
	if err != nil {
		msg := fmt.Sprintf("unexpected error calling Cap: %q", err)
		error(t, context, msg)
	}
	// fill up the queue
	for i := range Seq(capacity) {
		if err := q.Enqueue(i); err != nil {
			msg := fmt.Sprintf(
				"unexpected error filling up queue:\n"+
					"on enqueue operation #%d: %s", i, err)
			error(t, context, msg)
		}
	}
	Full(t, q, true, context)
	// check that enqueueing once more gives ErrFull
	err = q.Enqueue(0)
	if err == nil {
		msg := fmt.Sprintf("enqueue on a full queue: return nil error")
		error(t, context, msg)
	}
	if err != queue.ErrFull {
		msg := fmt.Sprintf(
			"enqueue on a full queue: expected ErrFull, got %q", err)
		error(t, context, msg)
	}
}
<|endoftext|>


<commit_before>package hey

import "time"

type Chronograph interface {
	// двигаться по lastts
	RecentActivityByLastTS(threadID string, lastts time.Time) ([]EventObserver, error)

	// подписка конкретного юзера на трэд
	Observe(userID, threadID string) error

	ThreadObservers(threadID string) ([]User, error)

	// RecentActivityByLastTS возвращает события позже lastts
	RecentActivityByLastTS(threadID string, limit, lastts time.Time) ([]Event, error)
	// двигаться по limit,offset что предлагает tnt
	RecentActivity(threadID string, limit, offset int) ([]Event, error)

	// events
	// 1. Достаём всех подписчиков трэда.
	// 2. Вставляем в Timeline для всех подписчиков этот eventID
	NewEvent(threadID string, eventID string) error

	NewEventWithData(
		threadID string,
		eventID string,
		dataType DataType,
		data interface{},
	) error

	// и так далее по каждому из
}
<commit_msg>add some methods<commit_after>package hey

import "time"

// Chronograph represents storage methods
type Chronograph interface {
	// threads
	NewThread(threadID string) error

	NewThreadWithData(threadID string, dataType DataType, data interface{}) error

	// 1. Удаляем все записи из events
	DeleteThread(threadID) error

	// подписка конкретного юзера на трэд
	Observe(userID, threadID string) error

	ThreadObservers(threadID string) ([]User, error)

	// RecentActivityByLastTS возвращает события позже lastts
	RecentActivityByLastTS(threadID string, limit, lastts time.Time) ([]Event, error)
	// двигаться по limit,offset что предлагает tnt
	RecentActivity(threadID string, limit, offset int) ([]Event, error)

	// events
	// 1. Достаём всех подписчиков трэда.
	// 2. Вставляем в Timeline для всех подписчиков этот eventID
	NewEvent(threadID string, eventID string) error

	NewEventWithData(
		threadID string,
		eventID string,
		dataType DataType,
		data interface{},
	) error

	UpdateEvent(ev *Event) error
	DeleteEvent(eventID string) error
}
<|endoftext|>


<commit_before>package beacon

import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"

	"appengine"
	"appengine/delay"
	"appengine/urlfetch"
)

const beaconURL = "http://www.google-analytics.com/collect"

var (
	pixel        = mustReadFile("static/pixel.gif")
	badge        = mustReadFile("static/badge.svg")
	badgeGif     = mustReadFile("static/badge.gif")
	badgeFlat    = mustReadFile("static/badge-flat.svg")
	badgeFlatGif = mustReadFile("static/badge-flat.gif")
	pageTemplate = template.Must(template.New("page").ParseFiles("page.html"))
)

func init() {
	http.HandleFunc("/", handler)
}

func mustReadFile(path string) []byte {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	return b
}

func generateUUID(cid *string) error {
	b := make([]byte, 16)
	_, err := rand.Read(b)
	if err != nil {
		return err
	}

	b[8] = (b[8] | 0x80) & 0xBF // what's the purpose ?
	b[6] = (b[6] | 0x40) & 0x4F // what's the purpose ?
	*cid = hex.EncodeToString(b)
	return nil
}

var delayHit = delay.Func("collect", logHit)

func log(c appengine.Context, ua string, ip string, cid string, values url.Values) error {
	req, _ := http.NewRequest("POST", beaconURL, strings.NewReader(values.Encode()))
	req.Header.Add("User-Agent", ua)
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

	if resp, err := urlfetch.Client(c).Do(req); err != nil {
		c.Errorf("GA collector POST error: %s", err.Error())
		return err
	} else {
		c.Debugf("GA collector status: %v, cid: %v, ip: %s", resp.Status, cid, ip)
		c.Debugf("Reported payload: %v", values)
	}
	return nil
}

func logHit(c appengine.Context, params []string, query url.Values, ua string, ip string, cid string) error {
	// 1) Initialize default values from path structure
	// 2) Allow query param override to report arbitrary values to GA
	//
	// GA Protocol reference: https://developers.google.com/analytics/devguides/collection/protocol/v1/reference

	payload := url.Values{
		"v":   {"1"},        // protocol version = 1
		"t":   {"pageview"}, // hit type
		"tid": {params[0]},  // tracking / property ID
		"cid": {cid},        // unique client ID (server generated UUID)
		"dp":  {params[1]},  // page path
		"uip": {ip},         // IP address of the user
	}

	for key, val := range query {
		payload[key] = val
	}

	return log(c, ua, ip, cid, payload)
}

func handler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	params := strings.SplitN(strings.Trim(r.URL.Path, "/"), "/", 2)
	query, _ := url.ParseQuery(r.URL.RawQuery)
	refOrg := r.Header.Get("Referer")

	// / -> redirect
	if len(params[0]) == 0 {
		http.Redirect(w, r, "https://github.com/igrigorik/ga-beacon", http.StatusFound)
		return
	}

	// activate referrer path if ?useReferer is used and if referer exists
	if _, ok := query["useReferer"]; ok {
		if len(refOrg) != 0 {
			referer := strings.Replace(strings.Replace(refOrg, "http://", "", 1), "https://", "", 1)
			if len(referer) != 0 {
				// if the useReferer is present and the referer information exists
				//  the path is ignored and the beacon referer information is used instead.
				params = strings.SplitN(strings.Trim(r.URL.Path, "/")+"/"+referer, "/", 2)
			}
		}
	}
	// /account -> account template
	if len(params) == 1 {
		templateParams := struct {
			Account string
			Referer string
		}{
			Account: params[0],
			Referer: refOrg,
		}
		if err := pageTemplate.ExecuteTemplate(w, "page.html", templateParams); err != nil {
			http.Error(w, "could not show account page", 500)
			c.Errorf("Cannot execute template: %v", err)
		}
		return
	}

	// /account/page -> GIF + log pageview to GA collector
	var cid string
	if cookie, err := r.Cookie("cid"); err != nil {
		if err := generateUUID(&cid); err != nil {
			c.Debugf("Failed to generate client UUID: %v", err)
		} else {
			c.Debugf("Generated new client UUID: %v", cid)
			http.SetCookie(w, &http.Cookie{Name: "cid", Value: cid, Path: fmt.Sprint("/", params[0])})
		}
	} else {
		cid = cookie.Value
		c.Debugf("Existing CID found: %v", cid)
	}

	if len(cid) != 0 {
		var cacheUntil = time.Now().Format(http.TimeFormat)
		w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate, private")
		w.Header().Set("Expires", cacheUntil)
		w.Header().Set("CID", cid)

		logHit(c, params, query, r.Header.Get("User-Agent"), r.RemoteAddr, cid)
		// delayHit.Call(c, params, r.Header.Get("User-Agent"), cid)
	}

	// Write out GIF pixel or badge, based on presence of "pixel" param.
	if _, ok := query["pixel"]; ok {
		w.Header().Set("Content-Type", "image/gif")
		w.Write(pixel)
	} else if _, ok := query["gif"]; ok {
		w.Header().Set("Content-Type", "image/gif")
		w.Write(badgeGif)
	} else if _, ok := query["flat"]; ok {
		w.Header().Set("Content-Type", "image/svg+xml")
		w.Write(badgeFlat)
	} else if _, ok := query["flat-gif"]; ok {
		w.Header().Set("Content-Type", "image/gif")
		w.Write(badgeFlatGif)
	} else {
		w.Header().Set("Content-Type", "image/svg+xml")
		w.Write(badge)
	}
}
<commit_msg>required main fucntion<commit_after>package main

import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"

	"appengine"
	"appengine/delay"
	"appengine/urlfetch"
)

const beaconURL = "http://www.google-analytics.com/collect"

var (
	pixel        = mustReadFile("static/pixel.gif")
	badge        = mustReadFile("static/badge.svg")
	badgeGif     = mustReadFile("static/badge.gif")
	badgeFlat    = mustReadFile("static/badge-flat.svg")
	badgeFlatGif = mustReadFile("static/badge-flat.gif")
	pageTemplate = template.Must(template.New("page").ParseFiles("page.html"))
)

func init() {
	http.HandleFunc("/", handler)
}

//required
func main() {
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
		log.Printf("Defaulting to port %s", port)
	}

	log.Printf("Listening on port %s", port)
	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatal(err)
	}
}

func mustReadFile(path string) []byte {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	return b
}

func generateUUID(cid *string) error {
	b := make([]byte, 16)
	_, err := rand.Read(b)
	if err != nil {
		return err
	}

	b[8] = (b[8] | 0x80) & 0xBF // what's the purpose ?
	b[6] = (b[6] | 0x40) & 0x4F // what's the purpose ?
	*cid = hex.EncodeToString(b)
	return nil
}

var delayHit = delay.Func("collect", logHit)

func log(c appengine.Context, ua string, ip string, cid string, values url.Values) error {
	req, _ := http.NewRequest("POST", beaconURL, strings.NewReader(values.Encode()))
	req.Header.Add("User-Agent", ua)
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

	if resp, err := urlfetch.Client(c).Do(req); err != nil {
		c.Errorf("GA collector POST error: %s", err.Error())
		return err
	} else {
		c.Debugf("GA collector status: %v, cid: %v, ip: %s", resp.Status, cid, ip)
		c.Debugf("Reported payload: %v", values)
	}
	return nil
}

func logHit(c appengine.Context, params []string, query url.Values, ua string, ip string, cid string) error {
	// 1) Initialize default values from path structure
	// 2) Allow query param override to report arbitrary values to GA
	//
	// GA Protocol reference: https://developers.google.com/analytics/devguides/collection/protocol/v1/reference

	payload := url.Values{
		"v":   {"1"},        // protocol version = 1
		"t":   {"pageview"}, // hit type
		"tid": {params[0]},  // tracking / property ID
		"cid": {cid},        // unique client ID (server generated UUID)
		"dp":  {params[1]},  // page path
		"uip": {ip},         // IP address of the user
	}

	for key, val := range query {
		payload[key] = val
	}

	return log(c, ua, ip, cid, payload)
}

func handler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	params := strings.SplitN(strings.Trim(r.URL.Path, "/"), "/", 2)
	query, _ := url.ParseQuery(r.URL.RawQuery)
	refOrg := r.Header.Get("Referer")

	// / -> redirect
	if len(params[0]) == 0 {
		http.Redirect(w, r, "https://github.com/igrigorik/ga-beacon", http.StatusFound)
		return
	}

	// activate referrer path if ?useReferer is used and if referer exists
	if _, ok := query["useReferer"]; ok {
		if len(refOrg) != 0 {
			referer := strings.Replace(strings.Replace(refOrg, "http://", "", 1), "https://", "", 1)
			if len(referer) != 0 {
				// if the useReferer is present and the referer information exists
				//  the path is ignored and the beacon referer information is used instead.
				params = strings.SplitN(strings.Trim(r.URL.Path, "/")+"/"+referer, "/", 2)
			}
		}
	}
	// /account -> account template
	if len(params) == 1 {
		templateParams := struct {
			Account string
			Referer string
		}{
			Account: params[0],
			Referer: refOrg,
		}
		if err := pageTemplate.ExecuteTemplate(w, "page.html", templateParams); err != nil {
			http.Error(w, "could not show account page", 500)
			c.Errorf("Cannot execute template: %v", err)
		}
		return
	}

	// /account/page -> GIF + log pageview to GA collector
	var cid string
	if cookie, err := r.Cookie("cid"); err != nil {
		if err := generateUUID(&cid); err != nil {
			c.Debugf("Failed to generate client UUID: %v", err)
		} else {
			c.Debugf("Generated new client UUID: %v", cid)
			http.SetCookie(w, &http.Cookie{Name: "cid", Value: cid, Path: fmt.Sprint("/", params[0])})
		}
	} else {
		cid = cookie.Value
		c.Debugf("Existing CID found: %v", cid)
	}

	if len(cid) != 0 {
		var cacheUntil = time.Now().Format(http.TimeFormat)
		w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate, private")
		w.Header().Set("Expires", cacheUntil)
		w.Header().Set("CID", cid)

		logHit(c, params, query, r.Header.Get("User-Agent"), r.RemoteAddr, cid)
		// delayHit.Call(c, params, r.Header.Get("User-Agent"), cid)
	}

	// Write out GIF pixel or badge, based on presence of "pixel" param.
	if _, ok := query["pixel"]; ok {
		w.Header().Set("Content-Type", "image/gif")
		w.Write(pixel)
	} else if _, ok := query["gif"]; ok {
		w.Header().Set("Content-Type", "image/gif")
		w.Write(badgeGif)
	} else if _, ok := query["flat"]; ok {
		w.Header().Set("Content-Type", "image/svg+xml")
		w.Write(badgeFlat)
	} else if _, ok := query["flat-gif"]; ok {
		w.Header().Set("Content-Type", "image/gif")
		w.Write(badgeFlatGif)
	} else {
		w.Header().Set("Content-Type", "image/svg+xml")
		w.Write(badge)
	}
}
<|endoftext|>


<commit_before>/**
 * @file game.go
 * @author Mikhail Klementyev jollheef<AT>riseup.net
 * @license GNU GPLv3
 * @date November, 2015
 * @brief game api
 *
 * Contain functions for calculate score, check flag etc.
 */

package game

import (
	"database/sql"
	"errors"
	"github.com/jollheef/henhouse/db"
	"log"
	"sort"
	"sync"
	"time"
)

// Game struct
type Game struct {
	db              *sql.DB
	Start           time.Time
	End             time.Time
	OpenTimeout     time.Duration // after solve task
	AutoOpen        bool
	AutoOpenTimeout time.Duration // if task does not solved
	tasksLock       sync.Mutex
	scoreboardLock  sync.Mutex
}

// TaskInfo provide information about task
type TaskInfo struct {
	ID       int
	Name     string
	Desc     string
	Author   string
	Price    int
	Opened   bool
	Level    int
	SolvedBy []int
}

// CategoryInfo provide information about categories and tasks
type CategoryInfo struct {
	Name      string
	TasksInfo []TaskInfo
}

// TeamScoreInfo provide information about team score
type TeamScoreInfo struct {
	ID    int
	Name  string
	Desc  string
	Score int
}

type byScore []TeamScoreInfo

func (tr byScore) Len() int           { return len(tr) }
func (tr byScore) Swap(i, j int)      { tr[i], tr[j] = tr[j], tr[i] }
func (tr byScore) Less(i, j int) bool { return tr[i].Score > tr[j].Score }

type byLevel []TaskInfo

func (ti byLevel) Len() int           { return len(ti) }
func (ti byLevel) Swap(i, j int)      { ti[i], ti[j] = ti[j], ti[i] }
func (ti byLevel) Less(i, j int) bool { return ti[i].Level < ti[j].Level }

// NewGame create new game
func NewGame(database *sql.DB, start, end time.Time) (g Game, err error) {

	g.db = database
	g.Start = start
	g.End = end

	err = g.RecalcScoreboard()
	if err != nil {
		return
	}

	return
}

func (g Game) findTaskByID(id int, tasks []db.Task) (t db.Task, err error) {

	for _, task := range tasks {
		if task.ID == id {
			t = task
			return
		}
	}

	err = errors.New("task no found")

	return
}

// Run open first level tasks and start auto open routine
func (g Game) Run() (err error) {

	for time.Now().Before(g.Start) {
		time.Sleep(time.Second)
	}

	cats, err := g.Tasks()
	if err != nil {
		return
	}

	for _, c := range cats {
		for _, t := range c.TasksInfo {
			err = db.SetOpened(g.db, t.ID, true)
			if err != nil {
				return
			}

			break
		}
	}

	return
}

func taskPrice(database *sql.DB, taskID int) (price int, err error) {

	count, err := db.GetSolvedCount(database, taskID)

	fprice := float64(count) / 20.0

	if fprice <= 0.1 {
		price = 500
	} else if fprice <= 0.15 {
		price = 400
	} else if fprice <= 0.3 {
		price = 300
	} else if fprice <= 0.5 {
		price = 200
	} else {
		price = 100
	}

	return
}

// Tasks returns categories with tasks
func (g Game) Tasks() (cats []CategoryInfo, err error) {

	tasks, err := db.GetTasks(g.db)
	if err != nil {
		return
	}

	categories, err := db.GetCategories(g.db)
	if err != nil {
		return
	}

	for _, category := range categories {

		cat := CategoryInfo{Name: category.Name}

		for _, task := range tasks {

			if task.CategoryID == category.ID {

				var price int
				price, err = taskPrice(g.db, task.ID)
				if err != nil {
					return
				}

				var solvedBy []int
				solvedBy, err = db.GetSolvedBy(g.db, task.ID)
				if err != nil {
					return
				}

				tInfo := TaskInfo{
					ID:       task.ID,
					Name:     task.Name,
					Desc:     task.Desc,
					Price:    price,
					Opened:   task.Opened,
					SolvedBy: solvedBy,
					Author:   task.Author,
					Level:    task.Level,
				}

				cat.TasksInfo = append(cat.TasksInfo, tInfo)
			}
		}

		sort.Sort(byLevel(cat.TasksInfo))

		cats = append(cats, cat)
	}

	return
}

// Scoreboard returns sorted scoreboard
func (g Game) Scoreboard() (scores []TeamScoreInfo, err error) {

	g.scoreboardLock.Lock()

	teams, err := db.GetTeams(g.db)
	if err != nil {
		return
	}

	for _, team := range teams {

		if team.Test {
			continue
		}

		var s db.Score
		s, err = db.GetLastScore(g.db, team.ID)
		if err != nil {
			return
		}

		scores = append(scores,
			TeamScoreInfo{team.ID, team.Name, team.Desc, s.Score})
	}

	sort.Sort(byScore(scores))

	g.scoreboardLock.Unlock()

	return
}

// RecalcScoreboard update scoreboard
func (g Game) RecalcScoreboard() (err error) {

	g.scoreboardLock.Lock()

	teams, err := db.GetTeams(g.db)
	if err != nil {
		return
	}

	tasks, err := db.GetTasks(g.db)
	if err != nil {
		return
	}

	for _, team := range teams {

		if team.Test {
			continue
		}

		score := 0

		for _, task := range tasks {

			var price int
			price, err = taskPrice(g.db, task.ID)
			if err != nil {
				return
			}

			var solved bool
			solved, err = db.IsSolved(g.db, team.ID, task.ID)
			if err != nil {
				return
			}

			if solved {
				score += price
			}
		}

		err = db.AddScore(g.db, &db.Score{TeamID: team.ID, Score: score})
		if err != nil {
			return
		}
	}

	g.scoreboardLock.Unlock()

	return
}

// OpenNextTask open next task by level
func (g Game) OpenNextTask(t db.Task) (err error) {

	time.Sleep(g.OpenTimeout)

	tasks, err := db.GetTasks(g.db)
	if err != nil {
		return
	}

	for _, task := range tasks {
		// If same category and next level
		if t.CategoryID == task.CategoryID && t.Level+1 == task.Level {
			// If not already opened
			if !task.Opened {
				// Open it!
				err = db.SetOpened(g.db, task.ID, true)
				if err != nil {
					return
				}
			}
		}
	}

	return
}

func (g Game) isTestTeam(teamID int) bool {

	teams, err := db.GetTeams(g.db)
	if err != nil {
		log.Println("Get teams fail:", err)
		return true
	}

	for _, team := range teams {
		if team.ID == teamID {
			return team.Test
		}
	}

	return false
}

// Solve check flag for task and recalc scoreboard if flag correct
func (g Game) Solve(teamID, taskID int, flag string) (solved bool, err error) {

	tasks, err := db.GetTasks(g.db)
	if err != nil {
		return
	}

	for _, task := range tasks {
		if task.ID == taskID {

			if task.Flag == flag { // fix to regex

				solved = true

				if g.isTestTeam(teamID) {
					return
				}

				now := time.Now()

				if now.After(g.Start) && now.Before(g.End) {
					err = db.AddFlag(g.db, &db.Flag{
						TeamID: teamID,
						TaskID: taskID,
						Flag:   flag,
						Solved: solved,
					})
					if err != nil {
						return
					}

					go g.OpenNextTask(task)
				}
			}

			break
		}
	}

	return
}
<commit_msg>Add auto open next task (with timeout) at solve<commit_after>/**
 * @file game.go
 * @author Mikhail Klementyev jollheef<AT>riseup.net
 * @license GNU GPLv3
 * @date November, 2015
 * @brief game api
 *
 * Contain functions for calculate score, check flag etc.
 */

package game

import (
	"database/sql"
	"errors"
	"github.com/jollheef/henhouse/db"
	"log"
	"sort"
	"sync"
	"time"
)

// Game struct
type Game struct {
	db              *sql.DB
	Start           time.Time
	End             time.Time
	OpenTimeout     time.Duration // after solve task
	AutoOpen        bool
	AutoOpenTimeout time.Duration // if task does not solved
	tasksLock       sync.Mutex
	scoreboardLock  sync.Mutex
}

// TaskInfo provide information about task
type TaskInfo struct {
	ID       int
	Name     string
	Desc     string
	Author   string
	Price    int
	Opened   bool
	Level    int
	SolvedBy []int
}

// CategoryInfo provide information about categories and tasks
type CategoryInfo struct {
	Name      string
	TasksInfo []TaskInfo
}

// TeamScoreInfo provide information about team score
type TeamScoreInfo struct {
	ID    int
	Name  string
	Desc  string
	Score int
}

type byScore []TeamScoreInfo

func (tr byScore) Len() int           { return len(tr) }
func (tr byScore) Swap(i, j int)      { tr[i], tr[j] = tr[j], tr[i] }
func (tr byScore) Less(i, j int) bool { return tr[i].Score > tr[j].Score }

type byLevel []TaskInfo

func (ti byLevel) Len() int           { return len(ti) }
func (ti byLevel) Swap(i, j int)      { ti[i], ti[j] = ti[j], ti[i] }
func (ti byLevel) Less(i, j int) bool { return ti[i].Level < ti[j].Level }

// NewGame create new game
func NewGame(database *sql.DB, start, end time.Time) (g Game, err error) {

	g.db = database
	g.Start = start
	g.End = end

	err = g.RecalcScoreboard()
	if err != nil {
		return
	}

	return
}

func (g Game) findTaskByID(id int, tasks []db.Task) (t db.Task, err error) {

	for _, task := range tasks {
		if task.ID == id {
			t = task
			return
		}
	}

	err = errors.New("task no found")

	return
}

// Run open first level tasks and start auto open routine
func (g Game) Run() (err error) {

	for time.Now().Before(g.Start) {
		time.Sleep(time.Second)
	}

	cats, err := g.Tasks()
	if err != nil {
		return
	}

	for _, c := range cats {
		for _, t := range c.TasksInfo {
			err = db.SetOpened(g.db, t.ID, true)
			if err != nil {
				return
			}

			break
		}
	}

	return
}

func taskPrice(database *sql.DB, taskID int) (price int, err error) {

	count, err := db.GetSolvedCount(database, taskID)

	fprice := float64(count) / 20.0

	if fprice <= 0.1 {
		price = 500
	} else if fprice <= 0.15 {
		price = 400
	} else if fprice <= 0.3 {
		price = 300
	} else if fprice <= 0.5 {
		price = 200
	} else {
		price = 100
	}

	return
}

// Tasks returns categories with tasks
func (g Game) Tasks() (cats []CategoryInfo, err error) {

	tasks, err := db.GetTasks(g.db)
	if err != nil {
		return
	}

	categories, err := db.GetCategories(g.db)
	if err != nil {
		return
	}

	for _, category := range categories {

		cat := CategoryInfo{Name: category.Name}

		for _, task := range tasks {

			if task.CategoryID == category.ID {

				var price int
				price, err = taskPrice(g.db, task.ID)
				if err != nil {
					return
				}

				var solvedBy []int
				solvedBy, err = db.GetSolvedBy(g.db, task.ID)
				if err != nil {
					return
				}

				tInfo := TaskInfo{
					ID:       task.ID,
					Name:     task.Name,
					Desc:     task.Desc,
					Price:    price,
					Opened:   task.Opened,
					SolvedBy: solvedBy,
					Author:   task.Author,
					Level:    task.Level,
				}

				cat.TasksInfo = append(cat.TasksInfo, tInfo)
			}
		}

		sort.Sort(byLevel(cat.TasksInfo))

		cats = append(cats, cat)
	}

	return
}

// Scoreboard returns sorted scoreboard
func (g Game) Scoreboard() (scores []TeamScoreInfo, err error) {

	g.scoreboardLock.Lock()

	teams, err := db.GetTeams(g.db)
	if err != nil {
		return
	}

	for _, team := range teams {

		if team.Test {
			continue
		}

		var s db.Score
		s, err = db.GetLastScore(g.db, team.ID)
		if err != nil {
			return
		}

		scores = append(scores,
			TeamScoreInfo{team.ID, team.Name, team.Desc, s.Score})
	}

	sort.Sort(byScore(scores))

	g.scoreboardLock.Unlock()

	return
}

// RecalcScoreboard update scoreboard
func (g Game) RecalcScoreboard() (err error) {

	g.scoreboardLock.Lock()

	teams, err := db.GetTeams(g.db)
	if err != nil {
		return
	}

	tasks, err := db.GetTasks(g.db)
	if err != nil {
		return
	}

	for _, team := range teams {

		if team.Test {
			continue
		}

		score := 0

		for _, task := range tasks {

			var price int
			price, err = taskPrice(g.db, task.ID)
			if err != nil {
				return
			}

			var solved bool
			solved, err = db.IsSolved(g.db, team.ID, task.ID)
			if err != nil {
				return
			}

			if solved {
				score += price
			}
		}

		err = db.AddScore(g.db, &db.Score{TeamID: team.ID, Score: score})
		if err != nil {
			return
		}
	}

	g.scoreboardLock.Unlock()

	return
}

func (g Game) autoOpen(task db.Task) {
	time.Sleep(g.AutoOpenTimeout)
	err := g.OpenNextTask(task)
	if err != nil {
		log.Println("Auto open next task fail:", err)
	}
}

// OpenNextTask open next task by level
func (g Game) OpenNextTask(t db.Task) (err error) {

	time.Sleep(g.OpenTimeout)

	tasks, err := db.GetTasks(g.db)
	if err != nil {
		return
	}

	for _, task := range tasks {
		// If same category and next level
		if t.CategoryID == task.CategoryID && t.Level+1 == task.Level {
			// If not already opened
			if !task.Opened {
				// Open it!
				err = db.SetOpened(g.db, task.ID, true)
				if err != nil {
					return
				}

				if g.AutoOpen {
					go g.autoOpen(task)
				}
			}
		}
	}

	return
}

func (g Game) isTestTeam(teamID int) bool {

	teams, err := db.GetTeams(g.db)
	if err != nil {
		log.Println("Get teams fail:", err)
		return true
	}

	for _, team := range teams {
		if team.ID == teamID {
			return team.Test
		}
	}

	return false
}

// Solve check flag for task and recalc scoreboard if flag correct
func (g Game) Solve(teamID, taskID int, flag string) (solved bool, err error) {

	tasks, err := db.GetTasks(g.db)
	if err != nil {
		return
	}

	for _, task := range tasks {
		if task.ID == taskID {

			if task.Flag == flag { // fix to regex

				solved = true

				if g.isTestTeam(teamID) {
					return
				}

				now := time.Now()

				if now.After(g.Start) && now.Before(g.End) {
					err = db.AddFlag(g.db, &db.Flag{
						TeamID: teamID,
						TaskID: taskID,
						Flag:   flag,
						Solved: solved,
					})
					if err != nil {
						return
					}

					go g.OpenNextTask(task)
				}
			}

			break
		}
	}

	return
}
<|endoftext|>


<commit_before>package data

import (
	"time"
)

const (
	rippleTimeEpoch  int64  = 946684800
	rippleTimeFormat string = "2006-Jan-02 15:04:05"
)

// Represents a time as the number of seconds since the Ripple epoch: January 1st, 2000 (00:00 UTC)
type RippleTime struct {
	T uint32
}

type rippleHumanTime struct {
	RippleTime
}

func NewRippleTime(t uint32) *RippleTime {
	return &RippleTime{t}
}

func convertToRippleTime(t time.Time) uint32 {
	return uint32(t.Sub(time.Unix(rippleTimeEpoch, 0)).Nanoseconds() / 1000000000)
}

func (t RippleTime) Time() time.Time {
	return time.Unix(int64(t.T)+rippleTimeEpoch, 0)
}

func Now() *RippleTime {
	return &RippleTime{convertToRippleTime(time.Now())}
}

// Accepts time formatted as 2006-Jan-02 15:04:05
func (t *RippleTime) SetString(s string) error {
	v, err := time.Parse(rippleTimeFormat, s)
	if err != nil {
		return err
	}
	t.SetUint32(convertToRippleTime(v))
	return nil
}

func (t *RippleTime) SetUint32(n uint32) {
	t.T = n
}

func (t RippleTime) Uint32() uint32 {
	return t.T
}

func (t RippleTime) human() *rippleHumanTime {
	return &rippleHumanTime{t}
}

// Returns time formatted as 2006-Jan-02 15:04:05
func (t RippleTime) String() string {
	return t.Time().UTC().Format(rippleTimeFormat)
}

// Returns time formatted as 15:04:05
func (t RippleTime) Short() string {
	return t.Time().UTC().Format("15:04:05")
}
<commit_msg>Update time.go<commit_after>package data

import (
	"time"
)

const (
	rippleTimeEpoch  int64  = 946684800
	rippleTimeFormat string = "2006-Jan-02 15:04:05 UTC"
)

// Represents a time as the number of seconds since the Ripple epoch: January 1st, 2000 (00:00 UTC)
type RippleTime struct {
	T uint32
}

type rippleHumanTime struct {
	RippleTime
}

func NewRippleTime(t uint32) *RippleTime {
	return &RippleTime{t}
}

func convertToRippleTime(t time.Time) uint32 {
	return uint32(t.Sub(time.Unix(rippleTimeEpoch, 0)).Nanoseconds() / 1000000000)
}

func (t RippleTime) Time() time.Time {
	return time.Unix(int64(t.T)+rippleTimeEpoch, 0)
}

func Now() *RippleTime {
	return &RippleTime{convertToRippleTime(time.Now())}
}

// Accepts time formatted as 2006-Jan-02 15:04:05
func (t *RippleTime) SetString(s string) error {
	v, err := time.Parse(rippleTimeFormat, s)
	if err != nil {
		return err
	}
	t.SetUint32(convertToRippleTime(v))
	return nil
}

func (t *RippleTime) SetUint32(n uint32) {
	t.T = n
}

func (t RippleTime) Uint32() uint32 {
	return t.T
}

func (t RippleTime) human() *rippleHumanTime {
	return &rippleHumanTime{t}
}

// Returns time formatted as 2006-Jan-02 15:04:05
func (t RippleTime) String() string {
	return t.Time().UTC().Format(rippleTimeFormat)
}

// Returns time formatted as 15:04:05
func (t RippleTime) Short() string {
	return t.Time().UTC().Format("15:04:05")
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 cli

import (
	"bufio"
	"fmt"
	"os"
)

func initHistory() {
	if _, err := os.Stat(cfg.HistoryFile); os.IsNotExist(err) {
		os.OpenFile(cfg.HistoryFile, os.O_RDONLY|os.O_CREATE, 0600)
	}
}

func readHistory() []string {
	initHistory()
	file, err := os.Open(cfg.HistoryFile)
	if err != nil {
		fmt.Println("Failed to open history file:", err)
		return nil
	}
	defer file.Close()

	var lines []string
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	if scanner.Err() != nil {
		fmt.Println("Failed to read history:", scanner.Err())
	}
	return lines
}

func writeHistory(in string) {
	file, err := os.OpenFile(cfg.HistoryFile, os.O_APPEND|os.O_WRONLY, 0600)
	if err != nil {
		fmt.Println("Failed to open history file:", err)
	}
	defer file.Close()

	if _, err = file.WriteString(in + "\n"); err != nil {
		fmt.Println("Failed to write history:", err)
	}
}
<commit_msg>history: ignore duplicate and empty inputs for shell history<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 cli

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func initHistory() {
	if _, err := os.Stat(cfg.HistoryFile); os.IsNotExist(err) {
		os.OpenFile(cfg.HistoryFile, os.O_RDONLY|os.O_CREATE, 0600)
	}
}

func readHistory() []string {
	initHistory()
	file, err := os.Open(cfg.HistoryFile)
	if err != nil {
		fmt.Println("Failed to open history file:", err)
		return nil
	}
	defer file.Close()

	var lines []string
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	if scanner.Err() != nil {
		fmt.Println("Failed to read history:", scanner.Err())
	}
	return lines
}

var lastInput string

func writeHistory(in string) {
	if len(strings.TrimSpace(in)) < 1 || in == lastInput {
		return
	}
	file, err := os.OpenFile(cfg.HistoryFile, os.O_APPEND|os.O_WRONLY, 0600)
	if err != nil {
		fmt.Println("Failed to open history file:", err)
	}
	defer file.Close()

	if _, err = file.WriteString(in + "\n"); err != nil {
		fmt.Println("Failed to write history:", err)
	}
	lastInput = in
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/url"
	"os"

	functions "github.com/funcy/functions_go"
	"github.com/urfave/cli"
)

// Version of Functions CLI
var Version = "0.3.34"

func version() cli.Command {
	r := versionCmd{VersionApi: functions.NewVersionApi()}
	return cli.Command{
		Name:   "version",
		Usage:  "displays fn and functions daemon versions",
		Action: r.version,
	}
}

type versionCmd struct {
	*functions.VersionApi
}

func (r *versionCmd) version(c *cli.Context) error {
	apiURL := os.Getenv("API_URL")
	if apiURL == "" {
		apiURL = "http://localhost:8080"
	}

	u, err := url.Parse(apiURL)
	if err != nil {
		return err
	}
	r.Configuration.BasePath = u.String()

	fmt.Println("Client version:", Version)
	v, _, err := r.VersionGet()
	if err != nil {
		return err
	}
	fmt.Println("Server version", v.Version)
	return nil
}
<commit_msg>fn tool: 0.3.35 release [skip ci]<commit_after>package main

import (
	"fmt"
	"net/url"
	"os"

	functions "github.com/funcy/functions_go"
	"github.com/urfave/cli"
)

// Version of Functions CLI
var Version = "0.3.35"

func version() cli.Command {
	r := versionCmd{VersionApi: functions.NewVersionApi()}
	return cli.Command{
		Name:   "version",
		Usage:  "displays fn and functions daemon versions",
		Action: r.version,
	}
}

type versionCmd struct {
	*functions.VersionApi
}

func (r *versionCmd) version(c *cli.Context) error {
	apiURL := os.Getenv("API_URL")
	if apiURL == "" {
		apiURL = "http://localhost:8080"
	}

	u, err := url.Parse(apiURL)
	if err != nil {
		return err
	}
	r.Configuration.BasePath = u.String()

	fmt.Println("Client version:", Version)
	v, _, err := r.VersionGet()
	if err != nil {
		return err
	}
	fmt.Println("Server version", v.Version)
	return nil
}
<|endoftext|>


<commit_before>package gcp

import (
	"bytes"
	"crypto/x509"
	"path"

	"github.com/lestrrat/go-cloud-acmeagent/store"
	"github.com/lestrrat/go-jwx/jwk"
	"github.com/lestrrat/go-pdebug"
	"google.golang.org/api/storage/v1"
)

func NewStorage(s *storage.Service, projectID, email, bucketName string) *Storage {
	return &Storage{
		Service:    s,
		BucketName: bucketName,
		ID:         email,
		Project:    projectID,
	}
}

func (s Storage) pathTo(args ...string) string {
	l := append([]string{s.BucketName}, args...)
	return path.Join(l...)
}

func (s Storage) assertBucket() error {
	b, err := s.Service.Buckets.Get(s.BucketName).Do()
	if err == nil {
		return nil
	}

	b = &storage.Bucket{
		Name: s.BucketName,
	}

	if _, err := s.Service.Buckets.Insert(s.Project, b).Do(); err != nil {
		return err
	}
	return nil
}

// Parameter `authz` is an interface{} to avoid circular dependencies.
// In reality this must be a pointer to `acmeagent.Account`
func (s Storage) SaveAccount(acct interface{}) (err error) {
	path := s.pathTo(s.ID, "info", "account.json")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.SaveAccount (%s)", path).BindError(&err)
		defer g.End()
	}

	if err := s.assertBucket(); err != nil {
		return err
	}

	dst := bytes.Buffer{}
	if err := store.SaveAccount(&dst, acct); err != nil {
		return err
	}

	object := storage.Object{
		Name: path,
	}
	if _, err := s.Service.Objects.Insert(s.BucketName, &object).Media(&dst).Do(); err != nil {
		return err
	}
	return nil
}

// Parameter `authz` is an interface{} to avoid circular dependencies.
// In reality this must be a pointer to `acmeagent.Account`
func (s Storage) LoadAccount(acct interface{}) (err error) {
	path := s.pathTo(s.ID, "info", "account.json")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.LoadAccount (%s)", path).BindError(&err)
		defer g.End()
	}

	res, err := s.Service.Objects.Get(s.BucketName, path).Download()
	if err != nil {
		return err
	}
	defer res.Body.Close()

	return store.LoadAccount(res.Body, acct)
}

// Parameter `authz` is an interface{} to avoid circular dependencies.
// In reality this must be a `acmeagent.Authorization`
func (s Storage) SaveAuthorization(domain string, authz interface{}) (err error) {
	path := s.pathTo(s.ID, "domains", domain, "authz.json")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.SaveAuthorization (%s)", path).BindError(&err)
		defer g.End()
	}

	if err := s.assertBucket(); err != nil {
		return err
	}

	dst := bytes.Buffer{}
	if err := store.SaveAuthorization(&dst, authz); err != nil {
		return err
	}

	object := storage.Object{
		Name: path,
	}
	if _, err := s.Service.Objects.Insert(s.BucketName, &object).Media(&dst).Do(); err != nil {
		return err
	}
	return nil
}

// Parameter `authz` is an interface{} to avoid circular dependencies.
// In reality this must be a pointer to `acmeagent.Authorization`
func (s Storage) LoadAuthorization(domain string, authz interface{}) (err error) {
	path := s.pathTo(s.ID, "domains", domain, "authz.json")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.LoadAuthorization (%s)", path).BindError(&err)
		defer g.End()
	}

	res, err := s.Service.Objects.Get(s.BucketName, path).Download()
	if err != nil {
		return err
	}
	defer res.Body.Close()

	return store.LoadAuthorization(res.Body, authz)
}

func (s Storage) SaveKey(k *jwk.RsaPrivateKey) (err error) {
	path := s.pathTo(s.ID, "info", "privkey.jwk")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.SaveKey (%s)", path).BindError(&err)
		defer g.End()
	}

	if err := s.assertBucket(); err != nil {
		return err
	}

	dst := bytes.Buffer{}
	if err := store.SaveKey(&dst, k); err != nil {
		return err
	}

	object := storage.Object{
		Name: path,
	}
	if _, err := s.Service.Objects.Insert(s.BucketName, &object).Media(&dst).Do(); err != nil {
		return err
	}
	return nil
}

func (s Storage) LoadKey() (key *jwk.RsaPrivateKey, err error) {
	path := s.pathTo(s.ID, "info", "privkey.jwk")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.LoadKey (%s)", path).BindError(&err)
		defer g.End()
	}

	res, err := s.Service.Objects.Get(s.BucketName, path).Download()
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	return store.LoadKey(res.Body)
}

func (s Storage) SaveCertKey(domain string, k *jwk.RsaPrivateKey) (err error) {
	path := s.pathTo(s.ID, "domains", domain, "privkey.pem")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.SaveCertKey (%s)", path).BindError(&err)
		defer g.End()
	}

	if err := s.assertBucket(); err != nil {
		return err
	}

	dst := bytes.Buffer{}
	if err := store.SaveCertKey(&dst, k); err != nil {
		return err
	}

	object := storage.Object{
		Name: path,
	}
	if _, err := s.Service.Objects.Insert(s.BucketName, &object).Media(&dst).Do(); err != nil {
		return err
	}
	return nil
}

func (s Storage) LoadCertKey(domain string) (key *jwk.RsaPrivateKey, err error) {
	path := s.pathTo(s.ID, "domains", domain, "privkey.pem")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.LoadCertKey (%s)", path).BindError(&err)
		defer g.End()
	}

	res, err := s.Service.Objects.Get(s.BucketName, path).Download()
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	return store.LoadCertKey(res.Body)
}

func (s Storage) SaveCert(domain string, issuerCert, myCert *x509.Certificate) (err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.SaveCert").BindError(&err)
		defer g.End()
	}

	names := []string{"fullchain.pem", "cert.pem", "chain.pem"}
	certs := [][]*x509.Certificate{
		[]*x509.Certificate{myCert, issuerCert},
		[]*x509.Certificate{myCert},
		[]*x509.Certificate{issuerCert},
	}

	if err := s.assertBucket(); err != nil {
		return err
	}

	for i := 0; i < 3; i++ {
		path := s.pathTo(s.ID, "domains", domain, names[i])
		dst := bytes.Buffer{}
		if err := store.SaveCert(&dst, certs[i]...); err != nil {
			return err
		}
		object := storage.Object{
			Name: path,
		}
		if _, err := s.Service.Objects.Insert(s.BucketName, &object).Media(&dst).Do(); err != nil {
			return err
		}
	}
	return nil
}

func (s Storage) LoadCert(domain string) (cert *x509.Certificate, err error) {
	path := s.pathTo(s.ID, "domains", domain, "cert.pem")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.LoadCert (%s)", path).BindError(&err)
		defer g.End()
	}

	res, err := s.Service.Objects.Get(s.BucketName, path).Download()
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	return store.LoadCert(res.Body)
}

func (s Storage) LoadCertIssuer(domain string) (cert *x509.Certificate, err error) {
	path := s.pathTo(s.ID, "domains", domain, "chain.pem")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.LoadCertIssuer (%s)", path).BindError(&err)
		defer g.End()
	}

	res, err := s.Service.Objects.Get(s.BucketName, path).Download()
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	return store.LoadCert(res.Body)
}

func (s Storage) LoadCertFullChain(domain string) (cert *x509.Certificate, err error) {
	path := s.pathTo(s.ID, "domains", domain, "fullchain.pem")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.LoadCertFullChain (%s)", path).BindError(&err)
		defer g.End()
	}

	res, err := s.Service.Objects.Get(s.BucketName, path).Download()
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	return store.LoadCert(res.Body)
}
<commit_msg>do not include the bucket name<commit_after>package gcp

import (
	"bytes"
	"crypto/x509"
	"path"

	"github.com/lestrrat/go-cloud-acmeagent/store"
	"github.com/lestrrat/go-jwx/jwk"
	"github.com/lestrrat/go-pdebug"
	"google.golang.org/api/storage/v1"
)

func NewStorage(s *storage.Service, projectID, email, bucketName string) *Storage {
	return &Storage{
		Service:    s,
		BucketName: bucketName,
		ID:         email,
		Project:    projectID,
	}
}

func (s Storage) pathTo(args ...string) string {
	return path.Join(args...)
}

func (s Storage) assertBucket() error {
	b, err := s.Service.Buckets.Get(s.BucketName).Do()
	if err == nil {
		return nil
	}

	b = &storage.Bucket{
		Name: s.BucketName,
	}

	if _, err := s.Service.Buckets.Insert(s.Project, b).Do(); err != nil {
		return err
	}
	return nil
}

// Parameter `authz` is an interface{} to avoid circular dependencies.
// In reality this must be a pointer to `acmeagent.Account`
func (s Storage) SaveAccount(acct interface{}) (err error) {
	path := s.pathTo(s.ID, "info", "account.json")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.SaveAccount (%s)", path).BindError(&err)
		defer g.End()
	}

	if err := s.assertBucket(); err != nil {
		return err
	}

	dst := bytes.Buffer{}
	if err := store.SaveAccount(&dst, acct); err != nil {
		return err
	}

	object := storage.Object{
		Name: path,
	}
	if _, err := s.Service.Objects.Insert(s.BucketName, &object).Media(&dst).Do(); err != nil {
		return err
	}
	return nil
}

// Parameter `authz` is an interface{} to avoid circular dependencies.
// In reality this must be a pointer to `acmeagent.Account`
func (s Storage) LoadAccount(acct interface{}) (err error) {
	path := s.pathTo(s.ID, "info", "account.json")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.LoadAccount (%s)", path).BindError(&err)
		defer g.End()
	}

	res, err := s.Service.Objects.Get(s.BucketName, path).Download()
	if err != nil {
		return err
	}
	defer res.Body.Close()

	return store.LoadAccount(res.Body, acct)
}

// Parameter `authz` is an interface{} to avoid circular dependencies.
// In reality this must be a `acmeagent.Authorization`
func (s Storage) SaveAuthorization(domain string, authz interface{}) (err error) {
	path := s.pathTo(s.ID, "domains", domain, "authz.json")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.SaveAuthorization (%s)", path).BindError(&err)
		defer g.End()
	}

	if err := s.assertBucket(); err != nil {
		return err
	}

	dst := bytes.Buffer{}
	if err := store.SaveAuthorization(&dst, authz); err != nil {
		return err
	}

	object := storage.Object{
		Name: path,
	}
	if _, err := s.Service.Objects.Insert(s.BucketName, &object).Media(&dst).Do(); err != nil {
		return err
	}
	return nil
}

// Parameter `authz` is an interface{} to avoid circular dependencies.
// In reality this must be a pointer to `acmeagent.Authorization`
func (s Storage) LoadAuthorization(domain string, authz interface{}) (err error) {
	path := s.pathTo(s.ID, "domains", domain, "authz.json")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.LoadAuthorization (%s)", path).BindError(&err)
		defer g.End()
	}

	res, err := s.Service.Objects.Get(s.BucketName, path).Download()
	if err != nil {
		return err
	}
	defer res.Body.Close()

	return store.LoadAuthorization(res.Body, authz)
}

func (s Storage) SaveKey(k *jwk.RsaPrivateKey) (err error) {
	path := s.pathTo(s.ID, "info", "privkey.jwk")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.SaveKey (%s)", path).BindError(&err)
		defer g.End()
	}

	if err := s.assertBucket(); err != nil {
		return err
	}

	dst := bytes.Buffer{}
	if err := store.SaveKey(&dst, k); err != nil {
		return err
	}

	object := storage.Object{
		Name: path,
	}
	if _, err := s.Service.Objects.Insert(s.BucketName, &object).Media(&dst).Do(); err != nil {
		return err
	}
	return nil
}

func (s Storage) LoadKey() (key *jwk.RsaPrivateKey, err error) {
	path := s.pathTo(s.ID, "info", "privkey.jwk")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.LoadKey (%s)", path).BindError(&err)
		defer g.End()
	}

	res, err := s.Service.Objects.Get(s.BucketName, path).Download()
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	return store.LoadKey(res.Body)
}

func (s Storage) SaveCertKey(domain string, k *jwk.RsaPrivateKey) (err error) {
	path := s.pathTo(s.ID, "domains", domain, "privkey.pem")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.SaveCertKey (%s)", path).BindError(&err)
		defer g.End()
	}

	if err := s.assertBucket(); err != nil {
		return err
	}

	dst := bytes.Buffer{}
	if err := store.SaveCertKey(&dst, k); err != nil {
		return err
	}

	object := storage.Object{
		Name: path,
	}
	if _, err := s.Service.Objects.Insert(s.BucketName, &object).Media(&dst).Do(); err != nil {
		return err
	}
	return nil
}

func (s Storage) LoadCertKey(domain string) (key *jwk.RsaPrivateKey, err error) {
	path := s.pathTo(s.ID, "domains", domain, "privkey.pem")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.LoadCertKey (%s)", path).BindError(&err)
		defer g.End()
	}

	res, err := s.Service.Objects.Get(s.BucketName, path).Download()
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	return store.LoadCertKey(res.Body)
}

func (s Storage) SaveCert(domain string, issuerCert, myCert *x509.Certificate) (err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.SaveCert").BindError(&err)
		defer g.End()
	}

	names := []string{"fullchain.pem", "cert.pem", "chain.pem"}
	certs := [][]*x509.Certificate{
		[]*x509.Certificate{myCert, issuerCert},
		[]*x509.Certificate{myCert},
		[]*x509.Certificate{issuerCert},
	}

	if err := s.assertBucket(); err != nil {
		return err
	}

	for i := 0; i < 3; i++ {
		path := s.pathTo(s.ID, "domains", domain, names[i])
		dst := bytes.Buffer{}
		if err := store.SaveCert(&dst, certs[i]...); err != nil {
			return err
		}
		object := storage.Object{
			Name: path,
		}
		if _, err := s.Service.Objects.Insert(s.BucketName, &object).Media(&dst).Do(); err != nil {
			return err
		}
	}
	return nil
}

func (s Storage) LoadCert(domain string) (cert *x509.Certificate, err error) {
	path := s.pathTo(s.ID, "domains", domain, "cert.pem")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.LoadCert (%s)", path).BindError(&err)
		defer g.End()
	}

	res, err := s.Service.Objects.Get(s.BucketName, path).Download()
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	return store.LoadCert(res.Body)
}

func (s Storage) LoadCertIssuer(domain string) (cert *x509.Certificate, err error) {
	path := s.pathTo(s.ID, "domains", domain, "chain.pem")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.LoadCertIssuer (%s)", path).BindError(&err)
		defer g.End()
	}

	res, err := s.Service.Objects.Get(s.BucketName, path).Download()
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	return store.LoadCert(res.Body)
}

func (s Storage) LoadCertFullChain(domain string) (cert *x509.Certificate, err error) {
	path := s.pathTo(s.ID, "domains", domain, "fullchain.pem")
	if pdebug.Enabled {
		g := pdebug.Marker("gcp.Storage.LoadCertFullChain (%s)", path).BindError(&err)
		defer g.End()
	}

	res, err := s.Service.Objects.Get(s.BucketName, path).Download()
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	return store.LoadCert(res.Body)
}
<|endoftext|>


<commit_before>package main

import (
    "gopkg.in/redis.v5"
)

type Datastore struct {
    db *redis.Client
}

func NewDatastore(uri string) (d Datastore, err error) {
    var opts *redis.Options

    if opts, err = redis.ParseURL(uri); err != nil {
        return
    }

    d.db = redis.NewClient(opts)

    _,err = d.db.Ping().Result()
    return
}
<commit_msg>Load and unload workflow state from redis<commit_after>package main

import (
    "encoding/json"
    "fmt"
    "strings"

    "gopkg.in/redis.v5"
)

type Datastore struct {
    db *redis.Client
}

func NewDatastore(uri string) (d Datastore, err error) {
    var opts *redis.Options

    if opts, err = redis.ParseURL(uri); err != nil {
        return
    }

    d.db = redis.NewClient(opts)

    _,err = d.db.Ping().Result()
    return
}

func (d Datastore)LoadWorkflow(name string) (wf Workflow, err error) {
    var config string

    if config, err = d.load( wfConfigName(name) ); err != nil {
        return
    }

    return ParseWorkflow(config)
}

func (d Datastore)LoadWorkflowRunner(uuid string) (wfr WorkflowRunner, err error) {
    var config string

    if config, err = d.load( wfStateName(uuid) ); err != nil {
        return
    }

    return ParseWorkflowRunner(config)
}

func (d Datastore)DumpWorkflowRunner(wfr WorkflowRunner) error{
    j, err := json.Marshal(wfr)
    if err != nil {
        return err
    }

    return d.db.Set(wfStateName(wfr.UUID), j, 0).Err()
}

func (d Datastore)load(key string) (string, error) {
    return d.db.Get(key).Result()
}

func normaliseName(wfName string) string {
    return strings.Replace(wfName, " ", "_", -1)
}

func wfConfigName(wfName string) string {
    return fmt.Sprintf("workflow.%s", normaliseName(wfName))
}

func wfStateName(uuid string) string {
    return fmt.Sprintf("state.%s", uuid)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os/exec"
	"strings"

	"github.com/blang/semver"
)

func getTag(match ...string) (string, *semver.PRVersion) {
	args := append([]string{
		"describe", "--tags",
	}, match...)
	if tag, err := exec.Command("git", args...).Output(); err != nil {
		return "", nil
	} else {
		tagParts := strings.Split(string(tag), "-")
		if len(tagParts) == 3 {
			if ahead, err := semver.NewPRVersion(tagParts[1]); err == nil {
				return tagParts[0], &ahead
			}
		} else if len(tagParts) == 4 {
			if ahead, err := semver.NewPRVersion(tagParts[2]); err == nil {
				return tagParts[0] + "-" + tagParts[1], &ahead
			}
		}

		return tagParts[0], nil
	}
}

func main() {
	// Find the last vX.X.X Tag and get how many builds we are ahead of it.
	versionStr, ahead := getTag("--match", "v*")
	version, err := semver.ParseTolerant(versionStr)
	if err != nil {
		// no version tag found so just return what ever we can find.
		fmt.Println("0.0.0-unknown")
		return
	}
	// Get the tag of the current revision.
	tag, _ := getTag("--exact-match")
	if tag == versionStr {
		// Seems that we are going to build a release.
		// So the version number should already be correct.
		fmt.Println(version.String())
		return
	}

	// If we don't have any tag assume "dev"
	if tag == "" {
		tag = "dev"
	}
	// Get the most likely next version:
	if !strings.Contains(version.String(), "rc") {
		version.Patch = version.Patch + 1
	}

	if pr, err := semver.NewPRVersion(tag); err == nil {
		// append the tag as pre-release name
		version.Pre = append(version.Pre, pr)
	}

	if ahead != nil {
		// if we know how many commits we are ahead of the last release, append that too.
		version.Pre = append(version.Pre, *ahead)
	}

	fmt.Println(version.String())
}
<commit_msg>Support rc tags in build version<commit_after>package main

import (
	"fmt"
	"os/exec"
	"strings"

	"github.com/blang/semver"
)

func getTag(match ...string) (string, *semver.PRVersion) {
	args := append([]string{
		"describe", "--tags",
	}, match...)
	if tag, err := exec.Command("git", args...).Output(); err != nil {
		return "", nil
	} else {
		tagParts := strings.Split(string(tag), "-")
		if len(tagParts) == 3 {
			if ahead, err := semver.NewPRVersion(tagParts[1]); err == nil {
				return tagParts[0], &ahead
			}
		} else if len(tagParts) == 4 {
			if ahead, err := semver.NewPRVersion(tagParts[2]); err == nil {
				return tagParts[0] + "-" + tagParts[1], &ahead
			}
		}

		return string(tag), nil
	}
}

func main() {
	// Find the last vX.X.X Tag and get how many builds we are ahead of it.
	versionStr, ahead := getTag("--match", "v*")
	version, err := semver.ParseTolerant(versionStr)
	if err != nil {
		// no version tag found so just return what ever we can find.
		fmt.Println("0.0.0-unknown")
		return
	}
	// Get the tag of the current revision.
	tag, _ := getTag("--exact-match")
	if tag == versionStr {
		// Seems that we are going to build a release.
		// So the version number should already be correct.
		fmt.Println(version.String())
		return
	}

	// If we don't have any tag assume "dev"
	if tag == "" {
		tag = "dev"
	}
	// Get the most likely next version:
	if !strings.Contains(version.String(), "rc") {
		version.Patch = version.Patch + 1
	}

	if pr, err := semver.NewPRVersion(tag); err == nil {
		// append the tag as pre-release name
		version.Pre = append(version.Pre, pr)
	}

	if ahead != nil {
		// if we know how many commits we are ahead of the last release, append that too.
		version.Pre = append(version.Pre, *ahead)
	}

	fmt.Println(version.String())
}
<|endoftext|>