<commit_before>package msgpack

import (
	"reflect"
	"sync"
)

var errorType = reflect.TypeOf((*error)(nil)).Elem()

var customEncoderType = reflect.TypeOf((*CustomEncoder)(nil)).Elem()
var customDecoderType = reflect.TypeOf((*CustomDecoder)(nil)).Elem()

var marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
var unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()

type encoderFunc func(*Encoder, reflect.Value) error
type decoderFunc func(*Decoder, reflect.Value) error

var typEncMap = make(map[reflect.Type]encoderFunc)
var typDecMap = make(map[reflect.Type]decoderFunc)

// Register registers encoder and decoder functions for a value.
// This is low level API and in most cases you should prefer implementing
// Marshaler/CustomEncoder and Unmarshaler/CustomDecoder interfaces.
func Register(value interface{}, enc encoderFunc, dec decoderFunc) {
	typ := reflect.TypeOf(value)
	if enc != nil {
		typEncMap[typ] = enc
	}
	if dec != nil {
		typDecMap[typ] = dec
	}
}

//------------------------------------------------------------------------------

var structs = newStructCache()

type structCache struct {
	l sync.RWMutex
	m map[reflect.Type]*fields
}

func newStructCache() *structCache {
	return &structCache{
		m: make(map[reflect.Type]*fields),
	}
}

func (m *structCache) Fields(typ reflect.Type) *fields {
	m.l.RLock()
	fs, ok := m.m[typ]
	m.l.RUnlock()
	if !ok {
		m.l.Lock()
		fs, ok = m.m[typ]
		if !ok {
			fs = getFields(typ)
			m.m[typ] = fs
		}
		m.l.Unlock()
	}

	return fs
}

//------------------------------------------------------------------------------

type field struct {
	name      string
	index     []int
	omitEmpty bool

	encoder encoderFunc
	decoder decoderFunc
}

func (f *field) value(strct reflect.Value) reflect.Value {
	return strct.FieldByIndex(f.index)
}

func (f *field) Omit(strct reflect.Value) bool {
	return f.omitEmpty && isEmptyValue(f.value(strct))
}

func (f *field) EncodeValue(e *Encoder, strct reflect.Value) error {
	return f.encoder(e, f.value(strct))
}

func (f *field) DecodeValue(d *Decoder, strct reflect.Value) error {
	return f.decoder(d, f.value(strct))
}

//------------------------------------------------------------------------------

type fields struct {
	List  []*field
	Table map[string]*field

	asArray   bool
	omitEmpty bool
}

func newFields(numField int) *fields {
	return &fields{
		List:  make([]*field, 0, numField),
		Table: make(map[string]*field, numField),
	}
}

func (fs *fields) Len() int {
	return len(fs.List)
}

func (fs *fields) Add(field *field) {
	fs.List = append(fs.List, field)
	fs.Table[field.name] = field
	if field.omitEmpty {
		fs.omitEmpty = field.omitEmpty
	}
}

func (fs *fields) OmitEmpty(strct reflect.Value) []*field {
	if !fs.omitEmpty {
		return fs.List
	}

	fields := make([]*field, 0, fs.Len())
	for _, f := range fs.List {
		if !f.Omit(strct) {
			fields = append(fields, f)
		}
	}
	return fields
}

func getFields(typ reflect.Type) *fields {
	numField := typ.NumField()
	fs := newFields(numField)

	var omitEmpty bool
	for i := 0; i < numField; i++ {
		f := typ.Field(i)

		name, opt := parseTag(f.Tag.Get("msgpack"))
		if name == "-" {
			continue
		}

		if f.Name == "_msgpack" {
			if opt.Contains("asArray") {
				fs.asArray = true
			}
			if opt.Contains("omitempty") {
				omitEmpty = true
			}
		}

		if f.PkgPath != "" && !f.Anonymous {
			continue
		}

		if opt.Contains("inline") {
			inlineFields(fs, f)
			continue
		}

		if name == "" {
			name = f.Name
		}
		field := field{
			name:      name,
			index:     f.Index,
			omitEmpty: omitEmpty || opt.Contains("omitempty"),
			encoder:   getEncoder(f.Type),
			decoder:   getDecoder(f.Type),
		}
		fs.Add(&field)
	}
	return fs
}

func inlineFields(fs *fields, f reflect.StructField) {
	typ := f.Type
	if typ.Kind() == reflect.Ptr {
		typ = typ.Elem()
	}
	inlinedFields := getFields(typ).List
	for _, field := range inlinedFields {
		if _, ok := fs.Table[field.name]; ok {
			// Don't overwrite shadowed fields.
			continue
		}
		field.index = append(f.Index, field.index...)
		fs.Add(field)
	}
}

func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}
	return false
}
<commit_msg>Code cleanup<commit_after>package msgpack

import (
	"reflect"
	"sync"
)

var errorType = reflect.TypeOf((*error)(nil)).Elem()

var customEncoderType = reflect.TypeOf((*CustomEncoder)(nil)).Elem()
var customDecoderType = reflect.TypeOf((*CustomDecoder)(nil)).Elem()

var marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
var unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()

type encoderFunc func(*Encoder, reflect.Value) error
type decoderFunc func(*Decoder, reflect.Value) error

var typEncMap = make(map[reflect.Type]encoderFunc)
var typDecMap = make(map[reflect.Type]decoderFunc)

// Register registers encoder and decoder functions for a value.
// This is low level API and in most cases you should prefer implementing
// Marshaler/CustomEncoder and Unmarshaler/CustomDecoder interfaces.
func Register(value interface{}, enc encoderFunc, dec decoderFunc) {
	typ := reflect.TypeOf(value)
	if enc != nil {
		typEncMap[typ] = enc
	}
	if dec != nil {
		typDecMap[typ] = dec
	}
}

//------------------------------------------------------------------------------

var structs = newStructCache()

type structCache struct {
	mu sync.RWMutex
	m  map[reflect.Type]*fields
}

func newStructCache() *structCache {
	return &structCache{
		m: make(map[reflect.Type]*fields),
	}
}

func (m *structCache) Fields(typ reflect.Type) *fields {
	m.mu.RLock()
	fs, ok := m.m[typ]
	m.mu.RUnlock()
	if ok {
		return fs
	}

	m.mu.Lock()
	fs, ok = m.m[typ]
	if !ok {
		fs = getFields(typ)
		m.m[typ] = fs
	}
	m.mu.Unlock()

	return fs
}

//------------------------------------------------------------------------------

type field struct {
	name      string
	index     []int
	omitEmpty bool

	encoder encoderFunc
	decoder decoderFunc
}

func (f *field) value(strct reflect.Value) reflect.Value {
	return strct.FieldByIndex(f.index)
}

func (f *field) Omit(strct reflect.Value) bool {
	return f.omitEmpty && isEmptyValue(f.value(strct))
}

func (f *field) EncodeValue(e *Encoder, strct reflect.Value) error {
	return f.encoder(e, f.value(strct))
}

func (f *field) DecodeValue(d *Decoder, strct reflect.Value) error {
	return f.decoder(d, f.value(strct))
}

//------------------------------------------------------------------------------

type fields struct {
	List  []*field
	Table map[string]*field

	asArray   bool
	omitEmpty bool
}

func newFields(numField int) *fields {
	return &fields{
		List:  make([]*field, 0, numField),
		Table: make(map[string]*field, numField),
	}
}

func (fs *fields) Len() int {
	return len(fs.List)
}

func (fs *fields) Add(field *field) {
	fs.List = append(fs.List, field)
	fs.Table[field.name] = field
	if field.omitEmpty {
		fs.omitEmpty = field.omitEmpty
	}
}

func (fs *fields) OmitEmpty(strct reflect.Value) []*field {
	if !fs.omitEmpty {
		return fs.List
	}

	fields := make([]*field, 0, fs.Len())
	for _, f := range fs.List {
		if !f.Omit(strct) {
			fields = append(fields, f)
		}
	}
	return fields
}

func getFields(typ reflect.Type) *fields {
	numField := typ.NumField()
	fs := newFields(numField)

	var omitEmpty bool
	for i := 0; i < numField; i++ {
		f := typ.Field(i)

		name, opt := parseTag(f.Tag.Get("msgpack"))
		if name == "-" {
			continue
		}

		if f.Name == "_msgpack" {
			if opt.Contains("asArray") {
				fs.asArray = true
			}
			if opt.Contains("omitempty") {
				omitEmpty = true
			}
		}

		if f.PkgPath != "" && !f.Anonymous {
			continue
		}

		if opt.Contains("inline") {
			inlineFields(fs, f)
			continue
		}

		if name == "" {
			name = f.Name
		}
		field := field{
			name:      name,
			index:     f.Index,
			omitEmpty: omitEmpty || opt.Contains("omitempty"),
			encoder:   getEncoder(f.Type),
			decoder:   getDecoder(f.Type),
		}
		fs.Add(&field)
	}
	return fs
}

func inlineFields(fs *fields, f reflect.StructField) {
	typ := f.Type
	if typ.Kind() == reflect.Ptr {
		typ = typ.Elem()
	}
	inlinedFields := getFields(typ).List
	for _, field := range inlinedFields {
		if _, ok := fs.Table[field.name]; ok {
			// Don't overwrite shadowed fields.
			continue
		}
		field.index = append(f.Index, field.index...)
		fs.Add(field)
	}
}

func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}
	return false
}
<|endoftext|>


<commit_before>package dockerclient

import (
	"time"
)

type ContainerConfig struct {
	Hostname        string
	Domainname      string
	User            string
	Memory          int64
	MemorySwap      int64
	CpuShares       int64
	Cpuset          string
	AttachStdin     bool
	AttachStdout    bool
	AttachStderr    bool
	PortSpecs       []string
	ExposedPorts    map[string]struct{}
	Tty             bool
	OpenStdin       bool
	StdinOnce       bool
	Env             []string
	Cmd             []string
	Image           string
	Labels          map[string]string
	Volumes         map[string]struct{}
	WorkingDir      string
	Entrypoint      []string
	NetworkDisabled bool
	OnBuild         []string

	// This is used only by the create command
	HostConfig HostConfig
}

type HostConfig struct {
	Binds           []string
	ContainerIDFile string
	LxcConf         []map[string]string
	Privileged      bool
	PortBindings    map[string][]PortBinding
	Links           []string
	PublishAllPorts bool
	Dns             []string
	DnsSearch       []string
	VolumesFrom     []string
	SecurityOpt     []string
	NetworkMode     string
	RestartPolicy   RestartPolicy
}

type ExecConfig struct {
	AttachStdin  bool
	AttachStdout bool
	AttachStderr bool
	Tty          bool
	Cmd          []string
	Container    string
	Detach       bool
}

type LogOptions struct {
	Follow     bool
	Stdout     bool
	Stderr     bool
	Timestamps bool
	Tail       int64
}

type RestartPolicy struct {
	Name              string
	MaximumRetryCount int64
}

type PortBinding struct {
	HostIp   string
	HostPort string
}

type ContainerInfo struct {
	Id      string
	Created string
	Path    string
	Name    string
	Args    []string
	ExecIDs []string
	Config  *ContainerConfig
	State   struct {
		Running    bool
		Paused     bool
		Restarting bool
		Pid        int
		ExitCode   int
		StartedAt  time.Time
		FinishedAt time.Time
		Ghost      bool
	}
	Image           string
	NetworkSettings struct {
		IpAddress   string
		IpPrefixLen int
		Gateway     string
		Bridge      string
		Ports       map[string][]PortBinding
	}
	SysInitPath    string
	ResolvConfPath string
	Volumes        map[string]string
	HostConfig     *HostConfig
}

type ContainerChanges struct {
	Path string
	Kind int
}

type Port struct {
	IP          string
	PrivatePort int
	PublicPort  int
	Type        string
}

type Container struct {
	Id         string
	Names      []string
	Image      string
	Command    string
	Created    int64
	Status     string
	Ports      []Port
	SizeRw     int64
	SizeRootFs int64
}

type Event struct {
	Id     string
	Status string
	From   string
	Time   int64
}

type Version struct {
	Version   string
	GitCommit string
	GoVersion string
}

type RespContainersCreate struct {
	Id       string
	Warnings []string
}

type Image struct {
	Created     int64
	Id          string
	ParentId    string
	RepoTags    []string
	Size        int64
	VirtualSize int64
}

type Info struct {
	ID              string
	Containers      int64
	Driver          string
	DriverStatus    [][]string
	ExecutionDriver string
	Images          int64
	KernelVersion   string
	OperatingSystem string
	NCPU            int64
	MemTotal        int64
	Name            string
	Labels          []string
}

type ImageDelete struct {
	Deleted  string
	Untagged string
}

// The following are types for the API stats endpoint
type ThrottlingData struct {
	// Number of periods with throttling active
	Periods uint64 `json:"periods"`
	// Number of periods when the container hit its throttling limit.
	ThrottledPeriods uint64 `json:"throttled_periods"`
	// Aggregate time the container was throttled for in nanoseconds.
	ThrottledTime uint64 `json:"throttled_time"`
}

// Stats types below
// All CPU stats are aggregated since container inception.
type CpuUsage struct {
	// Total CPU time consumed.
	// Units: nanoseconds.
	TotalUsage uint64 `json:"total_usage"`
	// Total CPU time consumed per core.
	// Units: nanoseconds.
	PercpuUsage []uint64 `json:"percpu_usage"`
	// Time spent by tasks of the cgroup in kernel mode.
	// Units: nanoseconds.
	UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
	// Time spent by tasks of the cgroup in user mode.
	// Units: nanoseconds.
	UsageInUsermode uint64 `json:"usage_in_usermode"`
}

type CpuStats struct {
	CpuUsage       CpuUsage       `json:"cpu_usage"`
	SystemUsage    uint64         `json:"system_cpu_usage"`
	ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
}

type MemoryStats struct {
	Usage    uint64            `json:"usage"`
	MaxUsage uint64            `json:"max_usage"`
	Stats    map[string]uint64 `json:"stats"`
	Failcnt  uint64            `json:"failcnt"`
	Limit    uint64            `json:"limit"`
}

type BlkioStatEntry struct {
	Major uint64 `json:"major"`
	Minor uint64 `json:"minor"`
	Op    string `json:"op"`
	Value uint64 `json:"value"`
}

type BlkioStats struct {
	// number of bytes tranferred to and from the block device
	IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"`
	IoServicedRecursive     []BlkioStatEntry `json:"io_serviced_recursive"`
	IoQueuedRecursive       []BlkioStatEntry `json:"io_queue_recursive"`
	IoServiceTimeRecursive  []BlkioStatEntry `json:"io_service_time_recursive"`
	IoWaitTimeRecursive     []BlkioStatEntry `json:"io_wait_time_recursive"`
	IoMergedRecursive       []BlkioStatEntry `json:"io_merged_recursive"`
	IoTimeRecursive         []BlkioStatEntry `json:"io_time_recursive"`
	SectorsRecursive        []BlkioStatEntry `json:"sectors_recursive"`
}

type Stats struct {
	Read    time.Time `json:"read"`
	Network struct {
		RxBytes   uint64 `json:"rx_bytes"`
		RxPackets uint64 `json:"rx_packets"`
		RxErrors  uint64 `json:"rx_errors"`
		RxDropped uint64 `json:"rx_dropped"`
		TxBytes   uint64 `json:"tx_bytes"`
		TxPackets uint64 `json:"tx_packets"`
		TxErrors  uint64 `json:"tx_errors"`
		TxDropped uint64 `json:"tx_dropped"`
	}

	CpuStats    CpuStats    `json:"cpu_stats,omitempty"`
	MemoryStats MemoryStats `json:"memory_stats,omitempty"`
	BlkioStats  BlkioStats  `json:"blkio_stats,omitempty"`
}
<commit_msg>add NetworkStats struct<commit_after>package dockerclient

import (
	"time"
)

type ContainerConfig struct {
	Hostname        string
	Domainname      string
	User            string
	Memory          int64
	MemorySwap      int64
	CpuShares       int64
	Cpuset          string
	AttachStdin     bool
	AttachStdout    bool
	AttachStderr    bool
	PortSpecs       []string
	ExposedPorts    map[string]struct{}
	Tty             bool
	OpenStdin       bool
	StdinOnce       bool
	Env             []string
	Cmd             []string
	Image           string
	Labels          map[string]string
	Volumes         map[string]struct{}
	WorkingDir      string
	Entrypoint      []string
	NetworkDisabled bool
	OnBuild         []string

	// This is used only by the create command
	HostConfig HostConfig
}

type HostConfig struct {
	Binds           []string
	ContainerIDFile string
	LxcConf         []map[string]string
	Privileged      bool
	PortBindings    map[string][]PortBinding
	Links           []string
	PublishAllPorts bool
	Dns             []string
	DnsSearch       []string
	VolumesFrom     []string
	SecurityOpt     []string
	NetworkMode     string
	RestartPolicy   RestartPolicy
}

type ExecConfig struct {
	AttachStdin  bool
	AttachStdout bool
	AttachStderr bool
	Tty          bool
	Cmd          []string
	Container    string
	Detach       bool
}

type LogOptions struct {
	Follow     bool
	Stdout     bool
	Stderr     bool
	Timestamps bool
	Tail       int64
}

type RestartPolicy struct {
	Name              string
	MaximumRetryCount int64
}

type PortBinding struct {
	HostIp   string
	HostPort string
}

type ContainerInfo struct {
	Id      string
	Created string
	Path    string
	Name    string
	Args    []string
	ExecIDs []string
	Config  *ContainerConfig
	State   struct {
		Running    bool
		Paused     bool
		Restarting bool
		Pid        int
		ExitCode   int
		StartedAt  time.Time
		FinishedAt time.Time
		Ghost      bool
	}
	Image           string
	NetworkSettings struct {
		IpAddress   string
		IpPrefixLen int
		Gateway     string
		Bridge      string
		Ports       map[string][]PortBinding
	}
	SysInitPath    string
	ResolvConfPath string
	Volumes        map[string]string
	HostConfig     *HostConfig
}

type ContainerChanges struct {
	Path string
	Kind int
}

type Port struct {
	IP          string
	PrivatePort int
	PublicPort  int
	Type        string
}

type Container struct {
	Id         string
	Names      []string
	Image      string
	Command    string
	Created    int64
	Status     string
	Ports      []Port
	SizeRw     int64
	SizeRootFs int64
}

type Event struct {
	Id     string
	Status string
	From   string
	Time   int64
}

type Version struct {
	Version   string
	GitCommit string
	GoVersion string
}

type RespContainersCreate struct {
	Id       string
	Warnings []string
}

type Image struct {
	Created     int64
	Id          string
	ParentId    string
	RepoTags    []string
	Size        int64
	VirtualSize int64
}

type Info struct {
	ID              string
	Containers      int64
	Driver          string
	DriverStatus    [][]string
	ExecutionDriver string
	Images          int64
	KernelVersion   string
	OperatingSystem string
	NCPU            int64
	MemTotal        int64
	Name            string
	Labels          []string
}

type ImageDelete struct {
	Deleted  string
	Untagged string
}

// The following are types for the API stats endpoint
type ThrottlingData struct {
	// Number of periods with throttling active
	Periods uint64 `json:"periods"`
	// Number of periods when the container hit its throttling limit.
	ThrottledPeriods uint64 `json:"throttled_periods"`
	// Aggregate time the container was throttled for in nanoseconds.
	ThrottledTime uint64 `json:"throttled_time"`
}

// Stats types below
// All CPU stats are aggregated since container inception.
type CpuUsage struct {
	// Total CPU time consumed.
	// Units: nanoseconds.
	TotalUsage uint64 `json:"total_usage"`
	// Total CPU time consumed per core.
	// Units: nanoseconds.
	PercpuUsage []uint64 `json:"percpu_usage"`
	// Time spent by tasks of the cgroup in kernel mode.
	// Units: nanoseconds.
	UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
	// Time spent by tasks of the cgroup in user mode.
	// Units: nanoseconds.
	UsageInUsermode uint64 `json:"usage_in_usermode"`
}

type CpuStats struct {
	CpuUsage       CpuUsage       `json:"cpu_usage"`
	SystemUsage    uint64         `json:"system_cpu_usage"`
	ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
}

type NetworkStats struct {
	RxBytes   uint64 `json:"rx_bytes"`
	RxPackets uint64 `json:"rx_packets"`
	RxErrors  uint64 `json:"rx_errors"`
	RxDropped uint64 `json:"rx_dropped"`
	TxBytes   uint64 `json:"tx_bytes"`
	TxPackets uint64 `json:"tx_packets"`
	TxErrors  uint64 `json:"tx_errors"`
	TxDropped uint64 `json:"tx_dropped"`
}

type MemoryStats struct {
	Usage    uint64            `json:"usage"`
	MaxUsage uint64            `json:"max_usage"`
	Stats    map[string]uint64 `json:"stats"`
	Failcnt  uint64            `json:"failcnt"`
	Limit    uint64            `json:"limit"`
}

type BlkioStatEntry struct {
	Major uint64 `json:"major"`
	Minor uint64 `json:"minor"`
	Op    string `json:"op"`
	Value uint64 `json:"value"`
}

type BlkioStats struct {
	// number of bytes tranferred to and from the block device
	IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"`
	IoServicedRecursive     []BlkioStatEntry `json:"io_serviced_recursive"`
	IoQueuedRecursive       []BlkioStatEntry `json:"io_queue_recursive"`
	IoServiceTimeRecursive  []BlkioStatEntry `json:"io_service_time_recursive"`
	IoWaitTimeRecursive     []BlkioStatEntry `json:"io_wait_time_recursive"`
	IoMergedRecursive       []BlkioStatEntry `json:"io_merged_recursive"`
	IoTimeRecursive         []BlkioStatEntry `json:"io_time_recursive"`
	SectorsRecursive        []BlkioStatEntry `json:"sectors_recursive"`
}

type Stats struct {
	Read         time.Time    `json:"read"`
	NetworkStats NetworkStats `json:"network_stats,omitempty"`
	CpuStats     CpuStats     `json:"cpu_stats,omitempty"`
	MemoryStats  MemoryStats  `json:"memory_stats,omitempty"`
	BlkioStats   BlkioStats   `json:"blkio_stats,omitempty"`
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"sync"

	"github.com/tucnak/telebot"
	yaml "gopkg.in/yaml.v2"
)

// UserStore writes the users to a file for persistence
type UserStore struct {
	mu    sync.Mutex
	file  string
	users map[int]telebot.User
}

// NewUserStore from a filename and loading the contents if there is
func NewUserStore(file string) (*UserStore, error) {
	store := &UserStore{
		file:  file,
		users: make(map[int]telebot.User),
	}

	usersBytes, err := ioutil.ReadFile(store.file)
	if err != nil {
		return store, err
	}

	store.mu.Lock()
	if err := yaml.Unmarshal(usersBytes, &store.users); err != nil {
		return store, err
	}
	store.mu.Unlock()

	return store, nil
}

// Len returns the users count
func (s *UserStore) Len() int {
	return len(s.users)
}

// List all users as slice to range over
func (s *UserStore) List() []telebot.User {
	var users []telebot.User
	for _, u := range s.users {
		users = append(users, u)
	}
	return users
}

// Add a telebot User to the store and write the current users to disk
func (s *UserStore) Add(u telebot.User) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	s.users[u.ID] = u

	out, err := yaml.Marshal(s.users)
	if err != nil {
		return err
	}
	ioutil.WriteFile(s.file, out, 0644)

	return nil
}

// Remove a telebot User from the store and write the current users to disk
func (s *UserStore) Remove(u telebot.User) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	delete(s.users, u.ID)

	out, err := yaml.Marshal(s.users)
	if err != nil {
		return err
	}
	ioutil.WriteFile(s.file, out, 0644)

	return nil
}
<commit_msg>If store file doesn’t exist create it<commit_after>package main

import (
	"io/ioutil"
	"log"
	"os"
	"sync"

	"github.com/tucnak/telebot"
	yaml "gopkg.in/yaml.v2"
)

const fileMode = 0600

// UserStore writes the users to a file for persistence
type UserStore struct {
	mu    sync.Mutex
	file  string
	users map[int]telebot.User
}

// NewUserStore from a filename and loading the contents if there is
func NewUserStore(file string) (*UserStore, error) {
	store := &UserStore{
		file:  file,
		users: make(map[int]telebot.User),
	}

	// If file for storing not present create it
	_, err := os.Stat(store.file)
	if err != nil {
		_, err := os.Create(store.file)
		if err != nil {
			return nil, err
		}
		log.Printf("created %s", store.file)
	}

	usersBytes, err := ioutil.ReadFile(store.file)
	if err != nil {
		return store, err
	}

	store.mu.Lock()
	if err := yaml.Unmarshal(usersBytes, &store.users); err != nil {
		return store, err
	}
	store.mu.Unlock()

	return store, nil
}

// Len returns the users count
func (s *UserStore) Len() int {
	return len(s.users)
}

// List all users as slice to range over
func (s *UserStore) List() []telebot.User {
	var users []telebot.User
	for _, u := range s.users {
		users = append(users, u)
	}
	return users
}

// Add a telebot User to the store and write the current users to disk
func (s *UserStore) Add(u telebot.User) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	s.users[u.ID] = u

	out, err := yaml.Marshal(s.users)
	if err != nil {
		return err
	}
	ioutil.WriteFile(s.file, out, fileMode)

	return nil
}

// Remove a telebot User from the store and write the current users to disk
func (s *UserStore) Remove(u telebot.User) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	delete(s.users, u.ID)

	out, err := yaml.Marshal(s.users)
	if err != nil {
		return err
	}

	ioutil.WriteFile(s.file, out, fileMode)

	return nil
}
<|endoftext|>


<commit_before>// chris 071615 Validator code.

package main

import (
	"fmt"
	"strings"
	"unicode"

	"go/ast"
	"unicode/utf8"
)

// validateString writes validator code for a string to the given *buf.
func validateString(b *buf, fldname string) {
	b.writef("\tret.%s = data[\"%s\"]\n", fldname, fldname)
}

// validateBool writes validator code for a bool to the given *buf.
func validateBool(b *buf, fldname string) {
	b.writef("\tret.%s, err = strconv.ParseBool(data[\"%s\"])\n", fldname, fldname)
	b.writef("\tif err != nil {\n")
	b.writef("\t\treturn nil, err\n")
	b.writef("\t}\n")
}

// validator writes validator code for the given struct to the given
// *buf.  It iterates through the struct fields, and for those for which
// it can generate validator code, it does so.
func validator(b *buf, name string, s *ast.StructType) {
	first, _ := utf8.DecodeRune([]byte(name))
	isPublic := unicode.IsUpper(first)
	var fname string
	if isPublic {
		fname = fmt.Sprintf("Validate%s", name)
	} else {
		fname = fmt.Sprintf("validate%s", strings.Title(name))
	}

	b.writef("\n") // Newline to separate from above content.
	b.writef("func %s(data map[string]string) (*%s, error) {\n", fname, name)
	b.writef("\tret := new(%s)\n", name)

	for _, fld := range s.Fields.List {
		nam := fld.Names[0].Name
		typ, ok := fld.Type.(*ast.Ident)
		if !ok {
			continue
		}
		b.writef("\t// %s %s\n", nam, typ)
		switch typ.Name {
		case "string":
			validateString(b, nam)
		case "bool":
			validateBool(b, nam)
			b.needsStrconv = true
		}
	}

	b.writef("\t\n")
	b.writef("\treturn ret, nil\n")
	b.writef("}\n")
}
<commit_msg>Spaces out validation code.<commit_after>// chris 071615 Validator code.

package main

import (
	"fmt"
	"strings"
	"unicode"

	"go/ast"
	"unicode/utf8"
)

// validateString writes validator code for a string to the given *buf.
func validateString(b *buf, fldname string) {
	b.writef("\tret.%s = data[\"%s\"]\n", fldname, fldname)
}

// validateBool writes validator code for a bool to the given *buf.
func validateBool(b *buf, fldname string) {
	b.writef("\tret.%s, err = strconv.ParseBool(data[\"%s\"])\n", fldname, fldname)
	b.writef("\tif err != nil {\n")
	b.writef("\t\treturn nil, err\n")
	b.writef("\t}\n")
}

// validator writes validator code for the given struct to the given
// *buf.  It iterates through the struct fields, and for those for which
// it can generate validator code, it does so.
func validator(b *buf, name string, s *ast.StructType) {
	first, _ := utf8.DecodeRune([]byte(name))
	isPublic := unicode.IsUpper(first)
	var fname string
	if isPublic {
		fname = fmt.Sprintf("Validate%s", name)
	} else {
		fname = fmt.Sprintf("validate%s", strings.Title(name))
	}

	b.writef("\n") // Newline to separate from above content.
	b.writef("func %s(data map[string]string) (*%s, error) {\n", fname, name)
	b.writef("\tret := new(%s)\n", name)

	for _, fld := range s.Fields.List {
		nam := fld.Names[0].Name
		typ, ok := fld.Type.(*ast.Ident)
		if !ok {
			continue
		}
		b.writef("\t// %s %s\n", nam, typ)
		switch typ.Name {
		case "string":
			validateString(b, nam)

		case "bool":
			validateBool(b, nam)
			b.needsStrconv = true
		}
	}

	b.writef("\t\n")
	b.writef("\treturn ret, nil\n")
	b.writef("}\n")
}
<|endoftext|>


<commit_before>// +build appengine

// Package value provides a utility method to retrieve string values in an
// App Engine app, so they can be stored in the datastore instead of in source.
//
// Values can be added using the admin interface served at /_ah/value/admin
// (app.yaml must map this URL to script: _go_app to support this), or by using
// the App Engine Datastore Viewer UI.
//
// Once retrieved, values will be cached in memcache and local instance
// memory for quick lookup. Values cannot be updated, except via the Admin UI.
//
// Intended use cases are OAuth client secrets or API keys, for instance, which
// are used across many requests are should be quick to look up, but shouldn't
// be stored in source control as consts for security reasons.
//
// Values are not encrypted or obfuscated, and will be easily visible to any
// other app admin.
package value

import (
	"errors"
	"fmt"
	"html/template"
	"net/http"
	"time"

	"appengine"
	"appengine/datastore"
	"appengine/memcache"
	"appengine/user"
)

// Kind is the name used to store values in the datastore.
var Kind = "Values"

// Prefix to use when storing values in memcache.
var MemcacheKeyPrefix = ""

var local = map[string]string{}

type e struct {
	Value string `datastore:",noindex"`
}

// Get returns the value associated with the key.
//
// If the value cannot be found in any of local instance memory, memcache, or
// the datastore, an empty string will be returned.
func Get(c appengine.Context, key string) string {
	if v, ok := local[key]; ok {
		// Found value in instance memory, return it.
		return v
	}

	i, err := memcache.Get(c, key)
	if err == nil {
		// Found value in memcache, return it.
		return string(i.Value)
	}

	if err != nil && err != memcache.ErrCacheMiss {
		c.Errorf("error getting %q from memcache: %v", key, err)
	}

	// Get value from datastore if missing from memcache.
	k := datastore.NewKey(c, Kind, key, 0, nil)
	var e e
	if err := datastore.Get(c, k, &e); err != nil {
		c.Errorf("error getting %q from datastore: %v", key, err)
		return ""
	}

	// Store value in instance memory for next time.
	local[key] = e.Value

	// Store value in memcache for next time.
	if err := memcache.Set(c, &memcache.Item{
		Key:   MemcacheKeyPrefix + key,
		Value: []byte(e.Value),
	}); err != nil {
		c.Errorf("error setting %q in memcache: %v", key, err)
	}

	return e.Value
}

func init() {
	http.HandleFunc("/_ah/value/admin", adminHandler)
	http.HandleFunc("/_ah/value/update", updateHandler)
}

var adminTmpl = template.Must(template.New("admin").Parse(`

Admin

<form action="/_ah/value/update" method="POST">

{{range $key, $val := .}}

{{$key}}	{{$val}}

{{else}}
no values currently configured

{{end}}

<input type="text" name="key"></input>	<input type="text" name="val"></input>

<input type="submit" value="Save"></input>

</form>
`))

func adminHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	if !user.IsAdmin(c) {
		if user.Current(c) == nil {
			loginURL, _ := user.LoginURL(c, "/_ah/value/admin")
			fmt.Fprintf(w, "Log in", loginURL)
		} else {
			http.Error(w, "Forbidden", http.StatusForbidden)
		}
		return
	}
	if r.Method != "GET" {
		return
	}
	v := map[string]string{}
	q := datastore.NewQuery(Kind)
	for t := q.Run(c); ; {
		var e e
		k, err := t.Next(&e)
		if err == datastore.Done {
			break
		} else if err != nil {
			c.Errorf("%+v", err)
			return
		}
		v[k.StringID()] = e.Value
	}

	// TODO
	adminTmpl.Execute(w, v)
}

func updateHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Redirect(w, r, "/_ah/value/admin", http.StatusSeeOther)
		return
	}
	c := appengine.NewContext(r)
	if !user.IsAdmin(c) {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}

	key := r.FormValue("key")
	val := r.FormValue("val")
	if err := set(c, key, val); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	// TODO: remove this hack.
	time.Sleep(time.Millisecond * 500)
	http.Redirect(w, r, "/_ah/value/admin", http.StatusSeeOther)
}

func set(c appengine.Context, key string, val string) error {
	if _, ok := local[key]; ok {
		return errors.New("key found in local instance")
	}
	if _, err := memcache.Get(c, key); err != memcache.ErrCacheMiss {
		return errors.New("key found in memcache")
	}
	return datastore.RunInTransaction(c, func(tc appengine.Context) error {
		// Fail if the value is already stored.
		k := datastore.NewKey(c, Kind, key, 0, nil)
		if err := datastore.Get(tc, k, nil); err == nil {
			return errors.New("key found in datastore")
		} else if err == datastore.ErrNoSuchEntity {
			// Okay, good. Keep going.
		} else if err != nil {
			return err
		}

		// Put the value in the datastore.
		_, err := datastore.Put(tc, k, &e{Value: key})
		return err
	}, nil)
}
<commit_msg>fix set bug, move Save button<commit_after>// +build appengine

// Package value provides a utility method to retrieve string values in an
// App Engine app, so they can be stored in the datastore instead of in source.
//
// Values can be added using the admin interface served at /_ah/value/admin
// (app.yaml must map this URL to script: _go_app to support this), or by using
// the App Engine Datastore Viewer UI.
//
// Once retrieved, values will be cached in memcache and local instance
// memory for quick lookup. Values cannot be updated, except via the Admin UI.
//
// Intended use cases are OAuth client secrets or API keys, for instance, which
// are used across many requests are should be quick to look up, but shouldn't
// be stored in source control as consts for security reasons.
//
// Values are not encrypted or obfuscated, and will be easily visible to any
// other app admin.
package value

import (
	"errors"
	"fmt"
	"html/template"
	"net/http"
	"time"

	"appengine"
	"appengine/datastore"
	"appengine/memcache"
	"appengine/user"
)

// Kind is the name used to store values in the datastore.
var Kind = "Values"

// Prefix to use when storing values in memcache.
var MemcacheKeyPrefix = ""

var local = map[string]string{}

type e struct {
	Value string `datastore:",noindex"`
}

// Get returns the value associated with the key.
//
// If the value cannot be found in any of local instance memory, memcache, or
// the datastore, an empty string will be returned.
func Get(c appengine.Context, key string) string {
	if v, ok := local[key]; ok {
		// Found value in instance memory, return it.
		return v
	}

	i, err := memcache.Get(c, key)
	if err == nil {
		// Found value in memcache, return it.
		return string(i.Value)
	}

	if err != nil && err != memcache.ErrCacheMiss {
		c.Errorf("error getting %q from memcache: %v", key, err)
	}

	// Get value from datastore if missing from memcache.
	k := datastore.NewKey(c, Kind, key, 0, nil)
	var e e
	if err := datastore.Get(c, k, &e); err != nil {
		c.Errorf("error getting %q from datastore: %v", key, err)
		return ""
	}

	// Store value in instance memory for next time.
	local[key] = e.Value

	// Store value in memcache for next time.
	if err := memcache.Set(c, &memcache.Item{
		Key:   MemcacheKeyPrefix + key,
		Value: []byte(e.Value),
	}); err != nil {
		c.Errorf("error setting %q in memcache: %v", key, err)
	}

	return e.Value
}

func init() {
	http.HandleFunc("/_ah/value/admin", adminHandler)
	http.HandleFunc("/_ah/value/update", updateHandler)
}

var adminTmpl = template.Must(template.New("admin").Parse(`

Admin

<form action="/_ah/value/update" method="POST">

{{range $key, $val := .}}

{{$key}}	{{$val}}

{{else}}
no values currently configured

{{end}}

<input type="text" name="key"></input>	<input type="text" name="val"></input>

<input type="submit" value="Save"></input>
</form>
`))

func adminHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	if !user.IsAdmin(c) {
		if user.Current(c) == nil {
			loginURL, _ := user.LoginURL(c, "/_ah/value/admin")
			fmt.Fprintf(w, "Log in", loginURL)
		} else {
			http.Error(w, "Forbidden", http.StatusForbidden)
		}
		return
	}
	if r.Method != "GET" {
		return
	}
	v := map[string]string{}
	q := datastore.NewQuery(Kind)
	for t := q.Run(c); ; {
		var e e
		k, err := t.Next(&e)
		if err == datastore.Done {
			break
		} else if err != nil {
			c.Errorf("%+v", err)
			return
		}
		v[k.StringID()] = e.Value
	}

	// TODO
	adminTmpl.Execute(w, v)
}

func updateHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Redirect(w, r, "/_ah/value/admin", http.StatusSeeOther)
		return
	}
	c := appengine.NewContext(r)
	if !user.IsAdmin(c) {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}

	key := r.FormValue("key")
	val := r.FormValue("val")
	if err := set(c, key, val); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	// TODO: remove this hack.
	time.Sleep(time.Millisecond * 500)
	http.Redirect(w, r, "/_ah/value/admin", http.StatusSeeOther)
}

func set(c appengine.Context, key string, val string) error {
	if _, ok := local[key]; ok {
		return errors.New("key found in local instance")
	}
	if _, err := memcache.Get(c, key); err != memcache.ErrCacheMiss {
		return errors.New("key found in memcache")
	}
	return datastore.RunInTransaction(c, func(tc appengine.Context) error {
		// Fail if the value is already stored.
		k := datastore.NewKey(c, Kind, key, 0, nil)
		if err := datastore.Get(tc, k, nil); err == nil {
			return errors.New("key found in datastore")
		} else if err == datastore.ErrNoSuchEntity {
			// Okay, good. Keep going.
		} else if err != nil {
			return err
		}

		// Put the value in the datastore.
		_, err := datastore.Put(tc, k, &e{Value: val})
		return err
	}, nil)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"text/tabwriter"
	"time"

	"github.com/coreos-inc/updatectl/third_party/code.google.com/p/go-uuid/uuid"
	"github.com/coreos-inc/updatectl/third_party/github.com/codegangsta/cli"
	"github.com/coreos-inc/updatectl/third_party/github.com/coreos/go-omaha/omaha"

	"github.com/coreos-inc/updatectl/client/update/v1"
)

func WatchCommands() []cli.Command {
	return []cli.Command{
		{
			Name:        "watch",
			Usage:       "watch [OPTION]... <appID> <groupID> <clientID> <cmd> <args>",
			Description: `Watch for app versions and exec a script`,
			Action:      handle(watch),
			Flags: []cli.Flag{
				cli.IntFlag{"interval, i", 1, "Update polling interval"},
				cli.StringFlag{"version, v", "0.0.0", "Client ID for the watcher"},
			},
		},
	}
}

func fetchVersion(server string, appID string, groupID string, clientID string, version string, debug bool) string {
	client := &http.Client{}

	// TODO: Fill out the OS field correctly based on /etc/os-release
	request := omaha.NewRequest("lsb", "CoreOS", "", "")
	app := request.AddApp(fmt.Sprintf("{%s}", appID), version)
	app.AddUpdateCheck()
	app.MachineID = clientID
	app.BootId = uuid.New()
	app.Track = groupID

	event := app.AddEvent()
	event.Type = "1"
	event.Result = "0"

	raw, err := xml.MarshalIndent(request, "", " ")
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return version
	}

	if debug {
		fmt.Fprintf(os.Stderr, "Request: %s%s\n", xml.Header, raw)
	}

	resp, err := client.Post(server+"/v1/update/", "text/xml", bytes.NewReader(raw))
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return version
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return version
	}

	if debug {
		fmt.Fprintf(os.Stderr, "Response: %s%s\n", xml.Header, string(body))
	}

	oresp := &omaha.Response{}
	err = xml.Unmarshal(body, oresp)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return version
	}

	if oresp.Apps[0].UpdateCheck.Status == "noupdate" {
		return version
	} else if oresp.Apps[0].UpdateCheck.Status == "error-version" {
		return version
	}

	newVersion := oresp.Apps[0].UpdateCheck.Manifest.Version

	return newVersion
}

func runCmd(cmdName string, args []string, version string, oldVersion string, appID string) {
	cmd := exec.Command(cmdName, args...)

	env := os.Environ()
	env = append(env, "UPDATE_SERVICE_VERSION="+version)
	if oldVersion != "" {
		env = append(env, "UPDATE_SERVICE_OLD_VERSION="+oldVersion)
	}
	env = append(env, "UPDATE_SERVICE_APP_ID="+appID)
	cmd.Env = env

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	err = cmd.Start()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	go io.Copy(os.Stdout, stdout)
	go io.Copy(os.Stderr, stderr)
	cmd.Wait()
}

func watch(c *cli.Context, service *update.Service, out *tabwriter.Writer) {
	tick := time.NewTicker(time.Second * time.Duration(c.Int("interval")))
	server := c.GlobalString("server")
	debug := c.GlobalBool("debug")
	version := c.String("version")
	args := c.Args()

	if len(args) < 4 {
		log.Fatalf("appID, groupID and clientID required")
	}

	appID := args[0]
	groupID := args[1]
	clientID := args[2]

	// TODO: Have a better way of asking omaha for whatever version
	version = fetchVersion(server, appID, groupID, clientID, version, debug)
	runCmd(args[3], args[4:], version, "", appID)

	for {
		select {
		case <-tick.C:
			newVersion := fetchVersion(server, appID, groupID, clientID, version, debug)
			if newVersion != version {
				runCmd(args[3], args[4:], newVersion, version, appID)
			}
			version = newVersion
		}
	}

	tick.Stop()
}
<commit_msg>feat(watch): add UPDATE_SERVICE_URL<commit_after>package main

import (
	"bytes"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"text/tabwriter"
	"time"

	"github.com/coreos-inc/updatectl/third_party/code.google.com/p/go-uuid/uuid"
	"github.com/coreos-inc/updatectl/third_party/github.com/codegangsta/cli"
	"github.com/coreos-inc/updatectl/third_party/github.com/coreos/go-omaha/omaha"

	"github.com/coreos-inc/updatectl/client/update/v1"
)

func WatchCommands() []cli.Command {
	return []cli.Command{
		{
			Name:        "watch",
			Usage:       "watch [OPTION]... <appID> <groupID> <clientID> <cmd> <args>",
			Description: `Watch for app versions and exec a script`,
			Action:      handle(watch),
			Flags: []cli.Flag{
				cli.IntFlag{"interval, i", 1, "Update polling interval"},
				cli.StringFlag{"version, v", "0.0.0", "Starting version number"},
			},
		},
	}
}

func fetchUpdateCheck(server string, appID string, groupID string, clientID string, version string, debug bool) (*omaha.UpdateCheck, error) {
	client := &http.Client{}

	// TODO: Fill out the OS field correctly based on /etc/os-release
	request := omaha.NewRequest("lsb", "CoreOS", "", "")
	app := request.AddApp(fmt.Sprintf("{%s}", appID), version)
	app.AddUpdateCheck()
	app.MachineID = clientID
	app.BootId = uuid.New()
	app.Track = groupID

	event := app.AddEvent()
	event.Type = "1"
	event.Result = "0"

	raw, err := xml.MarshalIndent(request, "", " ")
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return nil, err
	}

	if debug {
		fmt.Fprintf(os.Stderr, "Request: %s%s\n", xml.Header, raw)
	}

	resp, err := client.Post(server+"/v1/update/", "text/xml", bytes.NewReader(raw))
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return nil, err
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return nil, err
	}

	if debug {
		fmt.Fprintf(os.Stderr, "Response: %s%s\n", xml.Header, string(body))
	}

	oresp := &omaha.Response{}
	err = xml.Unmarshal(body, oresp)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return nil, err
	}

	return oresp.Apps[0].UpdateCheck, nil
}

func prepareEnvironment(appID string, version string, oldVersion string, updateCheck *omaha.UpdateCheck) []string {
	env := os.Environ()
	env = append(env, "UPDATE_SERVICE_VERSION="+version)
	if oldVersion != "" {
		env = append(env, "UPDATE_SERVICE_OLD_VERSION="+oldVersion)
	}
	env = append(env, "UPDATE_SERVICE_APP_ID="+appID)
	env = append(env, "UPDATE_SERVICE_URL="+updateCheck.Urls.Urls[0].CodeBase)
	return env
}

func runCmd(cmdName string, args []string, appID string, version string, oldVersion string, updateCheck *omaha.UpdateCheck) {
	cmd := exec.Command(cmdName, args...)
	cmd.Env = prepareEnvironment(appID, version, oldVersion, updateCheck)

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	err = cmd.Start()
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	go io.Copy(os.Stdout, stdout)
	go io.Copy(os.Stderr, stderr)
	cmd.Wait()
}

func watch(c *cli.Context, service *update.Service, out *tabwriter.Writer) {
	tick := time.NewTicker(time.Second * time.Duration(c.Int("interval")))
	server := c.GlobalString("server")
	debug := c.GlobalBool("debug")
	version := c.String("version")
	args := c.Args()

	if len(args) < 4 {
		log.Fatalf("appID, groupID and clientID required")
	}

	appID := args[0]
	groupID := args[1]
	clientID := args[2]

	// initial check
	updateCheck, err := fetchUpdateCheck(server, appID, groupID, clientID, version, debug)
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	runCmd(args[3], args[4:], appID, version, "", updateCheck)

	for {
		select {
		case <-tick.C:

			updateCheck, err := fetchUpdateCheck(server, appID, groupID, clientID, version, debug)
			if err != nil {
				fmt.Fprintf(os.Stderr, err.Error())
				os.Exit(1)
			}

			if updateCheck.Status == "noupdate" {
				continue
			} else if updateCheck.Status == "error-version" {
				continue
			}

			newVersion := updateCheck.Manifest.Version

			if newVersion != version {
				runCmd(args[3], args[4:], appID, newVersion, version, updateCheck)
			}
			version = newVersion
		}
	}

	tick.Stop()
}
<|endoftext|>


<commit_before>package dagr

import (
	"bytes"
	"io"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"
)

const (
	minBufferCapacity = 128
	maxBufferCapacity = 65000
)

func allocMinimumBuffer() *tempBuffer {
	return &tempBuffer{bytes.NewBuffer(make([]byte, 0, minBufferCapacity)), true, 0}
}

type tempBuffer struct {
	*bytes.Buffer
	owned bool
	head  int64
}

var _ = (io.Writer)((*tempBuffer)(nil))
var _ = (io.WriterTo)((*tempBuffer)(nil))

func (t *tempBuffer) WriteTo(w io.Writer) (int64, error) {
	diffWriters := true
	if b, ok := w.(*bytes.Buffer); ok {
		diffWriters = b != t.Buffer
	}

	if diffWriters {
		return t.Buffer.WriteTo(w)
	}

	// If we're writing to an unowned buffer, just return how much we wrote to the buffer.
	n := int64(t.Len())
	if n < t.head {
		// Panic if the buffer was truncated to somewhere before head. This case is supposedly impossible for
		// owned buffers, since their heads are always 0 and their lengths are never < 0.
		panic("tempBuffer: head > buffer length - buffer was truncated during write")
	}

	return n - t.head, nil
}

var tempBuffers = sync.Pool{
	New: func() interface{} { return allocMinimumBuffer() },
}

func getBuffer(w io.Writer) *tempBuffer {
	if b, ok := w.(*bytes.Buffer); b != nil && ok {
		return &tempBuffer{b, false, int64(b.Len())}
	}

	if b, ok := tempBuffers.Get().(*tempBuffer); ok {
		return b
	}

	// Bizzaro case: tempBuffers.New didn't work? Something should've panicked by now.
	return allocMinimumBuffer()
}

func putBuffer(b *tempBuffer) {
	if !b.owned {
		return
	}

	b.head = 0
	b.Reset()

	tempBuffers.Put(b)
}

var tagEscaper = strings.NewReplacer(
	` `, `\ `,
	`=`, `\=`,
	`,`, `\,`,
)

func writeFields(buf *tempBuffer, fields Fields, names []string) error {
	for i, name := range names {
		field := fields[name]
		if i > 0 {
			buf.WriteByte(',')
		}
		buf.WriteString(tagEscaper.Replace(name))
		buf.WriteByte('=')

		// On the off chance that the field reports an error writing, we have to be careful with it and truncate
		// the buffer we got back to where the write started so we can leave the buffer sort of intact.
		if _, err := field.WriteTo(buf); err != nil {
			// This has the potential to panic IFF the buffer is being messed with from multiple goroutines.
			return err
		}
	}

	return nil
}

func writeTags(buf *tempBuffer, tags Tags, names []string) {
	for _, name := range names {
		tag := tags[name]
		buf.WriteByte(',') // Because tags must necessarily follow a key or tag, always include the comma
		buf.WriteString(tagEscaper.Replace(name))
		buf.WriteByte('=')
		buf.WriteString(tagEscaper.Replace(tag))
	}
}

// WriteMeasurement writes a single measurement, m, to w. It returns the number of bytes written and any error that
// occurred when writing the measurement.
//
// When writing tags and fields, both are sorted by name in ascending order. So, a tag named "pid" will precede a tag
// named "version", and a field name "depth" will precede a field named "value".
//
// If the measurement has no fields, it returns 0 and ErrNoFields.
//
// If the measurement implements io.WriterTo, this simply calls that instead of WriteMeasurement.
func WriteMeasurement(w io.Writer, m Measurement) (n int64, err error) {
	buf := getBuffer(w)
	defer putBuffer(buf)

	if mw, ok := m.(io.WriterTo); ok {
		n, err := mw.WriteTo(buf)
		if err != nil {
			return n, err
		}
		return buf.WriteTo(w)
	}

	var when time.Time
	if m, ok := m.(TimeMeasurement); ok {
		when = m.Time()
	} else {
		when = clock.Now()
	}

	tags := m.Tags()
	fields := m.Fields()

	if len(fields) == 0 {
		return 0, ErrNoFields
	}

	// Write key
	buf.WriteString(m.Key())

	nameLen := len(tags)
	if l := len(fields); l > nameLen {
		nameLen = l
	}
	names := make([]string, 0, nameLen)

	// Write tags
	if len(tags) > 0 {
		for name := range tags {
			names = append(names, name)
		}
		sort.Strings(names)
		writeTags(buf, tags, names)

		// Reset names slice so we can sort field names
		names = names[0:0]
	}

	// Write fields
	for name := range fields {
		names = append(names, name)
	}
	sort.Strings(names)
	buf.WriteByte(' ')
	if err := writeFields(buf, fields, names); err != nil {
		buf.Truncate(int(buf.head))
		return 0, err
	}

	buf.WriteByte(' ')
	writeTimestamp(buf, when)
	buf.WriteByte('\n')

	return buf.WriteTo(w)
}

func writeTimestamp(w io.Writer, ts time.Time) (n int64, err error) {
	var buf [20]byte
	tsb := strconv.AppendInt(buf[0:0], ts.UnixNano(), 10)
	in, err := w.Write(tsb)
	return int64(in), err
}

func writeByte(w io.Writer, b byte) error {
	if bw, ok := w.(io.ByteWriter); ok {
		return bw.WriteByte(b)
	}

	buf := [1]byte{b}
	n, err := w.Write(buf[0:1])
	if err == nil && n == 0 {
		err = io.ErrShortWrite
	}
	return err
}
<commit_msg>Fix getBuffer/WriteTo not knowing about tempBuffers<commit_after>package dagr

import (
	"bytes"
	"io"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"
)

const (
	minBufferCapacity = 128
	maxBufferCapacity = 65000
)

func allocMinimumBuffer() *tempBuffer {
	return &tempBuffer{bytes.NewBuffer(make([]byte, 0, minBufferCapacity)), true, 0}
}

type tempBuffer struct {
	*bytes.Buffer
	owned bool
	head  int64
}

var _ = (io.Writer)((*tempBuffer)(nil))
var _ = (io.WriterTo)((*tempBuffer)(nil))

func (t *tempBuffer) WriteTo(w io.Writer) (int64, error) {
	w = getWriter(w)

	diffWriters := true
	if b, ok := w.(*bytes.Buffer); ok {
		diffWriters = b != t.Buffer
	}

	if diffWriters {
		return t.Buffer.WriteTo(w)
	}

	// If we're writing to an unowned buffer, just return how much we wrote to the buffer.
	n := int64(t.Len())
	if n < t.head {
		// Panic if the buffer was truncated to somewhere before head. This case is supposedly impossible for
		// owned buffers, since their heads are always 0 and their lengths are never < 0.
		panic("dagr: tempBuffer.WriteTo: head > buffer length - buffer was truncated during write")
	}

	return n - t.head, nil
}

var tempBuffers = sync.Pool{
	New: func() interface{} { return allocMinimumBuffer() },
}

// getWriter unwrap a *tempBuffer and returns its underlying *bytes.Buffer. This is to ensure we can test if two writers
// are the same in a tempBuffer.WriteTo call and skip the write, because not doing so would be weird. If w is not
// a *tempBuffer, it returns w. If w is a *tempBuffer and it's nil, getWriter panics.
func getWriter(w io.Writer) io.Writer {
	if tb, ok := w.(*tempBuffer); ok {
		if tb == nil {
			panic("dagr: getBuffer: target tempBuffer is nil")
		}
		return tb.Buffer
	}

	return w
}

func getBuffer(w io.Writer) *tempBuffer {
	w = getWriter(w)
	// If either is nil, something will eventually panic, so we might as well do it here
	switch w := w.(type) {
	case *bytes.Buffer:
		if w == nil {
			panic("dagr: getBuffer: target *bytes.Buffer is nil")
		}
		return &tempBuffer{w, false, int64(w.Len())}
	}

	if b, ok := tempBuffers.Get().(*tempBuffer); ok {
		return b
	}

	// Bizzaro case: tempBuffers.New didn't work? Something should've panicked by now.
	return allocMinimumBuffer()
}

func putBuffer(b *tempBuffer) {
	if !b.owned {
		return
	}

	b.head = 0
	b.Reset()

	tempBuffers.Put(b)
}

var tagEscaper = strings.NewReplacer(
	` `, `\ `,
	`=`, `\=`,
	`,`, `\,`,
)

func writeFields(buf *tempBuffer, fields Fields, names []string) error {
	for i, name := range names {
		field := fields[name]
		if i > 0 {
			buf.WriteByte(',')
		}
		buf.WriteString(tagEscaper.Replace(name))
		buf.WriteByte('=')

		// On the off chance that the field reports an error writing, we have to be careful with it and truncate
		// the buffer we got back to where the write started so we can leave the buffer sort of intact.
		if _, err := field.WriteTo(buf); err != nil {
			// This has the potential to panic IFF the buffer is being messed with from multiple goroutines.
			return err
		}
	}

	return nil
}

func writeTags(buf *tempBuffer, tags Tags, names []string) {
	for _, name := range names {
		tag := tags[name]
		buf.WriteByte(',') // Because tags must necessarily follow a key or tag, always include the comma
		buf.WriteString(tagEscaper.Replace(name))
		buf.WriteByte('=')
		buf.WriteString(tagEscaper.Replace(tag))
	}
}

// WriteMeasurement writes a single measurement, m, to w. It returns the number of bytes written and any error that
// occurred when writing the measurement.
//
// When writing tags and fields, both are sorted by name in ascending order. So, a tag named "pid" will precede a tag
// named "version", and a field name "depth" will precede a field named "value".
//
// If the measurement has no fields, it returns 0 and ErrNoFields.
//
// If the measurement implements io.WriterTo, this simply calls that instead of WriteMeasurement.
func WriteMeasurement(w io.Writer, m Measurement) (n int64, err error) {
	buf := getBuffer(w)
	defer putBuffer(buf)

	if mw, ok := m.(io.WriterTo); ok {
		n, err := mw.WriteTo(buf)
		if err != nil {
			return n, err
		}
		return buf.WriteTo(w)
	}

	var when time.Time
	if m, ok := m.(TimeMeasurement); ok {
		when = m.Time()
	} else {
		when = clock.Now()
	}

	tags := m.Tags()
	fields := m.Fields()

	if len(fields) == 0 {
		return 0, ErrNoFields
	}

	// Write key
	buf.WriteString(m.Key())

	nameLen := len(tags)
	if l := len(fields); l > nameLen {
		nameLen = l
	}
	names := make([]string, 0, nameLen)

	// Write tags
	if len(tags) > 0 {
		for name := range tags {
			names = append(names, name)
		}
		sort.Strings(names)
		writeTags(buf, tags, names)

		// Reset names slice so we can sort field names
		names = names[0:0]
	}

	// Write fields
	for name := range fields {
		names = append(names, name)
	}
	sort.Strings(names)
	buf.WriteByte(' ')
	if err := writeFields(buf, fields, names); err != nil {
		buf.Truncate(int(buf.head))
		return 0, err
	}

	buf.WriteByte(' ')
	writeTimestamp(buf, when)
	buf.WriteByte('\n')

	return buf.WriteTo(w)
}

func writeTimestamp(w io.Writer, ts time.Time) (n int64, err error) {
	var buf [20]byte
	tsb := strconv.AppendInt(buf[0:0], ts.UnixNano(), 10)
	in, err := w.Write(tsb)
	return int64(in), err
}

func writeByte(w io.Writer, b byte) error {
	if bw, ok := w.(io.ByteWriter); ok {
		return bw.WriteByte(b)
	}

	buf := [1]byte{b}
	n, err := w.Write(buf[0:1])
	if err == nil && n == 0 {
		err = io.ErrShortWrite
	}
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"container/heap"
	"flag"
	"fmt"
	"github.com/syndtr/goleveldb/leveldb"
	"github.com/syndtr/goleveldb/leveldb/opt"
	"log"
	"os"
	"runtime/pprof"
	"strings"
)

const DEBUG = false

// Parses a ghi and emits the label of each stmt on out, followed by an empty
// sentinel.
func parseInterface(fn string, out chan *Entry) {
	file, err := os.Open(fn)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Can't open interface %s: %v\n", fn, err)
		os.Exit(-1)
	}
	scanner := NewScanner(file)
	for scanner.Scan() {
		_ = scanner.Text()
		e := scanner.Entry()
		if DEBUG {
			fmt.Fprintf(os.Stderr, "Axiom: %s\n%s\n%s\n",
				e.Fact.Skin.Name, e.Key, e.Fact)
		}
		out <- e
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintf(os.Stderr, "Scanner error: %v", err)
		panic(err)
	}
	out <- nil
}

func parseInterfaces(interfaces []string) map[string]*Entry {
	out := make(map[string]*Entry)
	ch := make(chan *Entry)
	jobs := 0
	for _, interfaceFn := range interfaces {
		if len(interfaceFn) > 0 {
			go parseInterface(interfaceFn, ch)
			jobs++
		}
	}
	for jobs > 0 {
		axiom := <-ch
		if axiom != nil {
			out[axiom.MarkStr()] = axiom
		} else {
			jobs--
		}
	}
	return out
}

// Given a depmap of entries, return a compact prooflist with duplicates removed
// (each duplicated entry only keeps the last copy); also returns the number of
// ungrounded stmts in the output. The given entry st will be prepended.
func compactify(st *Entry, groundSet map[string]*Entry,
	depMap map[string][]*Entry) (out []*Entry, stmts int) {
	stmts = 0
	out = make([]*Entry, 0)
	seen := make(map[string]bool)
	for _, es := range depMap {
		for i := range es {
			e := es[len(es)-i-1]
			if !seen[e.Key] {
				seen[e.Key] = true
				out = append(out, e)
				if (len(e.Fact.Deps()) == 0) &&
					(groundSet[e.Fact.Skin.Name] != nil) {
					stmts++
				}
			}
		}
	}
	out = append(out, st)
	// Reverse out
	for i, j := 0, len(out)-1; i < j; i, j = i+1, j-1 {
		out[i], out[j] = out[j], out[i]
	}
	return out, stmts
}

func churn(db *leveldb.DB, groundBones map[string][]*Entry,
	drafts *DraftHeap) *Draft {
	//draftsSeen := make(map[string]bool)
	laps := 0
	for len(*drafts) > 0 {
		draft := heap.Pop(drafts).(*Draft)
		mark, ok := draft.TopNeed()
		if !ok {
			panic("No need!?")
		}
		bone := mark.BoneKey()
		needers := make([]*Draft, 1) // TODO: scan for other drafts needing this
		needers[0] = draft
		if DEBUG {
			fmt.Fprintf(os.Stderr, "%s (%f) needs %v\n", "draft", draft.Score,
				mark.String())
		}
		// First check axioms in the groundSet
		for _, v := range groundBones[bone] {
			//TODO:PICKUP: need to disallow conflating ground terms
			if DEBUG {
				fmt.Fprintf(os.Stderr, "Ground Using %s = %s ",
					v.MarkStr()[len(bone):], v.Fact.Skin.Name)
			}
			newDraft := draft.AddEntry(mark, v)
			if newDraft != nil {
				heap.Push(drafts, newDraft)
				if DEBUG {
					fmt.Fprintf(os.Stderr, "==> %f\n", newDraft.Score)
				}
				if _, ok := newDraft.TopNeed(); !ok {
					return newDraft
				}
			} else {
				if DEBUG {
					fmt.Fprintf(os.Stderr, "==> Nil!\n")
				}
			}
		}
		// Then check proved theorems
		resolved := make(chan *Entry, 100)
		GetFactsByPrefix(db, bone, resolved)

		for e := range resolved {
			if len(e.Fact.Deps()) > 0 {
				if DEBUG {
					fmt.Fprintf(os.Stderr, "Using %s = %s ",
						e.MarkStr()[len(bone):], e.Fact.Skin.Name)
				}
				for _, d := range needers {
					newDraft := d.AddEntry(mark, e)
					if newDraft != nil {
						if _, ok := newDraft.TopNeed(); !ok {
							return newDraft
						}
						//hash := newDraft.Hash()
						if true { //!draftsSeen[hash] {
							//draftsSeen[hash] = true
							if DEBUG {
								fmt.Fprintf(os.Stderr, "==> %f\n",
									newDraft.Score)
							}
							heap.Push(drafts, newDraft)
						} else {
							// TODO: this never seems to happen in practice...
							fmt.Fprintf(os.Stderr, "==> Already Seen!\n")
						}
					} else {
						if DEBUG {
							fmt.Fprintf(os.Stderr, "==> Nil!\n")
						}
					}
				}
			}
		}
		laps += 1
		if laps > 4000 {
			fmt.Fprintf(os.Stderr, "Too many laps, giving up!")
			return nil
		}
		fmt.Fprintf(os.Stderr, "\nDrafts length: %d\n", drafts.Len())
	}
	fmt.Fprintf(os.Stderr, "Out of drafts!")
	return nil
}
func main() {
	dbPath := flag.String("d", "facts.leveldb", "path to facts.leveldb")
	imports := flag.String("i", "", "comma-separated list of .ghi imports")
	exports := flag.String("e", "", "comma-separated list of .ghi exports")
	flag.Parse()
	opt := opt.Options{ErrorIfMissing: true}
	db, err := leveldb.OpenFile(*dbPath, &opt)
	if err != nil {
		fmt.Print(err)
		os.Exit(-1)
	}
	defer db.Close()
	importList := strings.Split(*imports, ",")
	exportList := strings.Split(*exports, ",")
	groundSet := parseInterfaces(importList)
	targets := parseInterfaces(exportList)
	groundBones := make(map[string][]*Entry)
	for k, e := range groundSet {
		arr := groundBones[BonePrefix(k)]
		arr = append(arr, e)
		groundBones[BonePrefix(k)] = arr
	}

	draft := new(Draft)
	for _, e := range targets {
		targetMark := e.Mark()
		if DEBUG {
			fmt.Fprintf(os.Stderr, "Target: %s\n%s\n%s\n%v\n",
				e.Fact.Skin.Name, e.Key, e.Fact, e.Mark())
		}
		draft = draft.AddTarget(targetMark)
	}
	drafts := new(DraftHeap)
	heap.Init(drafts)
	heap.Push(drafts, draft)

	cpu, err := os.Create("pprof-cpu.txt")
	if err != nil {
		log.Fatal("Couldn't create pprof.txt! ", err)
	}
	heap, err := os.Create("pprof-heap.txt")
	if err != nil {
		log.Fatal("Couldn't create pprof.txt! ", err)
	}
	pprof.StartCPUProfile(cpu)
	winner := churn(db, groundBones, drafts)
	pprof.StopCPUProfile()
	cpu.Close()
	pprof.WriteHeapProfile(heap)
	heap.Close()

	fmt.Fprintf(os.Stderr, "\nResult: %s\n", winner)
	if winner == nil {
		os.Exit(-1)
	}
	for _, imp := range importList {
		fmt.Printf("import (%s %s () \"\")\n", imp, imp)
	}
	_, err = WriteProofs(os.Stdout, winner.Flatten(), targets, winner.Bind)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(-1)
	}

	for _, exp := range exportList {
		fmt.Printf("export (%s %s () \"\")\n", exp, exp)
	}

	os.Exit(0)
}
<commit_msg>Guard profiling by flag. Default on.<commit_after>package main

import (
	"container/heap"
	"flag"
	"fmt"
	"github.com/syndtr/goleveldb/leveldb"
	"github.com/syndtr/goleveldb/leveldb/opt"
	"log"
	"os"
	"runtime/pprof"
	"strings"
)

const DEBUG = false

// Parses a ghi and emits the label of each stmt on out, followed by an empty
// sentinel.
func parseInterface(fn string, out chan *Entry) {
	file, err := os.Open(fn)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Can't open interface %s: %v\n", fn, err)
		os.Exit(-1)
	}
	scanner := NewScanner(file)
	for scanner.Scan() {
		_ = scanner.Text()
		e := scanner.Entry()
		if DEBUG {
			fmt.Fprintf(os.Stderr, "Axiom: %s\n%s\n%s\n",
				e.Fact.Skin.Name, e.Key, e.Fact)
		}
		out <- e
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintf(os.Stderr, "Scanner error: %v", err)
		panic(err)
	}
	out <- nil
}

func parseInterfaces(interfaces []string) map[string]*Entry {
	out := make(map[string]*Entry)
	ch := make(chan *Entry)
	jobs := 0
	for _, interfaceFn := range interfaces {
		if len(interfaceFn) > 0 {
			go parseInterface(interfaceFn, ch)
			jobs++
		}
	}
	for jobs > 0 {
		axiom := <-ch
		if axiom != nil {
			out[axiom.MarkStr()] = axiom
		} else {
			jobs--
		}
	}
	return out
}

// Given a depmap of entries, return a compact prooflist with duplicates removed
// (each duplicated entry only keeps the last copy); also returns the number of
// ungrounded stmts in the output. The given entry st will be prepended.
func compactify(st *Entry, groundSet map[string]*Entry,
	depMap map[string][]*Entry) (out []*Entry, stmts int) {
	stmts = 0
	out = make([]*Entry, 0)
	seen := make(map[string]bool)
	for _, es := range depMap {
		for i := range es {
			e := es[len(es)-i-1]
			if !seen[e.Key] {
				seen[e.Key] = true
				out = append(out, e)
				if (len(e.Fact.Deps()) == 0) &&
					(groundSet[e.Fact.Skin.Name] != nil) {
					stmts++
				}
			}
		}
	}
	out = append(out, st)
	// Reverse out
	for i, j := 0, len(out)-1; i < j; i, j = i+1, j-1 {
		out[i], out[j] = out[j], out[i]
	}
	return out, stmts
}

func churn(db *leveldb.DB, groundBones map[string][]*Entry,
	drafts *DraftHeap) *Draft {
	//draftsSeen := make(map[string]bool)
	laps := 0
	for len(*drafts) > 0 {
		draft := heap.Pop(drafts).(*Draft)
		mark, ok := draft.TopNeed()
		if !ok {
			panic("No need!?")
		}
		bone := mark.BoneKey()
		needers := make([]*Draft, 1) // TODO: scan for other drafts needing this
		needers[0] = draft
		if DEBUG {
			fmt.Fprintf(os.Stderr, "%s (%f) needs %v\n", "draft", draft.Score,
				mark.String())
		}
		// First check axioms in the groundSet
		for _, v := range groundBones[bone] {
			//TODO:PICKUP: need to disallow conflating ground terms
			if DEBUG {
				fmt.Fprintf(os.Stderr, "Ground Using %s = %s ",
					v.MarkStr()[len(bone):], v.Fact.Skin.Name)
			}
			newDraft := draft.AddEntry(mark, v)
			if newDraft != nil {
				heap.Push(drafts, newDraft)
				if DEBUG {
					fmt.Fprintf(os.Stderr, "==> %f\n", newDraft.Score)
				}
				if _, ok := newDraft.TopNeed(); !ok {
					return newDraft
				}
			} else {
				if DEBUG {
					fmt.Fprintf(os.Stderr, "==> Nil!\n")
				}
			}
		}
		// Then check proved theorems
		resolved := make(chan *Entry, 100)
		GetFactsByPrefix(db, bone, resolved)

		for e := range resolved {
			if len(e.Fact.Deps()) > 0 {
				if DEBUG {
					fmt.Fprintf(os.Stderr, "Using %s = %s ",
						e.MarkStr()[len(bone):], e.Fact.Skin.Name)
				}
				for _, d := range needers {
					newDraft := d.AddEntry(mark, e)
					if newDraft != nil {
						if _, ok := newDraft.TopNeed(); !ok {
							return newDraft
						}
						//hash := newDraft.Hash()
						if true { //!draftsSeen[hash] {
							//draftsSeen[hash] = true
							if DEBUG {
								fmt.Fprintf(os.Stderr, "==> %f\n",
									newDraft.Score)
							}
							heap.Push(drafts, newDraft)
						} else {
							// TODO: this never seems to happen in practice...
							fmt.Fprintf(os.Stderr, "==> Already Seen!\n")
						}
					} else {
						if DEBUG {
							fmt.Fprintf(os.Stderr, "==> Nil!\n")
						}
					}
				}
			}
		}
		laps += 1
		if laps > 4000 {
			fmt.Fprintf(os.Stderr, "Too many laps, giving up!")
			return nil
		}
		fmt.Fprintf(os.Stderr, "Drafts length: %d\n", drafts.Len())
	}
	fmt.Fprintf(os.Stderr, "Out of drafts!")
	return nil
}
func main() {
	dbPath := flag.String("d", "facts.leveldb", "path to facts.leveldb")
	imports := flag.String("i", "", "comma-separated list of .ghi imports")
	exports := flag.String("e", "", "comma-separated list of .ghi exports")
	prof := flag.Bool("prof", true, "do profiling?")
	flag.Parse()
	opt := opt.Options{ErrorIfMissing: true}
	db, err := leveldb.OpenFile(*dbPath, &opt)
	if err != nil {
		fmt.Print(err)
		os.Exit(-1)
	}
	defer db.Close()
	importList := strings.Split(*imports, ",")
	exportList := strings.Split(*exports, ",")
	groundSet := parseInterfaces(importList)
	targets := parseInterfaces(exportList)
	groundBones := make(map[string][]*Entry)
	for k, e := range groundSet {
		arr := groundBones[BonePrefix(k)]
		arr = append(arr, e)
		groundBones[BonePrefix(k)] = arr
	}

	draft := new(Draft)
	for _, e := range targets {
		targetMark := e.Mark()
		if DEBUG {
			fmt.Fprintf(os.Stderr, "Target: %s\n%s\n%s\n%v\n",
				e.Fact.Skin.Name, e.Key, e.Fact, e.Mark())
		}
		draft = draft.AddTarget(targetMark)
	}
	drafts := new(DraftHeap)
	heap.Init(drafts)
	heap.Push(drafts, draft)

	var cpu, heap *os.File
	if *prof {
		cpu, err = os.Create("pprof-cpu.txt")
		if err != nil {
			log.Fatal("Couldn't create pprof.txt! ", err)
		}
		heap, err = os.Create("pprof-heap.txt")
		if err != nil {
			log.Fatal("Couldn't create pprof.txt! ", err)
		}
		pprof.StartCPUProfile(cpu)
	}
	winner := churn(db, groundBones, drafts)
	if *prof {
		pprof.StopCPUProfile()
		pprof.WriteHeapProfile(heap)
		cpu.Close()
		heap.Close()
	}
	fmt.Fprintf(os.Stderr, "\nResult: %s\n", winner)
	if winner == nil {
		os.Exit(-1)
	}
	for _, imp := range importList {
		fmt.Printf("import (%s %s () \"\")\n", imp, imp)
	}
	_, err = WriteProofs(os.Stdout, winner.Flatten(), targets, winner.Bind)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(-1)
	}

	for _, exp := range exportList {
		fmt.Printf("export (%s %s () \"\")\n", exp, exp)
	}

	os.Exit(0)
}
<|endoftext|>


<commit_before>package badger

import (
	"fmt"
	"strings"
)

type Query interface {
	perform(coll *Collection) docSet
	String() string
}

type allQuery struct {
}

// NewAllQuery returns a query which matches all docs
func NewAllQuery() Query {
	return &allQuery{}
}

func (q *allQuery) String() string {
	return "<ALL>"
}

func (q *allQuery) perform(coll *Collection) docSet {
	return coll.findAll()
}

//
type exactQuery struct {
	field  string
	values []string
}

// NewExactQuery returns a query to match a field exactly (but still case insensitively)
// If multiple values are given, then a match against _any_ of the values is sufficient for the
// document to be matched (ie the values can be considered to be separated by ORs rather than ANDs)
func NewExactQuery(field string, values ...string) Query {
	for i, _ := range values {
		values[i] = strings.ToLower(values[i])
	}
	return &exactQuery{field: field, values: values}
}

func (q *exactQuery) String() string {
	// TODO
	return q.field + ":blahblah"
}

func (q *exactQuery) perform(coll *Collection) docSet {
	return coll.find(q.field, func(foo string) bool {
		foo = strings.ToLower(foo)
		for _, v := range q.values {
			if foo == v {
				return true
			}
		}
		return false
	})
}

type containsQuery struct {
	field  string
	values []string
}

// NewContainsQuery finds docs with field containing the value
func NewContainsQuery(field, value string) Query {
	return &containsQuery{field: field, values: []string{strings.ToLower(value)}}
}

func (q *containsQuery) String() string {
	// TODO
	if len(q.values) == 1 {
		return fmt.Sprintf(`%s:%s`, q.field, q.values[0])
	} else {
		return fmt.Sprintf(`%s: IN %v`, q.field, q.values)
	}
}

func (q *containsQuery) perform(coll *Collection) docSet {
	return coll.find(q.field, func(foo string) bool {
		foo = strings.ToLower(foo)
		for _, v := range q.values {
			if strings.Contains(foo, v) {
				return true
			}
		}

		return false
	})
}

type notQuery struct {
	subQuery Query
}

// NewNOTQuery returns everything that doesn't match subquery q
func NewNOTQuery(q Query) Query {
	return &notQuery{subQuery: q}
}
func (q *notQuery) String() string {
	return "-" + q.subQuery.String()
}

func (q *notQuery) perform(coll *Collection) docSet {
	out := coll.findAll()
	out.Subtract(q.subQuery.perform(coll))
	return out
}

type orQuery struct {
	left, right Query
}

// NewORQuery returns a boolean OR of two subqueries
func NewORQuery(left, right Query) Query {
	return &orQuery{left: left, right: right}
}
func (q *orQuery) String() string {
	return "(" + q.left.String() + " OR " + q.right.String() + ")"
}

func (q *orQuery) perform(coll *Collection) docSet {
	a := q.left.perform(coll)
	b := q.right.perform(coll)
	return Union(a, b)
}

type andQuery struct {
	left, right Query
}

// NewANDQuery returns a boolean AND of two subqueries
func NewANDQuery(left, right Query) Query {
	return &andQuery{left: left, right: right}
}

func (q *andQuery) String() string {
	return "(" + q.left.String() + " AND " + q.right.String() + ")"
}

func (q *andQuery) perform(coll *Collection) docSet {
	a := q.left.perform(coll)
	b := q.right.perform(coll)
	return Intersect(a, b)
}

type rangeQuery struct {
	field, first, last string
}

// NewRangeQuery returns a query to match docs with field values within
// inclusive range [first,last]
func NewRangeQuery(field, first, last string) Query {
	return &rangeQuery{field: field, first: strings.ToLower(first), last: strings.ToLower(last)}
}

func (q *rangeQuery) String() string {
	return q.field + ": [" + q.first + " TO " + q.last + "]"
}

func (q *rangeQuery) perform(coll *Collection) docSet {
	return coll.find(q.field, func(foo string) bool {
		foo = strings.ToLower(foo)
		// TODO: handle dates better!
		return foo >= q.first && foo <= q.last
	})
}
<commit_msg>add special-case compare for date ranges<commit_after>package badger

import (
	"fmt"
	"regexp"
	"strings"
)

type Query interface {
	perform(coll *Collection) docSet
	String() string
}

type allQuery struct {
}

// NewAllQuery returns a query which matches all docs
func NewAllQuery() Query {
	return &allQuery{}
}

func (q *allQuery) String() string {
	return "<ALL>"
}

func (q *allQuery) perform(coll *Collection) docSet {
	return coll.findAll()
}

//
type exactQuery struct {
	field  string
	values []string
}

// NewExactQuery returns a query to match a field exactly (but still case insensitively)
// If multiple values are given, then a match against _any_ of the values is sufficient for the
// document to be matched (ie the values can be considered to be separated by ORs rather than ANDs)
func NewExactQuery(field string, values ...string) Query {
	for i, _ := range values {
		values[i] = strings.ToLower(values[i])
	}
	return &exactQuery{field: field, values: values}
}

func (q *exactQuery) String() string {
	// TODO
	return q.field + ":blahblah"
}

func (q *exactQuery) perform(coll *Collection) docSet {
	return coll.find(q.field, func(foo string) bool {
		foo = strings.ToLower(foo)
		for _, v := range q.values {
			if foo == v {
				return true
			}
		}
		return false
	})
}

type containsQuery struct {
	field  string
	values []string
}

// NewContainsQuery finds docs with field containing the value
func NewContainsQuery(field, value string) Query {
	return &containsQuery{field: field, values: []string{strings.ToLower(value)}}
}

func (q *containsQuery) String() string {
	// TODO
	if len(q.values) == 1 {
		return fmt.Sprintf(`%s:%s`, q.field, q.values[0])
	} else {
		return fmt.Sprintf(`%s: IN %v`, q.field, q.values)
	}
}

func (q *containsQuery) perform(coll *Collection) docSet {
	return coll.find(q.field, func(foo string) bool {
		foo = strings.ToLower(foo)
		for _, v := range q.values {
			if strings.Contains(foo, v) {
				return true
			}
		}

		return false
	})
}

type notQuery struct {
	subQuery Query
}

// NewNOTQuery returns everything that doesn't match subquery q
func NewNOTQuery(q Query) Query {
	return &notQuery{subQuery: q}
}
func (q *notQuery) String() string {
	return "-" + q.subQuery.String()
}

func (q *notQuery) perform(coll *Collection) docSet {
	out := coll.findAll()
	out.Subtract(q.subQuery.perform(coll))
	return out
}

type orQuery struct {
	left, right Query
}

// NewORQuery returns a boolean OR of two subqueries
func NewORQuery(left, right Query) Query {
	return &orQuery{left: left, right: right}
}
func (q *orQuery) String() string {
	return "(" + q.left.String() + " OR " + q.right.String() + ")"
}

func (q *orQuery) perform(coll *Collection) docSet {
	a := q.left.perform(coll)
	b := q.right.perform(coll)
	return Union(a, b)
}

type andQuery struct {
	left, right Query
}

// NewANDQuery returns a boolean AND of two subqueries
func NewANDQuery(left, right Query) Query {
	return &andQuery{left: left, right: right}
}

func (q *andQuery) String() string {
	return "(" + q.left.String() + " AND " + q.right.String() + ")"
}

func (q *andQuery) perform(coll *Collection) docSet {
	a := q.left.perform(coll)
	b := q.right.perform(coll)
	return Intersect(a, b)
}

type rangeKind int

const (
	str rangeKind = iota
	date
)

type rangeQuery struct {
	kind               rangeKind
	field, first, last string
}

// NewRangeQuery returns a query to match docs with field values within
// inclusive range [first,last]
func NewRangeQuery(field, first, last string) Query {
	datePat := regexp.MustCompile(`^\d{4}-\d{2}-\d{2}$`)

	var kind rangeKind
	if first == "" && last == "" {
		kind = str
	} else if first == "" && datePat.MatchString(last) {
		kind = date
	} else if last == "" && datePat.MatchString(first) {
		kind = date
	} else if datePat.MatchString(first) && datePat.MatchString(last) {
		kind = date
	}

	return &rangeQuery{kind: kind, field: field, first: strings.ToLower(first), last: strings.ToLower(last)}
}

func (q *rangeQuery) String() string {
	return q.field + ": [" + q.first + " TO " + q.last + "]"
}

var dateExtractPat *regexp.Regexp = regexp.MustCompile(`\d{4}-\d{2}-\d{2}`)

func (q *rangeQuery) perform(coll *Collection) docSet {
	if q.kind == str {
		// straight string compare
		return coll.find(q.field, func(foo string) bool {
			foo = strings.ToLower(foo)
			return foo >= q.first && foo <= q.last
		})
	} else {
		// date compare
		return coll.find(q.field, func(foo string) bool {
			foo = dateExtractPat.FindString(foo)
			return foo >= q.first && foo <= q.last
		})
	}
}
<|endoftext|>


<commit_before>package xql

import (
    "errors"
    log "github.com/Sirupsen/logrus"
    "reflect"
    "database/sql"
)

func (qc QueryColumn) String(as...bool) string {
    s := ""
    if qc.Function != "" {
        s = qc.Function+"("+qc.FieldName+")"
    }else{
        s = qc.FieldName
    }
    if qc.Alias != "" && len(as)>0 && as[0] {
        s = s + " AS " + qc.Alias
    }
    return s
}

type QuerySet struct {
    session *Session
    table   *Table
    queries []QueryColumn
    filters []QueryFilter
    orders  []QueryOrder
    offset  int64
    limit   int64
}

type XRow struct {
    row *sql.Row
    qs *QuerySet
}

func (self *XRow) Scan(dest ...interface{}) error {
    if nil == self.row {
        return errors.New("Nil row.")
    }
    if len(dest) < 1 {
        panic("Empty output!")
    }
    if len(dest) == 1 {
        d := dest[0]
        if reflect.TypeOf(d) == reflect.TypeOf(self.qs.table.Entity) {
            var outputs []interface{}
            r := reflect.ValueOf(d)
            for _, qc := range self.qs.queries {
                c, _ := self.qs.table.Columns[qc.FieldName]
                vp := r.Elem().FieldByName(c.PropertyName).Addr().Interface()
                outputs = append(outputs, vp)
            }
            return self.row.Scan(outputs...)
        }
    }
    return self.row.Scan(dest...)
}

type XRows struct {
    rows *sql.Rows
    qs *QuerySet
}

func (self *XRows) Scan(dest ...interface{}) error {
    if nil == self.rows {
        return errors.New("No rows.")
    }
    if len(dest) < 1 {
        panic("Empty output!")
    }
    if len(dest) == 1 {
        d := dest[0]
        if reflect.TypeOf(d) == reflect.TypeOf(self.qs.table.Entity) {
            var outputs []interface{}
            r := reflect.ValueOf(d)
            for _, qc := range self.qs.queries {
                c, _ := self.qs.table.Columns[qc.FieldName]
                vp := r.Elem().FieldByName(c.PropertyName).Addr().Interface()
                outputs = append(outputs, vp)
            }
            return self.rows.Scan(outputs...)
        }
    }
    return self.rows.Scan(dest...)
}

func (self *XRows) Next() bool {
    if nil == self.rows {
        return false
    }
    return self.rows.Next()
}

func (self *XRows) Close() {
    self.rows.Close()
    self.rows = nil
}

func makeQueryOrder(table *Table, s string) QueryOrder {
    qo := QueryOrder{}
    if s[:1] == "-" {
        qo.Type = ORDER_DESC
        qo.Field = s[1:]
    } else {
        qo.Type = ORDER_ASC
        qo.Field = s
    }
    return qo
}

func (self *QuerySet) Filter(cons ...interface{}) *QuerySet {
    for _, con := range cons {
        if vs, ok := con.(string); ok {
            self.filters = append(self.filters, QueryFilter{
                Field: vs,
            })
        }else if vm, ok := con.(map[string]interface{}); ok {
            for k, v := range vm {
                self.filters = append(self.filters, QueryFilter{
                    Field:k,
                    Value:v,
                    Operator: "=",
                })
            }
        }else if vf, ok := con.(QueryFilter); ok {
            self.filters = append(self.filters, vf)
        }
    }
    return self
}

func (self *QuerySet) OrderBy(orders ...interface{}) *QuerySet {
    for _, x := range orders {
        switch x.(type) {
        case string:
            qo := makeQueryOrder(self.table, x.(string))
            self.orders = append(self.orders, qo)
        case QueryOrder:
            self.orders = append(self.orders, x.(QueryOrder))
        default:
            panic("Not supported parameter type.")
        }
    }
    return self
}

func (self *QuerySet) Offset(offset int64) *QuerySet {
    self.offset = offset
    return self
}

func (self *QuerySet) Limit(limit int64) *QuerySet {
    self.limit = limit
    return self
}

func (self *QuerySet) Count(cols...string) (int64,error) {
    s, args, err := self.session.getStatementBuilder().Select(self.table,
        []QueryColumn{{Function:"COUNT", FieldName:"*"}},
        self.filters, nil, -1, -1)
    if nil != err {
        return 0, err
    }
    row := self.session.doQueryRow(s, args...)
    var n int64
    if e := row.Scan(&n); nil != e {
        return 0, e
    }
    return n, nil
}

func (self *QuerySet) All() (*XRows, error) {
    s, args, err := self.session.getStatementBuilder().Select(self.table, self.queries,
        self.filters, self.orders, self.offset, self.limit)
    if nil != err {
        return nil, err
    }
    rows, err := self.session.doQuery(s, args...)
    if nil != err {
        return nil, err
    }
    xrows := &XRows{rows:rows, qs:self}
    return xrows, nil
}

func (self *QuerySet) One() *XRow {
    s, args, err := self.session.getStatementBuilder().Select(self.table, self.queries,
        self.filters, self.orders, self.offset, 1)
    if nil != err {
        return nil
    }
    row := self.session.doQueryRow(s, args...)
    xrow := &XRow{row:row, qs:self}
    return xrow
}

func (self *QuerySet) Update(vals interface{}) (int64, error) {
    cols := []UpdateColumn{}
    if cm, ok := vals.(map[string]interface{}); ok {
        for k, v := range cm {
            uc := UpdateColumn{Field:k, Value:v, Operator:"="}
            cols = append(cols, uc)
        }
    }else if cx, ok := vals.([]UpdateColumn); ok {
        cols = cx
    }
    s, args, err := self.session.getStatementBuilder().Update(self.table, self.filters, cols...)
    if nil != err {
        return 0, err
    }
    var ret sql.Result
    ret, err = self.session.doExec(s, args...)
    if nil != err {
        return 0, err
    }else{
        rows, e := ret.RowsAffected()
        return rows, e
    }
    return 0, nil
}

func (self *QuerySet) Delete() (int64, error) {
    s, args, err := self.session.getStatementBuilder().Delete(self.table, self.filters)
    if nil != err {
        return 0, err
    }
    var ret sql.Result
    ret, err = self.session.doExec(s, args...)
    if nil != err {
        return 0, err
    }else{
        rows, e := ret.RowsAffected()
        return rows, e
    }
    return 0, nil
}

func (self *QuerySet) Insert(objs ...interface{}) (int64, error) {
    //log.Debugln("Insert:> ", objs)
    //log.Debugln("Table:> ", self.table)
    //var ret sql.Result
    var rows int64 = 0
    var cols []string
    if len(self.queries) > 0 {
        for _,x := range self.queries {
            cols = append(cols, x.FieldName)
        }
    }
    for _, obj := range objs {
        //log.Debugln("reflect.TypeOf(obj)>", reflect.TypeOf(obj))
        //log.Debugln("reflect.TypeOf(self.table.Entity)>", reflect.TypeOf(self.table.Entity))
        if reflect.TypeOf(obj) != reflect.TypeOf(self.table.Entity) {
           return 0, errors.New("Invalid data type.")
        }
        s, args, err := self.session.getStatementBuilder().Insert(self.table, obj, cols...)
        if nil != err {
            return 0, err
        }
        _, err = self.session.doExec(s, args...)
        if nil != err {
            return 0, err
        }else{
            //if nil != ret {
            //    n, e := ret.LastInsertId()
            //    if nil == e {
            //        rows += n
            //    }else{
            //        rows += 1
            //    }
            //    //log.Debugln("Insert:> ", n)
            //}else{
            //    rows += 1
            //}
            rows += 1
        }
    }
    return rows, nil
}
<commit_msg>Removed debug log.<commit_after>package xql

import (
    "errors"
    //log "github.com/Sirupsen/logrus"
    "reflect"
    "database/sql"
)

func (qc QueryColumn) String(as...bool) string {
    s := ""
    if qc.Function != "" {
        s = qc.Function+"("+qc.FieldName+")"
    }else{
        s = qc.FieldName
    }
    if qc.Alias != "" && len(as)>0 && as[0] {
        s = s + " AS " + qc.Alias
    }
    return s
}

type QuerySet struct {
    session *Session
    table   *Table
    queries []QueryColumn
    filters []QueryFilter
    orders  []QueryOrder
    offset  int64
    limit   int64
}

type XRow struct {
    row *sql.Row
    qs *QuerySet
}

func (self *XRow) Scan(dest ...interface{}) error {
    if nil == self.row {
        return errors.New("Nil row.")
    }
    if len(dest) < 1 {
        panic("Empty output!")
    }
    if len(dest) == 1 {
        d := dest[0]
        if reflect.TypeOf(d) == reflect.TypeOf(self.qs.table.Entity) {
            var outputs []interface{}
            r := reflect.ValueOf(d)
            for _, qc := range self.qs.queries {
                c, _ := self.qs.table.Columns[qc.FieldName]
                vp := r.Elem().FieldByName(c.PropertyName).Addr().Interface()
                outputs = append(outputs, vp)
            }
            return self.row.Scan(outputs...)
        }
    }
    return self.row.Scan(dest...)
}

type XRows struct {
    rows *sql.Rows
    qs *QuerySet
}

func (self *XRows) Scan(dest ...interface{}) error {
    if nil == self.rows {
        return errors.New("No rows.")
    }
    if len(dest) < 1 {
        panic("Empty output!")
    }
    if len(dest) == 1 {
        d := dest[0]
        if reflect.TypeOf(d) == reflect.TypeOf(self.qs.table.Entity) {
            var outputs []interface{}
            r := reflect.ValueOf(d)
            for _, qc := range self.qs.queries {
                c, _ := self.qs.table.Columns[qc.FieldName]
                vp := r.Elem().FieldByName(c.PropertyName).Addr().Interface()
                outputs = append(outputs, vp)
            }
            return self.rows.Scan(outputs...)
        }
    }
    return self.rows.Scan(dest...)
}

func (self *XRows) Next() bool {
    if nil == self.rows {
        return false
    }
    return self.rows.Next()
}

func (self *XRows) Close() {
    self.rows.Close()
    self.rows = nil
}

func makeQueryOrder(table *Table, s string) QueryOrder {
    qo := QueryOrder{}
    if s[:1] == "-" {
        qo.Type = ORDER_DESC
        qo.Field = s[1:]
    } else {
        qo.Type = ORDER_ASC
        qo.Field = s
    }
    return qo
}

func (self *QuerySet) Filter(cons ...interface{}) *QuerySet {
    for _, con := range cons {
        if vs, ok := con.(string); ok {
            self.filters = append(self.filters, QueryFilter{
                Field: vs,
            })
        }else if vm, ok := con.(map[string]interface{}); ok {
            for k, v := range vm {
                self.filters = append(self.filters, QueryFilter{
                    Field:k,
                    Value:v,
                    Operator: "=",
                })
            }
        }else if vf, ok := con.(QueryFilter); ok {
            self.filters = append(self.filters, vf)
        }
    }
    return self
}

func (self *QuerySet) OrderBy(orders ...interface{}) *QuerySet {
    for _, x := range orders {
        switch x.(type) {
        case string:
            qo := makeQueryOrder(self.table, x.(string))
            self.orders = append(self.orders, qo)
        case QueryOrder:
            self.orders = append(self.orders, x.(QueryOrder))
        default:
            panic("Not supported parameter type.")
        }
    }
    return self
}

func (self *QuerySet) Offset(offset int64) *QuerySet {
    self.offset = offset
    return self
}

func (self *QuerySet) Limit(limit int64) *QuerySet {
    self.limit = limit
    return self
}

func (self *QuerySet) Count(cols...string) (int64,error) {
    s, args, err := self.session.getStatementBuilder().Select(self.table,
        []QueryColumn{{Function:"COUNT", FieldName:"*"}},
        self.filters, nil, -1, -1)
    if nil != err {
        return 0, err
    }
    row := self.session.doQueryRow(s, args...)
    var n int64
    if e := row.Scan(&n); nil != e {
        return 0, e
    }
    return n, nil
}

func (self *QuerySet) All() (*XRows, error) {
    s, args, err := self.session.getStatementBuilder().Select(self.table, self.queries,
        self.filters, self.orders, self.offset, self.limit)
    if nil != err {
        return nil, err
    }
    rows, err := self.session.doQuery(s, args...)
    if nil != err {
        return nil, err
    }
    xrows := &XRows{rows:rows, qs:self}
    return xrows, nil
}

func (self *QuerySet) One() *XRow {
    s, args, err := self.session.getStatementBuilder().Select(self.table, self.queries,
        self.filters, self.orders, self.offset, 1)
    if nil != err {
        return nil
    }
    row := self.session.doQueryRow(s, args...)
    xrow := &XRow{row:row, qs:self}
    return xrow
}

func (self *QuerySet) Update(vals interface{}) (int64, error) {
    cols := []UpdateColumn{}
    if cm, ok := vals.(map[string]interface{}); ok {
        for k, v := range cm {
            uc := UpdateColumn{Field:k, Value:v, Operator:"="}
            cols = append(cols, uc)
        }
    }else if cx, ok := vals.([]UpdateColumn); ok {
        cols = cx
    }
    s, args, err := self.session.getStatementBuilder().Update(self.table, self.filters, cols...)
    if nil != err {
        return 0, err
    }
    var ret sql.Result
    ret, err = self.session.doExec(s, args...)
    if nil != err {
        return 0, err
    }else{
        rows, e := ret.RowsAffected()
        return rows, e
    }
    return 0, nil
}

func (self *QuerySet) Delete() (int64, error) {
    s, args, err := self.session.getStatementBuilder().Delete(self.table, self.filters)
    if nil != err {
        return 0, err
    }
    var ret sql.Result
    ret, err = self.session.doExec(s, args...)
    if nil != err {
        return 0, err
    }else{
        rows, e := ret.RowsAffected()
        return rows, e
    }
    return 0, nil
}

func (self *QuerySet) Insert(objs ...interface{}) (int64, error) {
    //log.Debugln("Insert:> ", objs)
    //log.Debugln("Table:> ", self.table)
    //var ret sql.Result
    var rows int64 = 0
    var cols []string
    if len(self.queries) > 0 {
        for _,x := range self.queries {
            cols = append(cols, x.FieldName)
        }
    }
    for _, obj := range objs {
        //log.Debugln("reflect.TypeOf(obj)>", reflect.TypeOf(obj))
        //log.Debugln("reflect.TypeOf(self.table.Entity)>", reflect.TypeOf(self.table.Entity))
        if reflect.TypeOf(obj) != reflect.TypeOf(self.table.Entity) {
           return 0, errors.New("Invalid data type.")
        }
        s, args, err := self.session.getStatementBuilder().Insert(self.table, obj, cols...)
        if nil != err {
            return 0, err
        }
        _, err = self.session.doExec(s, args...)
        if nil != err {
            return 0, err
        }else{
            //if nil != ret {
            //    n, e := ret.LastInsertId()
            //    if nil == e {
            //        rows += n
            //    }else{
            //        rows += 1
            //    }
            //    //log.Debugln("Insert:> ", n)
            //}else{
            //    rows += 1
            //}
            rows += 1
        }
    }
    return rows, nil
}
<|endoftext|>


<commit_before>package bigq

import (
	"errors"
	"fmt"
	"time"

	"google.golang.org/api/bigquery/v2"
)

type Config struct {
	DatasetID string
	ProjectID string
}

type Service struct {
	config  Config
	service *bigquery.Service
}

var errInvalidConfig = errors.New("dataset and project can not be empty")

func NewService(clientOptions ClientOptions, config Config) (*Service, error) {
	bqService, err := clientOptions.Service()
	if err != nil {
		return nil, err
	}

	if config.DatasetID == "" || config.ProjectID == "" {
		return nil, errInvalidConfig
	}

	return &Service{config, bqService}, nil
}

type Query struct {
	service     *bigquery.Service
	jobID       string
	projectID   string
	pageToken   string
	gotRows     uint64
	initialRows []*bigquery.TableRow
}

func (s *Service) Query(query string, args ...uint64) (*Query, error) {
	var start, maxResults uint64
	switch len(args) {
	case 0:
	case 2:
		maxResults = args[1]
		fallthrough
	case 1:
		start = args[0]
	default:
		return nil, fmt.Errorf("too many arguments given to query: %d", len(args))
	}

	req := &bigquery.QueryRequest{
		DefaultDataset: &bigquery.DatasetReference{
			DatasetId: s.config.DatasetID,
			ProjectId: s.config.ProjectID,
		},
		Query: query,
	}

	if maxResults > 0 {
		req.MaxResults = int64(maxResults)
	}

	resp, err := s.service.Jobs.Query(s.config.ProjectID, req).Do()
	if err != nil {
		return nil, err
	}

	var rows []*bigquery.TableRow
	if !resp.JobComplete {
		if err := s.waitForJob(resp.JobReference.JobId); err != nil {
			return nil, err
		}
	} else {
		rows = resp.Rows
	}

	return &Query{
		jobID:       resp.JobReference.JobId,
		projectID:   s.config.ProjectID,
		service:     s.service,
		gotRows:     start,
		initialRows: rows,
	}, nil
}

func (s *Service) waitForJob(jobID string) error {
	for {
		job, err := s.service.Jobs.Get(s.config.ProjectID, jobID).Do()
		if err != nil {
			return err
		}

		if job.Status.State == "DONE" {
			if job.Status.ErrorResult != nil {
				return errors.New(job.Status.ErrorResult.Message)
			}

			break
		}
		<-time.After(300 * time.Millisecond)
	}
	return nil
}

func (q *Query) GetNextPage() ([]*bigquery.TableRow, error) {
	if q.gotRows == 0 && len(q.initialRows) > 0 {
		q.gotRows += uint64(len(q.initialRows))
		return q.initialRows, nil
	}

	if len(q.initialRows) > 0 {
		q.initialRows = nil
	}

	call := q.service.Jobs.GetQueryResults(q.projectID, q.jobID)
	call.StartIndex(q.gotRows)
	if q.pageToken != "" {
		call.PageToken(q.pageToken)
	}

	results, err := call.Do()
	if err != nil {
		return nil, err
	}

	q.gotRows += uint64(len(results.Rows))
	if q.gotRows > results.TotalRows {
		return nil, nil
	}

	q.pageToken = results.PageToken
	return results.Rows, nil
}
<commit_msg>Transform rows<commit_after>package bigq

import (
	"errors"
	"fmt"
	"time"

	"google.golang.org/api/bigquery/v2"
)

type Config struct {
	DatasetID string
	ProjectID string
}

type Service struct {
	config  Config
	service *bigquery.Service
}

var errInvalidConfig = errors.New("dataset and project can not be empty")

func NewService(clientOptions ClientOptions, config Config) (*Service, error) {
	bqService, err := clientOptions.Service()
	if err != nil {
		return nil, err
	}

	if config.DatasetID == "" || config.ProjectID == "" {
		return nil, errInvalidConfig
	}

	return &Service{config, bqService}, nil
}

type Query struct {
	service     *bigquery.Service
	jobID       string
	projectID   string
	pageToken   string
	gotRows     uint64
	initialRows []*bigquery.TableRow
}

func (s *Service) Query(query string, args ...uint64) (*Query, error) {
	var start, maxResults uint64
	switch len(args) {
	case 0:
	case 2:
		maxResults = args[1]
		fallthrough
	case 1:
		start = args[0]
	default:
		return nil, fmt.Errorf("too many arguments given to query: %d", len(args))
	}

	req := &bigquery.QueryRequest{
		DefaultDataset: &bigquery.DatasetReference{
			DatasetId: s.config.DatasetID,
			ProjectId: s.config.ProjectID,
		},
		Query: query,
	}

	if maxResults > 0 {
		req.MaxResults = int64(maxResults)
	}

	resp, err := s.service.Jobs.Query(s.config.ProjectID, req).Do()
	if err != nil {
		return nil, err
	}

	var rows []*bigquery.TableRow
	if !resp.JobComplete {
		if err := s.waitForJob(resp.JobReference.JobId); err != nil {
			return nil, err
		}
	} else {
		rows = resp.Rows
	}

	return &Query{
		jobID:       resp.JobReference.JobId,
		projectID:   s.config.ProjectID,
		service:     s.service,
		gotRows:     start,
		initialRows: rows,
	}, nil
}

func (s *Service) waitForJob(jobID string) error {
	for {
		job, err := s.service.Jobs.Get(s.config.ProjectID, jobID).Do()
		if err != nil {
			return err
		}

		if job.Status.State == "DONE" {
			if job.Status.ErrorResult != nil {
				return errors.New(job.Status.ErrorResult.Message)
			}

			break
		}
		<-time.After(300 * time.Millisecond)
	}
	return nil
}

func (q *Query) GetNextPage() ([][]interface{}, error) {
	if q.gotRows == 0 && len(q.initialRows) > 0 {
		q.gotRows += uint64(len(q.initialRows))
		return transformRows(q.initialRows), nil
	}

	if len(q.initialRows) > 0 {
		q.initialRows = nil
	}

	call := q.service.Jobs.GetQueryResults(q.projectID, q.jobID)
	call.StartIndex(q.gotRows)
	if q.pageToken != "" {
		call.PageToken(q.pageToken)
	}

	results, err := call.Do()
	if err != nil {
		return nil, err
	}

	q.gotRows += uint64(len(results.Rows))
	if q.gotRows > results.TotalRows {
		return nil, nil
	}

	q.pageToken = results.PageToken
	return transformRows(results.Rows), nil
}

func transformRows(rows []*bigquery.TableRow) [][]interface{} {
	var result [][]interface{}
	for _, r := range rows {
		result = append(result, transformRow(r.F))
	}
	return result
}

func transformRow(row []*bigquery.TableCell) []interface{} {
	var result []interface{}
	for _, c := range row {
		result = append(result, c.V)
	}
	return result
}
<|endoftext|>