<commit_before>package aws

import (
	"fmt"
	"log"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/elb"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsElbAttachment() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsElbAttachmentCreate,
		Read:   resourceAwsElbAttachmentRead,
		Delete: resourceAwsElbAttachmentDelete,

		Schema: map[string]*schema.Schema{
			"elb": {
				Type:     schema.TypeString,
				ForceNew: true,
				Required: true,
			},

			"instance": {
				Type:     schema.TypeString,
				ForceNew: true,
				Required: true,
			},
		},
	}
}

func resourceAwsElbAttachmentCreate(d *schema.ResourceData, meta interface{}) error {
	elbconn := meta.(*AWSClient).elbconn
	elbName := d.Get("elb").(string)

	instance := d.Get("instance").(string)

	registerInstancesOpts := elb.RegisterInstancesWithLoadBalancerInput{
		LoadBalancerName: aws.String(elbName),
		Instances:        []*elb.Instance{{InstanceId: aws.String(instance)}},
	}

	log.Printf("[INFO] registering instance %s with ELB %s", instance, elbName)

	_, err := elbconn.RegisterInstancesWithLoadBalancer(&registerInstancesOpts)
	if err != nil {
		return fmt.Errorf("Failure registering instances with ELB: %s", err)
	}

	d.SetId(resource.PrefixedUniqueId(fmt.Sprintf("%s-", elbName)))

	return nil
}

func resourceAwsElbAttachmentRead(d *schema.ResourceData, meta interface{}) error {
	elbconn := meta.(*AWSClient).elbconn
	elbName := d.Get("elb").(string)

	// only add the instance that was previously defined for this resource
	expected := d.Get("instance").(string)

	// Retrieve the ELB properties to get a list of attachments
	describeElbOpts := &elb.DescribeLoadBalancersInput{
		LoadBalancerNames: []*string{aws.String(elbName)},
	}

	resp, err := elbconn.DescribeLoadBalancers(describeElbOpts)
	if err != nil {
		if isLoadBalancerNotFound(err) {
			log.Printf("[ERROR] ELB %s not found", elbName)
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error retrieving ELB: %s", err)
	}
	if len(resp.LoadBalancerDescriptions) != 1 {
		log.Printf("[ERROR] Unable to find ELB: %s", resp.LoadBalancerDescriptions)
		d.SetId("")
		return nil
	}

	// only set the instance Id that this resource manages
	found := false
	for _, i := range resp.LoadBalancerDescriptions[0].Instances {
		if expected == *i.InstanceId {
			d.Set("instance", expected)
			found = true
		}
	}

	if !found {
		log.Printf("[WARN] instance %s not found in elb attachments", expected)
		d.SetId("")
	}

	return nil
}

func resourceAwsElbAttachmentDelete(d *schema.ResourceData, meta interface{}) error {
	elbconn := meta.(*AWSClient).elbconn
	elbName := d.Get("elb").(string)

	instance := d.Get("instance").(string)

	log.Printf("[INFO] Deleting Attachment %s from: %s", instance, elbName)

	deRegisterInstancesOpts := elb.DeregisterInstancesFromLoadBalancerInput{
		LoadBalancerName: aws.String(elbName),
		Instances:        []*elb.Instance{{InstanceId: aws.String(instance)}},
	}

	_, err := elbconn.DeregisterInstancesFromLoadBalancer(&deRegisterInstancesOpts)
	if err != nil {
		return fmt.Errorf("Failure deregistering instances from ELB: %s", err)
	}

	return nil
}
<commit_msg>resource/aws_elb_attachment: Retry ELB attachment on `InvalidTarget` error (#8483)<commit_after>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/elb"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsElbAttachment() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsElbAttachmentCreate,
		Read:   resourceAwsElbAttachmentRead,
		Delete: resourceAwsElbAttachmentDelete,

		Schema: map[string]*schema.Schema{
			"elb": {
				Type:     schema.TypeString,
				ForceNew: true,
				Required: true,
			},

			"instance": {
				Type:     schema.TypeString,
				ForceNew: true,
				Required: true,
			},
		},
	}
}

func resourceAwsElbAttachmentCreate(d *schema.ResourceData, meta interface{}) error {
	elbconn := meta.(*AWSClient).elbconn
	elbName := d.Get("elb").(string)

	instance := d.Get("instance").(string)

	registerInstancesOpts := elb.RegisterInstancesWithLoadBalancerInput{
		LoadBalancerName: aws.String(elbName),
		Instances:        []*elb.Instance{{InstanceId: aws.String(instance)}},
	}

	log.Printf("[INFO] registering instance %s with ELB %s", instance, elbName)

	err := resource.Retry(10*time.Minute, func() *resource.RetryError {
		_, err := elbconn.RegisterInstancesWithLoadBalancer(&registerInstancesOpts)

		if isAWSErr(err, "InvalidTarget", "") {
			return resource.RetryableError(fmt.Errorf("Error attaching instance to ELB, retrying: %s", err))
		}

		if err != nil {
			return resource.NonRetryableError(err)
		}

		return nil
	})

	if err != nil {
		return fmt.Errorf("Failure registering instances with ELB: %s", err)
	}

	d.SetId(resource.PrefixedUniqueId(fmt.Sprintf("%s-", elbName)))

	return nil
}

func resourceAwsElbAttachmentRead(d *schema.ResourceData, meta interface{}) error {
	elbconn := meta.(*AWSClient).elbconn
	elbName := d.Get("elb").(string)

	// only add the instance that was previously defined for this resource
	expected := d.Get("instance").(string)

	// Retrieve the ELB properties to get a list of attachments
	describeElbOpts := &elb.DescribeLoadBalancersInput{
		LoadBalancerNames: []*string{aws.String(elbName)},
	}

	resp, err := elbconn.DescribeLoadBalancers(describeElbOpts)
	if err != nil {
		if isLoadBalancerNotFound(err) {
			log.Printf("[ERROR] ELB %s not found", elbName)
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error retrieving ELB: %s", err)
	}
	if len(resp.LoadBalancerDescriptions) != 1 {
		log.Printf("[ERROR] Unable to find ELB: %s", resp.LoadBalancerDescriptions)
		d.SetId("")
		return nil
	}

	// only set the instance Id that this resource manages
	found := false
	for _, i := range resp.LoadBalancerDescriptions[0].Instances {
		if expected == *i.InstanceId {
			d.Set("instance", expected)
			found = true
		}
	}

	if !found {
		log.Printf("[WARN] instance %s not found in elb attachments", expected)
		d.SetId("")
	}

	return nil
}

func resourceAwsElbAttachmentDelete(d *schema.ResourceData, meta interface{}) error {
	elbconn := meta.(*AWSClient).elbconn
	elbName := d.Get("elb").(string)

	instance := d.Get("instance").(string)

	log.Printf("[INFO] Deleting Attachment %s from: %s", instance, elbName)

	deRegisterInstancesOpts := elb.DeregisterInstancesFromLoadBalancerInput{
		LoadBalancerName: aws.String(elbName),
		Instances:        []*elb.Instance{{InstanceId: aws.String(instance)}},
	}

	_, err := elbconn.DeregisterInstancesFromLoadBalancer(&deRegisterInstancesOpts)
	if err != nil {
		return fmt.Errorf("Failure deregistering instances from ELB: %s", err)
	}

	return nil
}
<|endoftext|>


<commit_before>/*
   Copyright The containerd Authors.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package cache

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"

	"github.com/golang/groupcache/lru"
	"github.com/pkg/errors"
)

// TODO: contents validation.

type BlobCache interface {
	Fetch(blobHash string) ([]byte, error)
	Add(blobHash string, p []byte)
}

type dirOpt struct {
	syncAdd bool
}

type DirOption func(o *dirOpt) *dirOpt

func SyncAdd() DirOption {
	return func(o *dirOpt) *dirOpt {
		o.syncAdd = true
		return o
	}
}

func NewDirectoryCache(directory string, memCacheSize int, opts ...DirOption) (BlobCache, error) {
	opt := &dirOpt{}
	for _, o := range opts {
		opt = o(opt)
	}
	err := os.MkdirAll(directory, os.ModePerm)
	if err != nil {
		return nil, err
	}
	dc := &directoryCache{
		cache:     lru.New(memCacheSize),
		directory: directory,
	}
	if opt.syncAdd {
		dc.syncAdd = true
	}
	return dc, nil
}

// directoryCache is a cache implementation which backend is a directory.
type directoryCache struct {
	cache     *lru.Cache
	directory string
	syncAdd   bool
	mmu       sync.Mutex
	fmu       sync.Mutex
}

func (dc *directoryCache) Fetch(blobHash string) (p []byte, err error) {
	dc.mmu.Lock()
	defer dc.mmu.Unlock()

	if cache, ok := dc.cache.Get(blobHash); ok {
		p, ok := cache.([]byte)
		if ok {
			return p, nil
		}
	}

	c := filepath.Join(dc.directory, blobHash[:2], blobHash)
	if _, err := os.Stat(c); err != nil {
		return nil, errors.Wrapf(err, "Missed cache %q", c)
	}

	file, err := os.Open(c)
	if err != nil {
		return nil, errors.Wrapf(err, "Failed to Open cached blob file %q", c)
	}
	defer file.Close()

	if p, err = ioutil.ReadAll(file); err != nil && err != io.EOF {
		return nil, errors.Wrapf(err, "failed to read cached data %q", c)
	}
	dc.cache.Add(blobHash, p)

	return
}

func (dc *directoryCache) Add(blobHash string, p []byte) {
	dc.mmu.Lock()
	defer dc.mmu.Unlock()

	dc.cache.Add(blobHash, p)

	addFunc := func() {
		dc.fmu.Lock()
		defer dc.fmu.Unlock()

		// Check if cache exists.
		c := filepath.Join(dc.directory, blobHash[:2], blobHash)
		if _, err := os.Stat(c); err == nil {
			return
		}

		// Create cache file
		if err := os.MkdirAll(filepath.Dir(c), os.ModePerm); err != nil {
			fmt.Printf("Warning: Failed to Create blob cache directory %q: %v\n", c, err)
			return
		}
		f, err := os.Create(c)
		if err != nil {
			fmt.Printf("Warning: could not create a cache file at %q: %v\n", c, err)
			return
		}
		defer f.Close()
		if n, err := f.Write(p); err != nil || n != len(p) {
			fmt.Printf("Warning: failed to write cache: %d(wrote)/%d(expected): %v\n",
				n, len(p), err)
		}
	}

	if dc.syncAdd {
		addFunc()
	} else {
		go addFunc()
	}
}

func NewMemoryCache() BlobCache {
	return &memoryCache{
		membuf: map[string]string{},
	}
}

// memoryCache is a cache implementation which backend is a memory.
type memoryCache struct {
	membuf map[string]string // read-only []byte map is more ideal but we don't have it in golang...
	mu     sync.Mutex
}

func (mc *memoryCache) Fetch(blobHash string) ([]byte, error) {
	mc.mu.Lock()
	defer mc.mu.Unlock()

	cache, ok := mc.membuf[blobHash]
	if !ok {
		return nil, fmt.Errorf("Missed cache: %q", blobHash)
	}
	return []byte(cache), nil
}

func (mc *memoryCache) Add(blobHash string, p []byte) {
	mc.mu.Lock()
	defer mc.mu.Unlock()
	mc.membuf[blobHash] = string(p)
}
<commit_msg>Use reasonable name for mutexes in the cache<commit_after>/*
   Copyright The containerd Authors.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package cache

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"

	"github.com/golang/groupcache/lru"
	"github.com/pkg/errors"
)

// TODO: contents validation.

type BlobCache interface {
	Fetch(blobHash string) ([]byte, error)
	Add(blobHash string, p []byte)
}

type dirOpt struct {
	syncAdd bool
}

type DirOption func(o *dirOpt) *dirOpt

func SyncAdd() DirOption {
	return func(o *dirOpt) *dirOpt {
		o.syncAdd = true
		return o
	}
}

func NewDirectoryCache(directory string, memCacheSize int, opts ...DirOption) (BlobCache, error) {
	opt := &dirOpt{}
	for _, o := range opts {
		opt = o(opt)
	}
	if err := os.MkdirAll(directory, os.ModePerm); err != nil {
		return nil, err
	}
	dc := &directoryCache{
		cache:     lru.New(memCacheSize),
		directory: directory,
	}
	if opt.syncAdd {
		dc.syncAdd = true
	}
	return dc, nil
}

// directoryCache is a cache implementation which backend is a directory.
type directoryCache struct {
	cache     *lru.Cache
	cacheMu   sync.Mutex
	directory string
	syncAdd   bool
	fileMu    sync.Mutex
}

func (dc *directoryCache) Fetch(blobHash string) (p []byte, err error) {
	dc.cacheMu.Lock()
	defer dc.cacheMu.Unlock()

	if cache, ok := dc.cache.Get(blobHash); ok {
		p, ok := cache.([]byte)
		if ok {
			return p, nil
		}
	}

	c := filepath.Join(dc.directory, blobHash[:2], blobHash)
	if _, err := os.Stat(c); err != nil {
		return nil, errors.Wrapf(err, "Missed cache %q", c)
	}

	file, err := os.Open(c)
	if err != nil {
		return nil, errors.Wrapf(err, "Failed to Open cached blob file %q", c)
	}
	defer file.Close()

	if p, err = ioutil.ReadAll(file); err != nil && err != io.EOF {
		return nil, errors.Wrapf(err, "failed to read cached data %q", c)
	}
	dc.cache.Add(blobHash, p)

	return
}

func (dc *directoryCache) Add(blobHash string, p []byte) {
	dc.cacheMu.Lock()
	defer dc.cacheMu.Unlock()

	dc.cache.Add(blobHash, p)

	addFunc := func() {
		dc.fileMu.Lock()
		defer dc.fileMu.Unlock()

		// Check if cache exists.
		c := filepath.Join(dc.directory, blobHash[:2], blobHash)
		if _, err := os.Stat(c); err == nil {
			return
		}

		// Create cache file
		if err := os.MkdirAll(filepath.Dir(c), os.ModePerm); err != nil {
			fmt.Printf("Warning: Failed to Create blob cache directory %q: %v\n", c, err)
			return
		}
		f, err := os.Create(c)
		if err != nil {
			fmt.Printf("Warning: could not create a cache file at %q: %v\n", c, err)
			return
		}
		defer f.Close()
		if n, err := f.Write(p); err != nil || n != len(p) {
			fmt.Printf("Warning: failed to write cache: %d(wrote)/%d(expected): %v\n",
				n, len(p), err)
		}
	}

	if dc.syncAdd {
		addFunc()
	} else {
		go addFunc()
	}
}

func NewMemoryCache() BlobCache {
	return &memoryCache{
		membuf: map[string]string{},
	}
}

// memoryCache is a cache implementation which backend is a memory.
type memoryCache struct {
	membuf map[string]string // read-only []byte map is more ideal but we don't have it in golang...
	mu     sync.Mutex
}

func (mc *memoryCache) Fetch(blobHash string) ([]byte, error) {
	mc.mu.Lock()
	defer mc.mu.Unlock()

	cache, ok := mc.membuf[blobHash]
	if !ok {
		return nil, fmt.Errorf("Missed cache: %q", blobHash)
	}
	return []byte(cache), nil
}

func (mc *memoryCache) Add(blobHash string, p []byte) {
	mc.mu.Lock()
	defer mc.mu.Unlock()
	mc.membuf[blobHash] = string(p)
}
<|endoftext|>


<commit_before>package cache

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"os"
	"time"

	"github.com/STNS/STNS/stns"
	"github.com/STNS/libnss_stns/settings"
	_gocache "github.com/pyama86/go-cache"
)

var attrStore = _gocache.New(time.Second*settings.CACHE_TIME, 60*time.Second)
var lockStore = _gocache.New(time.Second*settings.LOCK_TIME, 60*time.Second)

var workDir = settings.WORK_DIR

type cacheObject struct {
	userGroup *stns.Attributes
	createAt  time.Time
	err       error
}

func SetWorkDir(path string) {
	workDir = path
}

func Read(path string) (stns.Attributes, error) {
	c, exist := attrStore.Get(path)
	if exist {
		co := c.(*cacheObject)
		if co.err != nil {
			return nil, co.err
		} else {
			return *co.userGroup, co.err
		}
	}
	return nil, nil
}

func Write(path string, attr stns.Attributes, err error) {
	attrStore.Set(path, &cacheObject{&attr, time.Now(), err}, _gocache.DefaultExpiration)
}

func ReadMinID(resourceType string) int {
	return readID(resourceType, "min")
}

func ReadMaxID(resourceType string) int {
	return readID(resourceType, "max")
}

func readID(resourceType, minMax string) int {
	n, exist := attrStore.Get(resourceType + "_" + minMax + "_id")
	if exist {
		id := n.(int)
		return id
	}
	return 0
}

func WriteID(resourceType, minMax string, id int) {
	attrStore.Set(resourceType+"_"+minMax+"_id", id, _gocache.DefaultExpiration)
}

func SaveResultList(resourceType string, list stns.Attributes) {
	j, err := json.Marshal(list)
	if err != nil {
		log.Println(err)
		return
	}

	if err := os.MkdirAll(workDir, 0777); err != nil {
		log.Println(err)
		return
	}
	f := workDir + "/.libnss_stns_" + resourceType + "_cache"

	if err := ioutil.WriteFile(f, j, os.ModePerm); err != nil {
		log.Println(err)
		return
	}

	os.Chmod(f, 0777)
}

func LastResultList(resourceType string) *stns.Attributes {
	var attr stns.Attributes
	f := workDir + "/.libnss_stns_" + resourceType + "_cache"

	if _, err := os.Stat(f); err == nil {
		f, err := ioutil.ReadFile(f)
		if err != nil {
			log.Println(err)
			return &attr
		}

		err = json.Unmarshal(f, &attr)
		if err != nil {
			log.Println(err)
		}
	}
	return &attr
}

func LockEndPoint(path string) {
	lockStore.Set(path+"_lock", true, _gocache.DefaultExpiration)

	err := lockStore.SaveFile(settings.LOCK_FILE)
	if err != nil {
		log.Printf("lock file write error:%s", err.Error())
	}

	os.Chmod(settings.LOCK_FILE, 0777)
}

func IsLockEndPoint(path string) bool {
	_, e1 := lockStore.Get(path + "_lock")
	if e1 {
		return true
	} else {
		err := lockStore.LoadFile(settings.LOCK_FILE)
		if err != nil {
			return false
		}

		_, e2 := lockStore.Get(path + "_lock")
		if e2 {
			return true
		}
	}
	return false
}

func Flush() {
	attrStore.Flush()
	lockStore.Flush()
}
<commit_msg>キャッシュのポーリングをやめることで不要なgoroutinを起動しない<commit_after>package cache

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"os"
	"time"

	"github.com/STNS/STNS/stns"
	"github.com/STNS/libnss_stns/settings"
	_gocache "github.com/pyama86/go-cache"
)

var attrStore = _gocache.New(time.Second*settings.CACHE_TIME, 0*time.Second)
var lockStore = _gocache.New(time.Second*settings.LOCK_TIME, 0*time.Second)

var workDir = settings.WORK_DIR

type cacheObject struct {
	userGroup *stns.Attributes
	createAt  time.Time
	err       error
}

func SetWorkDir(path string) {
	workDir = path
}

func Read(path string) (stns.Attributes, error) {
	c, exist := attrStore.Get(path)
	if exist {
		co := c.(*cacheObject)
		if co.err != nil {
			return nil, co.err
		} else {
			return *co.userGroup, co.err
		}
	}
	return nil, nil
}

func Write(path string, attr stns.Attributes, err error) {
	attrStore.Set(path, &cacheObject{&attr, time.Now(), err}, _gocache.DefaultExpiration)
}

func ReadMinID(resourceType string) int {
	return readID(resourceType, "min")
}

func ReadMaxID(resourceType string) int {
	return readID(resourceType, "max")
}

func readID(resourceType, minMax string) int {
	n, exist := attrStore.Get(resourceType + "_" + minMax + "_id")
	if exist {
		id := n.(int)
		return id
	}
	return 0
}

func WriteID(resourceType, minMax string, id int) {
	attrStore.Set(resourceType+"_"+minMax+"_id", id, _gocache.DefaultExpiration)
}

func SaveResultList(resourceType string, list stns.Attributes) {
	j, err := json.Marshal(list)
	if err != nil {
		log.Println(err)
		return
	}

	if err := os.MkdirAll(workDir, 0777); err != nil {
		log.Println(err)
		return
	}
	f := workDir + "/.libnss_stns_" + resourceType + "_cache"

	if err := ioutil.WriteFile(f, j, os.ModePerm); err != nil {
		log.Println(err)
		return
	}

	os.Chmod(f, 0777)
}

func LastResultList(resourceType string) *stns.Attributes {
	var attr stns.Attributes
	f := workDir + "/.libnss_stns_" + resourceType + "_cache"

	if _, err := os.Stat(f); err == nil {
		f, err := ioutil.ReadFile(f)
		if err != nil {
			log.Println(err)
			return &attr
		}

		err = json.Unmarshal(f, &attr)
		if err != nil {
			log.Println(err)
		}
	}
	return &attr
}

func LockEndPoint(path string) {
	lockStore.Set(path+"_lock", true, _gocache.DefaultExpiration)

	err := lockStore.SaveFile(settings.LOCK_FILE)
	if err != nil {
		log.Printf("lock file write error:%s", err.Error())
	}

	os.Chmod(settings.LOCK_FILE, 0777)
}

func IsLockEndPoint(path string) bool {
	_, e1 := lockStore.Get(path + "_lock")
	if e1 {
		return true
	} else {
		err := lockStore.LoadFile(settings.LOCK_FILE)
		if err != nil {
			return false
		}

		_, e2 := lockStore.Get(path + "_lock")
		if e2 {
			return true
		}
	}
	return false
}

func Flush() {
	attrStore.Flush()
	lockStore.Flush()
}
<|endoftext|>


<commit_before>package cache

import "github.com/garyburd/redigo/redis"

type bRedis struct {
	*redis.Pool
}

func NewRedis(ip string) *bRedis {
	if ip == "" {
		return nil
	}
	var pool = &redis.Pool{
		MaxIdle:   80,
		MaxActive: 12000, // max number of connections
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", ip)
			if err != nil {
				panic(err.Error())
			}
			return c, err
		},
	}

	cache := bRedis{
		Pool: pool,
	}
	return &cache
}

func (p *bRedis) HGETALL(key string) (mapper map[string]interface{}, err error) {
	c := p.Get()
	defer func() {
		c.Close()
	}()
	reply, err := c.Do("HGETALL", key)
	if err != nil {
		return
	}

	mapper = map[string]interface{}{}

	kvs := reply.([]interface{})

	for i := len(kvs) - 1; i >= 0; i = i - 2 {
		key := string(kvs[i-1].([]uint8))
		mapper[key] = kvs[i]
	}
	return
}

func (p *bRedis) MHSET(table string, mapper map[string]interface{}, expire int) error {
	params := []interface{}{}
	for key, value := range mapper {
		params = append(params, key, value)
	}

	params = append([]interface{}{table}, params...)
	c := p.Get()

	defer c.Close()

	_, err := c.Do("HMSET", params...)
	if err != nil {
		return err
	}
	if expire != 0 {
		c.Do("expire", table, expire)
	}

	return nil
}

func (p *bRedis) HMGETOne(tableName string, key string) (value string, err error) {
	c := p.Get()
	defer func() {
		c.Close()
	}()
	reply, err := c.Do("HMGET", tableName, key)
	if err != nil {
		return
	}

	ga := reply.([]interface{})[0]
	if ga != nil {
		value = string(ga.([]uint8))
	}
	return
}

func (p *bRedis) HMSET(tableName string, key string, value interface{}, expire int) (err error) {
	c := p.Get()
	defer func() {
		c.Close()
	}()
	_, err = c.Do("HMSET", tableName, key, value)
	if err != nil {
		return
	}
	if expire != 0 {
		c.Do("expire", key, expire)
	}

	return
}

func (p *bRedis) SET(key string, value interface{}, expire int) (err error) {
	c := p.Get()
	defer func() {
		c.Close()
	}()
	_, err = c.Do("SET", key, value)
	if err != nil {
		return
	}
	if expire != 0 {
		c.Do("expire", key, expire)
	}
	return
}

func (p *bRedis) GET(key string) (str string, err error) {
	c := p.Get()

	defer func() {
		c.Close()
	}()
	value, err := c.Do("GET", key)
	if err != nil {
		return
	}
	if value != nil {
		str = string(value.([]uint8))
	}
	return
}

func (p *bRedis) RPUSH(key string, value interface{}) (err error) {
	c := p.Get()

	defer func() {
		c.Close()
	}()

	_, err = c.Do("RPUSH", key, value)
	return
}

func (p *bRedis) DEL(key string) (err error) {
	c := p.Get()
	defer func() {
		c.Close()
	}()
	_, err = c.Do("DEL", key)
	if err != nil {
		return
	}
	return
}
<commit_msg>add redis.HDEL<commit_after>package cache

import "github.com/garyburd/redigo/redis"

type bRedis struct {
	*redis.Pool
}

func NewRedis(ip string) *bRedis {
	if ip == "" {
		return nil
	}
	var pool = &redis.Pool{
		MaxIdle:   80,
		MaxActive: 12000, // max number of connections
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", ip)
			if err != nil {
				panic(err.Error())
			}
			return c, err
		},
	}

	cache := bRedis{
		Pool: pool,
	}
	return &cache
}

func (p *bRedis) HGETALL(tableName string) (mapper map[string]interface{}, err error) {
	c := p.Get()
	defer func() {
		c.Close()
	}()
	reply, err := c.Do("HGETALL", tableName)
	if err != nil {
		return
	}

	mapper = map[string]interface{}{}

	kvs := reply.([]interface{})

	for i := len(kvs) - 1; i >= 0; i = i - 2 {
		key := string(kvs[i-1].([]uint8))
		mapper[key] = kvs[i]
	}
	return
}

func (p *bRedis) MHSET(table string, mapper map[string]interface{}, expire int) error {
	params := []interface{}{}
	for key, value := range mapper {
		params = append(params, key, value)
	}

	params = append([]interface{}{table}, params...)
	c := p.Get()

	defer c.Close()

	_, err := c.Do("HMSET", params...)
	if err != nil {
		return err
	}
	if expire != 0 {
		c.Do("expire", table, expire)
	}

	return nil
}

func (p *bRedis) HMGETOne(tableName string, key string) (value string, err error) {
	c := p.Get()
	defer func() {
		c.Close()
	}()
	reply, err := c.Do("HMGET", tableName, key)
	if err != nil {
		return
	}

	ga := reply.([]interface{})[0]
	if ga != nil {
		value = string(ga.([]uint8))
	}
	return
}

func (p *bRedis) HMSET(tableName string, key string, value interface{}, expire int) (err error) {
	c := p.Get()
	defer func() {
		c.Close()
	}()
	_, err = c.Do("HMSET", tableName, key, value)
	if err != nil {
		return
	}
	if expire != 0 {
		c.Do("expire", key, expire)
	}

	return
}

func (p *bRedis) SET(key string, value interface{}, expire int) (err error) {
	c := p.Get()
	defer func() {
		c.Close()
	}()
	_, err = c.Do("SET", key, value)
	if err != nil {
		return
	}
	if expire != 0 {
		c.Do("expire", key, expire)
	}
	return
}

func (p *bRedis) GET(key string) (str string, err error) {
	c := p.Get()

	defer func() {
		c.Close()
	}()
	value, err := c.Do("GET", key)
	if err != nil {
		return
	}
	if value != nil {
		str = string(value.([]uint8))
	}
	return
}

func (p *bRedis) RPUSH(key string, value interface{}) (err error) {
	c := p.Get()

	defer func() {
		c.Close()
	}()

	_, err = c.Do("RPUSH", key, value)
	return
}

func (p *bRedis) DEL(key string) (err error) {
	c := p.Get()
	defer func() {
		c.Close()
	}()
	_, err = c.Do("DEL", key)
	if err != nil {
		return
	}
	return
}

func (p *bRedis) HDEL(tableName string, keys ...string) (err error) {
	c := p.Get()
	defer func() {
		c.Close()
	}()

	ps := make([]interface{}, len(keys)+1)
	ps[0] = tableName
	for i,v:=range keys{
		ps[i+1] = v
	}

	_, err = c.Do("HDEL", ps...)
	if err != nil {
		return
	}
	return
}
<|endoftext|>


<commit_before>// cubied manages processes as per the cubie configuration manifest.
package main

import (
	"encoding/json"
	"flag"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"strings"
	"sync"
	"syscall"
	"time"

	"golang.org/x/sys/unix"
)

// PR_SET_CHILD_SUBREAPER is defined in <sys/prctl.h> for linux >= 3.4
const PR_SET_CHILD_SUBREAPER = 36

var (
	confDir = flag.String("conf", "/etc/cubie.d", "directory holding cubie configuration files")

	ctl = NewControl()
)

func main() {
	flag.Parse()

	log.Printf("::: starting cubie-daemon [%v]...\n", Version)

	if os.Getpid() != 1 {
		// try to register as a subreaper
		err := unix.Prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0)
		log.Printf("subreaper: %v\n", err == nil)
	}

	confs, err := filepath.Glob(filepath.Join(*confDir, "*.conf"))
	if err != nil {
		log.Fatalf("could not collect configuration files: %v\n", err)
	}

	for _, fname := range confs {
		f, err := os.Open(fname)
		if err != nil {
			log.Fatalf("could not open configuration file [%s]: %v\n", fname, err)
		}
		defer f.Close()

		var proc Process
		err = json.NewDecoder(f).Decode(&proc)
		if err != nil {
			log.Fatalf(
				"could not decode configuration file [%s]: %v\n",
				fname,
				err,
			)
		}

		ctl.procs = append(ctl.procs, &proc)
	}

	if flag.NArg() > 0 {
		ctl.cmd = newProcess(flag.Args()...)
	}

	go func() {
		sigch := make(chan os.Signal)
		signal.Notify(sigch, os.Interrupt, os.Kill)
		for {
			select {
			case <-sigch:
				err = ctl.killProcs()
				if err != nil {
					log.Fatalf("error killing managed processes: %v\n", err)
				}
			}
		}
	}()

	ctl.run()

	os.Exit(0)
}

type procKeyType int

var procKey procKeyType = 0

// Process represents a process to be launched and how it needs to be launched.
type Process struct {
	Cmd    string            // Cmd is the name of the command to be launched
	Args   []string          // Args holds command-line arguments, excluding the command name
	Env    map[string]string // Env specifies the environment of the command
	Dir    string            // Dir specifies the working directory of the command
	Daemon bool

	proc *exec.Cmd
	err  error
	quit chan struct{}
}

// newProcess creates a new Process from a command and its (optional) arguments.
func newProcess(cmd ...string) *Process {
	proc := &Process{
		Cmd: cmd[0],
	}

	if len(cmd) > 1 {
		proc.Args = append(proc.Args, cmd[1:]...)
	}

	return proc
}

func (p *Process) title() string {
	return strings.Join(p.proc.Args, " ")
}

func (p *Process) run(done chan *Process) {
	p.proc.SysProcAttr = &syscall.SysProcAttr{
		Setpgid: true,
	}

	defer func() { done <- p }()

	if !p.Daemon {
		log.Printf("running [%s]...\n", p.title())
		p.err = p.proc.Run()
		log.Printf("running [%s]... [done]\n", p.title())
	} else {
		log.Printf("starting [%s]...\n", p.title())
		p.err = p.proc.Start()
		if p.err != nil {
			return
		}

		p.err = p.proc.Wait()
		log.Printf("running [%s]... [done]\n", p.title())
	}
	return
}

// Control runs and manages processes.
type Control struct {
	pid   int
	cmd   *Process
	procs []*Process
	quit  chan struct{}
}

// NewControl creates a Control handle.
func NewControl() *Control {
	ctl := &Control{
		pid:   os.Getpid(),
		procs: make([]*Process, 0, 2),
		quit:  make(chan struct{}),
	}
	return ctl
}

// run runs all processes according to cubie configuration.
func (ctl *Control) run() {
	n := 0
	for _, p := range ctl.procs {
		if !p.Daemon {
			n++
		}
	}

	var wg sync.WaitGroup
	wg.Add(n)
	nprocs := ""
	if n > 1 {
		nprocs = "es"
	}
	log.Printf("starting %d go-process%s...\n", n, nprocs)

	go ctl.runProcs(&wg)
	wg.Wait()

	log.Printf("now running main go-process...\n")
	ctl.runCmd()
}

func (ctl *Control) setupProc(proc *Process) {
	proc.proc = exec.Command(proc.Cmd, proc.Args...)
	if len(proc.Env) > 0 {
		env := make([]string, 0, len(proc.Env))
		for k, v := range proc.Env {
			env = append(env, k+"="+v)
		}
		proc.proc.Env = env
	}

	if proc.Dir != "" {
		proc.proc.Dir = proc.Dir
	}

	proc.proc.Stdout = os.Stdout
	proc.proc.Stderr = os.Stderr
	proc.proc.Stdin = os.Stdin
}

func (ctl *Control) runProcs(wg *sync.WaitGroup) {

	done := make(chan *Process)
	for _, p := range ctl.procs {
		ctl.setupProc(p)
		go p.run(done)
	}

	sigch := make(chan os.Signal)
	signal.Notify(sigch, syscall.SIGCHLD)

reaploop:
	for {
		select {
		case <-ctl.quit:
			ctl.killProcs()
			return

		case <-sigch:
			const nretries = 1000
			var ws syscall.WaitStatus
			for i := 0; i < nretries; i++ {
				pid, err := syscall.Wait4(ctl.pid, &ws, syscall.WNOHANG, nil)
				// pid > 0 => pid is the ID of the child that died, but
				//  there could be other children that are signalling us
				//  and not the one we in particular are waiting for.
				// pid -1 && errno == ECHILD => no new status children
				// pid -1 && errno != ECHILD => syscall interupped by signal
				// pid == 0 => no more children to wait for.
				switch {
				case err != nil:
					continue reaploop
				case pid == ctl.pid:
					return
				case pid == 0:
					// this is what we get when SIGSTOP is sent on OSX. ws == 0 in this case.
					// Note that on OSX we never get a SIGCONT signal.
					// Under WNOHANG, pid == 0 means there is nobody left to wait for,
					// so just go back to waiting for another SIGCHLD.
					continue reaploop
				default:
					time.Sleep(time.Millisecond)
				}
			}
			log.Fatalf("failed to reap children after [%d] retries\n", nretries)

		case p := <-done:
			i := -1
			for j, pp := range ctl.procs {
				if pp == p {
					i = j
					break
				}
			}
			if i < 0 {
				panic("impossible")
			}

			nprocs := len(ctl.procs)
			ctl.procs[nprocs-1], ctl.procs = nil, append(ctl.procs[:i], ctl.procs[i+1:]...)
			ctl.procs = ctl.procs[:len(ctl.procs):len(ctl.procs)]
			wg.Done()
			if p.err != nil {
				ctl.killProcs()
				log.Fatalf("error running process [%v]: %v\n", p.title(), p.err)
			}
			if len(ctl.procs) <= 0 {
				return
			}
		}
	}
}

func (ctl *Control) runCmd() {
	if ctl.cmd == nil {
		return
	}
	done := make(chan *Process)
	ctl.setupProc(ctl.cmd)
	go ctl.cmd.run(done)

	for {
		select {
		case <-ctl.quit:
			ctl.killProcs()
			return

		case p := <-done:
			if p.err != nil {
				ctl.killProcs()
				log.Fatalf("error running process [%v]: %v\n", p.title(), p.err)
			}
			return
		}
	}
}

func (ctl *Control) killProcs() error {
	var err error
	for _, p := range ctl.procs {
		if p.proc == nil {
			continue
		}
		errp := killProc(p.proc.Process)
		if errp != nil && err != nil {
			err = errp
		}
	}
	if ctl.cmd != nil && ctl.cmd.proc != nil {
		errp := killProc(ctl.cmd.proc.Process)
		if err != nil && err != nil {
			err = errp
		}
	}
	return err
}

func killProc(p *os.Process) error {
	if p == nil {
		return nil
	}
	pgid, err := syscall.Getpgid(p.Pid)
	if err != nil {
		return err
	}
	err = syscall.Kill(-pgid, syscall.SIGKILL) // note the minus sign
	return err
}
<commit_msg>cubied: fix non-daemon processes<commit_after>// cubied manages processes as per the cubie configuration manifest.
package main

import (
	"encoding/json"
	"flag"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"strings"
	"sync"
	"syscall"
	"time"

	"golang.org/x/sys/unix"
)

// PR_SET_CHILD_SUBREAPER is defined in <sys/prctl.h> for linux >= 3.4
const PR_SET_CHILD_SUBREAPER = 36

var (
	confDir = flag.String("conf", "/etc/cubie.d", "directory holding cubie configuration files")

	ctl = NewControl()
)

func main() {
	flag.Parse()

	log.Printf("::: starting cubie-daemon [%v]...\n", Version)

	if os.Getpid() != 1 {
		// try to register as a subreaper
		err := unix.Prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0)
		log.Printf("subreaper: %v\n", err == nil)
	}

	confs, err := filepath.Glob(filepath.Join(*confDir, "*.conf"))
	if err != nil {
		log.Fatalf("could not collect configuration files: %v\n", err)
	}

	for _, fname := range confs {
		f, err := os.Open(fname)
		if err != nil {
			log.Fatalf("could not open configuration file [%s]: %v\n", fname, err)
		}
		defer f.Close()

		var proc Process
		err = json.NewDecoder(f).Decode(&proc)
		if err != nil {
			log.Fatalf(
				"could not decode configuration file [%s]: %v\n",
				fname,
				err,
			)
		}

		ctl.procs = append(ctl.procs, &proc)
	}

	if flag.NArg() > 0 {
		ctl.cmd = newProcess(flag.Args()...)
	}

	go func() {
		sigch := make(chan os.Signal)
		signal.Notify(sigch, os.Interrupt, os.Kill)
		for {
			select {
			case <-sigch:
				err = ctl.killProcs()
				if err != nil {
					log.Fatalf("error killing managed processes: %v\n", err)
				}
			}
		}
	}()

	ctl.run()

	os.Exit(0)
}

type procKeyType int

var procKey procKeyType = 0

// Process represents a process to be launched and how it needs to be launched.
type Process struct {
	Cmd    string            // Cmd is the name of the command to be launched
	Args   []string          // Args holds command-line arguments, excluding the command name
	Env    map[string]string // Env specifies the environment of the command
	Dir    string            // Dir specifies the working directory of the command
	Daemon bool

	proc *exec.Cmd
	err  error
	quit chan struct{}
}

// newProcess creates a new Process from a command and its (optional) arguments.
func newProcess(cmd ...string) *Process {
	proc := &Process{
		Cmd: cmd[0],
	}

	if len(cmd) > 1 {
		proc.Args = append(proc.Args, cmd[1:]...)
	}

	return proc
}

func (p *Process) title() string {
	return strings.Join(p.proc.Args, " ")
}

func (p *Process) run(done chan *Process) {
	if p.Daemon {
		p.proc.SysProcAttr = &syscall.SysProcAttr{
			Setpgid: true,
		}
	}

	defer func() { done <- p }()

	if !p.Daemon {
		log.Printf("running [%s]...\n", p.title())
		p.err = p.proc.Run()
		log.Printf("running [%s]... [done]\n", p.title())
	} else {
		log.Printf("starting [%s]...\n", p.title())
		p.err = p.proc.Start()
		if p.err != nil {
			return
		}

		p.err = p.proc.Wait()
		log.Printf("running [%s]... [done]\n", p.title())
	}
	return
}

// Control runs and manages processes.
type Control struct {
	pid   int
	cmd   *Process
	procs []*Process
	quit  chan struct{}
}

// NewControl creates a Control handle.
func NewControl() *Control {
	ctl := &Control{
		pid:   os.Getpid(),
		procs: make([]*Process, 0, 2),
		quit:  make(chan struct{}),
	}
	return ctl
}

// run runs all processes according to cubie configuration.
func (ctl *Control) run() {
	n := 0
	for _, p := range ctl.procs {
		if !p.Daemon {
			n++
		}
	}

	var wg sync.WaitGroup
	wg.Add(n)
	nprocs := ""
	if n > 1 {
		nprocs = "es"
	}
	log.Printf("starting %d go-process%s...\n", n, nprocs)

	go ctl.runProcs(&wg)
	wg.Wait()

	log.Printf("now running main go-process...\n")
	ctl.runCmd()
}

func (ctl *Control) setupProc(proc *Process) {
	proc.proc = exec.Command(proc.Cmd, proc.Args...)
	if len(proc.Env) > 0 {
		env := make([]string, 0, len(proc.Env))
		for k, v := range proc.Env {
			env = append(env, k+"="+v)
		}
		proc.proc.Env = env
	}

	if proc.Dir != "" {
		proc.proc.Dir = proc.Dir
	}

	proc.proc.Stdout = os.Stdout
	proc.proc.Stderr = os.Stderr
	proc.proc.Stdin = os.Stdin
}

func (ctl *Control) runProcs(wg *sync.WaitGroup) {

	done := make(chan *Process)
	for _, p := range ctl.procs {
		ctl.setupProc(p)
		go p.run(done)
	}

	sigch := make(chan os.Signal)
	signal.Notify(sigch, syscall.SIGCHLD)

reaploop:
	for {
		select {
		case <-ctl.quit:
			ctl.killProcs()
			return

		case <-sigch:
			const nretries = 1000
			var ws syscall.WaitStatus
			for i := 0; i < nretries; i++ {
				pid, err := syscall.Wait4(ctl.pid, &ws, syscall.WNOHANG, nil)
				// pid > 0 => pid is the ID of the child that died, but
				//  there could be other children that are signalling us
				//  and not the one we in particular are waiting for.
				// pid -1 && errno == ECHILD => no new status children
				// pid -1 && errno != ECHILD => syscall interupped by signal
				// pid == 0 => no more children to wait for.
				switch {
				case err != nil:
					continue reaploop
				case pid == ctl.pid:
					return
				case pid == 0:
					// this is what we get when SIGSTOP is sent on OSX. ws == 0 in this case.
					// Note that on OSX we never get a SIGCONT signal.
					// Under WNOHANG, pid == 0 means there is nobody left to wait for,
					// so just go back to waiting for another SIGCHLD.
					continue reaploop
				default:
					time.Sleep(time.Millisecond)
				}
			}
			log.Fatalf("failed to reap children after [%d] retries\n", nretries)

		case p := <-done:
			i := -1
			for j, pp := range ctl.procs {
				if pp == p {
					i = j
					break
				}
			}
			if i < 0 {
				panic("impossible")
			}

			nprocs := len(ctl.procs)
			ctl.procs[nprocs-1], ctl.procs = nil, append(ctl.procs[:i], ctl.procs[i+1:]...)
			ctl.procs = ctl.procs[:len(ctl.procs):len(ctl.procs)]
			wg.Done()
			if p.err != nil {
				ctl.killProcs()
				log.Fatalf("error running process [%v]: %v\n", p.title(), p.err)
			}
			if len(ctl.procs) <= 0 {
				return
			}
		}
	}
}

func (ctl *Control) runCmd() {
	if ctl.cmd == nil {
		return
	}
	done := make(chan *Process)
	ctl.setupProc(ctl.cmd)
	go ctl.cmd.run(done)

	for {
		select {
		case <-ctl.quit:
			ctl.killProcs()
			return

		case p := <-done:
			if p.err != nil {
				ctl.killProcs()
				log.Fatalf("error running process [%v]: %v\n", p.title(), p.err)
			}
			return
		}
	}
}

func (ctl *Control) killProcs() error {
	var err error
	for _, p := range ctl.procs {
		if p.proc == nil {
			continue
		}
		errp := killProc(p.proc.Process)
		if errp != nil && err != nil {
			err = errp
		}
	}
	if ctl.cmd != nil && ctl.cmd.proc != nil {
		errp := killProc(ctl.cmd.proc.Process)
		if err != nil && err != nil {
			err = errp
		}
	}
	return err
}

func killProc(p *os.Process) error {
	if p == nil {
		return nil
	}
	pgid, err := syscall.Getpgid(p.Pid)
	if err != nil {
		return err
	}
	err = syscall.Kill(-pgid, syscall.SIGKILL) // note the minus sign
	return err
}
<|endoftext|>


<commit_before>package daemon

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path"
	"sync"
	"syscall"

	"github.com/subgraph/oz"
	"github.com/subgraph/oz/network"
	"github.com/subgraph/oz/oz-init"
	"github.com/subgraph/oz/xpra"

	"crypto/rand"
	"encoding/hex"
	"github.com/op/go-logging"
	"github.com/subgraph/oz/fs"
	"os/user"
)

type Sandbox struct {
	daemon  *daemonState
	id      int
	display int
	profile *oz.Profile
	init    *exec.Cmd
	cred    *syscall.Credential
	fs      *fs.Filesystem
	stderr  io.ReadCloser
	addr    string
	xpra    *xpra.Xpra
	ready   sync.WaitGroup
	network *network.SandboxNetwork
}

func createSocketPath(base string) (string, error) {
	bs := make([]byte, 8)
	_, err := rand.Read(bs)
	if err != nil {
		return "", err
	}

	return path.Join(base, fmt.Sprintf("oz-init-control-%s", hex.EncodeToString(bs))), nil
}

func createInitCommand(initPath, name string, socketPath string, env []string, uid uint32, display int, stn *network.SandboxNetwork) *exec.Cmd {
	cmd := exec.Command(initPath)
	cmd.Dir = "/"

	cloneFlags := uintptr(syscall.CLONE_NEWNS)
	cloneFlags |= syscall.CLONE_NEWIPC
	cloneFlags |= syscall.CLONE_NEWPID
	cloneFlags |= syscall.CLONE_NEWUTS

	if stn.Nettype != network.TYPE_HOST {
		cloneFlags |= syscall.CLONE_NEWNET
	}

	cmd.SysProcAttr = &syscall.SysProcAttr{
		//Chroot:     chroot,
		Cloneflags: cloneFlags,
	}
	cmd.Env = []string{
		"INIT_PROFILE=" + name,
		"INIT_SOCKET=" + socketPath,
		fmt.Sprintf("INIT_UID=%d", uid),
	}

	if stn.Ip != "" {
		cmd.Env = append(cmd.Env, "INIT_ADDR="+stn.Ip)
		cmd.Env = append(cmd.Env, "INIT_VHOST="+stn.VethHost)
		cmd.Env = append(cmd.Env, "INIT_VGUEST="+stn.VethGuest)
		cmd.Env = append(cmd.Env, "INIT_GATEWAY="+stn.Gateway.String()+"/"+stn.Class)
	}

	cmd.Env = append(cmd.Env, fmt.Sprintf("INIT_DISPLAY=%d", display))

	for _, e := range env {
		cmd.Env = append(cmd.Env, ozinit.EnvPrefix+e)
	}

	return cmd
}

func (d *daemonState) launch(p *oz.Profile, msg *LaunchMsg, uid, gid uint32, log *logging.Logger) (*Sandbox, error) {

	/*
		u, err := user.LookupId(fmt.Sprintf("%d", uid))
		if err != nil {
			return nil, fmt.Errorf("failed to lookup user for uid=%d: %v", uid, err)
		}

		fs := fs.NewFromProfile(p, u, d.config.SandboxPath, d.config.UseFullDev, d.log)
		if err := fs.Setup(d.config.ProfileDir); err != nil {
			return nil, err
		}
	*/

	display := 0
	if p.XServer.Enabled && p.Networking.Nettype == network.TYPE_HOST {
		display = d.nextDisplay
		d.nextDisplay += 1
	}

	var err error
	stn := new(network.SandboxNetwork)
	stn.Nettype = p.Networking.Nettype
	if p.Networking.Nettype == network.TYPE_BRIDGE {
		stn, err = network.PrepareSandboxNetwork(d.network, log)
		if err != nil {
			return nil, fmt.Errorf("Unable to prepare veth network: %+v", err)
		}
	}

	socketPath, err := createSocketPath(path.Join(d.config.SandboxPath, "sockets"))
	if err != nil {
		return nil, fmt.Errorf("Failed to create random socket path: %v", err)
	}
	cmd := createInitCommand(d.config.InitPath, p.Name, socketPath, msg.Env, uid, display, stn)
	log.Debug("Command environment: %+v", cmd.Env)
	pp, err := cmd.StderrPipe()
	if err != nil {
		//fs.Cleanup()
		return nil, fmt.Errorf("error creating stderr pipe for init process: %v", err)

	}

	if err := cmd.Start(); err != nil {
		//fs.Cleanup()
		return nil, fmt.Errorf("Unable to start process: %+v", err)
	}

	//rootfs := path.Join(d.config.SandboxPath, "rootfs")
	sbox := &Sandbox{
		daemon:  d,
		id:      d.nextSboxId,
		display: display,
		profile: p,
		init:    cmd,
		cred:    &syscall.Credential{Uid: uid, Gid: gid},
		fs:      fs.NewFilesystem(d.config, log),
		//addr:    path.Join(rootfs, ozinit.SocketAddress),
		addr:    socketPath,
		stderr:  pp,
		network: stn,
	}

	if p.Networking.Nettype == network.TYPE_BRIDGE {
		if err := network.NetInit(stn, d.network, cmd.Process.Pid, log); err != nil {
			cmd.Process.Kill()
			//fs.Cleanup()
			return nil, fmt.Errorf("Unable to create veth networking: %+v", err)
		}
	}

	sbox.ready.Add(1)
	go sbox.logMessages()

	wgNet := new(sync.WaitGroup)
	if p.Networking.Nettype != network.TYPE_HOST && len(p.Networking.Sockets) > 0 {
		wgNet.Add(1)
		go func() {
			defer wgNet.Done()
			sbox.ready.Wait()
			err := network.ProxySetup(sbox.init.Process.Pid, p.Networking.Sockets, d.log, sbox.ready)
			if err != nil {
				log.Warning("Unable to create connection proxy: %+s", err)
			}
		}()
	}

	if !msg.Noexec {
		go func() {
			sbox.ready.Wait()
			wgNet.Wait()
			go sbox.launchProgram(msg.Path, msg.Pwd, msg.Args, log)
		}()
	}

	if sbox.profile.XServer.Enabled {
		go func() {
			sbox.ready.Wait()
			go sbox.startXpraClient()
		}()
	}

    cmd2 := exec.Command("/bin/mount")
    stdout, err := cmd2.Output()

    if err != nil {
        println(err.Error())
    }
    log.Debug(string(stdout))

	d.nextSboxId += 1
	d.sandboxes = append(d.sandboxes, sbox)
	return sbox, nil
}

func (sbox *Sandbox) launchProgram(cpath, pwd string, args []string, log *logging.Logger) {
	/*
		if sbox.profile.AllowFiles {
			for _, fpath := range args {
				if _, err := os.Stat(fpath); err == nil {
					if filepath.IsAbs(fpath) == false {
						fpath = path.Join(pwd, fpath)
					}
					log.Info("Adding file `%s` to sandbox `%s`.", fpath, sbox.profile.Name)
					if err := sbox.fs.AddBindWhitelist(fpath, fpath, false); err != nil {
						log.Warning("Error adding file `%s`!", fpath)
					}
				}
			}
		}
	*/

	err := ozinit.RunProgram(sbox.addr, cpath, pwd, args)
	if err != nil {
		log.Error("start shell command failed: %v", err)
	}
}

func (sbox *Sandbox) remove(log *logging.Logger) {
	sboxes := []*Sandbox{}
	for _, sb := range sbox.daemon.sandboxes {
		if sb == sbox {
			//		sb.fs.Cleanup()
			if sb.profile.Networking.Nettype == network.TYPE_BRIDGE {
				sb.network.Cleanup(log)
			}
			os.Remove(sb.addr)
		} else {
			sboxes = append(sboxes, sb)
		}
	}
	sbox.daemon.sandboxes = sboxes
}

func (sbox *Sandbox) logMessages() {
	scanner := bufio.NewScanner(sbox.stderr)
	seenOk := false
	for scanner.Scan() {
		line := scanner.Text()
		if line == "OK" && !seenOk {
			sbox.daemon.log.Info("oz-init (%s) is ready", sbox.profile.Name)
			seenOk = true
			sbox.ready.Done()
		} else if len(line) > 1 {
			sbox.logLine(line)
		}
	}
	sbox.stderr.Close()
}

func (sbox *Sandbox) logLine(line string) {
	if len(line) < 2 {
		return
	}
	f := sbox.getLogFunc(line[0])
	msg := line[2:]
	if f != nil {
		f("[%s] %s", sbox.profile.Name, msg)
	} else {
		sbox.daemon.log.Info("[%s] %s", sbox.profile.Name, line)
	}
}

func (sbox *Sandbox) getLogFunc(c byte) func(string, ...interface{}) {
	log := sbox.daemon.log
	switch c {
	case 'D':
		return log.Debug
	case 'I':
		return log.Info
	case 'N':
		return log.Notice
	case 'W':
		return log.Warning
	case 'E':
		return log.Error
	case 'C':
		return log.Critical
	}
	return nil
}

func (sbox *Sandbox) startXpraClient() {
	u, err := user.LookupId(fmt.Sprintf("%d", sbox.cred.Uid))
	if err != nil {
		sbox.daemon.Error("Failed to lookup user for uid=%d, cannot start xpra", sbox.cred.Uid)
		return
	}
	xpraPath := path.Join(u.HomeDir, ".Xoz", sbox.profile.Name)
	sbox.xpra = xpra.NewClient(
		&sbox.profile.XServer,
		uint64(sbox.display),
		sbox.cred,
		xpraPath,
		sbox.profile.Name,
		sbox.daemon.log)

	if sbox.daemon.config.LogXpra {
		sbox.setupXpraLogging()
	}
	if err := sbox.xpra.Process.Start(); err != nil {
		sbox.daemon.Warning("Failed to start xpra client: %v", err)
	}
}

func (sbox *Sandbox) setupXpraLogging() {
	stdout, err := sbox.xpra.Process.StdoutPipe()
	if err != nil {
		sbox.daemon.Warning("Failed to create xpra stdout pipe: %v", err)
		return
	}
	stderr, err := sbox.xpra.Process.StderrPipe()
	if err != nil {
		stdout.Close()
		sbox.daemon.Warning("Failed to create xpra stderr pipe: %v", err)
	}
	go sbox.logPipeOutput(stdout, "xpra-stdout")
	go sbox.logPipeOutput(stderr, "xpra-stderr")
}

func (sbox *Sandbox) logPipeOutput(p io.Reader, label string) {
	scanner := bufio.NewScanner(p)
	for scanner.Scan() {
		line := scanner.Text()
		sbox.daemon.log.Info("(%s) %s", label, line)
	}
}
<commit_msg>Whoops<commit_after>package daemon

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path"
	"sync"
	"syscall"

	"github.com/subgraph/oz"
	"github.com/subgraph/oz/network"
	"github.com/subgraph/oz/oz-init"
	"github.com/subgraph/oz/xpra"

	"crypto/rand"
	"encoding/hex"
	"github.com/op/go-logging"
	"github.com/subgraph/oz/fs"
	"os/user"
)

type Sandbox struct {
	daemon  *daemonState
	id      int
	display int
	profile *oz.Profile
	init    *exec.Cmd
	cred    *syscall.Credential
	fs      *fs.Filesystem
	stderr  io.ReadCloser
	addr    string
	xpra    *xpra.Xpra
	ready   sync.WaitGroup
	network *network.SandboxNetwork
}

func createSocketPath(base string) (string, error) {
	bs := make([]byte, 8)
	_, err := rand.Read(bs)
	if err != nil {
		return "", err
	}

	return path.Join(base, fmt.Sprintf("oz-init-control-%s", hex.EncodeToString(bs))), nil
}

func createInitCommand(initPath, name string, socketPath string, env []string, uid uint32, display int, stn *network.SandboxNetwork) *exec.Cmd {
	cmd := exec.Command(initPath)
	cmd.Dir = "/"

	cloneFlags := uintptr(syscall.CLONE_NEWNS)
	cloneFlags |= syscall.CLONE_NEWIPC
	cloneFlags |= syscall.CLONE_NEWPID
	cloneFlags |= syscall.CLONE_NEWUTS

	if stn.Nettype != network.TYPE_HOST {
		cloneFlags |= syscall.CLONE_NEWNET
	}

	cmd.SysProcAttr = &syscall.SysProcAttr{
		//Chroot:     chroot,
		Cloneflags: cloneFlags,
	}
	cmd.Env = []string{
		"INIT_PROFILE=" + name,
		"INIT_SOCKET=" + socketPath,
		fmt.Sprintf("INIT_UID=%d", uid),
	}

	if stn.Ip != "" {
		cmd.Env = append(cmd.Env, "INIT_ADDR="+stn.Ip)
		cmd.Env = append(cmd.Env, "INIT_VHOST="+stn.VethHost)
		cmd.Env = append(cmd.Env, "INIT_VGUEST="+stn.VethGuest)
		cmd.Env = append(cmd.Env, "INIT_GATEWAY="+stn.Gateway.String()+"/"+stn.Class)
	}

	cmd.Env = append(cmd.Env, fmt.Sprintf("INIT_DISPLAY=%d", display))

	for _, e := range env {
		cmd.Env = append(cmd.Env, ozinit.EnvPrefix+e)
	}

	return cmd
}

func (d *daemonState) launch(p *oz.Profile, msg *LaunchMsg, uid, gid uint32, log *logging.Logger) (*Sandbox, error) {

	/*
		u, err := user.LookupId(fmt.Sprintf("%d", uid))
		if err != nil {
			return nil, fmt.Errorf("failed to lookup user for uid=%d: %v", uid, err)
		}

		fs := fs.NewFromProfile(p, u, d.config.SandboxPath, d.config.UseFullDev, d.log)
		if err := fs.Setup(d.config.ProfileDir); err != nil {
			return nil, err
		}
	*/

	display := 0
	if p.XServer.Enabled && p.Networking.Nettype == network.TYPE_HOST {
		display = d.nextDisplay
		d.nextDisplay += 1
	}

	var err error
	stn := new(network.SandboxNetwork)
	stn.Nettype = p.Networking.Nettype
	if p.Networking.Nettype == network.TYPE_BRIDGE {
		stn, err = network.PrepareSandboxNetwork(d.network, log)
		if err != nil {
			return nil, fmt.Errorf("Unable to prepare veth network: %+v", err)
		}
	}

	socketPath, err := createSocketPath(path.Join(d.config.SandboxPath, "sockets"))
	if err != nil {
		return nil, fmt.Errorf("Failed to create random socket path: %v", err)
	}
	cmd := createInitCommand(d.config.InitPath, p.Name, socketPath, msg.Env, uid, display, stn)
	log.Debug("Command environment: %+v", cmd.Env)
	pp, err := cmd.StderrPipe()
	if err != nil {
		//fs.Cleanup()
		return nil, fmt.Errorf("error creating stderr pipe for init process: %v", err)

	}

	if err := cmd.Start(); err != nil {
		//fs.Cleanup()
		return nil, fmt.Errorf("Unable to start process: %+v", err)
	}

	//rootfs := path.Join(d.config.SandboxPath, "rootfs")
	sbox := &Sandbox{
		daemon:  d,
		id:      d.nextSboxId,
		display: display,
		profile: p,
		init:    cmd,
		cred:    &syscall.Credential{Uid: uid, Gid: gid},
		fs:      fs.NewFilesystem(d.config, log),
		//addr:    path.Join(rootfs, ozinit.SocketAddress),
		addr:    socketPath,
		stderr:  pp,
		network: stn,
	}

	if p.Networking.Nettype == network.TYPE_BRIDGE {
		if err := network.NetInit(stn, d.network, cmd.Process.Pid, log); err != nil {
			cmd.Process.Kill()
			//fs.Cleanup()
			return nil, fmt.Errorf("Unable to create veth networking: %+v", err)
		}
	}

	sbox.ready.Add(1)
	go sbox.logMessages()

	wgNet := new(sync.WaitGroup)
	if p.Networking.Nettype != network.TYPE_HOST && len(p.Networking.Sockets) > 0 {
		wgNet.Add(1)
		go func() {
			defer wgNet.Done()
			sbox.ready.Wait()
			err := network.ProxySetup(sbox.init.Process.Pid, p.Networking.Sockets, d.log, sbox.ready)
			if err != nil {
				log.Warning("Unable to create connection proxy: %+s", err)
			}
		}()
	}

	if !msg.Noexec {
		go func() {
			sbox.ready.Wait()
			wgNet.Wait()
			go sbox.launchProgram(msg.Path, msg.Pwd, msg.Args, log)
		}()
	}

	if sbox.profile.XServer.Enabled {
		go func() {
			sbox.ready.Wait()
			go sbox.startXpraClient()
		}()
	}

	d.nextSboxId += 1
	d.sandboxes = append(d.sandboxes, sbox)
	return sbox, nil
}

func (sbox *Sandbox) launchProgram(cpath, pwd string, args []string, log *logging.Logger) {
	/*
		if sbox.profile.AllowFiles {
			for _, fpath := range args {
				if _, err := os.Stat(fpath); err == nil {
					if filepath.IsAbs(fpath) == false {
						fpath = path.Join(pwd, fpath)
					}
					log.Info("Adding file `%s` to sandbox `%s`.", fpath, sbox.profile.Name)
					if err := sbox.fs.AddBindWhitelist(fpath, fpath, false); err != nil {
						log.Warning("Error adding file `%s`!", fpath)
					}
				}
			}
		}
	*/

	err := ozinit.RunProgram(sbox.addr, cpath, pwd, args)
	if err != nil {
		log.Error("start shell command failed: %v", err)
	}
}

func (sbox *Sandbox) remove(log *logging.Logger) {
	sboxes := []*Sandbox{}
	for _, sb := range sbox.daemon.sandboxes {
		if sb == sbox {
			//		sb.fs.Cleanup()
			if sb.profile.Networking.Nettype == network.TYPE_BRIDGE {
				sb.network.Cleanup(log)
			}
			os.Remove(sb.addr)
		} else {
			sboxes = append(sboxes, sb)
		}
	}
	sbox.daemon.sandboxes = sboxes
}

func (sbox *Sandbox) logMessages() {
	scanner := bufio.NewScanner(sbox.stderr)
	seenOk := false
	for scanner.Scan() {
		line := scanner.Text()
		if line == "OK" && !seenOk {
			sbox.daemon.log.Info("oz-init (%s) is ready", sbox.profile.Name)
			seenOk = true
			sbox.ready.Done()
		} else if len(line) > 1 {
			sbox.logLine(line)
		}
	}
	sbox.stderr.Close()
}

func (sbox *Sandbox) logLine(line string) {
	if len(line) < 2 {
		return
	}
	f := sbox.getLogFunc(line[0])
	msg := line[2:]
	if f != nil {
		f("[%s] %s", sbox.profile.Name, msg)
	} else {
		sbox.daemon.log.Info("[%s] %s", sbox.profile.Name, line)
	}
}

func (sbox *Sandbox) getLogFunc(c byte) func(string, ...interface{}) {
	log := sbox.daemon.log
	switch c {
	case 'D':
		return log.Debug
	case 'I':
		return log.Info
	case 'N':
		return log.Notice
	case 'W':
		return log.Warning
	case 'E':
		return log.Error
	case 'C':
		return log.Critical
	}
	return nil
}

func (sbox *Sandbox) startXpraClient() {
	u, err := user.LookupId(fmt.Sprintf("%d", sbox.cred.Uid))
	if err != nil {
		sbox.daemon.Error("Failed to lookup user for uid=%d, cannot start xpra", sbox.cred.Uid)
		return
	}
	xpraPath := path.Join(u.HomeDir, ".Xoz", sbox.profile.Name)
	sbox.xpra = xpra.NewClient(
		&sbox.profile.XServer,
		uint64(sbox.display),
		sbox.cred,
		xpraPath,
		sbox.profile.Name,
		sbox.daemon.log)

	if sbox.daemon.config.LogXpra {
		sbox.setupXpraLogging()
	}
	if err := sbox.xpra.Process.Start(); err != nil {
		sbox.daemon.Warning("Failed to start xpra client: %v", err)
	}
}

func (sbox *Sandbox) setupXpraLogging() {
	stdout, err := sbox.xpra.Process.StdoutPipe()
	if err != nil {
		sbox.daemon.Warning("Failed to create xpra stdout pipe: %v", err)
		return
	}
	stderr, err := sbox.xpra.Process.StderrPipe()
	if err != nil {
		stdout.Close()
		sbox.daemon.Warning("Failed to create xpra stderr pipe: %v", err)
	}
	go sbox.logPipeOutput(stdout, "xpra-stdout")
	go sbox.logPipeOutput(stderr, "xpra-stderr")
}

func (sbox *Sandbox) logPipeOutput(p io.Reader, label string) {
	scanner := bufio.NewScanner(p)
	for scanner.Scan() {
		line := scanner.Text()
		sbox.daemon.log.Info("(%s) %s", label, line)
	}
}
<|endoftext|>


<commit_before>// Debug functions.
package core

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/DanielRenne/GoCore/core/extensions"
	"github.com/DanielRenne/GoCore/core/serverSettings"
	"github.com/davidrenne/reflections"
	"github.com/go-errors/errors"
	"log"
	"os"
	"reflect"
	"runtime"
	"runtime/debug"
	"strings"
	"time"
)

type core_debug struct{}

var core_logger = log.New(os.Stdout, "", 0)
var Debug = core_debug{}
var Logger = core_logger

// Nop is a dummy function that can be called in source files where
// other debug functions are constantly added and removed.
// That way import "github.com/ungerik/go-start/debug" won't cause an error when
// no other debug function is currently used.
// Arbitrary objects can be passed as arguments to avoid "declared and not used"
// error messages when commenting code out and in.
// The result is a nil interface{} dummy value.
func (self *core_debug) Nop(dummiesIn ...interface{}) (dummyOut interface{}) {
	return nil
}

func (self *core_debug) CallStackInfo(skip int) (info string) {
	pc, file, line, ok := runtime.Caller(skip)
	if ok {
		funcName := runtime.FuncForPC(pc).Name()
		info += fmt.Sprintf("In function %s()", funcName)
	}
	for i := 0; ok; i++ {
		info += fmt.Sprintf("\n%s:%d", file, line)
		_, file, line, ok = runtime.Caller(skip + i)
	}
	return info
}

func (self *core_debug) PrintCallStack() {
	debug.PrintStack()
}

func (self *core_debug) LogCallStack() {
	log.Print(self.Stack())
}

func (self *core_debug) Stack() string {
	return string(debug.Stack())
}

func (self *core_debug) formatValue(value interface{}) string {
	return fmt.Sprintf("\n     Type: %T\n    Value: %v\nGo Syntax: %#v", value, value, value)
}

func (self *core_debug) formatCallstack(skip int) string {
	return fmt.Sprintf("\nCallstack: %s", self.CallStackInfo(skip+1))
}

func (self *core_debug) FormatSkip(skip int, value interface{}) string {
	return self.formatValue(value) + self.formatCallstack(skip+1)
}

func (self *core_debug) Format(value interface{}) string {
	return self.FormatSkip(2, value)
}

func (self *core_debug) DumpQuiet(values ...interface{}) {
	// uncomment below to find your callers to quiet
	self.Print("Silently not dumping " + extensions.IntToString(len(values)) + " values")
	//Logger.Println("DumpQuiet has " + extensions.IntToString(len(values)) + " parameters called")
	//Logger.Println("")
	//self.ThrowAndPrintError()
}

func IsZeroOfUnderlyingType(x interface{}) bool {
	return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
}

func (self *core_debug) Dump(values ...interface{}) {
	if serverSettings.WebConfig.Application.FlushCoreDebugToStandardOut {
		//golog "github.com/DanielRenne/GoCore/core/log"
		//defer golog.TimeTrack(time.Now(), "Dump")
		t := time.Now()
		Logger.Println("!!!!!!!!!!!!! DEBUG " + t.String() + "!!!!!!!!!!!!!")
		Logger.Println("")
		Logger.Println("")
		var jsonString string
		var err error
		var structKeys []string
		self.ThrowAndPrintError()
		if Logger != nil {
			for _, value := range values {
				isAllJSON := true
				kind := reflections.ReflectKind(value)
				if IsZeroOfUnderlyingType(value) {
					isAllJSON = false
				} else {
					structKeys, err = reflections.FieldsDeep(value)
					if err == nil {
						for _, field := range structKeys {
							jsonString, err = reflections.GetFieldTag(value, field, "json")
							if err != nil {
								isAllJSON = false
							}
							if jsonString == "" {
								isAllJSON = false
							}
						}
					} else {
						isAllJSON = false
					}
				}

				//%T
				if isAllJSON || strings.TrimSpace(kind) == "map" {
					var rawBytes []byte
					rawBytes, err = json.MarshalIndent(value, "", "\t")
					if err == nil {
						value = string(rawBytes[:])
					}
					Logger.Println(fmt.Sprintf("%s: %+v\n", kind, value))
				} else {
					//  (%#v) can be used later possibly to reuse whats in memory into golang
					if strings.TrimSpace(kind) == "string" {
						var stringVal = value.(string)
						position := strings.Index(stringVal, "Desc->")
						if position == -1 {
							Logger.Println(fmt.Sprintf("%s:", kind))
							for _, tmp := range strings.Split(stringVal, "\\n") {
								Logger.Println(tmp)
							}
							Logger.Println()
							Logger.Println()
						} else {
							Logger.Print(stringVal[6:] + " --> ")
						}
					} else {
						Logger.Println(fmt.Sprintf("%s: %+v\n\n", kind, value))
					}
				}
			}
		}
		Logger.Println("")
		Logger.Println("")
		Logger.Println("!!!!!!!!!!!!! ENDDEBUG " + t.String() + "!!!!!!!!!!!!!")
	}
}

func (self *core_debug) ThrowAndPrintError() {
	if serverSettings.WebConfig.Application.CoreDebugStackTrace {
		Logger.Println("")
		errorInfo := self.ThrowError()
		stack := strings.Split(errorInfo.ErrorStack(), "\n")
		filePathSplit := strings.Split(stack[7], ".go:")
		filePaths := strings.Split(filePathSplit[0], "/")
		fileName := filePaths[len(filePaths)-1] + ".go"
		lineParts := strings.Split(filePathSplit[1], "(")
		lineNumber := strings.TrimSpace(lineParts[0])

		finalLineOfCode := strings.TrimSpace(stack[8])

		if strings.Index(finalLineOfCode, "Desc->Caller for Query") == -1 {
			Logger.Println("Dump Caller (" + fileName + ":" + lineNumber + "):")
			Logger.Println("---------------")
			Logger.Println(" goline ==> " + strings.TrimSpace(stack[8]))
			Logger.Println("---------------")
			Logger.Println("")
			Logger.Println("")
		}
	}
}

func (self *core_debug) ThrowError() *errors.Error {
	return errors.Errorf("Debug Dump")
}

func (self *core_debug) GetDump(values ...interface{}) string {
	var buffer bytes.Buffer
	for _, value := range values {
		buffer.WriteString("(" + reflect.TypeOf(value).Name() + ")" + fmt.Sprintf("%+v\n", value))
	}
	return buffer.String()
}

func (self *core_debug) Print(values ...interface{}) {
	if Logger != nil {
		Logger.Print(values...)
	}
}

func (self *core_debug) Printf(format string, values ...interface{}) {
	if Logger != nil {
		Logger.Printf(format, values...)
	}
}
<commit_msg>Changed up other logging on Dump<commit_after>// Debug functions.
package core

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/DanielRenne/GoCore/core/extensions"
	"github.com/DanielRenne/GoCore/core/serverSettings"
	"github.com/davidrenne/reflections"
	"github.com/go-errors/errors"
	"log"
	"os"
	"reflect"
	"runtime"
	"runtime/debug"
	"strings"
	"time"
)

type core_debug struct{}

var core_logger = log.New(os.Stdout, "", 0)
var Debug = core_debug{}
var Logger = core_logger

// Nop is a dummy function that can be called in source files where
// other debug functions are constantly added and removed.
// That way import "github.com/ungerik/go-start/debug" won't cause an error when
// no other debug function is currently used.
// Arbitrary objects can be passed as arguments to avoid "declared and not used"
// error messages when commenting code out and in.
// The result is a nil interface{} dummy value.
func (self *core_debug) Nop(dummiesIn ...interface{}) (dummyOut interface{}) {
	return nil
}

func (self *core_debug) CallStackInfo(skip int) (info string) {
	pc, file, line, ok := runtime.Caller(skip)
	if ok {
		funcName := runtime.FuncForPC(pc).Name()
		info += fmt.Sprintf("In function %s()", funcName)
	}
	for i := 0; ok; i++ {
		info += fmt.Sprintf("\n%s:%d", file, line)
		_, file, line, ok = runtime.Caller(skip + i)
	}
	return info
}

func (self *core_debug) PrintCallStack() {
	debug.PrintStack()
}

func (self *core_debug) LogCallStack() {
	log.Print(self.Stack())
}

func (self *core_debug) Stack() string {
	return string(debug.Stack())
}

func (self *core_debug) formatValue(value interface{}) string {
	return fmt.Sprintf("\n     Type: %T\n    Value: %v\nGo Syntax: %#v", value, value, value)
}

func (self *core_debug) formatCallstack(skip int) string {
	return fmt.Sprintf("\nCallstack: %s", self.CallStackInfo(skip+1))
}

func (self *core_debug) FormatSkip(skip int, value interface{}) string {
	return self.formatValue(value) + self.formatCallstack(skip+1)
}

func (self *core_debug) Format(value interface{}) string {
	return self.FormatSkip(2, value)
}

func (self *core_debug) DumpQuiet(values ...interface{}) {
	// uncomment below to find your callers to quiet
	self.Print("Silently not dumping " + extensions.IntToString(len(values)) + " values")
	//Logger.Println("DumpQuiet has " + extensions.IntToString(len(values)) + " parameters called")
	//Logger.Println("")
	//self.ThrowAndPrintError()
}

func IsZeroOfUnderlyingType(x interface{}) bool {
	return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
}

func IsZeroOfUnderlyingType2(x interface{}) bool {
	return x == reflect.Zero(reflect.TypeOf(x)).Interface()
}

func (self *core_debug) Dump(values ...interface{}) {
	if serverSettings.WebConfig.Application.FlushCoreDebugToStandardOut {
		//golog "github.com/DanielRenne/GoCore/core/log"
		//defer golog.TimeTrack(time.Now(), "Dump")
		t := time.Now()
		Logger.Println("!!!!!!!!!!!!! DEBUG " + t.String() + "!!!!!!!!!!!!!")
		Logger.Println("")
		Logger.Println("")
		var jsonString string
		var err error
		var structKeys []string
		self.ThrowAndPrintError()
		if Logger != nil {
			for _, value := range values {
				isAllJSON := true
				var kind string
				kind = strings.TrimSpace(fmt.Sprintf("%T", value))
				if kind == "struct" {
					kind = reflections.ReflectKind(value)
					structKeys, err = reflections.FieldsDeep(value)
					if err == nil {
						for _, field := range structKeys {
							jsonString, err = reflections.GetFieldTag(value, field, "json")
							if err != nil {
								isAllJSON = false
							}
							if jsonString == "" {
								isAllJSON = false
							}
						}
					} else {
						isAllJSON = false
					}
				} else {
					isAllJSON = false
				}

				if isAllJSON || kind == "map" || kind == "bson.M" {
					var rawBytes []byte
					rawBytes, err = json.MarshalIndent(value, "", "\t")
					if err == nil {
						value = string(rawBytes[:])
					}
					Logger.Println(fmt.Sprintf("%s: %+v\n", kind, value))
				} else {
					if strings.TrimSpace(kind) == "string" {
						var stringVal = value.(string)
						position := strings.Index(stringVal, "Desc->")
						if position == -1 {
							Logger.Println(fmt.Sprintf("%s:", kind))
							for _, tmp := range strings.Split(stringVal, "\\n") {
								Logger.Println(tmp)
							}
							Logger.Println()
							Logger.Println()
						} else {
							Logger.Print(stringVal[6:] + " --> ")
						}
					} else {
						Logger.Println(fmt.Sprintf("%s: %+v\n\n", kind, value))
					}
				}
			}
		}
		Logger.Println("")
		Logger.Println("")
		Logger.Println("!!!!!!!!!!!!! ENDDEBUG " + t.String() + "!!!!!!!!!!!!!")
	}
}

func (self *core_debug) ThrowAndPrintError() {
	if serverSettings.WebConfig.Application.CoreDebugStackTrace {
		Logger.Println("")
		errorInfo := self.ThrowError()
		stack := strings.Split(errorInfo.ErrorStack(), "\n")
		filePathSplit := strings.Split(stack[7], ".go:")
		filePaths := strings.Split(filePathSplit[0], "/")
		fileName := filePaths[len(filePaths)-1] + ".go"
		lineParts := strings.Split(filePathSplit[1], "(")
		lineNumber := strings.TrimSpace(lineParts[0])

		finalLineOfCode := strings.TrimSpace(stack[8])

		if strings.Index(finalLineOfCode, "Desc->Caller for Query") == -1 {
			Logger.Println("Dump Caller (" + fileName + ":" + lineNumber + "):")
			Logger.Println("---------------")
			Logger.Println(" goline ==> " + strings.TrimSpace(stack[8]))
			Logger.Println("---------------")
			Logger.Println("")
			Logger.Println("")
		}
	}
}

func (self *core_debug) ThrowError() *errors.Error {
	return errors.Errorf("Debug Dump")
}

func (self *core_debug) GetDump(values ...interface{}) string {
	var buffer bytes.Buffer
	for _, value := range values {
		buffer.WriteString("(" + reflect.TypeOf(value).Name() + ")" + fmt.Sprintf("%+v\n", value))
	}
	return buffer.String()
}

func (self *core_debug) Print(values ...interface{}) {
	if Logger != nil {
		Logger.Print(values...)
	}
}

func (self *core_debug) Printf(format string, values ...interface{}) {
	if Logger != nil {
		Logger.Printf(format, values...)
	}
}
<|endoftext|>


<commit_before>package handlers

import (
	"encoding/json"
	"net/http"
	"strconv"

	"github.com/gorilla/mux"
	"github.com/sirupsen/logrus"

	"github.com/ivan1993spb/snake-server/connections"
)

const URLRouteDeleteGameByID = "/games/{id}"

const MethodDeleteGame = http.MethodDelete

type responseDeleteGameHandler struct {
	ID int `json:"id"`
}

type deleteGameHandler struct {
	logger       logrus.FieldLogger
	groupManager *connections.ConnectionGroupManager
}

type ErrDeleteGameHandler string

func (e ErrDeleteGameHandler) Error() string {
	return "delete game handler error: " + string(e)
}

func NewDeleteGameHandler(logger logrus.FieldLogger, groupManager *connections.ConnectionGroupManager) http.Handler {
	return &deleteGameHandler{
		logger:       logger,
		groupManager: groupManager,
	}
}

func (h *deleteGameHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	h.logger.Info("delete game handler start")
	defer h.logger.Info("delete game handler end")

	vars := mux.Vars(r)

	id, err := strconv.Atoi(vars["id"])
	if err != nil {
		h.logger.Error(ErrDeleteGameHandler(err.Error()))
		http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
		return
	}

	h.logger.Infoln("group id to delete:", id)

	group, err := h.groupManager.Get(id)
	if err != nil {
		h.logger.Error(ErrDeleteGameHandler(err.Error()))

		switch err {
		case connections.ErrNotFoundGroup:
			http.NotFound(w, r)
		default:
			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		}
		return
	}

	if !group.IsEmpty() {
		h.logger.Warn(ErrDeleteGameHandler("try to delete not empty group"))
		h.logger.Warnf("there is %d opened connections in group %d", group.GetCount(), id)
		http.Error(w, http.StatusText(http.StatusServiceUnavailable), http.StatusServiceUnavailable)
		return
	}

	if err := h.groupManager.Delete(group); err != nil {
		h.logger.Error(ErrDeleteGameHandler(err.Error()))

		switch err {
		case connections.ErrDeleteNotFoundGroup:
			http.NotFound(w, r)
		case connections.ErrDeleteNotEmptyGroup:
			http.Error(w, http.StatusText(http.StatusServiceUnavailable), http.StatusServiceUnavailable)
		default:
			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		}
		return
	}

	h.logger.Info("stop group")
	group.Stop()

	h.logger.Infoln("group deleted:", id)

	w.Header().Add("Content-Type", "application/json; charset=utf-8")

	err = json.NewEncoder(w).Encode(responseDeleteGameHandler{
		ID: id,
	})
	if err != nil {
		h.logger.Error(ErrDeleteGameHandler(err.Error()))
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}
}
<commit_msg>Fix handler delete game handler<commit_after>package handlers

import (
	"encoding/json"
	"net/http"
	"strconv"

	"github.com/gorilla/mux"
	"github.com/sirupsen/logrus"

	"github.com/ivan1993spb/snake-server/connections"
)

const URLRouteDeleteGameByID = "/games/{id}"

const MethodDeleteGame = http.MethodDelete

type responseDeleteGameHandler struct {
	ID int `json:"id"`
}

type deleteGameHandler struct {
	logger       logrus.FieldLogger
	groupManager *connections.ConnectionGroupManager
}

type ErrDeleteGameHandler string

func (e ErrDeleteGameHandler) Error() string {
	return "delete game handler error: " + string(e)
}

func NewDeleteGameHandler(logger logrus.FieldLogger, groupManager *connections.ConnectionGroupManager) http.Handler {
	return &deleteGameHandler{
		logger:       logger,
		groupManager: groupManager,
	}
}

func (h *deleteGameHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)

	id, err := strconv.Atoi(vars["id"])
	if err != nil {
		h.logger.Error(ErrDeleteGameHandler(err.Error()))
		http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
		return
	}

	h.logger.Infoln("group id to delete:", id)

	group, err := h.groupManager.Get(id)
	if err != nil {
		h.logger.Error(ErrDeleteGameHandler(err.Error()))

		switch err {
		case connections.ErrNotFoundGroup:
			http.NotFound(w, r)
		default:
			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		}
		return
	}

	if !group.IsEmpty() {
		h.logger.Warn(ErrDeleteGameHandler("try to delete not empty group"))
		h.logger.Warnf("there is %d opened connections in group %d", group.GetCount(), id)
		http.Error(w, http.StatusText(http.StatusServiceUnavailable), http.StatusServiceUnavailable)
		return
	}

	if err := h.groupManager.Delete(group); err != nil {
		h.logger.Error(ErrDeleteGameHandler(err.Error()))

		switch err {
		case connections.ErrDeleteNotFoundGroup:
			http.NotFound(w, r)
		case connections.ErrDeleteNotEmptyGroup:
			http.Error(w, http.StatusText(http.StatusServiceUnavailable), http.StatusServiceUnavailable)
		default:
			http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		}
		return
	}

	h.logger.Info("stop group")
	group.Stop()

	h.logger.Infoln("group deleted:", id)

	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	err = json.NewEncoder(w).Encode(responseDeleteGameHandler{
		ID: id,
	})
	if err != nil {
		h.logger.Error(ErrDeleteGameHandler(err.Error()))
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}
}
<|endoftext|>


<commit_before>package endpoint

import (
	"github.com/brutella/hc/hap"
	"github.com/brutella/hc/log"
	"io"
	"io/ioutil"
	"net/http"
	"sync"
)

// Characteristics handles the /characteristics endpoint
//
// This endpoint is not session based and the same for all connections because
// the encryption/decryption is handled by the connection automatically.
type Characteristics struct {
	http.Handler

	controller hap.CharacteristicsHandler
	mutex      *sync.Mutex
	context    hap.Context
}

// NewCharacteristics returns a new handler for characteristics endpoint
func NewCharacteristics(context hap.Context, c hap.CharacteristicsHandler, mutex *sync.Mutex) *Characteristics {
	handler := Characteristics{
		controller: c,
		mutex:      mutex,
		context:    context,
	}

	return &handler
}

func (handler *Characteristics) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	var res io.Reader
	var err error

	handler.mutex.Lock()
	switch request.Method {
	case hap.MethodGET:
		log.Debug.Printf("%v GET /characteristics", request.RemoteAddr)
		request.ParseForm()
		session := handler.context.GetSessionForRequest(request)
		conn := session.Connection()
		res, err = handler.controller.HandleGetCharacteristics(request.Form, conn)
	case hap.MethodPUT:
		log.Debug.Printf("%v PUT /characteristics", request.RemoteAddr)
		session := handler.context.GetSessionForRequest(request)
		conn := session.Connection()
		err = handler.controller.HandleUpdateCharacteristics(request.Body, conn)
	default:
		log.Debug.Println("Cannot handle HTTP method", request.Method)
	}
	handler.mutex.Unlock()

	if err != nil {
		log.Info.Panic(err)
		response.WriteHeader(http.StatusInternalServerError)
	} else {
		if res != nil {
			response.Header().Set("Content-Type", hap.HTTPContentTypeHAPJson)
			wr := hap.NewChunkedWriter(response, 2048)
			b, _ := ioutil.ReadAll(res)
			wr.Write(b)
		} else {
			response.WriteHeader(http.StatusNoContent)
		}
	}
}
<commit_msg>Log GET /characteristic request form<commit_after>package endpoint

import (
	"github.com/brutella/hc/hap"
	"github.com/brutella/hc/log"
	"io"
	"io/ioutil"
	"net/http"
	"sync"
)

// Characteristics handles the /characteristics endpoint
//
// This endpoint is not session based and the same for all connections because
// the encryption/decryption is handled by the connection automatically.
type Characteristics struct {
	http.Handler

	controller hap.CharacteristicsHandler
	mutex      *sync.Mutex
	context    hap.Context
}

// NewCharacteristics returns a new handler for characteristics endpoint
func NewCharacteristics(context hap.Context, c hap.CharacteristicsHandler, mutex *sync.Mutex) *Characteristics {
	handler := Characteristics{
		controller: c,
		mutex:      mutex,
		context:    context,
	}

	return &handler
}

func (handler *Characteristics) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	var res io.Reader
	var err error

	handler.mutex.Lock()
	switch request.Method {
	case hap.MethodGET:
		request.ParseForm()
		log.Debug.Printf("%v GET /characteristics %v", request.RemoteAddr, request.Form)
		session := handler.context.GetSessionForRequest(request)
		conn := session.Connection()
		res, err = handler.controller.HandleGetCharacteristics(request.Form, conn)
	case hap.MethodPUT:
		log.Debug.Printf("%v PUT /characteristics", request.RemoteAddr)
		session := handler.context.GetSessionForRequest(request)
		conn := session.Connection()
		err = handler.controller.HandleUpdateCharacteristics(request.Body, conn)
	default:
		log.Debug.Println("Cannot handle HTTP method", request.Method)
	}
	handler.mutex.Unlock()

	if err != nil {
		log.Info.Panic(err)
		response.WriteHeader(http.StatusInternalServerError)
	} else {
		if res != nil {
			response.Header().Set("Content-Type", hap.HTTPContentTypeHAPJson)
			wr := hap.NewChunkedWriter(response, 2048)
			b, _ := ioutil.ReadAll(res)
			wr.Write(b)
		} else {
			response.WriteHeader(http.StatusNoContent)
		}
	}
}
<|endoftext|>


<commit_before>package models

import (
	"errors"
	"time"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"

	"github.com/ikeikeikeike/gopkg/convert"
)

type Blog struct {
	Id          int64  `orm:"auto"`
	Rss         string `orm:"size(255);null;unique" form:"Rss" valid:"Required;Match(/^https?/)"`
	Url         string `orm:"size(255);null"`
	Name        string `orm:"size(255);null" form:"Name" valid:"MaxSize(250)"`
	Mediatype   string `orm:"size(16)" form:"Mediatype" valid:"Required;Match(/^(movie|image)$/)"`
	Adsensetype string `orm:"size(16)" form:"Adsensetype" valid:"Required;Match(/^(2d|3d)$/)"`

	VerifyParts     int `orm:"default(1);null" form:"VerifyParts" valid:"Range(0,3)"`
	VerifyRss       int `orm:"default(1);null" form:"VerifyRss" valid:"Range(0,3)"`
	VerifyLink      int `orm:"default(1);null" form:"VerifyLink" valid:"Range(0,3)"`
	VerifyBookRss   int `orm:"default(1);null" form:"VerifyBookRss" valid:"Range(0,3)"`
	VerifyBookLink  int `orm:"default(1);null" form:"VerifyBookLink" valid:"Range(0,3)"`
	VerifyVideoRss  int `orm:"default(1);null" form:"VerifyVideoRss" valid:"Range(0,3)"`
	VerifyVideoLink int `orm:"default(1);null" form:"VerifyVideoLink" valid:"Range(0,3)"`

	IsBan string `orm:"default(none)" valid:"Match(/^(|none|soft|hard)$/)"`
	IsPenalty bool `orm:"default(0)"`

	LastModified time.Time `orm:"type(datetime);null;index"`

	Created time.Time `orm:"auto_now_add;type(datetime)"`
	Updated time.Time `orm:"auto_now;type(datetime)"`

	User *User  `orm:"rel(fk);null;index"`
	Icon *Image `orm:"rel(one);on_delete(set_null);index;null"`

	Scores  []*Score `orm:"reverse(many)"`
	Entries []*Entry `orm:"reverse(many)"`
}

func (m *Blog) VerifyScore() int {
	var score int = 1

	if m.VerifyParts >= 3 {
		score++
		score++
		score++
	}
	if m.VerifyRss >= 3 {
		score++
	}
	if m.VerifyLink >= 3 {
		score++
	}
	if m.VerifyBookRss >= 3 {
		score++
	}
	if m.VerifyBookLink >= 3 {
		score++
	}
	if m.VerifyVideoRss >= 3 {
		score++
	}
	if m.VerifyVideoLink >= 3 {
		score++
	}
	return score
}

func (m *Blog) LoadRelated() *Blog {
	o := orm.NewOrm()
	_, _ = o.LoadRelated(m, "User")
	_, _ = o.LoadRelated(m, "Icon")
	_, _ = o.LoadRelated(m, "Scores", 2, DefaultPerEntities)
	_, _ = o.LoadRelated(m, "Entries", 2, DefaultPerEntities, 0, "-id")
	return m
}

func (m *Blog) RelLoader() {
	m.LoadRelated()
}

func (m *Blog) IdStr() string {
	return convert.ToStr(m.Id)
}

func (m *Blog) Insert() error {
	if _, err := orm.NewOrm().Insert(m); err != nil {
		if err.Error() == "UNIQUE constraint failed: blog.rss" {
			msg := "入力されたRSSは既に登録されています。"
			err = errors.New(msg)
		}
		return err
	}
	return nil
}

func (m *Blog) Read(fields ...string) error {
	if err := orm.NewOrm().Read(m, fields...); err != nil {
		return err
	}
	return nil
}

func (m *Blog) ReadOrCreate(field string, fields ...string) (bool, int64, error) {
	return orm.NewOrm().ReadOrCreate(m, field, fields...)
}

func (m *Blog) Update(fields ...string) error {
	if _, err := orm.NewOrm().Update(m, fields...); err != nil {
		return err
	}
	return nil
}

func (m *Blog) Delete() error {
	if _, err := orm.NewOrm().Delete(m); err != nil {
		return err
	}
	return nil
}

// Ligical delete: Unrelate User and Blog, Set isnull to rss attribue.
func (m *Blog) LogicalDelete() error {
	params := orm.Params{"Rss": nil, "User": nil}
	if _, err := Blogs().Filter("id", m).Update(params); err != nil {
		return err
	}
	return nil
}

func Blogs() orm.QuerySeter {
	return orm.NewOrm().QueryTable("blog").OrderBy("-Id")
}

func init() {
	orm.RegisterModelWithPrefix(
		beego.AppConfig.String("dbprefix"),
		new(Blog))
}
<commit_msg>change default value in database<commit_after>package models

import (
	"errors"
	"time"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"

	"github.com/ikeikeikeike/gopkg/convert"
)

type Blog struct {
	Id          int64  `orm:"auto"`
	Rss         string `orm:"size(255);null;unique" form:"Rss" valid:"Required;Match(/^https?/)"`
	Url         string `orm:"size(255);null"`
	Name        string `orm:"size(255);null" form:"Name" valid:"MaxSize(250)"`
	Mediatype   string `orm:"size(16)" form:"Mediatype" valid:"Required;Match(/^(movie|image)$/)"`
	Adsensetype string `orm:"size(16)" form:"Adsensetype" valid:"Required;Match(/^(2d|3d)$/)"`

	VerifyParts     int `orm:"default(1);null" form:"VerifyParts" valid:"Range(0,3)"`
	VerifyRss       int `orm:"default(1);null" form:"VerifyRss" valid:"Range(0,3)"`
	VerifyLink      int `orm:"default(1);null" form:"VerifyLink" valid:"Range(0,3)"`
	VerifyBookRss   int `orm:"default(1);null" form:"VerifyBookRss" valid:"Range(0,3)"`
	VerifyBookLink  int `orm:"default(1);null" form:"VerifyBookLink" valid:"Range(0,3)"`
	VerifyVideoRss  int `orm:"default(1);null" form:"VerifyVideoRss" valid:"Range(0,3)"`
	VerifyVideoLink int `orm:"default(1);null" form:"VerifyVideoLink" valid:"Range(0,3)"`

	IsBan string `orm:"default(soft)" valid:"Match(/^(|none|soft|hard)$/)"`
	IsPenalty bool `orm:"default(0)"`

	LastModified time.Time `orm:"type(datetime);null;index"`

	Created time.Time `orm:"auto_now_add;type(datetime)"`
	Updated time.Time `orm:"auto_now;type(datetime)"`

	User *User  `orm:"rel(fk);null;index"`
	Icon *Image `orm:"rel(one);on_delete(set_null);index;null"`

	Scores  []*Score `orm:"reverse(many)"`
	Entries []*Entry `orm:"reverse(many)"`
}

func (m *Blog) VerifyScore() int {
	var score int = 1

	if m.VerifyParts >= 3 {
		score++
		score++
		score++
	}
	if m.VerifyRss >= 3 {
		score++
	}
	if m.VerifyLink >= 3 {
		score++
	}
	if m.VerifyBookRss >= 3 {
		score++
	}
	if m.VerifyBookLink >= 3 {
		score++
	}
	if m.VerifyVideoRss >= 3 {
		score++
	}
	if m.VerifyVideoLink >= 3 {
		score++
	}
	return score
}

func (m *Blog) LoadRelated() *Blog {
	o := orm.NewOrm()
	_, _ = o.LoadRelated(m, "User")
	_, _ = o.LoadRelated(m, "Icon")
	_, _ = o.LoadRelated(m, "Scores", 2, DefaultPerEntities)
	_, _ = o.LoadRelated(m, "Entries", 2, DefaultPerEntities, 0, "-id")
	return m
}

func (m *Blog) RelLoader() {
	m.LoadRelated()
}

func (m *Blog) IdStr() string {
	return convert.ToStr(m.Id)
}

func (m *Blog) Insert() error {
	if _, err := orm.NewOrm().Insert(m); err != nil {
		if err.Error() == "UNIQUE constraint failed: blog.rss" {
			msg := "入力されたRSSは既に登録されています。"
			err = errors.New(msg)
		}
		return err
	}
	return nil
}

func (m *Blog) Read(fields ...string) error {
	if err := orm.NewOrm().Read(m, fields...); err != nil {
		return err
	}
	return nil
}

func (m *Blog) ReadOrCreate(field string, fields ...string) (bool, int64, error) {
	return orm.NewOrm().ReadOrCreate(m, field, fields...)
}

func (m *Blog) Update(fields ...string) error {
	if _, err := orm.NewOrm().Update(m, fields...); err != nil {
		return err
	}
	return nil
}

func (m *Blog) Delete() error {
	if _, err := orm.NewOrm().Delete(m); err != nil {
		return err
	}
	return nil
}

// Ligical delete: Unrelate User and Blog, Set isnull to rss attribue.
func (m *Blog) LogicalDelete() error {
	params := orm.Params{"Rss": nil, "User": nil}
	if _, err := Blogs().Filter("id", m).Update(params); err != nil {
		return err
	}
	return nil
}

func Blogs() orm.QuerySeter {
	return orm.NewOrm().QueryTable("blog").OrderBy("-Id")
}

func init() {
	orm.RegisterModelWithPrefix(
		beego.AppConfig.String("dbprefix"),
		new(Blog))
}
<|endoftext|>


<commit_before>package gomodel

import "sync"

var (
	// InitialSQLCount is the initial capacity of sql storage,
	// it should bee changed before NewDB
	InitialSQLCount uint64 = 256
)

const (
	_InitialSQLBufsize = 256
)

type sqlStore struct {
	sqls []func(Executor) string
	sync.Mutex
}

var store sqlStore

func initSqlStore() {
	if store.sqls == nil {
		store.sqls = make([]func(Executor) string, 0, InitialSQLCount)
	}
}

func sqlById(executor Executor, id uint64) string {
	return store.sqls[id](executor)
}

// NewSqlId create an id for this sql creator used in methods like XXXById
func NewSqlId(create func(Executor) string) (id uint64) {
	store.Lock()

	id = uint64(len(store.sqls))
	store.sqls = append(store.sqls, create)

	store.Unlock()
	return
}
<commit_msg>add SqlIdKeeper for dynamic built sql<commit_after>package gomodel

import "sync"

var (
	// InitialSQLCount is the initial capacity of sql storage,
	// it should bee changed before NewDB
	InitialSQLCount uint64 = 256
)

const (
	_InitialSQLBufsize = 256
)

type sqlStore struct {
	sqls []func(Executor) string
	sync.Mutex
}

var store sqlStore

func initSqlStore() {
	if store.sqls == nil {
		store.sqls = make([]func(Executor) string, 0, InitialSQLCount)
	}
}

func sqlById(executor Executor, id uint64) string {
	return store.sqls[id](executor)
}

// NewSqlId create an id for this sql creator used in methods like XXXById
func NewSqlId(create func(Executor) string) (id uint64) {
	store.Lock()

	id = uint64(len(store.sqls))
	store.sqls = append(store.sqls, create)

	store.Unlock()
	return
}

type SqlIdKeeper struct {
	ids map[string]string
	mu  sync.RWMutex
}

func NewSqlIdKeeper() *SqlIdKeeper {
	return &SqlIdKeeper{
		ids: make(map[string]string),
	}
}

func (s *SqlIdKeeper) Get(key string) (string, bool) {
	s.mu.RLock()
	val, has := s.ids[key]
	s.mu.RUnlock()
	return val, has
}

func (s *SqlIdKeeper) Set(key, val string) {
	s.mu.Lock()
	s.ids[key] = val
	s.mu.Unlock()
}
<|endoftext|>


<commit_before>package rabbithole

import (
	"encoding/json"
	"net/http"
)

type ClusterName struct {
	Name string `json:"name"`
}

func (c *Client) GetClusterName() (rec *ClusterName, err error) {
	req, err := newGETRequest(c, "cluster-name/")
	if err != nil {
		return nil, err
	}

	if err = executeAndParseRequest(c, req, &rec); err != nil {
		return nil, err
	}

	return rec, nil
}

func (c *Client) SetClusterName(cn ClusterName) (res *http.Response, err error) {
	body, err := json.Marshal(cn)
	if err != nil {
		return nil, err
	}
	req, err := newRequestWithBody(c, "PUT", "cluster-name", body)
	if err != nil {
		return nil, err
	}

	res, err = executeRequest(c, req)

	return res, nil
}
<commit_msg>fix: error in SetClusterName request execution was never returned<commit_after>package rabbithole

import (
	"encoding/json"
	"net/http"
)

type ClusterName struct {
	Name string `json:"name"`
}

func (c *Client) GetClusterName() (rec *ClusterName, err error) {
	req, err := newGETRequest(c, "cluster-name/")
	if err != nil {
		return nil, err
	}

	if err = executeAndParseRequest(c, req, &rec); err != nil {
		return nil, err
	}

	return rec, nil
}

func (c *Client) SetClusterName(cn ClusterName) (res *http.Response, err error) {
	body, err := json.Marshal(cn)
	if err != nil {
		return nil, err
	}
	req, err := newRequestWithBody(c, "PUT", "cluster-name", body)
	if err != nil {
		return nil, err
	}

	if res, err = executeRequest(c, req); err != nil {
		return nil, err
	}

	return res, nil
}
<|endoftext|>


<commit_before>package models

import (
	"cloud.google.com/go/datastore"
	"golang.org/x/net/context"
	"github.com/miyurusagarage/memeeconomy/shared"
	"fmt"
	"time"
	"github.com/nu7hatch/gouuid"
	"github.com/miyurusagarage/memeeconomy/utils"
	"google.golang.org/api/iterator"
	"strconv"
)

type Meme struct {
	Key                 *datastore.Key `datastore:"__key__"`
	CreatedDate         time.Time
	CreatedUserId       string
	CurrentInvestments  int
	Description         string
	ExpirationDate      time.Time
	ImagePath           string
	InternalLikes       int
	ModifiedDate        time.Time
	SocialPostThreshold int
	SocialFbPostLink    string
	SocialLikes         int
	SocialPostsCreated  bool
	SocialPostedDate    time.Time
	SocialShares        int
	SocialUpdatedDate   time.Time
	IsExpired           bool
	Title               string
	TotalFame           int
}

func (this *Meme) Save() (err error) {
	this.CreatedDate = time.Now()
	socialPostThreshold, _ := GetConfigByName("SocialPostThreshold")
	this.SocialPostThreshold, _ = strconv.Atoi(socialPostThreshold.Value)
	this.IsExpired = false
	var id *uuid.UUID
	id, _ = uuid.NewV4()
	urlId := id.String()
	key := datastore.NameKey(this.kind(), urlId, nil)
	ctx := context.Background()
	memeExpirationInDaysConfig , _ := GetConfigByName("MemeExpirationInDays")
	memeExpirationInDays , _ := strconv.Atoi(memeExpirationInDaysConfig.Value)
	this.ExpirationDate = time.Now().Add(time.Duration(memeExpirationInDays) * (time.Hour * 24))
	if _, err := shared.DatastoreClient.Put(ctx, key, this); err != nil {
		fmt.Println(err)
		return err
	}
	return nil
}

func (this *Meme) Update() (err error) {
	this.ModifiedDate = time.Now()
	if this.CurrentInvestments >= this.SocialPostThreshold {
		if this.SocialFbPostLink == "" {
			postId := utils.PostMemeToFb(this.ImagePath, this.Title)
			this.SocialFbPostLink = postId
			this.SocialPostedDate = time.Now()
			memeExpirationInDaysConfig , _ := GetConfigByName("MemeExpirationInDays")
			memeExpirationInDays , _ := strconv.Atoi(memeExpirationInDaysConfig.Value)
			this.ExpirationDate = time.Now().Add(time.Duration(memeExpirationInDays) * (time.Hour * 24))
			this.SocialPostsCreated = true
		}
	}
	this.TotalFame = (this.SocialLikes * 2) + (this.SocialShares * 10) + this.CurrentInvestments + (this.InternalLikes * 2)
	ctx := context.Background()
	if _, err := shared.DatastoreClient.Put(ctx, this.Key, this); err != nil {
		fmt.Println(err)
		return err
	}
	return nil
}

func (this *Meme) kind() (str string) {
	return "meme"
}

func (this *Meme) TotalLikes() (str int) {
	return this.InternalLikes + this.SocialLikes
}

func (this *Meme) CanInvest() ( bool) {

	return !this.IsExpired
}

func (this *Meme) DaysToExpire() ( string) {
	diff := this.ExpirationDate.Sub(time.Now()).Hours()
	expireString := strconv.Itoa(int(diff/24)) + " days left"
	if diff < 0 {
		expireString = "Expired"
	}
	return expireString
}

func GetMemeFromId(id string) (objs *Meme, err error) {
	ctx := context.Background()

	key := datastore.NameKey("meme", id, nil)
	var data Meme
	er := shared.DatastoreClient.Get(ctx, key, &data)

	if er != nil {
		return nil, er
	}

	return &data, nil

}

func GetMemeFromKey(key *datastore.Key) (objs *Meme, err error) {
	ctx := context.Background()

	var data Meme
	er := shared.DatastoreClient.Get(ctx, key, &data)

	if er != nil {
		return nil, er
	}

	return &data, nil

}

func GetRecentMemes(offset int, pageSize int, fromTime time.Time) (objs *[]Meme, total int, err error) {

	ctx := context.Background()
	q := datastore.NewQuery("meme")
	q = q.Filter("CreatedDate <", fromTime)
	q = q.Order("-CreatedDate")
	q = q.Offset(offset)
	q = q.Limit(pageSize)

	var data []Meme
	_, er := shared.DatastoreClient.GetAll(ctx, q, &data)

	//count for pagination
	q = datastore.NewQuery("meme")
	count := 0
	count, er = shared.DatastoreClient.Count(ctx, q, )

	if er != nil {
		return nil, 0, er
	}
	return &data, count , nil
}

func GetTopMemes(offset int, pageSize int) (objs *[]Meme, total int, err error) {
	ctx := context.Background()
	q := datastore.NewQuery("meme")
	q = q.Filter("IsExpired =",false)
	q = q.Order("-TotalFame")
	q = q.Offset(offset)
	q = q.Limit(pageSize)
	var data []Meme
	it := shared.DatastoreClient.Run(ctx, q)
	for {
		var meme Meme
		_, err := it.Next(&meme)
		if err == iterator.Done {
			break
		}
		if err != nil {
			println(err.Error())
			break
		}
		data = append(data, meme)

	}

	//count for pagination
	q = datastore.NewQuery("meme")

	count, er := shared.DatastoreClient.Count(ctx, q, )

	if er != nil {
		return nil, 0, er
	}

	return &data, count , nil
}

func GetRecentMemesByUser(key string ,offset int, pageSize int) (objs *[]Meme, total int, err error) {

	ctx := context.Background()
	q := datastore.NewQuery("meme")

	q = q.Filter("CreatedUserId =", key)
	q = q.Offset(offset)
	q = q.Limit(pageSize)

	var data []Meme
	_, er := shared.DatastoreClient.GetAll(ctx, q, &data)

	//count for pagination
	q = datastore.NewQuery("meme")
	count := 0
	count, er = shared.DatastoreClient.Count(ctx, q, )

	if er != nil {
		return nil, 0, er
	}
	return &data, count , nil
}

func GetAllMemes( ) (objs *[]Meme, err error) {
	ctx := context.Background()
	q := datastore.NewQuery("meme")

	var data []Meme
	_, er := shared.DatastoreClient.GetAll(ctx, q, &data)

	if er != nil {
		return nil, er
	}
	return &data , nil
}

func GetToBeExpiredMemes( ) (objs *[]Meme, err error) {
	ctx := context.Background()
	q := datastore.NewQuery("meme").Filter("ExpirationDate <", time.Now()).Filter("IsExpired =", false)

	var data []Meme
	_, er := shared.DatastoreClient.GetAll(ctx, q, &data)

	if er != nil {
		return nil, er
	}
	return &data , nil
}
<commit_msg>expiry date check removed for top memes<commit_after>package models

import (
	"cloud.google.com/go/datastore"
	"golang.org/x/net/context"
	"github.com/miyurusagarage/memeeconomy/shared"
	"fmt"
	"time"
	"github.com/nu7hatch/gouuid"
	"github.com/miyurusagarage/memeeconomy/utils"
	"google.golang.org/api/iterator"
	"strconv"
)

type Meme struct {
	Key                 *datastore.Key `datastore:"__key__"`
	CreatedDate         time.Time
	CreatedUserId       string
	CurrentInvestments  int
	Description         string
	ExpirationDate      time.Time
	ImagePath           string
	InternalLikes       int
	ModifiedDate        time.Time
	SocialPostThreshold int
	SocialFbPostLink    string
	SocialLikes         int
	SocialPostsCreated  bool
	SocialPostedDate    time.Time
	SocialShares        int
	SocialUpdatedDate   time.Time
	IsExpired           bool
	Title               string
	TotalFame           int
}

func (this *Meme) Save() (err error) {
	this.CreatedDate = time.Now()
	socialPostThreshold, _ := GetConfigByName("SocialPostThreshold")
	this.SocialPostThreshold, _ = strconv.Atoi(socialPostThreshold.Value)
	this.IsExpired = false
	var id *uuid.UUID
	id, _ = uuid.NewV4()
	urlId := id.String()
	key := datastore.NameKey(this.kind(), urlId, nil)
	ctx := context.Background()
	memeExpirationInDaysConfig , _ := GetConfigByName("MemeExpirationInDays")
	memeExpirationInDays , _ := strconv.Atoi(memeExpirationInDaysConfig.Value)
	this.ExpirationDate = time.Now().Add(time.Duration(memeExpirationInDays) * (time.Hour * 24))
	if _, err := shared.DatastoreClient.Put(ctx, key, this); err != nil {
		fmt.Println(err)
		return err
	}
	return nil
}

func (this *Meme) Update() (err error) {
	this.ModifiedDate = time.Now()
	if this.CurrentInvestments >= this.SocialPostThreshold {
		if this.SocialFbPostLink == "" {
			postId := utils.PostMemeToFb(this.ImagePath, this.Title)
			this.SocialFbPostLink = postId
			this.SocialPostedDate = time.Now()
			memeExpirationInDaysConfig , _ := GetConfigByName("MemeExpirationInDays")
			memeExpirationInDays , _ := strconv.Atoi(memeExpirationInDaysConfig.Value)
			this.ExpirationDate = time.Now().Add(time.Duration(memeExpirationInDays) * (time.Hour * 24))
			this.SocialPostsCreated = true
		}
	}
	this.TotalFame = (this.SocialLikes * 2) + (this.SocialShares * 10) + this.CurrentInvestments + (this.InternalLikes * 2)
	ctx := context.Background()
	if _, err := shared.DatastoreClient.Put(ctx, this.Key, this); err != nil {
		fmt.Println(err)
		return err
	}
	return nil
}

func (this *Meme) kind() (str string) {
	return "meme"
}

func (this *Meme) TotalLikes() (str int) {
	return this.InternalLikes + this.SocialLikes
}

func (this *Meme) CanInvest() ( bool) {

	return !this.IsExpired
}

func (this *Meme) DaysToExpire() ( string) {
	diff := this.ExpirationDate.Sub(time.Now()).Hours()
	expireString := strconv.Itoa(int(diff/24)) + " days left"
	if diff < 0 {
		expireString = "Expired"
	}
	return expireString
}

func GetMemeFromId(id string) (objs *Meme, err error) {
	ctx := context.Background()

	key := datastore.NameKey("meme", id, nil)
	var data Meme
	er := shared.DatastoreClient.Get(ctx, key, &data)

	if er != nil {
		return nil, er
	}

	return &data, nil

}

func GetMemeFromKey(key *datastore.Key) (objs *Meme, err error) {
	ctx := context.Background()

	var data Meme
	er := shared.DatastoreClient.Get(ctx, key, &data)

	if er != nil {
		return nil, er
	}

	return &data, nil

}

func GetRecentMemes(offset int, pageSize int, fromTime time.Time) (objs *[]Meme, total int, err error) {

	ctx := context.Background()
	q := datastore.NewQuery("meme")
	q = q.Filter("CreatedDate <", fromTime)
	q = q.Order("-CreatedDate")
	q = q.Offset(offset)
	q = q.Limit(pageSize)

	var data []Meme
	_, er := shared.DatastoreClient.GetAll(ctx, q, &data)

	//count for pagination
	q = datastore.NewQuery("meme")
	count := 0
	count, er = shared.DatastoreClient.Count(ctx, q, )

	if er != nil {
		return nil, 0, er
	}
	return &data, count , nil
}

func GetTopMemes(offset int, pageSize int) (objs *[]Meme, total int, err error) {
	ctx := context.Background()
	q := datastore.NewQuery("meme")
	//q = q.Filter("IsExpired =",false)
	q = q.Order("-TotalFame")
	q = q.Offset(offset)
	q = q.Limit(pageSize)
	var data []Meme
	it := shared.DatastoreClient.Run(ctx, q)
	for {
		var meme Meme
		_, err := it.Next(&meme)
		if err == iterator.Done {
			break
		}
		if err != nil {
			println(err.Error())
			break
		}
		data = append(data, meme)

	}

	//count for pagination
	q = datastore.NewQuery("meme")

	count, er := shared.DatastoreClient.Count(ctx, q, )

	if er != nil {
		return nil, 0, er
	}

	return &data, count , nil
}

func GetRecentMemesByUser(key string ,offset int, pageSize int) (objs *[]Meme, total int, err error) {

	ctx := context.Background()
	q := datastore.NewQuery("meme")

	q = q.Filter("CreatedUserId =", key)
	q = q.Offset(offset)
	q = q.Limit(pageSize)

	var data []Meme
	_, er := shared.DatastoreClient.GetAll(ctx, q, &data)

	//count for pagination
	q = datastore.NewQuery("meme")
	count := 0
	count, er = shared.DatastoreClient.Count(ctx, q, )

	if er != nil {
		return nil, 0, er
	}
	return &data, count , nil
}

func GetAllMemes( ) (objs *[]Meme, err error) {
	ctx := context.Background()
	q := datastore.NewQuery("meme")

	var data []Meme
	_, er := shared.DatastoreClient.GetAll(ctx, q, &data)

	if er != nil {
		return nil, er
	}
	return &data , nil
}

func GetToBeExpiredMemes( ) (objs *[]Meme, err error) {
	ctx := context.Background()
	q := datastore.NewQuery("meme").Filter("ExpirationDate <", time.Now()).Filter("IsExpired =", false)

	var data []Meme
	_, er := shared.DatastoreClient.GetAll(ctx, q, &data)

	if er != nil {
		return nil, er
	}
	return &data , nil
}
<|endoftext|>