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

package ddl

import (
	"github.com/juju/errors"
	"github.com/pingcap/tidb/meta"
	"github.com/pingcap/tidb/meta/autoid"
	"github.com/pingcap/tidb/model"
	"github.com/pingcap/tidb/table"
	"github.com/pingcap/tidb/util/errors2"
)

func (d *ddl) onSchemaCreate(t *meta.TMeta, job *model.Job) error {
	schemaID := job.SchemaID
	var name model.CIStr
	if err := job.DecodeArgs(&name); err != nil {
		// arg error, cancel this job.
		job.State = model.JobCancelled
		return errors.Trace(err)
	}

	var dbInfo *model.DBInfo
	dbs, err := t.ListDatabases()
	if err != nil {
		return errors.Trace(err)
	}

	for _, db := range dbs {
		if db.Name.L == name.L {
			if db.ID != schemaID {
				// database exists, can't create, we should cancel this job now.
				job.State = model.JobCancelled
				return errors.Trace(ErrExists)
			}

			dbInfo = db
		}
	}

	_, err = t.GenSchemaVersion()
	if err != nil {
		return errors.Trace(err)
	}

	if dbInfo == nil {
		// first create, enter delete only state
		dbInfo = &model.DBInfo{
			ID:    schemaID,
			Name:  name,
			State: model.StateDeleteOnly,
		}

		err = t.CreateDatabase(dbInfo)
		return errors.Trace(err)
	}

	switch dbInfo.State {
	case model.StateDeleteOnly:
		// delete only -> write only
		dbInfo.State = model.StateWriteOnly
		err = t.UpdateDatabase(dbInfo)
		return errors.Trace(err)
	case model.StateWriteOnly:
		// write only -> public
		dbInfo.State = model.StatePublic
		err = t.UpdateDatabase(dbInfo)
		if err != nil {
			return errors.Trace(err)
		}

		// finish this job.
		job.State = model.JobDone
		return nil
	default:
		// we can't enter here.
		return errors.Errorf("invalid db state %v", dbInfo.State)
	}
}

func (d *ddl) onSchemaDrop(t *meta.TMeta, job *model.Job) error {
	dbInfo, err := t.GetDatabase(job.SchemaID)
	if err != nil {
		return errors.Trace(err)
	}
	if dbInfo == nil {
		job.State = model.JobCancelled
		return errors.Trace(ErrNotExists)
	}

	_, err = t.GenSchemaVersion()
	if err != nil {
		return errors.Trace(err)
	}

	switch dbInfo.State {
	case model.StatePublic:
		// public -> write only
		dbInfo.State = model.StateWriteOnly
		err = t.UpdateDatabase(dbInfo)
		return errors.Trace(err)
	case model.StateWriteOnly:
		// write only -> delete only
		dbInfo.State = model.StateDeleteOnly
		err = t.UpdateDatabase(dbInfo)
		return errors.Trace(err)
	case model.StateDeleteOnly:
		// delete only -> reorgnization
		dbInfo.State = model.StateReorgnization
		err = t.UpdateDatabase(dbInfo)
		return errors.Trace(err)
	case model.StateReorgnization:
		// wait reorgnization jobs done and drop meta.
		var tables []*model.TableInfo
		tables, err = t.ListTables(dbInfo.ID)
		if err != nil {
			return errors.Trace(err)
		}

		err = d.runReorgJob(func() error {
			return d.dropSchemaData(dbInfo, tables)
		})

		if errors2.ErrorEqual(err, errWaitReorgTimeout) {
			// if timeout, we will return, check the owner and retry wait job done again.
			return nil
		} else if err != nil {
			return errors.Trace(err)
		}

		// all reorgnization jobs done, drop this database
		if err = t.DropDatabase(dbInfo.ID); err != nil {
			return errors.Trace(err)
		}

		// finish this job
		job.State = model.JobDone
		return nil
	default:
		// we can't enter here.
		return errors.Errorf("invalid db state %v", dbInfo.State)
	}
}

func (d *ddl) dropSchemaData(dbInfo *model.DBInfo, tables []*model.TableInfo) error {
	ctx := d.newReorgContext()
	defer ctx.FinishTxn(true)

	txn, err := ctx.GetTxn(true)

	for _, tblInfo := range tables {

		alloc := autoid.NewAllocator(d.meta, dbInfo.ID)
		t := table.TableFromMeta(dbInfo.Name.L, alloc, tblInfo)

		err = t.Truncate(ctx)
		if err != nil {
			return errors.Trace(err)
		}

		// Remove indices.
		for _, v := range t.Indices() {
			if v != nil && v.X != nil {
				if err = v.X.Drop(txn); err != nil {
					return errors.Trace(err)
				}
			}
		}
	}
	return errors.Trace(ctx.FinishTxn(false))
}
<commit_msg>Tiny clean up<commit_after>// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package ddl

import (
	"github.com/juju/errors"
	"github.com/pingcap/tidb/meta"
	"github.com/pingcap/tidb/meta/autoid"
	"github.com/pingcap/tidb/model"
	"github.com/pingcap/tidb/table"
	"github.com/pingcap/tidb/util/errors2"
)

func (d *ddl) onSchemaCreate(t *meta.TMeta, job *model.Job) error {
	schemaID := job.SchemaID
	var name model.CIStr
	if err := job.DecodeArgs(&name); err != nil {
		// arg error, cancel this job.
		job.State = model.JobCancelled
		return errors.Trace(err)
	}

	var dbInfo *model.DBInfo
	dbs, err := t.ListDatabases()
	if err != nil {
		return errors.Trace(err)
	}

	for _, db := range dbs {
		if db.Name.L == name.L {
			if db.ID != schemaID {
				// database exists, can't create, we should cancel this job now.
				job.State = model.JobCancelled
				return errors.Trace(ErrExists)
			}

			dbInfo = db
		}
	}

	_, err = t.GenSchemaVersion()
	if err != nil {
		return errors.Trace(err)
	}

	if dbInfo == nil {
		// first create, enter delete only state
		dbInfo = &model.DBInfo{
			ID:    schemaID,
			Name:  name,
			State: model.StateDeleteOnly,
		}

		err = t.CreateDatabase(dbInfo)
		return errors.Trace(err)
	}

	switch dbInfo.State {
	case model.StateDeleteOnly:
		// delete only -> write only
		dbInfo.State = model.StateWriteOnly
		err = t.UpdateDatabase(dbInfo)
		return errors.Trace(err)
	case model.StateWriteOnly:
		// write only -> public
		dbInfo.State = model.StatePublic
		err = t.UpdateDatabase(dbInfo)
		if err != nil {
			return errors.Trace(err)
		}

		// finish this job.
		job.State = model.JobDone
		return nil
	default:
		// we can't enter here.
		return errors.Errorf("invalid db state %v", dbInfo.State)
	}
}

func (d *ddl) onSchemaDrop(t *meta.TMeta, job *model.Job) error {
	dbInfo, err := t.GetDatabase(job.SchemaID)
	if err != nil {
		return errors.Trace(err)
	}
	if dbInfo == nil {
		job.State = model.JobCancelled
		return errors.Trace(ErrNotExists)
	}

	_, err = t.GenSchemaVersion()
	if err != nil {
		return errors.Trace(err)
	}

	switch dbInfo.State {
	case model.StatePublic:
		// public -> write only
		dbInfo.State = model.StateWriteOnly
		err = t.UpdateDatabase(dbInfo)
		return errors.Trace(err)
	case model.StateWriteOnly:
		// write only -> delete only
		dbInfo.State = model.StateDeleteOnly
		err = t.UpdateDatabase(dbInfo)
		return errors.Trace(err)
	case model.StateDeleteOnly:
		// delete only -> reorgnization
		dbInfo.State = model.StateReorgnization
		err = t.UpdateDatabase(dbInfo)
		return errors.Trace(err)
	case model.StateReorgnization:
		// wait reorgnization jobs done and drop meta.
		var tables []*model.TableInfo
		tables, err = t.ListTables(dbInfo.ID)
		if err != nil {
			return errors.Trace(err)
		}

		err = d.runReorgJob(func() error {
			return d.dropSchemaData(dbInfo, tables)
		})

		if errors2.ErrorEqual(err, errWaitReorgTimeout) {
			// if timeout, we should return, check for the owner and re-wait job done.
			return nil
		}
		if err != nil {
			return errors.Trace(err)
		}

		// all reorgnization jobs done, drop this database
		if err = t.DropDatabase(dbInfo.ID); err != nil {
			return errors.Trace(err)
		}

		// finish this job
		job.State = model.JobDone
		return nil
	default:
		// we can't enter here.
		return errors.Errorf("invalid db state %v", dbInfo.State)
	}
}

func (d *ddl) dropSchemaData(dbInfo *model.DBInfo, tables []*model.TableInfo) error {
	ctx := d.newReorgContext()
	txn, err := ctx.GetTxn(true)

	for _, tblInfo := range tables {
		alloc := autoid.NewAllocator(d.meta, dbInfo.ID)
		t := table.TableFromMeta(dbInfo.Name.L, alloc, tblInfo)
		err = t.Truncate(ctx)
		if err != nil {
			ctx.FinishTxn(true)
			return errors.Trace(err)
		}

		// Remove indices.
		for _, v := range t.Indices() {
			if v != nil && v.X != nil {
				if err = v.X.Drop(txn); err != nil {
					ctx.FinishTxn(true)
					return errors.Trace(err)
				}
			}
		}
	}
	return errors.Trace(ctx.FinishTxn(false))
}
<|endoftext|>


<commit_before>// +build darwin

package gopsutil

import (
	"os/exec"
	"strconv"
	"strings"
)

// sys/resource.h
const (
	CPUser    = 0
	CPNice    = 1
	CPSys     = 2
	CPIntr    = 3
	CPIdle    = 4
	CPUStates = 5
)

// time.h
const (
	ClocksPerSec = 128
)

// TODO: get per cpus
func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
	var ret []CPUTimesStat

	cpuTime, err := doSysctrl("kern.cp_time")
	if err != nil {
		return ret, err
	}

	user, err := strconv.ParseFloat(cpuTime[CPUser], 32)
	if err != nil {
		return ret, err
	}
	nice, err := strconv.ParseFloat(cpuTime[CPNice], 32)
	if err != nil {
		return ret, err
	}
	sys, err := strconv.ParseFloat(cpuTime[CPSys], 32)
	if err != nil {
		return ret, err
	}
	idle, err := strconv.ParseFloat(cpuTime[CPIdle], 32)
	if err != nil {
		return ret, err
	}
	intr, err := strconv.ParseFloat(cpuTime[CPIntr], 32)
	if err != nil {
		return ret, err
	}

	c := CPUTimesStat{
		User:   float32(user / ClocksPerSec),
		Nice:   float32(nice / ClocksPerSec),
		System: float32(sys / ClocksPerSec),
		Idle:   float32(idle / ClocksPerSec),
		Irq:    float32(intr / ClocksPerSec),
	}

	ret = append(ret, c)

	return ret, nil
}

// Returns only one CPUInfoStat on FreeBSD
func CPUInfo() ([]CPUInfoStat, error) {
	var ret []CPUInfoStat

	out, err := exec.Command("/usr/sbin/sysctl", "machdep.cpu").Output()
	if err != nil {
		return ret, err
	}

	c := CPUInfoStat{}
	for _, line := range strings.Split(string(out), "\n") {
		values := strings.Fields(line)

		t, err := strconv.ParseInt(values[1], 10, 32)
		if err != nil {
			return ret, err
		}
		if strings.HasPrefix(line, "machdep.cpu.brand_string") {
			c.ModelName = strings.Join(values[1:], " ")
		} else if strings.HasPrefix(line, "machdep.cpu.family") {
			c.Family = values[1]
		} else if strings.HasPrefix(line, "machdep.cpu.model") {
			c.Model = values[1]
		} else if strings.HasPrefix(line, "machdep.cpu.stepping") {
			c.Stepping = int32(t)
		} else if strings.HasPrefix(line, "machdep.cpu.features") {
			for _, v := range values[1:] {
				c.Flags = append(c.Flags, strings.ToLower(v))
			}
		} else if strings.HasPrefix(line, "machdep.cpu.leaf7_features") {
			for _, v := range values[1:] {
				c.Flags = append(c.Flags, strings.ToLower(v))
			}
		} else if strings.HasPrefix(line, "machdep.cpu.extfeatures") {
			for _, v := range values[1:] {
				c.Flags = append(c.Flags, strings.ToLower(v))
			}
		} else if strings.HasPrefix(line, "machdep.cpu.core_count") {
			c.Cores = int32(t)
		} else if strings.HasPrefix(line, "machdep.cpu.cache.size") {
			c.CacheSize = int32(t)
		} else if strings.HasPrefix(line, "machdep.cpu.vendor") {
			c.VendorID = values[1]
		}

		// TODO:
		// c.Mhz = mustParseFloat64(values[1])
	}

	return append(ret, c), nil
}
<commit_msg>fix cpu info outofrange error on darwin.<commit_after>// +build darwin

package gopsutil

import (
	"os/exec"
	"strconv"
	"strings"
)

// sys/resource.h
const (
	CPUser    = 0
	CPNice    = 1
	CPSys     = 2
	CPIntr    = 3
	CPIdle    = 4
	CPUStates = 5
)

// time.h
const (
	ClocksPerSec = 128
)

// TODO: get per cpus
func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
	var ret []CPUTimesStat

	cpuTime, err := doSysctrl("kern.cp_time")
	if err != nil {
		return ret, err
	}

	user, err := strconv.ParseFloat(cpuTime[CPUser], 32)
	if err != nil {
		return ret, err
	}
	nice, err := strconv.ParseFloat(cpuTime[CPNice], 32)
	if err != nil {
		return ret, err
	}
	sys, err := strconv.ParseFloat(cpuTime[CPSys], 32)
	if err != nil {
		return ret, err
	}
	idle, err := strconv.ParseFloat(cpuTime[CPIdle], 32)
	if err != nil {
		return ret, err
	}
	intr, err := strconv.ParseFloat(cpuTime[CPIntr], 32)
	if err != nil {
		return ret, err
	}

	c := CPUTimesStat{
		User:   float32(user / ClocksPerSec),
		Nice:   float32(nice / ClocksPerSec),
		System: float32(sys / ClocksPerSec),
		Idle:   float32(idle / ClocksPerSec),
		Irq:    float32(intr / ClocksPerSec),
	}

	ret = append(ret, c)

	return ret, nil
}

// Returns only one CPUInfoStat on FreeBSD
func CPUInfo() ([]CPUInfoStat, error) {
	var ret []CPUInfoStat

	out, err := exec.Command("/usr/sbin/sysctl", "machdep.cpu").Output()
	if err != nil {
		return ret, err
	}

	c := CPUInfoStat{}
	for _, line := range strings.Split(string(out), "\n") {
		values := strings.Fields(line)

		t, err := strconv.ParseInt(values[1], 10, 64)
		if err != nil {
			return ret, err
		}
		if strings.HasPrefix(line, "machdep.cpu.brand_string") {
			c.ModelName = strings.Join(values[1:], " ")
		} else if strings.HasPrefix(line, "machdep.cpu.family") {
			c.Family = values[1]
		} else if strings.HasPrefix(line, "machdep.cpu.model") {
			c.Model = values[1]
		} else if strings.HasPrefix(line, "machdep.cpu.stepping") {
			c.Stepping = int32(t)
		} else if strings.HasPrefix(line, "machdep.cpu.features") {
			for _, v := range values[1:] {
				c.Flags = append(c.Flags, strings.ToLower(v))
			}
		} else if strings.HasPrefix(line, "machdep.cpu.leaf7_features") {
			for _, v := range values[1:] {
				c.Flags = append(c.Flags, strings.ToLower(v))
			}
		} else if strings.HasPrefix(line, "machdep.cpu.extfeatures") {
			for _, v := range values[1:] {
				c.Flags = append(c.Flags, strings.ToLower(v))
			}
		} else if strings.HasPrefix(line, "machdep.cpu.core_count") {
			c.Cores = int32(t)
		} else if strings.HasPrefix(line, "machdep.cpu.cache.size") {
			c.CacheSize = int32(t)
		} else if strings.HasPrefix(line, "machdep.cpu.vendor") {
			c.VendorID = values[1]
		}

		// TODO:
		// c.Mhz = mustParseFloat64(values[1])
	}

	return append(ret, c), nil
}
<|endoftext|>


<commit_before>package freetds

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"strings"
	"time"
)

const (
	//name               database type   go type
	SYBINT1 = 48  //tinyint       uint8
	SYBINT2 = 52  //smallint      int16
	SYBINT4 = 56  //int           int32
	SYBINT8 = 127 //bigint        int64

	SYBCHAR      = 47
	SYBVARCHAR   = 39  //varchar       string
	SYBNVARCHAR  = 103 //nvarchar      string
	XSYBNVARCHAR = 231 //nvarchar      string
	XSYBNCHAR    = 239 //nchar         string

	SYBREAL = 59 //real          float32
	SYBFLT8 = 62 //float(53)     float64

	SYBBIT  = 50  //bit           bool
	SYBBITN = 104 //bit           bool

	SYBMONEY4 = 122 //smallmoney    float64
	SYBMONEY  = 60  //money         float64

	SYBDATETIME  = 61 //datetime      time.Time
	SYBDATETIME4 = 58 //smalldatetime time.Time

	SYBIMAGE      = 34  //image         []byte
	SYBBINARY     = 45  //binary        []byte
	SYBVARBINARY  = 37  //varbinary     []byte
	XSYBVARBINARY = 165 //varbinary     []byte

	SYBNUMERIC = 108
	SYBDECIMAL = 106

	SYBUNIQUE = 36 //uniqueidentifier string
)

var sqlStartTime = time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC)

func toLocalTime(value time.Time) time.Time {
	value = value.In(time.Local)
	_, of := value.Zone()
	value = value.Add(time.Duration(-of) * time.Second)
	return value
}

func sqlBufToType(datatype int, data []byte) interface{} {
	buf := bytes.NewBuffer(data)
	switch datatype {
	case SYBINT1:
		var value uint8
		binary.Read(buf, binary.LittleEndian, &value)
		return value
	case SYBINT2:
		var value int16
		binary.Read(buf, binary.LittleEndian, &value)
		return value
	case SYBINT4:
		var value int32
		binary.Read(buf, binary.LittleEndian, &value)
		return value
	case SYBINT8:
		var value int64
		binary.Read(buf, binary.LittleEndian, &value)
		return value
	case SYBDATETIME:
		var days int32 /* number of days since 1/1/1900 */
		var sec uint32 /* 300ths of a second since midnight */
		binary.Read(buf, binary.LittleEndian, &days)
		binary.Read(buf, binary.LittleEndian, &sec)
		value := sqlStartTime.Add(time.Duration(days) * time.Hour * 24).Add(time.Duration(sec) * time.Second / 300)
		return toLocalTime(value)
	case SYBDATETIME4:
		var days uint16 /* number of days since 1/1/1900 */
		var mins uint16 /* number of minutes since midnight */
		binary.Read(buf, binary.LittleEndian, &days)
		binary.Read(buf, binary.LittleEndian, &mins)
		value := sqlStartTime.Add(time.Duration(days) * time.Hour * 24).Add(time.Duration(mins) * time.Minute)
		return toLocalTime(value)
	case SYBMONEY:
		var high int32
		var low uint32
		binary.Read(buf, binary.LittleEndian, &high)
		binary.Read(buf, binary.LittleEndian, &low)
		return float64(int64(high)*4294967296+int64(low)) / 10000
	case SYBMONEY4:
		var value int32
		binary.Read(buf, binary.LittleEndian, &value)
		return float64(value) / 10000
	case SYBREAL:
		var value float32
		binary.Read(buf, binary.LittleEndian, &value)
		return value
	case SYBFLT8:
		var value float64
		binary.Read(buf, binary.LittleEndian, &value)
		return value
	case SYBBIT, SYBBITN:
		return data[0] == 1
	case SYBIMAGE, SYBVARBINARY, SYBBINARY, XSYBVARBINARY:
		return append([]byte{}, data[:len(data)-1]...) // make copy of data

	default: //string
		len := strings.Index(string(data), "\x00")
		if len == -1 {
			return string(data)
		}
		return string(data[:len])
	}
}

func typeToSqlBuf(datatype int, value interface{}) (data []byte, err error) {
	buf := new(bytes.Buffer)
	switch datatype {
	case SYBINT1:
		var ui8 uint8
		if err = convertAssign(&ui8, value); err == nil {
			err = binary.Write(buf, binary.LittleEndian, ui8)
		}
	case SYBINT2:
		var i16 int16
		if err = convertAssign(&i16, value); err == nil {
			err = binary.Write(buf, binary.LittleEndian, i16)
		}
	case SYBINT4:
		var i32 int32
		if err = convertAssign(&i32, value); err == nil {
			err = binary.Write(buf, binary.LittleEndian, i32)
		}
	case SYBINT8:
		var i64 int64
		if err = convertAssign(&i64, value); err == nil {
			err = binary.Write(buf, binary.LittleEndian, i64)
		}
	case SYBREAL:
		var f32 float32
		if err = convertAssign(&f32, value); err == nil {
			err = binary.Write(buf, binary.LittleEndian, f32)
		}
	case SYBFLT8:
		var f64 float64
		if err = convertAssign(&f64, value); err == nil {
			err = binary.Write(buf, binary.LittleEndian, f64)
		}
	case SYBBIT, SYBBITN:
		if typedValue, ok := value.(bool); ok {
			if typedValue {
				data = []byte{1}
			} else {
				data = []byte{0}
			}
			return
		} else {
			err = errors.New(fmt.Sprintf("Could not convert %T to bool.", value))
		}
	case SYBMONEY4:
		var f64 float64
		if err = convertAssign(&f64, value); err == nil {
			i32 := int32(f64 * 10000)
			err = binary.Write(buf, binary.LittleEndian, i32)
		}
	case SYBMONEY:
		var f64 float64
		if err = convertAssign(&f64, value); err == nil {
			intValue := int64(f64 * 10000)
			high := int32(intValue >> 32)
			low := uint32(intValue - int64(high))
			err = binary.Write(buf, binary.LittleEndian, high)
			if err == nil {
				err = binary.Write(buf, binary.LittleEndian, low)
			}
		}
	case SYBDATETIME:
		//database time is always in local timezone
		if tm, ok := value.(time.Time); ok {
			tm = tm.Local()
			diff := tm.UnixNano() - sqlStartTime.UnixNano()
			_, of := tm.Zone()
			diff += int64(time.Duration(of) * time.Second)
			days := int32(diff / 1e9 / 60 / 60 / 24)
			secs := uint32(float64(diff-int64(days)*1e9*60*60*24) * 0.0000003)
			err = binary.Write(buf, binary.LittleEndian, days)
			if err == nil {
				err = binary.Write(buf, binary.LittleEndian, secs)
			}
		} else {
			err = errors.New(fmt.Sprintf("Could not convert %T to time.Time.", value))
		}
	case SYBDATETIME4:
		if tm, ok := value.(time.Time); ok {
			tm = tm.Local()
			diff := tm.Unix() - sqlStartTime.Unix()
			_, of := tm.Zone()
			diff += int64(of)
			days := uint16(diff / 60 / 60 / 24)
			mins := uint16((diff - int64(days)*60*60*24) / 60)
			err = binary.Write(buf, binary.LittleEndian, days)
			if err == nil {
				err = binary.Write(buf, binary.LittleEndian, mins)
			}
		} else {
			err = errors.New(fmt.Sprintf("Could not convert %T to time.Time.", value))
		}
	case SYBIMAGE, SYBVARBINARY, SYBBINARY, XSYBVARBINARY:
		if buf, ok := value.([]byte); ok {
			data = append(buf, []byte{0}[0])
			return
		} else {
			err = errors.New(fmt.Sprintf("Could not convert %T to []byte.", value))
		}
	default:
		if str, ok := value.(string); ok {
			if str == "" {
				//dbrpcparam treats any data with datalen 0 as NULL value
				//(rpc.c line 241 in freetds)
				//It is kinda safe to put this into db if len function is used to check for emtpy strings.
				//Len strips trailing spaces, and returns 0 for ' '.
				//Links:
				//  https://github.com/pymssql/pymssql/issues/243
				//  http://stackoverflow.com/questions/2025585/len-function-not-including-trailing-spaces-in-sql-server
				str = " "
				data = []byte{32}
				return
			}
			data = []byte(str)

			if datatype == XSYBNVARCHAR || datatype == XSYBNCHAR {
				//FIXME - adding len bytes to the end of the buf
				//        realy don't understand why this is necessary
				//        come to this solution by try and error
				l := len(data)
				for i := 0; i < l; i++ {
					data = append(data, byte(0))
				}
			}
			return
		} else {
			err = errors.New(fmt.Sprintf("Could not convert %T to string.", value))
		}
	}
	data = buf.Bytes()
	return
}
<commit_msg>Removing unused line<commit_after>package freetds

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"strings"
	"time"
)

const (
	//name               database type   go type
	SYBINT1 = 48  //tinyint       uint8
	SYBINT2 = 52  //smallint      int16
	SYBINT4 = 56  //int           int32
	SYBINT8 = 127 //bigint        int64

	SYBCHAR      = 47
	SYBVARCHAR   = 39  //varchar       string
	SYBNVARCHAR  = 103 //nvarchar      string
	XSYBNVARCHAR = 231 //nvarchar      string
	XSYBNCHAR    = 239 //nchar         string

	SYBREAL = 59 //real          float32
	SYBFLT8 = 62 //float(53)     float64

	SYBBIT  = 50  //bit           bool
	SYBBITN = 104 //bit           bool

	SYBMONEY4 = 122 //smallmoney    float64
	SYBMONEY  = 60  //money         float64

	SYBDATETIME  = 61 //datetime      time.Time
	SYBDATETIME4 = 58 //smalldatetime time.Time

	SYBIMAGE      = 34  //image         []byte
	SYBBINARY     = 45  //binary        []byte
	SYBVARBINARY  = 37  //varbinary     []byte
	XSYBVARBINARY = 165 //varbinary     []byte

	SYBNUMERIC = 108
	SYBDECIMAL = 106

	SYBUNIQUE = 36 //uniqueidentifier string
)

var sqlStartTime = time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC)

func toLocalTime(value time.Time) time.Time {
	value = value.In(time.Local)
	_, of := value.Zone()
	value = value.Add(time.Duration(-of) * time.Second)
	return value
}

func sqlBufToType(datatype int, data []byte) interface{} {
	buf := bytes.NewBuffer(data)
	switch datatype {
	case SYBINT1:
		var value uint8
		binary.Read(buf, binary.LittleEndian, &value)
		return value
	case SYBINT2:
		var value int16
		binary.Read(buf, binary.LittleEndian, &value)
		return value
	case SYBINT4:
		var value int32
		binary.Read(buf, binary.LittleEndian, &value)
		return value
	case SYBINT8:
		var value int64
		binary.Read(buf, binary.LittleEndian, &value)
		return value
	case SYBDATETIME:
		var days int32 /* number of days since 1/1/1900 */
		var sec uint32 /* 300ths of a second since midnight */
		binary.Read(buf, binary.LittleEndian, &days)
		binary.Read(buf, binary.LittleEndian, &sec)
		value := sqlStartTime.Add(time.Duration(days) * time.Hour * 24).Add(time.Duration(sec) * time.Second / 300)
		return toLocalTime(value)
	case SYBDATETIME4:
		var days uint16 /* number of days since 1/1/1900 */
		var mins uint16 /* number of minutes since midnight */
		binary.Read(buf, binary.LittleEndian, &days)
		binary.Read(buf, binary.LittleEndian, &mins)
		value := sqlStartTime.Add(time.Duration(days) * time.Hour * 24).Add(time.Duration(mins) * time.Minute)
		return toLocalTime(value)
	case SYBMONEY:
		var high int32
		var low uint32
		binary.Read(buf, binary.LittleEndian, &high)
		binary.Read(buf, binary.LittleEndian, &low)
		return float64(int64(high)*4294967296+int64(low)) / 10000
	case SYBMONEY4:
		var value int32
		binary.Read(buf, binary.LittleEndian, &value)
		return float64(value) / 10000
	case SYBREAL:
		var value float32
		binary.Read(buf, binary.LittleEndian, &value)
		return value
	case SYBFLT8:
		var value float64
		binary.Read(buf, binary.LittleEndian, &value)
		return value
	case SYBBIT, SYBBITN:
		return data[0] == 1
	case SYBIMAGE, SYBVARBINARY, SYBBINARY, XSYBVARBINARY:
		return append([]byte{}, data[:len(data)-1]...) // make copy of data

	default: //string
		len := strings.Index(string(data), "\x00")
		if len == -1 {
			return string(data)
		}
		return string(data[:len])
	}
}

func typeToSqlBuf(datatype int, value interface{}) (data []byte, err error) {
	buf := new(bytes.Buffer)
	switch datatype {
	case SYBINT1:
		var ui8 uint8
		if err = convertAssign(&ui8, value); err == nil {
			err = binary.Write(buf, binary.LittleEndian, ui8)
		}
	case SYBINT2:
		var i16 int16
		if err = convertAssign(&i16, value); err == nil {
			err = binary.Write(buf, binary.LittleEndian, i16)
		}
	case SYBINT4:
		var i32 int32
		if err = convertAssign(&i32, value); err == nil {
			err = binary.Write(buf, binary.LittleEndian, i32)
		}
	case SYBINT8:
		var i64 int64
		if err = convertAssign(&i64, value); err == nil {
			err = binary.Write(buf, binary.LittleEndian, i64)
		}
	case SYBREAL:
		var f32 float32
		if err = convertAssign(&f32, value); err == nil {
			err = binary.Write(buf, binary.LittleEndian, f32)
		}
	case SYBFLT8:
		var f64 float64
		if err = convertAssign(&f64, value); err == nil {
			err = binary.Write(buf, binary.LittleEndian, f64)
		}
	case SYBBIT, SYBBITN:
		if typedValue, ok := value.(bool); ok {
			if typedValue {
				data = []byte{1}
			} else {
				data = []byte{0}
			}
			return
		} else {
			err = errors.New(fmt.Sprintf("Could not convert %T to bool.", value))
		}
	case SYBMONEY4:
		var f64 float64
		if err = convertAssign(&f64, value); err == nil {
			i32 := int32(f64 * 10000)
			err = binary.Write(buf, binary.LittleEndian, i32)
		}
	case SYBMONEY:
		var f64 float64
		if err = convertAssign(&f64, value); err == nil {
			intValue := int64(f64 * 10000)
			high := int32(intValue >> 32)
			low := uint32(intValue - int64(high))
			err = binary.Write(buf, binary.LittleEndian, high)
			if err == nil {
				err = binary.Write(buf, binary.LittleEndian, low)
			}
		}
	case SYBDATETIME:
		//database time is always in local timezone
		if tm, ok := value.(time.Time); ok {
			tm = tm.Local()
			diff := tm.UnixNano() - sqlStartTime.UnixNano()
			_, of := tm.Zone()
			diff += int64(time.Duration(of) * time.Second)
			days := int32(diff / 1e9 / 60 / 60 / 24)
			secs := uint32(float64(diff-int64(days)*1e9*60*60*24) * 0.0000003)
			err = binary.Write(buf, binary.LittleEndian, days)
			if err == nil {
				err = binary.Write(buf, binary.LittleEndian, secs)
			}
		} else {
			err = errors.New(fmt.Sprintf("Could not convert %T to time.Time.", value))
		}
	case SYBDATETIME4:
		if tm, ok := value.(time.Time); ok {
			tm = tm.Local()
			diff := tm.Unix() - sqlStartTime.Unix()
			_, of := tm.Zone()
			diff += int64(of)
			days := uint16(diff / 60 / 60 / 24)
			mins := uint16((diff - int64(days)*60*60*24) / 60)
			err = binary.Write(buf, binary.LittleEndian, days)
			if err == nil {
				err = binary.Write(buf, binary.LittleEndian, mins)
			}
		} else {
			err = errors.New(fmt.Sprintf("Could not convert %T to time.Time.", value))
		}
	case SYBIMAGE, SYBVARBINARY, SYBBINARY, XSYBVARBINARY:
		if buf, ok := value.([]byte); ok {
			data = append(buf, []byte{0}[0])
			return
		} else {
			err = errors.New(fmt.Sprintf("Could not convert %T to []byte.", value))
		}
	default:
		if str, ok := value.(string); ok {
			if str == "" {
				//dbrpcparam treats any data with datalen 0 as NULL value
				//(rpc.c line 241 in freetds)
				//It is kinda safe to put this into db if len function is used to check for emtpy strings.
				//Len strips trailing spaces, and returns 0 for ' '.
				//Links:
				//  https://github.com/pymssql/pymssql/issues/243
				//  http://stackoverflow.com/questions/2025585/len-function-not-including-trailing-spaces-in-sql-server
				data = []byte{32}
				return
			}
			data = []byte(str)

			if datatype == XSYBNVARCHAR || datatype == XSYBNCHAR {
				//FIXME - adding len bytes to the end of the buf
				//        realy don't understand why this is necessary
				//        come to this solution by try and error
				l := len(data)
				for i := 0; i < l; i++ {
					data = append(data, byte(0))
				}
			}
			return
		} else {
			err = errors.New(fmt.Sprintf("Could not convert %T to string.", value))
		}
	}
	data = buf.Bytes()
	return
}
<|endoftext|>


<commit_before>// Copyright © 2017 NAME HERE <EMAIL ADDRESS>
//
// 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 cmd

import (
	"log"

	"github.com/ncodes/cocoon/core/cluster"
	"github.com/ncodes/cocoon/core/pod"
	"github.com/spf13/cobra"
)

// deployCmd represents the deploy command
var deployCmd = &cobra.Command{
	Use:   "deploy",
	Short: "Deploy a smart contract to cocoon cluster",
	Long:  `This command deploys a smart contract to the cocoon cluster`,
	Run: func(cmd *cobra.Command, args []string) {

		lang, _ := cmd.Flags().GetString("lang")
		url, _ := cmd.Flags().GetString("url")
		tag, _ := cmd.Flags().GetString("tag")
		clusterAddr, _ := cmd.Flags().GetString("cluster_addr")
		clusterAddrHTTPS, _ := cmd.Flags().GetBool("cluster_addr_https")

		cl := cluster.NewNomad()
		cl.SetAddr(clusterAddr, clusterAddrHTTPS)
		cocoonID, err := pod.Deploy(cl, lang, url, tag)
		log.Println(cocoonID, err)
	},
}

func init() {
	RootCmd.AddCommand(deployCmd)
	deployCmd.Flags().StringP("lang", "l", "go", "The smart contract language")
	deployCmd.Flags().StringP("url", "u", "", "A zip file or github link to the smart contract")
	deployCmd.Flags().StringP("tag", "t", "", "The github release tag")
	deployCmd.Flags().StringP("cluster_addr", "", "127.0.0.1:4646", "The cluster address as host:port")
	deployCmd.Flags().BoolP("cluster_addr_https", "", false, "Whether to include `https` when accessing cluster APIs")

	deployCmd.MarkFlagRequired("lang")
	deployCmd.MarkFlagRequired("url")
}
<commit_msg>update dev cluster addr<commit_after>// Copyright © 2017 NAME HERE <EMAIL ADDRESS>
//
// 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 cmd

import (
	"log"

	"github.com/ncodes/cocoon/core/cluster"
	"github.com/ncodes/cocoon/core/pod"
	"github.com/spf13/cobra"
)

// deployCmd represents the deploy command
var deployCmd = &cobra.Command{
	Use:   "deploy",
	Short: "Deploy a smart contract to cocoon cluster",
	Long:  `This command deploys a smart contract to the cocoon cluster`,
	Run: func(cmd *cobra.Command, args []string) {

		lang, _ := cmd.Flags().GetString("lang")
		url, _ := cmd.Flags().GetString("url")
		tag, _ := cmd.Flags().GetString("tag")
		clusterAddr, _ := cmd.Flags().GetString("cluster_addr")
		clusterAddrHTTPS, _ := cmd.Flags().GetBool("cluster_addr_https")

		cl := cluster.NewNomad()
		cl.SetAddr(clusterAddr, clusterAddrHTTPS)
		cocoonID, err := pod.Deploy(cl, lang, url, tag)
		log.Println(cocoonID, err)
	},
}

func init() {
	RootCmd.AddCommand(deployCmd)
	deployCmd.Flags().StringP("lang", "l", "go", "The smart contract language")
	deployCmd.Flags().StringP("url", "u", "", "A zip file or github link to the smart contract")
	deployCmd.Flags().StringP("tag", "t", "", "The github release tag")
	deployCmd.Flags().StringP("cluster_addr", "", "104.199.18.198:4646", "The cluster address as host:port")
	deployCmd.Flags().BoolP("cluster_addr_https", "", false, "Whether to include `https` when accessing cluster APIs")

	deployCmd.MarkFlagRequired("lang")
	deployCmd.MarkFlagRequired("url")
}
<|endoftext|>


<commit_before>// author: Jacky Boen

package main

import (
	"fmt"
	"math/rand"
	"os"
	"sync"
	"time"

	"github.com/veandco/go-sdl2/sdl"
)

var winTitle string = "Go-SDL2 Render"
var winWidth, winHeight int = 800, 600

func run() int {
	var window *sdl.Window
	var renderer *sdl.Renderer

	window, err := sdl.CreateWindow(winTitle, sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
		winWidth, winHeight, sdl.WINDOW_SHOWN)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to create window: %s\n", err)
		return 1
	}
	defer window.Destroy()

	renderer, err = sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
	if err != nil {
		fmt.Fprint(os.Stderr, "Failed to create renderer: %s\n", err)
		os.Exit(2)
	}
	renderer.Clear()
	defer renderer.Destroy()

	// Set a WaitGroup to wait until all pixels are drawn
	var wg sync.WaitGroup

	for y := 0; y < winHeight; y++ {
		for x := 0; x < winWidth; x++ {
			wg.Add(1)

			go func(x, y int) {
				// Do some fake processing before rendering
				r := byte(rand.Int())
				g := byte(rand.Int())
				b := byte(rand.Int())
				time.Sleep(1 * time.Millisecond)

				// Call the render function in the 'render' thread synchronously
				sdl.CallQueue <- func() {
					renderer.SetDrawColor(r, g, b, 255)
					renderer.DrawPoint(x, y)
					wg.Done()
				}
			}(x, y)
		}
	}

	// Wait until all pixels are drawn
	wg.Wait()

	// Show the pixels for a while
	renderer.Present()
	sdl.Delay(3000)

	return 0
}

func main() {
	os.Exit(run())
}
<commit_msg>examples: render_goroutines: updated example to be more interesting and robust<commit_after>package main

import (
	"fmt"
	"math/rand"
	"os"
	"sync"

	"github.com/veandco/go-sdl2/sdl"
)

const (
	WindowTitle = "Go-SDL2 Render"
	WindowWidth = 800
	WindowHeight = 600
	FrameRate = 60

	RectWidth = 20
	RectHeight = 20
	NumRects = WindowHeight / RectHeight
)

var rects [NumRects]sdl.Rect

func run() int {
	var window *sdl.Window
	var renderer *sdl.Renderer
	var err error

	sdl.CallQueue <- func() {
		window, err = sdl.CreateWindow(WindowTitle, sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, WindowWidth, WindowHeight, sdl.WINDOW_OPENGL)
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to create window: %s\n", err)
		return 1
	}
	defer func() {
		sdl.CallQueue <- func() {
			window.Destroy()
		}
	}()

	sdl.CallQueue <- func() {
		renderer, err = sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
	}
	if err != nil {
		fmt.Fprint(os.Stderr, "Failed to create renderer: %s\n", err)
		return 2
	}
	defer func() {
		sdl.CallQueue <- func() {
			renderer.Destroy()
		}
	}()

	sdl.CallQueue <- func() {
		renderer.Clear()
	}

	for i := range rects {
		rects[i] = sdl.Rect{
			X: int32(rand.Int() % WindowWidth),
			Y: int32(i * WindowHeight / len(rects)),
			W: RectWidth,
			H: RectHeight,
		}
	}

	running := true
	for running {
		sdl.CallQueue <- func() {
			for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
				switch event.(type) {
				case *sdl.QuitEvent:
					running = false
				}
			}

			renderer.Clear()
			renderer.SetDrawColor(0, 0, 0, 0x20)
			renderer.FillRect(&sdl.Rect{0, 0, WindowWidth, WindowHeight})
		}

		// Do expensive stuff using goroutines
		wg := sync.WaitGroup{}
		for i := range rects {
			wg.Add(1)
			go func(i int) {
				rects[i].X = (rects[i].X + 10) % WindowWidth
				sdl.CallQueue <- func() {
					renderer.SetDrawColor(0xff, 0xff, 0xff, 0xff)
					renderer.DrawRect(&rects[i])
				}
				wg.Done()
			}(i)
		}
		wg.Wait()

		sdl.CallQueue <- func() {
			renderer.Present()
			sdl.Delay(1000 / FrameRate)
		}
	}

	return 0
}

func main() {
	os.Exit(run())
}
<|endoftext|>


<commit_before>package dns

import (
	"bytes"
	"encoding/binary"
)

func decompress(b []byte, off int) (string, int) {
	buf := bytes.NewBuffer(nil)
	off0 := off
	for {
		c := b[off]
		if c >= 0xc0 { // TODO: handle 01 and 10 bits cases
			// technically offset is uint14 value
			// But message won't be longer than 512...
			offset := binary.BigEndian.Uint16([]byte{c ^ 0xc0, b[off+1]})
			off++
			s, _ := decompress(b, int(offset))
			buf.WriteString(s)
			break
		} else {
			if c == 0x0 {
				off++
				break
			}
			l := int(b[off])
			off++
			buf.Write(b[off : off+l])
			off += l
			buf.WriteString(".")
		}
	}
	return buf.String(), off - off0
}
<commit_msg>Add comments to decompress<commit_after>package dns

import (
	"bytes"
	"encoding/binary"
)

// decompress implements RFC 1035: 4.1.4. Message compression"
// which follows the pointer of offsets until it finds 0x0.
// It returns labels as string and length of bytes read as int
func decompress(b []byte, off int) (string, int) {
	buf := bytes.NewBuffer(nil)
	off0 := off
	for {
		c := b[off]
		off++
		if c >= 0xc0 { // TODO: handle 01 and 10 bits cases
			// technically offset is uint14 value
			// But message won't be longer than 512...
			offset := binary.BigEndian.Uint16([]byte{c ^ 0xc0, b[off]})
			s, _ := decompress(b, int(offset))
			buf.WriteString(s)
			break
		} else {
			if c == 0x0 {
				break
			}
			l := int(c)
			buf.Write(b[off : off+l])
			off += l
			buf.WriteString(".")
		}
	}
	return buf.String(), off - off0
}
<|endoftext|>


<commit_before>package packager

import(
	tp "tritium/proto"
	proto "goprotobuf.googlecode.com/hg/proto"
	yaml "launchpad.net/goyaml"
	"io/ioutil"
	api "tritium/api"
	"log"
	"strings"
	linker "tritium/linker"
	parser "tritium/parser"
	"path/filepath"
	"log4go"
	"os"
	"tritium/crypto"
)

type Package struct {
	loaded []*PackageInfo
	location string
	LoadPath string
	Log log4go.Logger
	*tp.Package
	Options PackageOptions
}

type PackageInfo struct {
	Name string
	Dependencies []string
	Types []string
}

type PackageOptions map[string]bool

var defaultOptions PackageOptions
var buildOptions PackageOptions

func BuildOptions() PackageOptions {
	if buildOptions == nil {
		buildOptions =  PackageOptions{
			"stdout" : true,
			"output_tpkg" : true,
			"use_tpkg" : false,
		}
	}
	return buildOptions
}

func fetchDefaultOptions() PackageOptions{
	if defaultOptions == nil {
		defaultOptions = PackageOptions{
			"stdout":false,
			"output_tpkg":false,
			"use_tpkg":true,
		}
	}
	return defaultOptions
}

var DefaultPackagePath = "packages"

func LoadDefaultPackage() (*Package) {
	return buildPackage(nil)
}

func BuildDefaultPackage() (*Package) {
	options := BuildOptions()
	return buildPackage(options)
}

func buildPackage(options PackageOptions) (*Package) {
	// Terrible directory handling here... has to be executed from Tritium root

	pkg := NewPackage(DefaultPackagePath, options)
	pkg.Load("libxml")

	return pkg
}

func mergeOptions(options PackageOptions) PackageOptions {
	defaults := fetchDefaultOptions()

	if options == nil {
		return defaults
	}

	for k, _ := range defaults {
		_, ok := options[k]

		if !ok {
			options[k] = defaults[k]
		}
	}

	return options
}

func NewPackage(loadPath string, options PackageOptions) (*Package){
	options = mergeOptions(options)

	return &Package{
		Package: &tp.Package{
			Name: proto.String("combined"),
			Functions: make([]*tp.Function, 0),
			Types: make([]*tp.Type, 0),
		},
		loaded: make([]*PackageInfo, 0),
  	        Log: newLog(),
		LoadPath: loadPath,
	        Options: options,
	}
}

func newLog() (log4go.Logger) {
	pkgLog := make(log4go.Logger)
	os.Mkdir("log", uint32(0777) )

	pkgLog.AddFilter("file", log4go.FINE, log4go.NewFileLogWriter("log/debug.log", false))
	return pkgLog
}

func (pkg *Package)Load(packageName string) {
	user := api.FetchSessionUser()
	approved := user.RequestFeature("package:" + packageName)

	if !approved {
		panic("Package " + packageName + " not approved for use.")
	}

	old_location := pkg.location

	location := filepath.Join(pkg.LoadPath, packageName)
	pkg.location = location

	pkg.Println(location)
	pkg.Log.Info("\n\n\n\nLoading:%v", location)

	info := readPackageInfoFile(location)

	if len(info.Dependencies) > 0 {

		for _, dependency := range(info.Dependencies) {
			pkg.loadPackageDependency(dependency)
		}

	}

	for _, typeName := range(info.Types) {
		split := strings.Split(typeName, " < ")
		typeObj := &tp.Type{}
		if len(split) == 2 {
			typeName = split[0]
			index := pkg.findTypeIndex(split[1])

			typeObj.Implements = proto.Int32(int32(index))
		}
		typeObj.Name = proto.String(typeName)
		pkg.Types = append(pkg.Types, typeObj)
	}

	pkg.readHeaderFile(location)

	pkg.readPackageDefinitions(location)

	pkg.inheritFunctions()

	if pkg.Options["output_tpkg"] {
		pkg.write()
	}

	pkg.Println(" -- done")
	pkg.Log.Close()

	// TODO(SJ) : Kind of lame. Ideally I think we load other packages as whole packages and write a *.Merge method
	pkg.location = old_location

}

func (pkg *Package)resolveFunction(fun *tp.Function) {
	linkingContext := linker.NewLinkingContext(pkg.Package)

//	pkg.resolveFunctionDescendants(fun)

	pkg.Log.Info("\t -- Resolving --\n")
	pkg.Log.Info("\t\t -- function: %v\n", fun)

	// Re-uses linker's logic to resolve function definitions
	if ( proto.GetBool( fun.BuiltIn ) == false) {
		typeName := proto.GetString(fun.ScopeType)

		if len(typeName) != 0 {
			// When I pass in functions from the inheritance resolver, they're typeId is already set
			fun.ScopeTypeId = pkg.GetProtoTypeId(fun.ScopeType)
			fun.ScopeType = nil
		}

		localScope := make(linker.LocalDef, len(fun.Args))

		//		fun.ReturnTypeId = pkg.GetProtoTypeId(fun.ReturnType)
		for _, arg := range(fun.Args) {
			argTypeName := arg.TypeString
			var argTypeId int

			if argTypeName != nil {
				// Similar deal. Input functions from inheritance resolution already have ids set

				arg.TypeId = pkg.GetProtoTypeId(arg.TypeString)
				//println("Processing %", proto.GetString(arg.Name))
				argTypeId = pkg.GetTypeId(proto.GetString(arg.TypeString))
				arg.TypeString = nil
			} else {
				argTypeId = int( proto.GetInt32(arg.TypeId) )
			}

			localScope[proto.GetString(arg.Name)] = argTypeId
		}

		//pkg.Log.Info("Some insitruction: %v, %s", fun.Instruction, proto.GetString(fun.Name) )
		scopeTypeId := int(proto.GetInt32(fun.ScopeTypeId))
		pkg.Log.Info("\t\t -- opening scope type : %v\n", scopeTypeId)
		returnType := linkingContext.ProcessInstructionWithLocalScope(fun.Instruction, scopeTypeId, localScope)
		fun.ReturnTypeId = proto.Int32(int32(returnType))
	}
	pkg.Package.Functions = append(pkg.Package.Functions, fun)
	pkg.Log.Info("\t\t -- done --\n")
}

func (pkg *Package)inheritFunctions() {
	pkg.Log.Info("pkg types: %v", pkg.Types)
	for _, function := range(pkg.Functions) {
		pkg.resolveFunctionDescendants(function)
	}
}

// TODO(SJ) : Make this not suck. I think I could make this 50% shorter if I use reflection
// - Also, I'm assuming a single depth level of inheritance. I'd have to run this function n times for n levels
// - Well that should be fine as long as I run it at the end of every package load

func (pkg *Package)resolveFunctionDescendants(fun *tp.Function) {

	// Check if this function contains any types that have descendants
	name := fun.Stub(pkg.Package)
	pkg.Log.Info("Checking for inheritance on function: %v", name )

	newFun := &tp.Function{}
	inherit := false

	// Iterate over ScopeType, Arg types, return Type, opens Type

	// ScopeType

	thisTypeId := proto.GetInt32(fun.ScopeTypeId)
	newType := pkg.Package.FindDescendantType(thisTypeId)

	if newType != -1 {
		if !inherit {
			pkg.Log.Info("\t -- ScopeType : Found ancestral type. Cloning function %v\n", proto.GetString( fun.Name ) )
			newFun = fun.Clone()
			// pkg.Log.Info("\t -- New fun: %v", newFun)
			inherit = true
		}
		pkg.Log.Info("\t -- Resetting scopeId")
		newFun.ScopeTypeId = proto.Int32( int32( newType ) )
	}

	// ReturnType

	thisTypeId = proto.GetInt32(fun.ReturnTypeId)
	newType = pkg.Package.FindDescendantType(thisTypeId)

	if newType != -1 {
		if !inherit {
			pkg.Log.Info("\t -- ReturnType : Found ancestral type. Cloning function %v\n", proto.GetString( fun.Name ) )
			newFun = fun.Clone()
			// pkg.Log.Info("\t -- New fun: %v", newFun)
			inherit = true
		}
		pkg.Log.Info("\t -- Resetting returnId")
		newFun.ReturnTypeId = proto.Int32( int32( newType ) )
	}

	// OpensType

	thisTypeId = proto.GetInt32(fun.OpensTypeId)
	newType = pkg.Package.FindDescendantType(thisTypeId)

	if newType != -1 {

		if !inherit {
			pkg.Log.Info("\t -- OpensType : Found ancestral type. Cloning function %v\n", proto.GetString( fun.Name ) )
			newFun = fun.Clone()
			// pkg.Log.Info("\t -- New fun: %v", newFun)
			inherit = true
		}
		pkg.Log.Info("\t -- Resetting openTypeId")
		newFun.OpensTypeId = proto.Int32( int32( newType ) )
	}

	// Arguments

	for index, arg := range( fun.Args) {
		thisTypeId = proto.GetInt32(arg.TypeId)
		newType = pkg.Package.FindDescendantType(thisTypeId)

		if newType != -1 {

			if !inherit {
				pkg.Log.Info("\t -- ArgType : Found ancestral type. Cloning function %v\n", proto.GetString( fun.Name ) )
				newFun = fun.Clone()
				// pkg.Log.Info("\t -- New fun: %v", newFun)
				inherit = true
			}
			pkg.Log.Info("\t -- Resetting argument")
			newFun.Args[index].TypeId = proto.Int32( int32( newType ) )
		}

	}

	pkg.Log.Info("\t -- Old function: %v\n\t -- New function: %v\n", fun, newFun)

	if inherit {
		pkg.resolveFunction(newFun)
	}

}

func (pkg *Package)readPackageDefinitions(location string) {

	pkg.Println(" -- reading definitions")

	input_file := filepath.Join(location, "functions.ts")

	definitions := parser.ParseFile(input_file)

	for _, function := range(definitions.Functions) {
		pkg.Log.Info("\t -- function: %v", function)
		pkg.resolveFunction(function)
	}
}

func (pkg *Package)Marshal() []byte {
	bytes, err := proto.Marshal(pkg.Package)
	if err != nil {
		log.Panic(err)
	}
	return bytes
}

func (pkg *Package)findTypeIndex(name string) int {
	for index, typeObj := range(pkg.Types) {
		if name == proto.GetString(typeObj.Name) {
			return index
		}
	}

	log.Panic("Bad type load order, type", name, "unknown")
	return -1
}

func (pkg *Package)loadPackageDependency(name string) {

	// Try and load the dependency
	// TODO : remove passing location around since I added it to the Package struct

	// TODO : Check for a pre-built package (pre-req is outputting a .tpkg file upon completion of a package load)

	newPath := filepath.Join(pkg.LoadPath, name)
	_, err := ioutil.ReadDir(newPath)

	if err == nil {
		// Directory exists
		pkg.Load(name)
	} else {
		println("Cannot find package at:", newPath)
		log.Panic(err)
	}

}

// Not fully functional. Dang it.
func readPackageInfoFile(location string) (*PackageInfo){
	packageInfo := &PackageInfo{}
	infoFile, err := ioutil.ReadFile(location + "/package.yml");
	if err != nil {
		log.Panic("No package info file found at " + location + "/package.yml")
	}
	yaml.Unmarshal([]byte(infoFile), &packageInfo)
	//fmt.Printf("--- m:\n%v\n\n", packageInfo)
	return packageInfo
}

func (pkg *Package)readHeaderFile(location string) {
	// TODO : plug in new go parser to do this
	input_file := location + "/headers.tf"

	stubs := parser.ParseFile(input_file)

	for _, function := range(stubs.Functions) {

		returnType := proto.GetString( function.ReturnType )
		if len(returnType) > 0 {
			function.ReturnTypeId = proto.Int32( int32( pkg.findTypeIndex( returnType ) ) )
			function.ReturnType = nil
		}

		scopeType := proto.GetString( function.ScopeType )
		if len(scopeType) > 0{
			function.ScopeTypeId = proto.Int32( int32( pkg.findTypeIndex( scopeType ) ) )
			function.ScopeType = nil
		}

		opensType := proto.GetString( function.OpensType )
		if len(opensType) > 0 {
			function.OpensTypeId = proto.Int32( int32( pkg.findTypeIndex( opensType ) ) )
			function.OpensType = nil
		}

		for _, arg := range(function.Args) {
			typeName := proto.GetString( arg.TypeString )
			if len(typeName) > 0 {
				arg.TypeId = proto.Int32( int32( pkg.findTypeIndex( typeName ) ) )
				arg.TypeString = nil
			}
		}

		function.BuiltIn = proto.Bool( true )

		pkg.Package.Functions = append(pkg.Package.Functions, function)
	}

}

func (pkg *Package)SerializedOutput() {

	bytes, err := proto.Marshal(pkg.Package)
	if err != nil {
		log.Panic(err)
	}
	println(string(bytes))
}

func (pkg *Package) DebugInfo() (string) {
	result := ""
	for _, fun := range(pkg.Package.Functions) {
		result = result + fun.DebugInfo(pkg.Package) + "\n"
	}
	return result
}

func (pkg *Package) write() {
	path, name := filepath.Split(pkg.location)
	outputFilename := filepath.Join(path, name, name + ".tpkg")

	bytes, err := proto.Marshal(pkg.Package)

	if err != nil {
		println("Could not marshal package:", name)
		log.Panic(err)
	}

	bytes = crypto.Encrypt(bytes)

	ioutil.WriteFile(outputFilename, bytes, uint32(0666) )

	pkg.Println(" -- output: " +  outputFilename)
}

func (pkg *Package)Println(message string) {
	if pkg.Options["stdout"] {
		println(message)
	}
}<commit_msg>Now have dummy encryption working. Almost have .tpkgs reloading properly<commit_after>package packager

import(
	tp "tritium/proto"
	proto "goprotobuf.googlecode.com/hg/proto"
	yaml "launchpad.net/goyaml"
	"io/ioutil"
	api "tritium/api"
	"log"
	"strings"
	linker "tritium/linker"
	parser "tritium/parser"
	"path/filepath"
	"log4go"
	"os"
	"tritium/crypto"
)

type Package struct {
	loaded []*PackageInfo
	location string
	LoadPath string
	Log log4go.Logger
	*tp.Package
	Options PackageOptions
}

type PackageInfo struct {
	Name string
	Dependencies []string
	Types []string
}

type PackageOptions map[string]bool

var defaultOptions PackageOptions
var buildOptions PackageOptions

func BuildOptions() PackageOptions {
	if buildOptions == nil {
		buildOptions =  PackageOptions{
			"stdout" : true,
			"output_tpkg" : true,
			"use_tpkg" : true,
		}
	}
	return buildOptions
}

func fetchDefaultOptions() PackageOptions{
	if defaultOptions == nil {
		defaultOptions = PackageOptions{
			"stdout":false,
			"output_tpkg":false,
			"use_tpkg":true,
		}
	}
	return defaultOptions
}

var DefaultPackagePath = "packages"

func LoadDefaultPackage() (*Package) {
	return buildPackage(nil)
}

func BuildDefaultPackage() (*Package) {
	options := BuildOptions()
	return buildPackage(options)
}

func buildPackage(options PackageOptions) (*Package) {
	// Terrible directory handling here... has to be executed from Tritium root

	pkg := NewPackage(DefaultPackagePath, options)
	pkg.Load("libxml")

	return pkg
}

func mergeOptions(options PackageOptions) PackageOptions {
	defaults := fetchDefaultOptions()

	if options == nil {
		return defaults
	}

	for k, _ := range defaults {
		_, ok := options[k]

		if !ok {
			options[k] = defaults[k]
		}
	}

	return options
}

func NewPackage(loadPath string, options PackageOptions) (*Package){
	options = mergeOptions(options)

	return &Package{
		Package: &tp.Package{
			Name: proto.String("combined"),
			Functions: make([]*tp.Function, 0),
			Types: make([]*tp.Type, 0),
		},
		loaded: make([]*PackageInfo, 0),
  	        Log: newLog(),
		LoadPath: loadPath,
	        Options: options,
	}
}

func newLog() (log4go.Logger) {
	pkgLog := make(log4go.Logger)
	os.Mkdir("log", uint32(0777) )

	pkgLog.AddFilter("file", log4go.FINE, log4go.NewFileLogWriter("log/debug.log", false))
	return pkgLog
}

func (pkg *Package)Load(packageName string) {
	user := api.FetchSessionUser()
	approved := user.RequestFeature("package:" + packageName)

	if !approved {
		panic("Package " + packageName + " not approved for use.")
	}

	old_location := pkg.location

	location := filepath.Join(pkg.LoadPath, packageName)

	pkg.Println(location)
	pkg.Log.Info("\n\n\n\nLoading:%v", location)

	if pkg.Options["use_tpkg"] {
		pkg.open(location)
		return
	}

	pkg.location = location
	info := readPackageInfoFile(location)

	if len(info.Dependencies) > 0 {

		for _, dependency := range(info.Dependencies) {
			pkg.loadPackageDependency(dependency)
		}

	}

	for _, typeName := range(info.Types) {
		split := strings.Split(typeName, " < ")
		typeObj := &tp.Type{}
		if len(split) == 2 {
			typeName = split[0]
			index := pkg.findTypeIndex(split[1])

			typeObj.Implements = proto.Int32(int32(index))
		}
		typeObj.Name = proto.String(typeName)
		pkg.Types = append(pkg.Types, typeObj)
	}

	pkg.readHeaderFile(location)

	pkg.readPackageDefinitions(location)

	pkg.inheritFunctions()

	if pkg.Options["output_tpkg"] {
		pkg.write()
	}

	pkg.Println(" -- done")
	pkg.Log.Close()

	// TODO(SJ) : Kind of lame. Ideally I think we load other packages as whole packages and write a *.Merge method
	pkg.location = old_location

}

func (pkg *Package)resolveFunction(fun *tp.Function) {
	linkingContext := linker.NewLinkingContext(pkg.Package)

//	pkg.resolveFunctionDescendants(fun)

	pkg.Log.Info("\t -- Resolving --\n")
	pkg.Log.Info("\t\t -- function: %v\n", fun)

	// Re-uses linker's logic to resolve function definitions
	if ( proto.GetBool( fun.BuiltIn ) == false) {
		typeName := proto.GetString(fun.ScopeType)

		if len(typeName) != 0 {
			// When I pass in functions from the inheritance resolver, they're typeId is already set
			fun.ScopeTypeId = pkg.GetProtoTypeId(fun.ScopeType)
			fun.ScopeType = nil
		}

		localScope := make(linker.LocalDef, len(fun.Args))

		//		fun.ReturnTypeId = pkg.GetProtoTypeId(fun.ReturnType)
		for _, arg := range(fun.Args) {
			argTypeName := arg.TypeString
			var argTypeId int

			if argTypeName != nil {
				// Similar deal. Input functions from inheritance resolution already have ids set

				arg.TypeId = pkg.GetProtoTypeId(arg.TypeString)
				//println("Processing %", proto.GetString(arg.Name))
				argTypeId = pkg.GetTypeId(proto.GetString(arg.TypeString))
				arg.TypeString = nil
			} else {
				argTypeId = int( proto.GetInt32(arg.TypeId) )
			}

			localScope[proto.GetString(arg.Name)] = argTypeId
		}

		//pkg.Log.Info("Some insitruction: %v, %s", fun.Instruction, proto.GetString(fun.Name) )
		scopeTypeId := int(proto.GetInt32(fun.ScopeTypeId))
		pkg.Log.Info("\t\t -- opening scope type : %v\n", scopeTypeId)
		returnType := linkingContext.ProcessInstructionWithLocalScope(fun.Instruction, scopeTypeId, localScope)
		fun.ReturnTypeId = proto.Int32(int32(returnType))
	}
	pkg.Package.Functions = append(pkg.Package.Functions, fun)
	pkg.Log.Info("\t\t -- done --\n")
}

func (pkg *Package)inheritFunctions() {
	pkg.Log.Info("pkg types: %v", pkg.Types)
	for _, function := range(pkg.Functions) {
		pkg.resolveFunctionDescendants(function)
	}
}

// TODO(SJ) : Make this not suck. I think I could make this 50% shorter if I use reflection
// - Also, I'm assuming a single depth level of inheritance. I'd have to run this function n times for n levels
// - Well that should be fine as long as I run it at the end of every package load

func (pkg *Package)resolveFunctionDescendants(fun *tp.Function) {

	// Check if this function contains any types that have descendants
	name := fun.Stub(pkg.Package)
	pkg.Log.Info("Checking for inheritance on function: %v", name )

	newFun := &tp.Function{}
	inherit := false

	// Iterate over ScopeType, Arg types, return Type, opens Type

	// ScopeType

	thisTypeId := proto.GetInt32(fun.ScopeTypeId)
	newType := pkg.Package.FindDescendantType(thisTypeId)

	if newType != -1 {
		if !inherit {
			pkg.Log.Info("\t -- ScopeType : Found ancestral type. Cloning function %v\n", proto.GetString( fun.Name ) )
			newFun = fun.Clone()
			// pkg.Log.Info("\t -- New fun: %v", newFun)
			inherit = true
		}
		pkg.Log.Info("\t -- Resetting scopeId")
		newFun.ScopeTypeId = proto.Int32( int32( newType ) )
	}

	// ReturnType

	thisTypeId = proto.GetInt32(fun.ReturnTypeId)
	newType = pkg.Package.FindDescendantType(thisTypeId)

	if newType != -1 {
		if !inherit {
			pkg.Log.Info("\t -- ReturnType : Found ancestral type. Cloning function %v\n", proto.GetString( fun.Name ) )
			newFun = fun.Clone()
			// pkg.Log.Info("\t -- New fun: %v", newFun)
			inherit = true
		}
		pkg.Log.Info("\t -- Resetting returnId")
		newFun.ReturnTypeId = proto.Int32( int32( newType ) )
	}

	// OpensType

	thisTypeId = proto.GetInt32(fun.OpensTypeId)
	newType = pkg.Package.FindDescendantType(thisTypeId)

	if newType != -1 {

		if !inherit {
			pkg.Log.Info("\t -- OpensType : Found ancestral type. Cloning function %v\n", proto.GetString( fun.Name ) )
			newFun = fun.Clone()
			// pkg.Log.Info("\t -- New fun: %v", newFun)
			inherit = true
		}
		pkg.Log.Info("\t -- Resetting openTypeId")
		newFun.OpensTypeId = proto.Int32( int32( newType ) )
	}

	// Arguments

	for index, arg := range( fun.Args) {
		thisTypeId = proto.GetInt32(arg.TypeId)
		newType = pkg.Package.FindDescendantType(thisTypeId)

		if newType != -1 {

			if !inherit {
				pkg.Log.Info("\t -- ArgType : Found ancestral type. Cloning function %v\n", proto.GetString( fun.Name ) )
				newFun = fun.Clone()
				// pkg.Log.Info("\t -- New fun: %v", newFun)
				inherit = true
			}
			pkg.Log.Info("\t -- Resetting argument")
			newFun.Args[index].TypeId = proto.Int32( int32( newType ) )
		}

	}

	pkg.Log.Info("\t -- Old function: %v\n\t -- New function: %v\n", fun, newFun)

	if inherit {
		pkg.resolveFunction(newFun)
	}

}

func (pkg *Package)readPackageDefinitions(location string) {

	pkg.Println(" -- reading definitions")

	input_file := filepath.Join(location, "functions.ts")

	definitions := parser.ParseFile(input_file)

	for _, function := range(definitions.Functions) {
		pkg.Log.Info("\t -- function: %v", function)
		pkg.resolveFunction(function)
	}
}

func (pkg *Package)Marshal() []byte {
	bytes, err := proto.Marshal(pkg.Package)
	if err != nil {
		log.Panic(err)
	}
	return bytes
}

func (pkg *Package)findTypeIndex(name string) int {
	for index, typeObj := range(pkg.Types) {
		if name == proto.GetString(typeObj.Name) {
			return index
		}
	}

	log.Panic("Bad type load order, type", name, "unknown")
	return -1
}

func (pkg *Package)loadPackageDependency(name string) {

	// Try and load the dependency
	// TODO : remove passing location around since I added it to the Package struct

	// TODO : Check for a pre-built package (pre-req is outputting a .tpkg file upon completion of a package load)

	newPath := filepath.Join(pkg.LoadPath, name)
	_, err := ioutil.ReadDir(newPath)

	if err == nil {
		// Directory exists
		pkg.Load(name)
	} else {
		println("Cannot find package at:", newPath)
		log.Panic(err)
	}

}

// Not fully functional. Dang it.
func readPackageInfoFile(location string) (*PackageInfo){
	packageInfo := &PackageInfo{}
	infoFile, err := ioutil.ReadFile(location + "/package.yml");
	if err != nil {
		log.Panic("No package info file found at " + location + "/package.yml")
	}
	yaml.Unmarshal([]byte(infoFile), &packageInfo)
	//fmt.Printf("--- m:\n%v\n\n", packageInfo)
	return packageInfo
}

func (pkg *Package)readHeaderFile(location string) {
	// TODO : plug in new go parser to do this
	input_file := location + "/headers.tf"

	stubs := parser.ParseFile(input_file)

	for _, function := range(stubs.Functions) {

		returnType := proto.GetString( function.ReturnType )
		if len(returnType) > 0 {
			function.ReturnTypeId = proto.Int32( int32( pkg.findTypeIndex( returnType ) ) )
			function.ReturnType = nil
		}

		scopeType := proto.GetString( function.ScopeType )
		if len(scopeType) > 0{
			function.ScopeTypeId = proto.Int32( int32( pkg.findTypeIndex( scopeType ) ) )
			function.ScopeType = nil
		}

		opensType := proto.GetString( function.OpensType )
		if len(opensType) > 0 {
			function.OpensTypeId = proto.Int32( int32( pkg.findTypeIndex( opensType ) ) )
			function.OpensType = nil
		}

		for _, arg := range(function.Args) {
			typeName := proto.GetString( arg.TypeString )
			if len(typeName) > 0 {
				arg.TypeId = proto.Int32( int32( pkg.findTypeIndex( typeName ) ) )
				arg.TypeString = nil
			}
		}

		function.BuiltIn = proto.Bool( true )

		pkg.Package.Functions = append(pkg.Package.Functions, function)
	}

}

func (pkg *Package)SerializedOutput() {

	bytes, err := proto.Marshal(pkg.Package)
	if err != nil {
		log.Panic(err)
	}
	println(string(bytes))
}

func (pkg *Package) DebugInfo() (string) {
	result := ""
	for _, fun := range(pkg.Package.Functions) {
		result = result + fun.DebugInfo(pkg.Package) + "\n"
	}
	return result
}

func (pkg *Package) write() {
	path, name := filepath.Split(pkg.location)
	outputFilename := filepath.Join(path, name, name + ".tpkg")

	bytes, err := proto.Marshal(pkg.Package)

	if err != nil {
		println("Could not marshal package:", name)
		log.Panic(err)
	}

	bytes = crypto.Encrypt(bytes)

	ioutil.WriteFile(outputFilename, bytes, uint32(0666) )

	pkg.Println(" -- output: " +  outputFilename)
}

func (pkg *Package) open(location string) {
	pathComponents := strings.Split(location, "/")
	name := pathComponents[len(pathComponents)-1]

	tpkg_path := filepath.Join(location, name + ".tpkg")

	data, err := ioutil.ReadFile(tpkg_path)

	if err != nil {
		pkg.Println("No tpkg at:" + tpkg_path)
		return
	}

	data = crypto.Decrypt(data)

	thisPackage := &tp.Package{}
	err = proto.Unmarshal(data, thisPackage)

	if err != nil {
		panic("Error unmarshalling package at:" + tpkg_path)
	}

	// Now load all the functions and resolve them

	pkg.Println("Using tpkg at:" + tpkg_path)

}

func (pkg *Package)Println(message string) {
	if pkg.Options["stdout"] {
		println(message)
	}
}<|endoftext|>


<commit_before>package network

import (
	"crypto/rand"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"strings"

	"github.com/golang/glog"
	"github.com/hyperhq/runv/api"
	"github.com/vishvananda/netlink"
)

const (
	ipv4ForwardConf     = "/proc/sys/net/ipv4/ip_forward"
	ipv4ForwardConfPerm = 0644
)

func InitNetwork(bIface, bIP string, disable bool) error {
	if err := ensureBridge(bIface, bIP); err != nil {
		return err
	}

	if err := setupIPForwarding(); err != nil {
		return err
	}

	return nil
}

func setupIPForwarding() error {
	// Get current IPv4 forward setup
	ipv4ForwardData, err := ioutil.ReadFile(ipv4ForwardConf)
	if err != nil {
		return fmt.Errorf("Cannot read IP forwarding setup: %v", err)
	}

	// Enable IPv4 forwarding only if it is not already enabled
	if ipv4ForwardData[0] != '1' {
		// Enable IPv4 forwarding
		if err := ioutil.WriteFile(ipv4ForwardConf, []byte{'1', '\n'}, ipv4ForwardConfPerm); err != nil {
			return fmt.Errorf("Setup IP forwarding failed: %v", err)
		}
	}

	return nil
}

func ensureBridge(bIface, bIP string) error {
	if bIface == "" {
		BridgeIface = DefaultBridgeIface
	} else {
		BridgeIface = bIface
	}

	if bIP == "" {
		BridgeIP = DefaultBridgeIP
	} else {
		BridgeIP = bIP
	}

	ipAddr, ipNet, err := net.ParseCIDR(BridgeIP)
	if err != nil {
		glog.Errorf("%s parsecidr failed", BridgeIP)
		return err
	}

	if brlink, err := netlink.LinkByName(BridgeIface); err != nil {
		glog.V(1).Infof("create bridge %s, ip %s", BridgeIface, BridgeIP)
		// No Bridge existent, create one
		if ipAddr.Equal(ipNet.IP) {
			ipAddr, err = IpAllocator.RequestIP(ipNet, nil)
		} else {
			ipAddr, err = IpAllocator.RequestIP(ipNet, ipAddr)
		}

		if err != nil {
			return err
		}

		glog.V(3).Infof("Allocate IP Address %s for bridge %s", ipAddr, BridgeIface)

		BridgeIPv4Net = &net.IPNet{IP: ipAddr, Mask: ipNet.Mask}
		if err := createBridgeIface(BridgeIface, BridgeIPv4Net); err != nil {
			// The bridge may already exist, therefore we can ignore an "exists" error
			if !os.IsExist(err) {
				glog.Errorf("CreateBridgeIface failed %s %s", BridgeIface, ipAddr)
				return err
			}
			// should not reach here
		}
	} else {
		glog.V(1).Info("bridge exist")
		// Validate that the bridge ip matches the ip specified by BridgeIP

		addrs, err := netlink.AddrList(brlink, netlink.FAMILY_V4)
		if err != nil {
			return err
		}
		if len(addrs) == 0 {
			return fmt.Errorf("Interface %v has no IPv4 addresses", BridgeIface)
		}

		BridgeIPv4Net = addrs[0].IPNet

		if !BridgeIPv4Net.Contains(ipAddr) {
			return fmt.Errorf("Bridge ip (%s) does not match existing bridge configuration %s", BridgeIPv4Net, BridgeIP)
		}

		mask1, _ := ipNet.Mask.Size()
		mask2, _ := BridgeIPv4Net.Mask.Size()

		if mask1 != mask2 {
			return fmt.Errorf("Bridge netmask (%d) does not match existing bridge netmask %d", mask1, mask2)
		}
	}

	IpAllocator.RequestIP(BridgeIPv4Net, BridgeIPv4Net.IP)

	return nil
}

func createBridgeIface(name string, addr *net.IPNet) error {
	la := netlink.NewLinkAttrs()
	la.Name = name
	bridge := &netlink.Bridge{LinkAttrs: la}
	if err := netlink.LinkAdd(bridge); err != nil {
		return err
	}
	if err := netlink.AddrAdd(bridge, &netlink.Addr{IPNet: addr}); err != nil {
		return err
	}
	return netlink.LinkSetUp(bridge)
}

func DeleteBridge(name string) error {
	if bridge, err := netlink.LinkByName(BridgeIface); err != nil {
		glog.Errorf("cannot find bridge %v", name)
	} else {
		netlink.LinkDel(bridge)
	}
	return nil
}

// addToBridge attch interface to the bridge,
// we only support ovs bridge and linux bridge at present.
func addToBridge(iface, master netlink.Link, options string) error {
	switch master.Type() {
	case "openvswitch":
		return addToOpenvswitchBridge(iface, master, options)
	case "bridge":
		return netlink.LinkSetMaster(iface, master.(*netlink.Bridge))
	default:
		return fmt.Errorf("unknown link type:%+v", master.Type())
	}
}

func addToOpenvswitchBridge(iface, master netlink.Link, options string) error {
	masterName := master.Attrs().Name
	ifaceName := iface.Attrs().Name
	glog.V(3).Infof("Found ovs bridge %s, attaching tap %s to it\n", masterName, ifaceName)

	// ovs command "ovs-vsctl add-port BRIDGE PORT" add netwok device PORT to BRIDGE,
	// PORT and BRIDGE here indicate the device name respectively.
	out, err := exec.Command("ovs-vsctl", "--may-exist", "add-port", masterName, ifaceName).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Ovs failed to add port: %s, error :%v", strings.TrimSpace(string(out)), err)
	}

	out, err = exec.Command("ovs-vsctl", "set", "port", ifaceName, options).CombinedOutput()
	return nil
}

func GenRandomMac() (string, error) {
	const alphanum = "0123456789abcdef"
	var bytes = make([]byte, 8)
	_, err := rand.Read(bytes)

	if err != nil {
		glog.Errorf("get random number faild")
		return "", err
	}

	for i, b := range bytes {
		bytes[i] = alphanum[b%byte(len(alphanum))]
	}

	tmp := []string{"52:54", string(bytes[0:2]), string(bytes[2:4]), string(bytes[4:6]), string(bytes[6:8])}
	return strings.Join(tmp, ":"), nil
}

func UpAndAddToBridge(name, bridge, options string) error {
	iface, err := netlink.LinkByName(name)
	if err != nil {
		glog.Error("cannot find network interface ", name)
		return err
	}
	if bridge == "" {
		bridge = BridgeIface
	}
	master, err := netlink.LinkByName(bridge)
	if err != nil {
		glog.Error("cannot find bridge interface ", bridge)
		return err
	}
	if err = addToBridge(iface, master, options); err != nil {
		glog.Errorf("cannot add %s to %s ", name, bridge)
		return err
	}
	if err = netlink.LinkSetUp(iface); err != nil {
		glog.Error("cannot up interface ", name)
		return err
	}

	return nil
}

func AllocateAddr(requestedIP string) (*Settings, error) {
	ip, err := IpAllocator.RequestIP(BridgeIPv4Net, net.ParseIP(requestedIP))
	if err != nil {
		return nil, err
	}

	maskSize, _ := BridgeIPv4Net.Mask.Size()

	mac, err := GenRandomMac()
	if err != nil {
		glog.Errorf("Generate Random Mac address failed")
		return nil, err
	}

	return &Settings{
		Mac:         mac,
		IPAddress:   ip.String(),
		Gateway:     BridgeIPv4Net.IP.String(),
		Bridge:      BridgeIface,
		IPPrefixLen: maskSize,
		Device:      "",
		Automatic:   true,
	}, nil
}

func Configure(inf *api.InterfaceDescription) (*Settings, error) {
	ip, mask, err := ipParser(inf.Ip)
	if err != nil {
		glog.Errorf("Parse config IP failed %s", err)
		return nil, err
	}

	maskSize, _ := mask.Size()

	mac := inf.Mac
	if mac == "" {
		mac, err = GenRandomMac()
		if err != nil {
			glog.Errorf("Generate Random Mac address failed")
			return nil, err
		}
	}

	return &Settings{
		Mac:         mac,
		IPAddress:   ip.String(),
		Gateway:     inf.Gw,
		Bridge:      inf.Bridge,
		IPPrefixLen: maskSize,
		Device:      inf.TapName,
		Automatic:   false,
	}, nil
}

func ReleaseAddr(releasedIP string) error {
	if err := IpAllocator.ReleaseIP(BridgeIPv4Net, net.ParseIP(releasedIP)); err != nil {
		return err
	}
	return nil
}

func ipParser(ipstr string) (net.IP, net.IPMask, error) {
	glog.V(1).Info("parse IP addr ", ipstr)
	ip, ipnet, err := net.ParseCIDR(ipstr)
	if err == nil {
		return ip, ipnet.Mask, nil
	}

	ip = net.ParseIP(ipstr)
	if ip != nil {
		return ip, ip.DefaultMask(), nil
	}

	return nil, nil, err
}
<commit_msg>make GenRandomMac as private function<commit_after>package network

import (
	"crypto/rand"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"strings"

	"github.com/golang/glog"
	"github.com/hyperhq/runv/api"
	"github.com/vishvananda/netlink"
)

const (
	ipv4ForwardConf     = "/proc/sys/net/ipv4/ip_forward"
	ipv4ForwardConfPerm = 0644
)

func InitNetwork(bIface, bIP string, disable bool) error {
	if err := ensureBridge(bIface, bIP); err != nil {
		return err
	}

	if err := setupIPForwarding(); err != nil {
		return err
	}

	return nil
}

func setupIPForwarding() error {
	// Get current IPv4 forward setup
	ipv4ForwardData, err := ioutil.ReadFile(ipv4ForwardConf)
	if err != nil {
		return fmt.Errorf("Cannot read IP forwarding setup: %v", err)
	}

	// Enable IPv4 forwarding only if it is not already enabled
	if ipv4ForwardData[0] != '1' {
		// Enable IPv4 forwarding
		if err := ioutil.WriteFile(ipv4ForwardConf, []byte{'1', '\n'}, ipv4ForwardConfPerm); err != nil {
			return fmt.Errorf("Setup IP forwarding failed: %v", err)
		}
	}

	return nil
}

func ensureBridge(bIface, bIP string) error {
	if bIface == "" {
		BridgeIface = DefaultBridgeIface
	} else {
		BridgeIface = bIface
	}

	if bIP == "" {
		BridgeIP = DefaultBridgeIP
	} else {
		BridgeIP = bIP
	}

	ipAddr, ipNet, err := net.ParseCIDR(BridgeIP)
	if err != nil {
		glog.Errorf("%s parsecidr failed", BridgeIP)
		return err
	}

	if brlink, err := netlink.LinkByName(BridgeIface); err != nil {
		glog.V(1).Infof("create bridge %s, ip %s", BridgeIface, BridgeIP)
		// No Bridge existent, create one
		if ipAddr.Equal(ipNet.IP) {
			ipAddr, err = IpAllocator.RequestIP(ipNet, nil)
		} else {
			ipAddr, err = IpAllocator.RequestIP(ipNet, ipAddr)
		}

		if err != nil {
			return err
		}

		glog.V(3).Infof("Allocate IP Address %s for bridge %s", ipAddr, BridgeIface)

		BridgeIPv4Net = &net.IPNet{IP: ipAddr, Mask: ipNet.Mask}
		if err := createBridgeIface(BridgeIface, BridgeIPv4Net); err != nil {
			// The bridge may already exist, therefore we can ignore an "exists" error
			if !os.IsExist(err) {
				glog.Errorf("CreateBridgeIface failed %s %s", BridgeIface, ipAddr)
				return err
			}
			// should not reach here
		}
	} else {
		glog.V(1).Info("bridge exist")
		// Validate that the bridge ip matches the ip specified by BridgeIP

		addrs, err := netlink.AddrList(brlink, netlink.FAMILY_V4)
		if err != nil {
			return err
		}
		if len(addrs) == 0 {
			return fmt.Errorf("Interface %v has no IPv4 addresses", BridgeIface)
		}

		BridgeIPv4Net = addrs[0].IPNet

		if !BridgeIPv4Net.Contains(ipAddr) {
			return fmt.Errorf("Bridge ip (%s) does not match existing bridge configuration %s", BridgeIPv4Net, BridgeIP)
		}

		mask1, _ := ipNet.Mask.Size()
		mask2, _ := BridgeIPv4Net.Mask.Size()

		if mask1 != mask2 {
			return fmt.Errorf("Bridge netmask (%d) does not match existing bridge netmask %d", mask1, mask2)
		}
	}

	IpAllocator.RequestIP(BridgeIPv4Net, BridgeIPv4Net.IP)

	return nil
}

func createBridgeIface(name string, addr *net.IPNet) error {
	la := netlink.NewLinkAttrs()
	la.Name = name
	bridge := &netlink.Bridge{LinkAttrs: la}
	if err := netlink.LinkAdd(bridge); err != nil {
		return err
	}
	if err := netlink.AddrAdd(bridge, &netlink.Addr{IPNet: addr}); err != nil {
		return err
	}
	return netlink.LinkSetUp(bridge)
}

func DeleteBridge(name string) error {
	if bridge, err := netlink.LinkByName(BridgeIface); err != nil {
		glog.Errorf("cannot find bridge %v", name)
	} else {
		netlink.LinkDel(bridge)
	}
	return nil
}

// addToBridge attch interface to the bridge,
// we only support ovs bridge and linux bridge at present.
func addToBridge(iface, master netlink.Link, options string) error {
	switch master.Type() {
	case "openvswitch":
		return addToOpenvswitchBridge(iface, master, options)
	case "bridge":
		return netlink.LinkSetMaster(iface, master.(*netlink.Bridge))
	default:
		return fmt.Errorf("unknown link type:%+v", master.Type())
	}
}

func addToOpenvswitchBridge(iface, master netlink.Link, options string) error {
	masterName := master.Attrs().Name
	ifaceName := iface.Attrs().Name
	glog.V(3).Infof("Found ovs bridge %s, attaching tap %s to it\n", masterName, ifaceName)

	// ovs command "ovs-vsctl add-port BRIDGE PORT" add netwok device PORT to BRIDGE,
	// PORT and BRIDGE here indicate the device name respectively.
	out, err := exec.Command("ovs-vsctl", "--may-exist", "add-port", masterName, ifaceName).CombinedOutput()
	if err != nil {
		return fmt.Errorf("Ovs failed to add port: %s, error :%v", strings.TrimSpace(string(out)), err)
	}

	out, err = exec.Command("ovs-vsctl", "set", "port", ifaceName, options).CombinedOutput()
	return nil
}

func genRandomMac() (string, error) {
	const alphanum = "0123456789abcdef"
	var bytes = make([]byte, 8)
	_, err := rand.Read(bytes)

	if err != nil {
		glog.Errorf("get random number faild")
		return "", err
	}

	for i, b := range bytes {
		bytes[i] = alphanum[b%byte(len(alphanum))]
	}

	tmp := []string{"52:54", string(bytes[0:2]), string(bytes[2:4]), string(bytes[4:6]), string(bytes[6:8])}
	return strings.Join(tmp, ":"), nil
}

func UpAndAddToBridge(name, bridge, options string) error {
	iface, err := netlink.LinkByName(name)
	if err != nil {
		glog.Error("cannot find network interface ", name)
		return err
	}
	if bridge == "" {
		bridge = BridgeIface
	}
	master, err := netlink.LinkByName(bridge)
	if err != nil {
		glog.Error("cannot find bridge interface ", bridge)
		return err
	}
	if err = addToBridge(iface, master, options); err != nil {
		glog.Errorf("cannot add %s to %s ", name, bridge)
		return err
	}
	if err = netlink.LinkSetUp(iface); err != nil {
		glog.Error("cannot up interface ", name)
		return err
	}

	return nil
}

func AllocateAddr(requestedIP string) (*Settings, error) {
	ip, err := IpAllocator.RequestIP(BridgeIPv4Net, net.ParseIP(requestedIP))
	if err != nil {
		return nil, err
	}

	maskSize, _ := BridgeIPv4Net.Mask.Size()

	mac, err := genRandomMac()
	if err != nil {
		glog.Errorf("Generate Random Mac address failed")
		return nil, err
	}

	return &Settings{
		Mac:         mac,
		IPAddress:   ip.String(),
		Gateway:     BridgeIPv4Net.IP.String(),
		Bridge:      BridgeIface,
		IPPrefixLen: maskSize,
		Device:      "",
		Automatic:   true,
	}, nil
}

func Configure(inf *api.InterfaceDescription) (*Settings, error) {
	ip, mask, err := ipParser(inf.Ip)
	if err != nil {
		glog.Errorf("Parse config IP failed %s", err)
		return nil, err
	}

	maskSize, _ := mask.Size()

	mac := inf.Mac
	if mac == "" {
		mac, err = genRandomMac()
		if err != nil {
			glog.Errorf("Generate Random Mac address failed")
			return nil, err
		}
	}

	return &Settings{
		Mac:         mac,
		IPAddress:   ip.String(),
		Gateway:     inf.Gw,
		Bridge:      inf.Bridge,
		IPPrefixLen: maskSize,
		Device:      inf.TapName,
		Automatic:   false,
	}, nil
}

func ReleaseAddr(releasedIP string) error {
	if err := IpAllocator.ReleaseIP(BridgeIPv4Net, net.ParseIP(releasedIP)); err != nil {
		return err
	}
	return nil
}

func ipParser(ipstr string) (net.IP, net.IPMask, error) {
	glog.V(1).Info("parse IP addr ", ipstr)
	ip, ipnet, err := net.ParseCIDR(ipstr)
	if err == nil {
		return ip, ipnet.Mask, nil
	}

	ip = net.ParseIP(ipstr)
	if ip != nil {
		return ip, ip.DefaultMask(), nil
	}

	return nil, nil, err
}
<|endoftext|>