<commit_before>package scheduler

import (
	"fmt"
)

// Job defines a nomad job specification
type Job struct {
	Region      string
	ID          string
	Name        string
	Type        string
	Priority    int
	AllAtOnce   bool
	Datacenters []string
	Constraints []Constraint
	TaskGroups  []TaskGroup
	Update      Update
}

// Constraint defines a job/task contraint
type Constraint struct {
	LTarget string
	RTarget string
	Operand string
}

// Update defines the update stanza
type Update struct {
	Stagger     int64
	MaxParallel int
}

// TaskGroups defines the task_group stanza
type TaskGroup struct {
	Name          string
	Count         int
	Constraints   []string
	Tasks         []Task
	Resources     Resources
	RestartPolicy RestartPolicy
	Meta          map[string]string
}

// Task defines a job task
type Task struct {
	Name            string
	Driver          string
	Config          Config
	Env             map[string]string
	Services        []NomadService
	Meta            map[string]string
	LogConfig       LogConfig
	Templates       []Template
	Artifacts       []Artifact
	Resources       Resources
	DispatchPayload DispatchPayload
}

// DispatchPayload configures tast to have access to dispatch payload
type DispatchPayload struct {
	File string
}

// Resources defines the resources to allocate to a task
type Resources struct {
	CPU      int
	MemoryMB int
	IOPS     int
	Networks []Network
}

// Network defines network allocation
type Network struct {
	MBits        int
	DynamicPorts []DynamicPort
}

// RestartPolicy defines restart policy
type RestartPolicy struct {
	Interval int64
	Attempts int
	Delay    int64
	Mode     string
}

// DynamicPort defines a dynamic port allocation
type DynamicPort struct {
	Label string
}

// Artifact defines an artifact to be downloaded
type Artifact struct {
	GetterSource  string
	RelativeDest  string
	GetterOptions map[string]string
}

// Template defines template objects to render for the task
type Template struct {
	SourcePath   string
	DestPath     string
	EmbeddedTmpl string
	ChangeMode   string
	ChangeSignal string
	Splay        int64
}

// LogConfig defines log configurations
type LogConfig struct {
	MaxFiles      int
	MaxFileSizeMB int
}

// NomadService defines a service
type NomadService struct {
	Name      string
	Tags      []string
	PortLabel string
	Checks    []Check
}

// Check defines a service check
type Check struct {
	ID       string `json:"Id"`
	Name     string
	Type     string
	Path     string
	Port     string
	Timeout  int64
	Interval int64
	Protocol string
}

// Config defines a driver/task configuration
type Config struct {
	Image       string   `json:"image"`
	ForcePull   bool     `json:"force_pull"`
	Command     string   `json:"command"`
	NetworkMode string   `json:"network_mode"`
	Args        []string `json:"args"`
	Privileged  bool     `json:"privileged"`
	PortMap     []string `json:"port_map"`
}

// NomadJob represents a nomad job
type NomadJob struct {
	Job *Job
}

// NewJob creates a new job with some default values.
func NewJob(id string, count int) *NomadJob {
	return &NomadJob{
		Job: &Job{
			Region:      "",
			ID:          id,
			Name:        id,
			Type:        "service",
			Priority:    50,
			AllAtOnce:   false,
			Datacenters: []string{},
			Constraints: []Constraint{
				Constraint{
					LTarget: "${attr.kernel.name}",
					RTarget: "linux",
					Operand: "=",
				},
			},
			TaskGroups: []TaskGroup{
				TaskGroup{
					Name:  fmt.Sprintf("tskgrp-%s", id),
					Count: count,
					Tasks: []Task{
						Task{
							Name:   fmt.Sprintf("task-%s", id),
							Driver: "docker",
							Config: Config{
								Image:       "ncodes/cocoon-launcher:latest",
								ForcePull:   true,
								Command:     "bash",
								NetworkMode: "host",
								Args:        []string{"${NOMAD_META_SCRIPTS_DIR}/${NOMAD_META_DEPLOY_SCRIPT_NAME}"},
								Privileged:  true,
							},
							Env: map[string]string{
								"COCOON_ID":           id,
								"COCOON_CODE_URL":     "",
								"COCOON_CODE_TAG":     "",
								"COCOON_CODE_LANG":    "",
								"COCOON_BUILD_PARAMS": "",
								"COCOON_DISK_LIMIT":   "",
							},
							Services: []NomadService{
								NomadService{
									Name:      fmt.Sprintf("cocoons-%s", id),
									Tags:      []string{id},
									PortLabel: "CONNECTOR_RPC",
								},
							},
							Meta: map[string]string{
								"DEPLOY_SCRIPT_NAME": "run-connector.sh",
								"SCRIPTS_DIR":        "/local/scripts",
							},
							LogConfig: LogConfig{
								MaxFiles:      10,
								MaxFileSizeMB: 10,
							},
							Templates: []Template{},
							Artifacts: []Artifact{
								Artifact{
									GetterSource: "https://raw.githubusercontent.com/ncodes/cocoon/master/scripts/${NOMAD_META_DEPLOY_SCRIPT_NAME}",
									RelativeDest: "/local/scripts",
								},
							},
							Resources: Resources{
								CPU:      100,
								MemoryMB: 100,
								IOPS:     0,
								Networks: []Network{
									Network{
										MBits: 100,
										DynamicPorts: []DynamicPort{
											DynamicPort{Label: "CONNECTOR_RPC"},
											DynamicPort{Label: "COCOON_RPC"},
										},
									},
								},
							},
							DispatchPayload: DispatchPayload{},
						},
					},
					Resources: Resources{
						CPU:      100,
						MemoryMB: 100,
						IOPS:     0,
						Networks: []Network{},
					},
					RestartPolicy: RestartPolicy{
						Interval: 300000000000,
						Attempts: 10,
						Delay:    25000000000,
						Mode:     "delay",
					},
					Meta: map[string]string{},
				},
			},
			Update: Update{
				Stagger:     10000000000,
				MaxParallel: 1,
			},
		},
	}
}

// GetSpec returns the job's specification
func (j *NomadJob) GetSpec() *Job {
	return j.Job
}
<commit_msg>comment it<commit_after>package scheduler

import (
	"fmt"
)

// Job defines a nomad job specification
type Job struct {
	Region      string
	ID          string
	Name        string
	Type        string
	Priority    int
	AllAtOnce   bool
	Datacenters []string
	Constraints []Constraint
	TaskGroups  []TaskGroup
	Update      Update
}

// Constraint defines a job/task contraint
type Constraint struct {
	LTarget string
	RTarget string
	Operand string
}

// Update defines the update stanza
type Update struct {
	Stagger     int64
	MaxParallel int
}

// TaskGroups defines the task_group stanza
type TaskGroup struct {
	Name          string
	Count         int
	Constraints   []string
	Tasks         []Task
	Resources     Resources
	RestartPolicy RestartPolicy
	Meta          map[string]string
}

// Task defines a job task
type Task struct {
	Name            string
	Driver          string
	Config          Config
	Env             map[string]string
	Services        []NomadService
	Meta            map[string]string
	LogConfig       LogConfig
	Templates       []Template
	Artifacts       []Artifact
	Resources       Resources
	DispatchPayload DispatchPayload
}

// DispatchPayload configures tast to have access to dispatch payload
type DispatchPayload struct {
	File string
}

// Resources defines the resources to allocate to a task
type Resources struct {
	CPU      int
	MemoryMB int
	IOPS     int
	Networks []Network
}

// Network defines network allocation
type Network struct {
	MBits        int
	DynamicPorts []DynamicPort
}

// RestartPolicy defines restart policy
type RestartPolicy struct {
	Interval int64
	Attempts int
	Delay    int64
	Mode     string
}

// DynamicPort defines a dynamic port allocation
type DynamicPort struct {
	Label string
}

// Artifact defines an artifact to be downloaded
type Artifact struct {
	GetterSource  string
	RelativeDest  string
	GetterOptions map[string]string
}

// Template defines template objects to render for the task
type Template struct {
	SourcePath   string
	DestPath     string
	EmbeddedTmpl string
	ChangeMode   string
	ChangeSignal string
	Splay        int64
}

// LogConfig defines log configurations
type LogConfig struct {
	MaxFiles      int
	MaxFileSizeMB int
}

// NomadService defines a service
type NomadService struct {
	Name      string
	Tags      []string
	PortLabel string
	Checks    []Check
}

// Check defines a service check
type Check struct {
	ID       string `json:"Id"`
	Name     string
	Type     string
	Path     string
	Port     string
	Timeout  int64
	Interval int64
	Protocol string
}

// Config defines a driver/task configuration
type Config struct {
	Image       string   `json:"image"`
	ForcePull   bool     `json:"force_pull"`
	Command     string   `json:"command"`
	NetworkMode string   `json:"network_mode"`
	Args        []string `json:"args"`
	Privileged  bool     `json:"privileged"`
	PortMap     []string `json:"port_map"`
}

// NomadJob represents a nomad job
type NomadJob struct {
	Job *Job
}

// NewJob creates a new job with some default values.
func NewJob(id string, count int) *NomadJob {
	return &NomadJob{
		Job: &Job{
			Region:      "",
			ID:          id,
			Name:        id,
			Type:        "service",
			Priority:    50,
			AllAtOnce:   false,
			Datacenters: []string{},
			Constraints: []Constraint{
				Constraint{
					LTarget: "${attr.kernel.name}",
					RTarget: "linux",
					Operand: "=",
				},
			},
			TaskGroups: []TaskGroup{
				TaskGroup{
					Name:  fmt.Sprintf("tskgrp-%s", id),
					Count: count,
					Tasks: []Task{
						Task{
							Name:   fmt.Sprintf("task-%s", id),
							Driver: "docker",
							Config: Config{
								Image:       "ncodes/cocoon-launcher:latest",
								ForcePull:   true,
								Command:     "bash",
								NetworkMode: "host",
								Args:        []string{"${NOMAD_META_SCRIPTS_DIR}/${NOMAD_META_DEPLOY_SCRIPT_NAME}"},
								Privileged:  true,
							},
							Env: map[string]string{
								"COCOON_ID":           id,
								"COCOON_CODE_URL":     "",
								"COCOON_CODE_TAG":     "",
								"COCOON_CODE_LANG":    "",
								"COCOON_BUILD_PARAMS": "",
								"COCOON_DISK_LIMIT":   "",
							},
							Services: []NomadService{
								NomadService{
									Name:      fmt.Sprintf("cocoons-%s", id),
									Tags:      []string{id},
									PortLabel: "CONNECTOR_RPC",
								},
							},
							Meta: map[string]string{
								"DEPLOY_SCRIPT_NAME": "run-connector.sh",
								"SCRIPTS_DIR":        "/local/scripts",
							},
							LogConfig: LogConfig{
								MaxFiles:      10,
								MaxFileSizeMB: 10,
							},
							Templates: []Template{},
							Artifacts: []Artifact{
								Artifact{
									GetterSource: "https://raw.githubusercontent.com/ncodes/cocoon/master/scripts/${NOMAD_META_DEPLOY_SCRIPT_NAME}",
									RelativeDest: "/local/scripts",
								},
							},
							Resources: Resources{
								CPU:      100,
								MemoryMB: 100,
								IOPS:     0,
								Networks: []Network{
									Network{
										MBits: 100,
										DynamicPorts: []DynamicPort{
											DynamicPort{Label: "CONNECTOR_RPC"},
											//	DynamicPort{Label: "CONNECTOR_HTTP"},
											DynamicPort{Label: "COCOON_RPC"},
										},
									},
								},
							},
							DispatchPayload: DispatchPayload{},
						},
					},
					Resources: Resources{
						CPU:      100,
						MemoryMB: 100,
						IOPS:     0,
						Networks: []Network{},
					},
					RestartPolicy: RestartPolicy{
						Interval: 300000000000,
						Attempts: 10,
						Delay:    25000000000,
						Mode:     "delay",
					},
					Meta: map[string]string{},
				},
			},
			Update: Update{
				Stagger:     10000000000,
				MaxParallel: 1,
			},
		},
	}
}

// GetSpec returns the job's specification
func (j *NomadJob) GetSpec() *Job {
	return j.Job
}
<|endoftext|>


<commit_before>/*
 * Datadog API for Go
 *
 * Please see the included LICENSE file for licensing information.
 *
 * Copyright 2013 by authors and contributors.
 */

package datadog

import (
	"errors"
)

// reqInviteUsers contains email addresses to send invitations to.
type reqInviteUsers struct {
	Emails []string `json:"emails"`
}

// InviteUsers takes a slice of email addresses and sends invitations to them.
func (self *Client) InviteUsers(emails []string) error {
	return errors.New("datadog API docs don't list the endpoint")

	//	return self.doJsonRequest("POST", "/v1/alert",
	//		reqInviteUsers{Emails: emails}, nil)
}
<commit_msg>Implement the user invitation method<commit_after>/*
 * Datadog API for Go
 *
 * Please see the included LICENSE file for licensing information.
 *
 * Copyright 2013 by authors and contributors.
 */

package datadog

// reqInviteUsers contains email addresses to send invitations to.
type reqInviteUsers struct {
	Emails []string `json:"emails"`
}

// InviteUsers takes a slice of email addresses and sends invitations to them.
func (self *Client) InviteUsers(emails []string) error {
	return self.doJsonRequest("POST", "/v1/account/invite",
		reqInviteUsers{Emails: emails}, nil)
}
<|endoftext|>


<commit_before>package db

import (
	"database/sql"
	"fmt"
	"reflect"

	"github.com/Mparaiso/go-orm/tools"
	"github.com/Mparaiso/go-tiger/db/platform"
	"github.com/Mparaiso/go-tiger/logger"
)

var (
	// ErrNotAPointer is yield when a pointer was expected
	ErrNotAPointer = fmt.Errorf("Error, value is not a pointer.")
)

// Connection is the db connection
type Connection interface {
	GetDatabasePlatform() platform.DatabasePlatform
}

// ConnectionOptions gather options related to Connection type.
type ConnectionOptions struct {
	Logger              logger.Logger
	IgnoreMissingFields bool
}

// DefaultConnection is a database connection.
// Please use NewConnectionto create a Connection.
type DefaultConnection struct {
	Db         *sql.DB
	DriverName string
	Options    *ConnectionOptions
	Platform   platform.DatabasePlatform
}

// NewConnection creates an new Connection
func NewConnection(driverName string, DB *sql.DB) *DefaultConnection {
	connection := NewConnectionWithOptions(driverName, DB, &ConnectionOptions{})
	return connection
}

// NewConnectionWithOptions creates an new connection with optional settings such as Logging.
func NewConnectionWithOptions(driverName string, DB *sql.DB, options *ConnectionOptions) *DefaultConnection {
	return &DefaultConnection{Db: DB, DriverName: driverName, Options: options}
}

// GetDriverName returns the DriverName
func (connection *DefaultConnection) GetDriverName() string {
	return connection.DriverName
}

// GetDatabasePlatform returns the database platform
func (connection *DefaultConnection) GetDatabasePlatform() platform.DatabasePlatform {
	if connection.Platform == nil {
		connection.detectDatabasePlatform()
	}
	return connection.Platform
}
func (connection *DefaultConnection) detectDatabasePlatform() {
	databasePlatform := platform.NewDefaultPlatform()
	switch connection.GetDriverName() {
	case "sqlite3":
		connection.Platform = platform.NewSqlitePlatform(databasePlatform)
	case "mysql":
		connection.Platform = platform.NewMySqlPlatform(databasePlatform)
	case "postgresql":
		connection.Platform = platform.NewPostgreSqlPlatform(databasePlatform)
	default:
		connection.Platform = databasePlatform
	}
}

// DB returns Go standard *sql.DB type
func (connection *DefaultConnection) DB() *sql.DB {
	return connection.Db
}

// Prepare prepares a statement
func (connection *DefaultConnection) Prepare(sql string) (*sql.Stmt, error) {
	return connection.DB().Prepare(sql)
}

// Exec will execute a query like INSERT,UPDATE,DELETE.
func (connection *DefaultConnection) Exec(query string, parameters ...interface{}) (sql.Result, error) {
	defer connection.log(append([]interface{}{query}, parameters...)...)
	return connection.DB().Exec(query, parameters...)
}

// Select with fetch multiple records.
func (connection *DefaultConnection) Select(records interface{}, query string, parameters ...interface{}) error {
	defer connection.log(append([]interface{}{query}, parameters...)...)

	rows, err := connection.Db.Query(query, parameters...)
	if err != nil {
		return err
	}
	err = tools.MapRowsToSliceOfStruct(rows, records, true)

	return err
}

// SelectMap queries the database and populates an array of mpa[string]interface{}
func (connection *DefaultConnection) SelectMap(Map *[]map[string]interface{}, query string, parameters ...interface{}) error {
	defer connection.log(append([]interface{}{query}, parameters...)...)

	rows, err := connection.Db.Query(query, parameters...)
	if err != nil {
		return err
	}
	return tools.MapRowsToSliceOfMaps(rows, Map)

}

// SelectSlice queryies the database an populates an array of arrays
func (connection *DefaultConnection) SelectSlice(slices *[][]interface{}, query string, parameters ...interface{}) error {
	defer connection.log(append([]interface{}{query}, parameters...)...)

	rows, err := connection.Db.Query(query, parameters...)
	if err != nil {
		return err
	}
	return tools.MapRowsToSliceOfSlices(rows, slices)

}

// Get will fetch a single record.
// expects record to be a pointer to a struct
// Exemple:
//    user := new(User)
//    err := connection.get(user,"SELECT * from users WHERE users.id = ?",1)
//
func (connection *DefaultConnection) Get(record interface{}, query string, parameters ...interface{}) error {
	// make a slice from the record type
	// pass a pointer to that slice to connection.Select
	// if the slice's length == 1 , put back the first value of that
	// slice in the record value.
	if reflect.TypeOf(record).Kind() != reflect.Ptr {
		return ErrNotAPointer
	}
	recordValue := reflect.ValueOf(record)
	recordType := recordValue.Type()
	sliceOfRecords := reflect.MakeSlice(reflect.SliceOf(recordType), 0, 1)
	pointerOfSliceOfRecords := reflect.New(sliceOfRecords.Type())
	pointerOfSliceOfRecords.Elem().Set(sliceOfRecords)
	//
	err := connection.Select(pointerOfSliceOfRecords.Interface(), query, parameters...)
	if err != nil {
		return err
	}
	if pointerOfSliceOfRecords.Elem().Len() >= 1 {
		recordValue.Elem().Set(reflect.Indirect(pointerOfSliceOfRecords).Index(0).Elem())

	} else {
		return sql.ErrNoRows
	}
	return nil
}

func (connection *DefaultConnection) log(messages ...interface{}) {
	if connection.Options.Logger != nil {
		connection.Options.Logger.Log(logger.Debug, messages...)
	}
}

// Begin initiates a transaction
func (connection *DefaultConnection) Begin() (*Transaction, error) {
	defer connection.log("Begin transaction")
	transaction, err := connection.DB().Begin()
	if err != nil {
		return nil, err
	}
	return &Transaction{Logger: connection.Options.Logger, Tx: transaction}, nil
}

// Close closes the connection
func (connection *DefaultConnection) Close() error {
	return connection.Db.Close()
}
<commit_msg>go-orm dependency removed<commit_after>package db

import (
	"database/sql"
	"fmt"
	"reflect"

	"github.com/Mparaiso/go-tiger/db/platform"
	"github.com/Mparaiso/go-tiger/logger"
)

var (
	// ErrNotAPointer is yield when a pointer was expected
	ErrNotAPointer = fmt.Errorf("Error, value is not a pointer.")
)

// Connection is the db connection
type Connection interface {
	GetDatabasePlatform() platform.DatabasePlatform
}

// ConnectionOptions gather options related to Connection type.
type ConnectionOptions struct {
	Logger              logger.Logger
	IgnoreMissingFields bool
}

// DefaultConnection is a database connection.
// Please use NewConnectionto create a Connection.
type DefaultConnection struct {
	Db         *sql.DB
	DriverName string
	Options    *ConnectionOptions
	Platform   platform.DatabasePlatform
}

// NewConnection creates an new Connection
func NewConnection(driverName string, DB *sql.DB) *DefaultConnection {
	connection := NewConnectionWithOptions(driverName, DB, &ConnectionOptions{})
	return connection
}

// NewConnectionWithOptions creates an new connection with optional settings such as Logging.
func NewConnectionWithOptions(driverName string, DB *sql.DB, options *ConnectionOptions) *DefaultConnection {
	return &DefaultConnection{Db: DB, DriverName: driverName, Options: options}
}

// GetDriverName returns the DriverName
func (connection *DefaultConnection) GetDriverName() string {
	return connection.DriverName
}

// GetDatabasePlatform returns the database platform
func (connection *DefaultConnection) GetDatabasePlatform() platform.DatabasePlatform {
	if connection.Platform == nil {
		connection.detectDatabasePlatform()
	}
	return connection.Platform
}
func (connection *DefaultConnection) detectDatabasePlatform() {
	databasePlatform := platform.NewDefaultPlatform()
	switch connection.GetDriverName() {
	case "sqlite3":
		connection.Platform = platform.NewSqlitePlatform(databasePlatform)
	case "mysql":
		connection.Platform = platform.NewMySqlPlatform(databasePlatform)
	case "postgresql":
		connection.Platform = platform.NewPostgreSqlPlatform(databasePlatform)
	default:
		connection.Platform = databasePlatform
	}
}

// DB returns Go standard *sql.DB type
func (connection *DefaultConnection) DB() *sql.DB {
	return connection.Db
}

// Prepare prepares a statement
func (connection *DefaultConnection) Prepare(sql string) (*sql.Stmt, error) {
	return connection.DB().Prepare(sql)
}

// Exec will execute a query like INSERT,UPDATE,DELETE.
func (connection *DefaultConnection) Exec(query string, parameters ...interface{}) (sql.Result, error) {
	defer connection.log(append([]interface{}{query}, parameters...)...)
	return connection.DB().Exec(query, parameters...)
}

// Select with fetch multiple records.
func (connection *DefaultConnection) Select(records interface{}, query string, parameters ...interface{}) error {
	defer connection.log(append([]interface{}{query}, parameters...)...)

	rows, err := connection.Db.Query(query, parameters...)
	if err != nil {
		return err
	}
	err = MapRowsToSliceOfStruct(rows, records, true)

	return err
}

// SelectMap queries the database and populates an array of mpa[string]interface{}
func (connection *DefaultConnection) SelectMap(Map *[]map[string]interface{}, query string, parameters ...interface{}) error {
	defer connection.log(append([]interface{}{query}, parameters...)...)

	rows, err := connection.Db.Query(query, parameters...)
	if err != nil {
		return err
	}
	return MapRowsToSliceOfMaps(rows, Map)

}

// SelectSlice queryies the database an populates an array of arrays
func (connection *DefaultConnection) SelectSlice(slices *[][]interface{}, query string, parameters ...interface{}) error {
	defer connection.log(append([]interface{}{query}, parameters...)...)

	rows, err := connection.Db.Query(query, parameters...)
	if err != nil {
		return err
	}
	return MapRowsToSliceOfSlices(rows, slices)

}

// Get will fetch a single record.
// expects record to be a pointer to a struct
// Exemple:
//    user := new(User)
//    err := connection.get(user,"SELECT * from users WHERE users.id = ?",1)
//
func (connection *DefaultConnection) Get(record interface{}, query string, parameters ...interface{}) error {
	// make a slice from the record type
	// pass a pointer to that slice to connection.Select
	// if the slice's length == 1 , put back the first value of that
	// slice in the record value.
	if reflect.TypeOf(record).Kind() != reflect.Ptr {
		return ErrNotAPointer
	}
	recordValue := reflect.ValueOf(record)
	recordType := recordValue.Type()
	sliceOfRecords := reflect.MakeSlice(reflect.SliceOf(recordType), 0, 1)
	pointerOfSliceOfRecords := reflect.New(sliceOfRecords.Type())
	pointerOfSliceOfRecords.Elem().Set(sliceOfRecords)
	//
	err := connection.Select(pointerOfSliceOfRecords.Interface(), query, parameters...)
	if err != nil {
		return err
	}
	if pointerOfSliceOfRecords.Elem().Len() >= 1 {
		recordValue.Elem().Set(reflect.Indirect(pointerOfSliceOfRecords).Index(0).Elem())

	} else {
		return sql.ErrNoRows
	}
	return nil
}

func (connection *DefaultConnection) log(messages ...interface{}) {
	if connection.Options.Logger != nil {
		connection.Options.Logger.Log(logger.Debug, messages...)
	}
}

// Begin initiates a transaction
func (connection *DefaultConnection) Begin() (*Transaction, error) {
	defer connection.log("Begin transaction")
	transaction, err := connection.DB().Begin()
	if err != nil {
		return nil, err
	}
	return &Transaction{Logger: connection.Options.Logger, Tx: transaction}, nil
}

// Close closes the connection
func (connection *DefaultConnection) Close() error {
	return connection.Db.Close()
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Che Wei, Lin
//
// 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 tinynet

import (
	"net"
	"strconv"
	"time"

	"github.com/John-Lin/ovsdb"
	log "github.com/Sirupsen/logrus"
)

// OVSSwitch is a bridge instance
type OVSSwitch struct {
	nodeType     string
	bridgeName   string
	ctrlHostPort string
	ovsdb        *ovsdb.OvsDriver
}

// NewOVSSwitch for creating a ovs bridge
func NewOVSSwitch(bridgeName string) (*OVSSwitch, error) {
	sw := new(OVSSwitch)
	sw.nodeType = "OVSSwitch"
	sw.bridgeName = bridgeName
	// sw.ctrlHostPort = ctrlHostPort

	sw.ovsdb = ovsdb.NewOvsDriverWithUnix(bridgeName)

	// Check if port is already part of the OVS and add it
	if !sw.ovsdb.IsPortNamePresent(bridgeName) {
		// Create an internal port in OVS
		err := sw.ovsdb.CreatePort(bridgeName, "internal", 0)
		if err != nil {
			log.Fatalf("Error creating the internal port. Err: %v", err)
			return nil, err
		}
	}

	time.Sleep(300 * time.Millisecond)
	log.Infof("Waiting for OVS bridge %s setup", bridgeName)

	// ip link set ovs up
	_, err := ifaceUp(bridgeName)
	if err != nil {
		return nil, err
	}

	return sw, nil
}

// addPort for asking OVSDB driver to add the port
func (sw *OVSSwitch) addPort(ifName string) error {
	if !sw.ovsdb.IsPortNamePresent(ifName) {
		err := sw.ovsdb.CreatePort(ifName, "", 0)
		if err != nil {
			log.Fatalf("Error creating the port. Err: %v", err)
			return err
		}
	}
	return nil
}

// setCtrl for seting up OpenFlow controller for ovs bridge
func (sw *OVSSwitch) setCtrl(hostport string) error {
	host, port, err := net.SplitHostPort(hostport)
	if err != nil {
		log.Fatalf("Invalid controller IP and port. Err: %v", err)
		return err
	}
	uPort, err := strconv.ParseUint(port, 10, 32)
	if err != nil {
		log.Fatalf("Invalid controller port number. Err: %v", err)
		return err
	}
	err = sw.ovsdb.AddController(host, uint16(uPort))
	if err != nil {
		log.Fatalf("Error adding controller to OVS. Err: %v", err)
		return err
	}
	return nil
}
<commit_msg>fixed: save openflow controller info<commit_after>// Copyright (c) 2017 Che Wei, Lin
//
// 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 tinynet

import (
	"net"
	"strconv"
	"time"

	"github.com/John-Lin/ovsdb"
	log "github.com/Sirupsen/logrus"
)

// OVSSwitch is a bridge instance
type OVSSwitch struct {
	nodeType     string
	bridgeName   string
	ctrlHostPort string
	ovsdb        *ovsdb.OvsDriver
}

// NewOVSSwitch for creating a ovs bridge
func NewOVSSwitch(bridgeName string) (*OVSSwitch, error) {
	sw := new(OVSSwitch)
	sw.nodeType = "OVSSwitch"
	sw.bridgeName = bridgeName

	sw.ovsdb = ovsdb.NewOvsDriverWithUnix(bridgeName)

	// Check if port is already part of the OVS and add it
	if !sw.ovsdb.IsPortNamePresent(bridgeName) {
		// Create an internal port in OVS
		err := sw.ovsdb.CreatePort(bridgeName, "internal", 0)
		if err != nil {
			log.Fatalf("Error creating the internal port. Err: %v", err)
			return nil, err
		}
	}

	time.Sleep(300 * time.Millisecond)
	log.Infof("Waiting for OVS bridge %s setup", bridgeName)

	// ip link set ovs up
	_, err := ifaceUp(bridgeName)
	if err != nil {
		return nil, err
	}

	return sw, nil
}

// addPort for asking OVSDB driver to add the port
func (sw *OVSSwitch) addPort(ifName string) error {
	if !sw.ovsdb.IsPortNamePresent(ifName) {
		err := sw.ovsdb.CreatePort(ifName, "", 0)
		if err != nil {
			log.Fatalf("Error creating the port. Err: %v", err)
			return err
		}
	}
	return nil
}

// setCtrl for seting up OpenFlow controller for ovs bridge
func (sw *OVSSwitch) setCtrl(hostport string) error {
	host, port, err := net.SplitHostPort(hostport)
	if err != nil {
		log.Fatalf("Invalid controller IP and port. Err: %v", err)
		return err
	}
	uPort, err := strconv.ParseUint(port, 10, 32)
	if err != nil {
		log.Fatalf("Invalid controller port number. Err: %v", err)
		return err
	}
	err = sw.ovsdb.AddController(host, uint16(uPort))
	if err != nil {
		log.Fatalf("Error adding controller to OVS. Err: %v", err)
		return err
	}
	sw.ctrlHostPort = hostport
	return nil
}
<|endoftext|>


<commit_before>package main // import "eriol.xyz/piken"

import (
	"io"
	"net/http"
	"os"

	"github.com/Sirupsen/logrus"
	"github.com/mitchellh/go-homedir"
)

func download(url, output string) error {

	r, err := http.Get(url)
	if err != nil {
		return err
	}
	defer r.Body.Close()

	out, err := os.Create(output)
	if err != nil {
		return err
	}
	defer out.Close()

	// io.copyBuffer, the actual implementation of io.Copy, reads maximum 32 KB
	// from input, writes to output and then repeats. No need to worry about
	// the size of file to download.
	_, err = io.Copy(out, r.Body)
	if err != nil {
		return err
	}

	return nil

}

// Get user home directory or exit with a fatal error.
func getHome() string {

	homeDir, err := homedir.Dir()
	if err != nil {
		logrus.Fatal(err)
	}

	return homeDir
}
<commit_msg>Read a CSV file and return a slice of slice<commit_after>package main // import "eriol.xyz/piken"

import (
	"encoding/csv"
	"io"
	"net/http"
	"os"

	"github.com/Sirupsen/logrus"
	"github.com/mitchellh/go-homedir"
)

func download(url, output string) error {

	r, err := http.Get(url)
	if err != nil {
		return err
	}
	defer r.Body.Close()

	out, err := os.Create(output)
	if err != nil {
		return err
	}
	defer out.Close()

	// io.copyBuffer, the actual implementation of io.Copy, reads maximum 32 KB
	// from input, writes to output and then repeats. No need to worry about
	// the size of file to download.
	_, err = io.Copy(out, r.Body)
	if err != nil {
		return err
	}

	return nil

}

// Get user home directory or exit with a fatal error.
func getHome() string {

	homeDir, err := homedir.Dir()
	if err != nil {
		logrus.Fatal(err)
	}

	return homeDir
}

// Read a CSV file and return a slice of slice.
func readCsvFile(filepath string) (records [][]string, err error) {

	file, err := os.Open(filepath)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	reader := csv.NewReader(file)
	reader.Comma = ';'
	records, err = reader.ReadAll()
	if err != nil {
		return nil, err
	}

	return records, nil

}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	log "github.com/sirupsen/logrus"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"
	"math"
)

const (
	everyInstance = -1 // Used when replacing strings

	// KiB is a kilobyte
	KiB = 1024
	// MiB is a megabyte
	MiB = 1024 * 1024
)

var (
	// A selection of allowed keywords for the HTML meta tag
	metaKeywords = []string{"application-name", "author", "description", "generator", "keywords", "robots", "language", "googlebot", "Slurp", "bingbot", "geo.position", "geo.placename", "geo.region", "ICBM", "viewport"}
)

// FileStat can cache calls to os.Stat. This requires that the user wants to
// assume that no files are removed from the server directory while the server
// is running, to gain some additional speed (and a tiny bit of memory use for
// the cache).
type FileStat struct {
	// If cache + mut are enabled
	useCache bool

	// Cache for checking if directories exists, if "everFile" is enabled
	dirCache map[string]bool
	dirMut   *sync.RWMutex

	// Cache for checking if files exists, if "everFile" is enabled
	exCache map[string]bool
	exMut   *sync.RWMutex
}

// NewFileStat creates a new FileStat struct, with optional caching.
// Only use the caching if it is not critical that os.Stat is always correct.
func NewFileStat(useCache bool, repeatedlyClearStatCache time.Duration) *FileStat {
	if !useCache {
		return &FileStat{false, nil, nil, nil, nil}
	}

	dirCache := make(map[string]bool)
	dirMut := new(sync.RWMutex)

	exCache := make(map[string]bool)
	exMut := new(sync.RWMutex)

	fs := &FileStat{true, dirCache, dirMut, exCache, exMut}

	// Clear the file stat cache every N seconds
	go func() {
		for {
			time.Sleep(repeatedlyClearStatCache)

			fs.dirMut.Lock()
			fs.dirCache = make(map[string]bool)
			fs.dirMut.Unlock()

			fs.exMut.Lock()
			fs.exCache = make(map[string]bool)
			fs.exMut.Unlock()
		}
	}()

	return fs
}

// Normalize a filename by removing the preceeding "./".
// Useful when caching, to avoid duplicate entries.
func normalize(filename string) string {
	if filename == "" {
		return ""
	}
	// Slight optimization:
	// Avoid taking the length of the string until we know it is needed
	if filename[0] == '.' {
		if len(filename) > 2 { // Don't remove "./" if that is all there is
			if filename[1] == '/' {
				return filename[2:]
			}
		}
	}
	return filename
}

// Check if a given path is a directory
func (fs *FileStat) isDir(path string) bool {
	if fs.useCache {
		path = normalize(path)
		// Assume this to be true
		if path == "." {
			return true
		}
		// Use the read mutex
		fs.dirMut.RLock()
		// Check the cache
		val, ok := fs.dirCache[path]
		if ok {
			fs.dirMut.RUnlock()
			return val
		}
		fs.dirMut.RUnlock()
		// Use the write mutex
		fs.dirMut.Lock()
		defer fs.dirMut.Unlock()
		// Check the filesystem
		fileInfo, err := os.Stat(path)
		if err != nil {
			// Save to cache and return
			fs.dirCache[path] = false
			return false
		}
		okDir := fileInfo.IsDir()
		// Save to cache and return
		fs.dirCache[path] = okDir
		return okDir
	}
	fileInfo, err := os.Stat(path)
	if err != nil {
		return false
	}
	return fileInfo.IsDir()
}

// Check if a given path exists
func (fs *FileStat) exists(path string) bool {
	if fs.useCache {
		path = normalize(path)
		// Use the read mutex
		fs.exMut.RLock()
		// Check the cache
		val, ok := fs.exCache[path]
		if ok {
			fs.exMut.RUnlock()
			return val
		}
		fs.exMut.RUnlock()
		// Use the write mutex
		fs.exMut.Lock()
		defer fs.exMut.Unlock()
		// Check the filesystem
		_, err := os.Stat(path)
		// Save to cache and return
		if err != nil {
			fs.exCache[path] = false
			return false
		}
		fs.exCache[path] = true
		return true
	}
	_, err := os.Stat(path)
	return err == nil
}

// Create an empty file if it doesn't exist
func touch(filename string) error {
	if !fs.exists(filename) {
		_, err := os.Create(filename)
		return err
	}
	return nil
}

// Translate a given URL path to a probable full filename
func url2filename(dirname, urlpath string) string {
	if strings.Contains(urlpath, "..") {
		log.Warn("Someone was trying to access a directory with .. in the URL")
		return dirname + pathsep
	}
	if strings.HasPrefix(urlpath, "/") {
		if strings.HasSuffix(dirname, pathsep) {
			return dirname + urlpath[1:]
		}
		return dirname + pathsep + urlpath[1:]
	}
	return dirname + "/" + urlpath
}

// Get a list of filenames from a given directory name (that must exist)
func getFilenames(dirname string) []string {
	dir, err := os.Open(dirname)
	defer dir.Close()
	if err != nil {
		log.WithFields(log.Fields{
			"dirname": dirname,
			"error":   err.Error(),
		}).Error("Could not open directory")
		return []string{}
	}
	filenames, err := dir.Readdirnames(-1)
	if err != nil {
		log.WithFields(log.Fields{
			"dirname": dirname,
			"error":   err.Error(),
		}).Error("Could not read filenames from directory")

		return []string{}
	}
	return filenames
}

// Easy way to output a HTML page
func easyPage(title, body string) string {
	return fmt.Sprintf("<!doctype html><title>%s</title>%s
%s
%s", title, defaultFont, defaultStyle, title, body)
}

// Easy way to build links to directories
func easyLink(text, url string, isDirectory bool) string {
	// Add a final slash, if needed
	if isDirectory {
		text += "/"
		url += "/"
	}
	return "" + text + "
"
}

// Build up a string on the form "functionname(arg1, arg2, arg3)"
func infostring(functionName string, args []string) string {
	s := functionName + "("
	if len(args) > 0 {
		s += "\"" + strings.Join(args, "\", \"") + "\""
	}
	return s + ")"
}

// Find one level of whitespace, given indented data
// and a keyword to extract the whitespace in front of
func oneLevelOfIndentation(data *[]byte, keyword string) string {
	whitespace := ""
	kwb := []byte(keyword)
	// If there is a line that contains the given word, extract the whitespace
	if bytes.Contains(*data, kwb) {
		// Find the line that contains they keyword
		var byteline []byte
		found := false
		// Try finding the line with keyword, using \n as the newline
		for _, byteline = range bytes.Split(*data, []byte("\n")) {
			if bytes.Contains(byteline, kwb) {
				found = true
				break
			}
		}
		if found {
			// Find the whitespace in front of the keyword
			whitespaceBytes := byteline[:bytes.Index(byteline, kwb)]
			// Whitespace for one level of indentation
			whitespace = string(whitespaceBytes)
		}
	}
	// Return an empty string, or whitespace for one level of indentation
	return whitespace
}

// Add a link to a stylesheet in the given Amber code
func linkToStyle(amberdata *[]byte, url string) {
	// If the given url is not already mentioned and the data contains "body"
	if !bytes.Contains(*amberdata, []byte(url)) && bytes.Contains(*amberdata, []byte("html")) && bytes.Contains(*amberdata, []byte("body")) {
		// Extract one level of indendation
		whitespace := oneLevelOfIndentation(amberdata, "body")
		// Check if there already is a head section
		if bytes.Contains(*amberdata, []byte("head")) {
			// Add a link to the stylesheet
			*amberdata = bytes.Replace(*amberdata, []byte("head\n"), []byte("head\n"+whitespace+whitespace+`link[href="`+url+`"][rel="stylesheet"][type="text/css"]`+"\n"), 1)

		} else if bytes.Contains(*amberdata, []byte("body")) {

			// Add a link to the stylesheet
			*amberdata = bytes.Replace(*amberdata, []byte("html\n"), []byte("html\n"+whitespace+"head\n"+whitespace+whitespace+`link[href="`+url+`"][rel="stylesheet"][type="text/css"]`+"\n"), 1)
		}
	}
}

// Filter []byte slices into two groups, depending on the given filter function
func filterIntoGroups(bytelines [][]byte, filterfunc func([]byte) bool) ([][]byte, [][]byte) {
	var special, regular [][]byte
	for _, byteline := range bytelines {
		if filterfunc(byteline) {
			// Special
			special = append(special, byteline)
		} else {
			// Regular
			regular = append(regular, byteline)
		}
	}
	return special, regular
}

// Given a source file, extract keywords and values into the given map.
// The map must be filled with keywords to look for.
// The keywords in the data must be on the form "keyword: value",
// and can be within single-line HTML comments (<-- ... -->).
// Returns the data for the lines that does not contain any of the keywords.
func extractKeywords(data []byte, special map[string]string) []byte {
	bnl := []byte("\n")
	// Find and separate the lines starting with one of the keywords in the special map
	_, regular := filterIntoGroups(bytes.Split(data, bnl), func(byteline []byte) bool {
		// Check if the current line has one of the special keywords
		for keyword := range special {
			// Check for lines starting with the keyword and a ":"
			if bytes.HasPrefix(byteline, []byte(keyword+":")) {
				// Set (possibly overwrite) the value in the map, if the keyword is found.
				// Trim the surrounding whitespace and skip the letters of the keyword itself.
				special[keyword] = strings.TrimSpace(string(byteline)[len(keyword)+1:])
				return true
			}
			// Check for lines that starts with "" and contains the keyword and a ":"
			if bytes.HasPrefix(byteline, []byte("")) {
				// Strip away the comment markers
				stripped := strings.TrimSpace(string(byteline[5 : len(byteline)-3]))
				// Check if one of the relevant keywords are present
				if strings.HasPrefix(stripped, keyword+":") {
					// Set (possibly overwrite) the value in the map, if the keyword is found.
					// Trim the surrounding whitespace and skip the letters of the keyword itself.
					special[keyword] = strings.TrimSpace(stripped[len(keyword)+1:])
					return true
				}
			}

		}
		// Not special
		return false
	})
	// Use the regular lines as the new data (remove the special lines)
	return bytes.Join(regular, bnl)
}

// Add meta tag names to the given map
func addMetaKeywords(keywords map[string]string) {
	for _, keyword := range metaKeywords {
		keywords[keyword] = ""
	}
}

// Fatal exit
func fatalExit(err error) {
	// Log to file, if a log file is used
	if serverLogFile != "" {
		log.Error(err)
	}
	// Then switch to stderr and log the message there as well
	log.SetOutput(os.Stderr)
	// Use the standard formatter
	log.SetFormatter(&log.TextFormatter{})
	// Log and exit
	log.Fatalln(err)
}

// Insert doctype in HTML, if missing
func insertDoctype(htmldata []byte) []byte {
	// If there are more than two lines
	if bytes.Count(htmldata, []byte("\n")) > 2 {
		fields := bytes.SplitN(htmldata, []byte("\n"), 3)
		line1 := strings.ToLower(string(fields[0]))
		line2 := strings.ToLower(string(fields[1]))
		if strings.Contains(line1, "doctype") || strings.Contains(line2, "doctype") {
			return htmldata
		}
		// Doctype is missing from the first two lines, add it
		return []byte("<!doctype html>" + string(htmldata))
	}
	return htmldata
}

// Convert time.Duration to milliseconds, as a string (without "ms")
func durationToMS(d time.Duration, multiplier float64) string {
	return strconv.Itoa(int(d.Seconds() * 1000.0 * multiplier))
}

// Return "enabled" or "disabled" depending on the given bool
func enabledStatus(enabled bool) string {
	if enabled {
		return "enabled"
	}
	return "disabled"
}

// Convert byte to KiB or MiB
func describeBytes(size int64) string {
	if (size < MiB) {
      return strconv.Itoa(int(round(float64(size) * 100.0 / KiB) / 100)) + " KiB"
    }
    return strconv.Itoa(int(round(float64(size) * 100.0 / MiB) / 100)) + " MiB"
}

func roundf(x float64) float64 {
	return math.Floor(0.5 + x)
}

func round(x float64) int64 {
	return int64(roundf(x))
}

<commit_msg>Formatting<commit_after>package main

import (
	"bytes"
	"fmt"
	log "github.com/sirupsen/logrus"
	"math"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"
)

const (
	everyInstance = -1 // Used when replacing strings

	// KiB is a kilobyte
	KiB = 1024
	// MiB is a megabyte
	MiB = 1024 * 1024
)

var (
	// A selection of allowed keywords for the HTML meta tag
	metaKeywords = []string{"application-name", "author", "description", "generator", "keywords", "robots", "language", "googlebot", "Slurp", "bingbot", "geo.position", "geo.placename", "geo.region", "ICBM", "viewport"}
)

// FileStat can cache calls to os.Stat. This requires that the user wants to
// assume that no files are removed from the server directory while the server
// is running, to gain some additional speed (and a tiny bit of memory use for
// the cache).
type FileStat struct {
	// If cache + mut are enabled
	useCache bool

	// Cache for checking if directories exists, if "everFile" is enabled
	dirCache map[string]bool
	dirMut   *sync.RWMutex

	// Cache for checking if files exists, if "everFile" is enabled
	exCache map[string]bool
	exMut   *sync.RWMutex
}

// NewFileStat creates a new FileStat struct, with optional caching.
// Only use the caching if it is not critical that os.Stat is always correct.
func NewFileStat(useCache bool, repeatedlyClearStatCache time.Duration) *FileStat {
	if !useCache {
		return &FileStat{false, nil, nil, nil, nil}
	}

	dirCache := make(map[string]bool)
	dirMut := new(sync.RWMutex)

	exCache := make(map[string]bool)
	exMut := new(sync.RWMutex)

	fs := &FileStat{true, dirCache, dirMut, exCache, exMut}

	// Clear the file stat cache every N seconds
	go func() {
		for {
			time.Sleep(repeatedlyClearStatCache)

			fs.dirMut.Lock()
			fs.dirCache = make(map[string]bool)
			fs.dirMut.Unlock()

			fs.exMut.Lock()
			fs.exCache = make(map[string]bool)
			fs.exMut.Unlock()
		}
	}()

	return fs
}

// Normalize a filename by removing the preceeding "./".
// Useful when caching, to avoid duplicate entries.
func normalize(filename string) string {
	if filename == "" {
		return ""
	}
	// Slight optimization:
	// Avoid taking the length of the string until we know it is needed
	if filename[0] == '.' {
		if len(filename) > 2 { // Don't remove "./" if that is all there is
			if filename[1] == '/' {
				return filename[2:]
			}
		}
	}
	return filename
}

// Check if a given path is a directory
func (fs *FileStat) isDir(path string) bool {
	if fs.useCache {
		path = normalize(path)
		// Assume this to be true
		if path == "." {
			return true
		}
		// Use the read mutex
		fs.dirMut.RLock()
		// Check the cache
		val, ok := fs.dirCache[path]
		if ok {
			fs.dirMut.RUnlock()
			return val
		}
		fs.dirMut.RUnlock()
		// Use the write mutex
		fs.dirMut.Lock()
		defer fs.dirMut.Unlock()
		// Check the filesystem
		fileInfo, err := os.Stat(path)
		if err != nil {
			// Save to cache and return
			fs.dirCache[path] = false
			return false
		}
		okDir := fileInfo.IsDir()
		// Save to cache and return
		fs.dirCache[path] = okDir
		return okDir
	}
	fileInfo, err := os.Stat(path)
	if err != nil {
		return false
	}
	return fileInfo.IsDir()
}

// Check if a given path exists
func (fs *FileStat) exists(path string) bool {
	if fs.useCache {
		path = normalize(path)
		// Use the read mutex
		fs.exMut.RLock()
		// Check the cache
		val, ok := fs.exCache[path]
		if ok {
			fs.exMut.RUnlock()
			return val
		}
		fs.exMut.RUnlock()
		// Use the write mutex
		fs.exMut.Lock()
		defer fs.exMut.Unlock()
		// Check the filesystem
		_, err := os.Stat(path)
		// Save to cache and return
		if err != nil {
			fs.exCache[path] = false
			return false
		}
		fs.exCache[path] = true
		return true
	}
	_, err := os.Stat(path)
	return err == nil
}

// Create an empty file if it doesn't exist
func touch(filename string) error {
	if !fs.exists(filename) {
		_, err := os.Create(filename)
		return err
	}
	return nil
}

// Translate a given URL path to a probable full filename
func url2filename(dirname, urlpath string) string {
	if strings.Contains(urlpath, "..") {
		log.Warn("Someone was trying to access a directory with .. in the URL")
		return dirname + pathsep
	}
	if strings.HasPrefix(urlpath, "/") {
		if strings.HasSuffix(dirname, pathsep) {
			return dirname + urlpath[1:]
		}
		return dirname + pathsep + urlpath[1:]
	}
	return dirname + "/" + urlpath
}

// Get a list of filenames from a given directory name (that must exist)
func getFilenames(dirname string) []string {
	dir, err := os.Open(dirname)
	defer dir.Close()
	if err != nil {
		log.WithFields(log.Fields{
			"dirname": dirname,
			"error":   err.Error(),
		}).Error("Could not open directory")
		return []string{}
	}
	filenames, err := dir.Readdirnames(-1)
	if err != nil {
		log.WithFields(log.Fields{
			"dirname": dirname,
			"error":   err.Error(),
		}).Error("Could not read filenames from directory")

		return []string{}
	}
	return filenames
}

// Easy way to output a HTML page
func easyPage(title, body string) string {
	return fmt.Sprintf("<!doctype html><title>%s</title>%s
%s
%s", title, defaultFont, defaultStyle, title, body)
}

// Easy way to build links to directories
func easyLink(text, url string, isDirectory bool) string {
	// Add a final slash, if needed
	if isDirectory {
		text += "/"
		url += "/"
	}
	return "" + text + "
"
}

// Build up a string on the form "functionname(arg1, arg2, arg3)"
func infostring(functionName string, args []string) string {
	s := functionName + "("
	if len(args) > 0 {
		s += "\"" + strings.Join(args, "\", \"") + "\""
	}
	return s + ")"
}

// Find one level of whitespace, given indented data
// and a keyword to extract the whitespace in front of
func oneLevelOfIndentation(data *[]byte, keyword string) string {
	whitespace := ""
	kwb := []byte(keyword)
	// If there is a line that contains the given word, extract the whitespace
	if bytes.Contains(*data, kwb) {
		// Find the line that contains they keyword
		var byteline []byte
		found := false
		// Try finding the line with keyword, using \n as the newline
		for _, byteline = range bytes.Split(*data, []byte("\n")) {
			if bytes.Contains(byteline, kwb) {
				found = true
				break
			}
		}
		if found {
			// Find the whitespace in front of the keyword
			whitespaceBytes := byteline[:bytes.Index(byteline, kwb)]
			// Whitespace for one level of indentation
			whitespace = string(whitespaceBytes)
		}
	}
	// Return an empty string, or whitespace for one level of indentation
	return whitespace
}

// Add a link to a stylesheet in the given Amber code
func linkToStyle(amberdata *[]byte, url string) {
	// If the given url is not already mentioned and the data contains "body"
	if !bytes.Contains(*amberdata, []byte(url)) && bytes.Contains(*amberdata, []byte("html")) && bytes.Contains(*amberdata, []byte("body")) {
		// Extract one level of indendation
		whitespace := oneLevelOfIndentation(amberdata, "body")
		// Check if there already is a head section
		if bytes.Contains(*amberdata, []byte("head")) {
			// Add a link to the stylesheet
			*amberdata = bytes.Replace(*amberdata, []byte("head\n"), []byte("head\n"+whitespace+whitespace+`link[href="`+url+`"][rel="stylesheet"][type="text/css"]`+"\n"), 1)

		} else if bytes.Contains(*amberdata, []byte("body")) {

			// Add a link to the stylesheet
			*amberdata = bytes.Replace(*amberdata, []byte("html\n"), []byte("html\n"+whitespace+"head\n"+whitespace+whitespace+`link[href="`+url+`"][rel="stylesheet"][type="text/css"]`+"\n"), 1)
		}
	}
}

// Filter []byte slices into two groups, depending on the given filter function
func filterIntoGroups(bytelines [][]byte, filterfunc func([]byte) bool) ([][]byte, [][]byte) {
	var special, regular [][]byte
	for _, byteline := range bytelines {
		if filterfunc(byteline) {
			// Special
			special = append(special, byteline)
		} else {
			// Regular
			regular = append(regular, byteline)
		}
	}
	return special, regular
}

// Given a source file, extract keywords and values into the given map.
// The map must be filled with keywords to look for.
// The keywords in the data must be on the form "keyword: value",
// and can be within single-line HTML comments (<-- ... -->).
// Returns the data for the lines that does not contain any of the keywords.
func extractKeywords(data []byte, special map[string]string) []byte {
	bnl := []byte("\n")
	// Find and separate the lines starting with one of the keywords in the special map
	_, regular := filterIntoGroups(bytes.Split(data, bnl), func(byteline []byte) bool {
		// Check if the current line has one of the special keywords
		for keyword := range special {
			// Check for lines starting with the keyword and a ":"
			if bytes.HasPrefix(byteline, []byte(keyword+":")) {
				// Set (possibly overwrite) the value in the map, if the keyword is found.
				// Trim the surrounding whitespace and skip the letters of the keyword itself.
				special[keyword] = strings.TrimSpace(string(byteline)[len(keyword)+1:])
				return true
			}
			// Check for lines that starts with "" and contains the keyword and a ":"
			if bytes.HasPrefix(byteline, []byte("")) {
				// Strip away the comment markers
				stripped := strings.TrimSpace(string(byteline[5 : len(byteline)-3]))
				// Check if one of the relevant keywords are present
				if strings.HasPrefix(stripped, keyword+":") {
					// Set (possibly overwrite) the value in the map, if the keyword is found.
					// Trim the surrounding whitespace and skip the letters of the keyword itself.
					special[keyword] = strings.TrimSpace(stripped[len(keyword)+1:])
					return true
				}
			}

		}
		// Not special
		return false
	})
	// Use the regular lines as the new data (remove the special lines)
	return bytes.Join(regular, bnl)
}

// Add meta tag names to the given map
func addMetaKeywords(keywords map[string]string) {
	for _, keyword := range metaKeywords {
		keywords[keyword] = ""
	}
}

// Fatal exit
func fatalExit(err error) {
	// Log to file, if a log file is used
	if serverLogFile != "" {
		log.Error(err)
	}
	// Then switch to stderr and log the message there as well
	log.SetOutput(os.Stderr)
	// Use the standard formatter
	log.SetFormatter(&log.TextFormatter{})
	// Log and exit
	log.Fatalln(err)
}

// Insert doctype in HTML, if missing
func insertDoctype(htmldata []byte) []byte {
	// If there are more than two lines
	if bytes.Count(htmldata, []byte("\n")) > 2 {
		fields := bytes.SplitN(htmldata, []byte("\n"), 3)
		line1 := strings.ToLower(string(fields[0]))
		line2 := strings.ToLower(string(fields[1]))
		if strings.Contains(line1, "doctype") || strings.Contains(line2, "doctype") {
			return htmldata
		}
		// Doctype is missing from the first two lines, add it
		return []byte("<!doctype html>" + string(htmldata))
	}
	return htmldata
}

// Convert time.Duration to milliseconds, as a string (without "ms")
func durationToMS(d time.Duration, multiplier float64) string {
	return strconv.Itoa(int(d.Seconds() * 1000.0 * multiplier))
}

// Return "enabled" or "disabled" depending on the given bool
func enabledStatus(enabled bool) string {
	if enabled {
		return "enabled"
	}
	return "disabled"
}

// Convert byte to KiB or MiB
func describeBytes(size int64) string {
	if size < MiB {
		return strconv.Itoa(int(round(float64(size)*100.0/KiB)/100)) + " KiB"
	}
	return strconv.Itoa(int(round(float64(size)*100.0/MiB)/100)) + " MiB"
}

func roundf(x float64) float64 {
	return math.Floor(0.5 + x)
}

func round(x float64) int64 {
	return int64(roundf(x))
}
<|endoftext|>


<commit_before>package cq_test

import (
	"database/sql"
	_ "github.com/wfreeman/cq"
	"log"
	"testing"
)

func testConn() *sql.DB {
	db, err := sql.Open("neo4j-cypher", "http://localhost:7474")
	if err != nil {
		log.Fatal(err)
	}
	return db
}

func prepareTest(query string) *sql.Stmt {
	db := testConn()
	stmt, err := db.Prepare(query)
	if err != nil {
		log.Fatal(err)
	}
	return stmt
}

func prepareAndQuery(query string) *sql.Rows {
	stmt := prepareTest(query)
	rows, err := stmt.Query()
	if err != nil {
		log.Fatal(err)
	}
	return rows
}

func TestQuerySimple(t *testing.T) {
	rows := prepareAndQuery("return 1")
	hasNext := rows.Next()
	if !hasNext {
		t.Fatal("no next!")
	}

	var test int
	err := rows.Scan(&test)
	if err != nil {
		t.Fatal(err)
	}

	if test != 1 {
		t.Fatal("test != 1")
	}
}

func TestQuerySimpleFloat(t *testing.T) {
	rows := prepareAndQuery("return 1.2")
	rows.Next()
	var test float64
	err := rows.Scan(&test)
	if err != nil {
		t.Fatal(err)
	}

	if test != 1.2 {
		t.Fatal("test != 1.2")
	}
}

func TestQuerySimpleString(t *testing.T) {
	rows := prepareAndQuery("return '123'")
	rows.Next()
	var test string
	err := rows.Scan(&test)
	if err != nil {
		t.Fatal(err)
	}

	if test != "123" {
		t.Fatal("test != '123'")
	}
}

func TestQueryIntParam(t *testing.T) {
	stmt := prepareTest("with {0} as test return test")
	rows, err := stmt.Query(123)
	if err != nil {
		t.Fatal(err)
	}
	rows.Next()
	var test int
	err = rows.Scan(&test)
	if err != nil {
		t.Fatal(err)
	}
	if test != 123 {
		t.Fatal("test != 123;", test)
	}
}

/* this fails, but java doesn't support numbers like this anyway...
leaving it to try again later in case I figure more stuff out about value converters
func TestLargeInt(t *testing.T) {
	i := uint64(10000000000000000000)
	stmt := prepareTest("return {big}")
	rows, err := stmt.Query(i)
	if err != nil {
		t.Fatal(err)
	}
	rows.Next()
	var test uint64
	err = rows.Scan(&test)
	if err != nil {
		t.Fatal(err)
	}
	if test != i {
		t.Fatal("test != i;", test)
	}
}
*/

// TODO array conversion
/*
func TestQuerySimpleIntArray(t *testing.T) {
	rows := prepareAndQuery("return [1,2,3]")
	rows.Next()
	var test []int
	err := rows.Scan(&test)
	if err != nil {
		t.Fatal(err)
	}

	if test[0] != 1 || test[1] != 2 || test[2] != 3 {
		t.Fatal("test != [1,2,3];", test)
	}
} */
<commit_msg>removing unsigned long test... neo doesn't support either (at least in cypher)<commit_after>package cq_test

import (
	"database/sql"
	_ "github.com/wfreeman/cq"
	"log"
	"testing"
)

func testConn() *sql.DB {
	db, err := sql.Open("neo4j-cypher", "http://localhost:7474")
	if err != nil {
		log.Fatal(err)
	}
	return db
}

func prepareTest(query string) *sql.Stmt {
	db := testConn()
	stmt, err := db.Prepare(query)
	if err != nil {
		log.Fatal(err)
	}
	return stmt
}

func prepareAndQuery(query string) *sql.Rows {
	stmt := prepareTest(query)
	rows, err := stmt.Query()
	if err != nil {
		log.Fatal(err)
	}
	return rows
}

func TestQuerySimple(t *testing.T) {
	rows := prepareAndQuery("return 1")
	hasNext := rows.Next()
	if !hasNext {
		t.Fatal("no next!")
	}

	var test int
	err := rows.Scan(&test)
	if err != nil {
		t.Fatal(err)
	}

	if test != 1 {
		t.Fatal("test != 1")
	}
}

func TestQuerySimpleFloat(t *testing.T) {
	rows := prepareAndQuery("return 1.2")
	rows.Next()
	var test float64
	err := rows.Scan(&test)
	if err != nil {
		t.Fatal(err)
	}

	if test != 1.2 {
		t.Fatal("test != 1.2")
	}
}

func TestQuerySimpleString(t *testing.T) {
	rows := prepareAndQuery("return '123'")
	rows.Next()
	var test string
	err := rows.Scan(&test)
	if err != nil {
		t.Fatal(err)
	}

	if test != "123" {
		t.Fatal("test != '123'")
	}
}

func TestQueryIntParam(t *testing.T) {
	stmt := prepareTest("with {0} as test return test")
	rows, err := stmt.Query(123)
	if err != nil {
		t.Fatal(err)
	}
	rows.Next()
	var test int
	err = rows.Scan(&test)
	if err != nil {
		t.Fatal(err)
	}
	if test != 123 {
		t.Fatal("test != 123;", test)
	}
}

// TODO array conversion
/*
func TestQuerySimpleIntArray(t *testing.T) {
	rows := prepareAndQuery("return [1,2,3]")
	rows.Next()
	var test []int
	err := rows.Scan(&test)
	if err != nil {
		t.Fatal(err)
	}

	if test[0] != 1 || test[1] != 2 || test[2] != 3 {
		t.Fatal("test != [1,2,3];", test)
	}
} */
<|endoftext|>


<commit_before>/*******************************************************************************
The MIT License (MIT)

Copyright (c) 2013 Hajime Nakagami

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/

package firebirdsql

import (
	"database/sql"
	"testing"
	"time"
)

func TestBasic(t *testing.T) {
	conn, err := sql.Open("firebirdsql", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
	if err != nil {
		t.Fatalf("Error connecting: %v", err)
	}
	var sql string
	var n int

	sql = "SELECT Count(*) FROM rdb$relations where rdb$relation_name='FOO'"
	err = conn.QueryRow(sql).Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n > 0 {
		conn.Exec("DROP TABLE foo")
	}

	sql = `
        CREATE TABLE foo (
            a INTEGER NOT NULL,
            b VARCHAR(30) NOT NULL UNIQUE,
            c VARCHAR(1024),
            d DECIMAL(16,3) DEFAULT -0.123,
            e DATE DEFAULT '1967-08-11',
            f TIMESTAMP DEFAULT '1967-08-11 23:45:01',
            g TIME DEFAULT '23:45:01',
            h BLOB SUB_TYPE 1,
            i DOUBLE PRECISION DEFAULT 0.0,
            j FLOAT DEFAULT 0.0,
            PRIMARY KEY (a),
            CONSTRAINT CHECK_A CHECK (a <> 0)
        )
    `
	conn.Exec(sql)
	_, err = conn.Exec("CREATE TABLE foo (a INTEGER)")
	if err == nil {
		t.Fatalf("Need metadata update error")
	}
	if err.Error() != "unsuccessful metadata update\nTable FOO already exists\n" {
		t.Fatalf("Bad message:%v", err.Error())
	}

	// 3 records insert
	conn.Exec("insert into foo(a, b, c,h) values (1, 'a', 'b','This is a memo')")
	conn.Exec("insert into foo(a, b, c, e, g, i, j) values (2, 'A', 'B', '1999-01-25', '00:00:01', 0.1, 0.1)")
	conn.Exec("insert into foo(a, b, c, e, g, i, j) values (3, 'X', 'Y', '2001-07-05', '00:01:02', 0.2, 0.2)")

	err = conn.QueryRow("select count(*) cnt from foo").Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n != 3 {
		t.Fatalf("Error bad record count: %v", n)
	}

	rows, err := conn.Query("select a, b, c, d, e, f, g, i, j from foo")
	var a int
	var b, c string
	var d float64
	var e time.Time
	var f time.Time
	var g time.Time
	var i float64
	var j float32

	for rows.Next() {
		rows.Scan(&a, &b, &c, &d, &e, &f, &g, &i, &j)
	}

	stmt, _ := conn.Prepare("select count(*) from foo where a=? and b=? and d=? and e=? and f=? and g=?")
	ep := time.Date(1967, 8, 11, 0, 0, 0, 0, time.UTC)
	fp := time.Date(1967, 8, 11, 23, 45, 1, 0, time.UTC)
	gp, err := time.Parse("15:04:05", "23:45:01")
	err = stmt.QueryRow(1, "a", -0.123, ep, fp, gp).Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n != 1 {
		t.Fatalf("Error bad record count: %v", n)
	}

	defer conn.Close()
}

func TestError(t *testing.T) {
	conn, err := sql.Open("firebirdsql", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
	if err != nil {
		t.Fatalf("Error connecting: %v", err)
	}
	_, err = conn.Exec("incorrect sql statement")
	if err != nil {
		t.Fatalf("Error conn.Exec(): %v", err)
	}
}

/*
func TestFB3(t *testing.T) {
	conn, err := sql.Open("firebirdsql", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
	if err != nil {
		t.Fatalf("Error connecting: %v", err)
	}
	var sql string
	var n int

	sql = "SELECT Count(*) FROM rdb$relations where rdb$relation_name='TEST_FB3'"
	err = conn.QueryRow(sql).Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n > 0 {
		conn.Exec("DROP TABLE test_fb3")
	}

	sql = `
        CREATE TABLE test_fb3 (
            b BOOLEAN
        )
    `
	conn.Exec(sql)
	conn.Exec("insert into test_fb3(b) values (true)")
	conn.Exec("insert into test_fb3(b) values (false)")
    var b bool
	err = conn.QueryRow("select * from test_fb3 where b is true").Scan(&b)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if b != true{
		conn.Exec("Invalid boolean value")
	}
	err = conn.QueryRow("select * from test_fb3 where b is false").Scan(&b)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if b != false{
		conn.Exec("Invalid boolean value")
	}

	stmt, _ := conn.Prepare("select * from test_fb3 where b=?")
	err = stmt.QueryRow(true).Scan(&b)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if b != false{
		conn.Exec("Invalid boolean value")
	}

	defer conn.Close()
}
*/
<commit_msg>fix error test<commit_after>/*******************************************************************************
The MIT License (MIT)

Copyright (c) 2013 Hajime Nakagami

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/

package firebirdsql

import (
	"database/sql"
	"testing"
	"time"
)

func TestBasic(t *testing.T) {
	conn, err := sql.Open("firebirdsql", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
	if err != nil {
		t.Fatalf("Error connecting: %v", err)
	}
	var sql string
	var n int

	sql = "SELECT Count(*) FROM rdb$relations where rdb$relation_name='FOO'"
	err = conn.QueryRow(sql).Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n > 0 {
		conn.Exec("DROP TABLE foo")
	}

	sql = `
        CREATE TABLE foo (
            a INTEGER NOT NULL,
            b VARCHAR(30) NOT NULL UNIQUE,
            c VARCHAR(1024),
            d DECIMAL(16,3) DEFAULT -0.123,
            e DATE DEFAULT '1967-08-11',
            f TIMESTAMP DEFAULT '1967-08-11 23:45:01',
            g TIME DEFAULT '23:45:01',
            h BLOB SUB_TYPE 1,
            i DOUBLE PRECISION DEFAULT 0.0,
            j FLOAT DEFAULT 0.0,
            PRIMARY KEY (a),
            CONSTRAINT CHECK_A CHECK (a <> 0)
        )
    `
	conn.Exec(sql)
	_, err = conn.Exec("CREATE TABLE foo (a INTEGER)")
	if err == nil {
		t.Fatalf("Need metadata update error")
	}
	if err.Error() != "unsuccessful metadata update\nTable FOO already exists\n" {
		t.Fatalf("Bad message:%v", err.Error())
	}

	// 3 records insert
	conn.Exec("insert into foo(a, b, c,h) values (1, 'a', 'b','This is a memo')")
	conn.Exec("insert into foo(a, b, c, e, g, i, j) values (2, 'A', 'B', '1999-01-25', '00:00:01', 0.1, 0.1)")
	conn.Exec("insert into foo(a, b, c, e, g, i, j) values (3, 'X', 'Y', '2001-07-05', '00:01:02', 0.2, 0.2)")

	err = conn.QueryRow("select count(*) cnt from foo").Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n != 3 {
		t.Fatalf("Error bad record count: %v", n)
	}

	rows, err := conn.Query("select a, b, c, d, e, f, g, i, j from foo")
	var a int
	var b, c string
	var d float64
	var e time.Time
	var f time.Time
	var g time.Time
	var i float64
	var j float32

	for rows.Next() {
		rows.Scan(&a, &b, &c, &d, &e, &f, &g, &i, &j)
	}

	stmt, _ := conn.Prepare("select count(*) from foo where a=? and b=? and d=? and e=? and f=? and g=?")
	ep := time.Date(1967, 8, 11, 0, 0, 0, 0, time.UTC)
	fp := time.Date(1967, 8, 11, 23, 45, 1, 0, time.UTC)
	gp, err := time.Parse("15:04:05", "23:45:01")
	err = stmt.QueryRow(1, "a", -0.123, ep, fp, gp).Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n != 1 {
		t.Fatalf("Error bad record count: %v", n)
	}

	defer conn.Close()
}

func TestError(t *testing.T) {
	conn, err := sql.Open("firebirdsql", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
	if err != nil {
		t.Fatalf("Error connecting: %v", err)
	}
	_, err = conn.Exec("incorrect sql statement")
	if err == nil {
		t.Fatalf("Bad conn.Exec() not return errro")
	}
}

/*
func TestFB3(t *testing.T) {
	conn, err := sql.Open("firebirdsql", "sysdba:masterkey@localhost:3050/tmp/go_test.fdb")
	if err != nil {
		t.Fatalf("Error connecting: %v", err)
	}
	var sql string
	var n int

	sql = "SELECT Count(*) FROM rdb$relations where rdb$relation_name='TEST_FB3'"
	err = conn.QueryRow(sql).Scan(&n)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if n > 0 {
		conn.Exec("DROP TABLE test_fb3")
	}

	sql = `
        CREATE TABLE test_fb3 (
            b BOOLEAN
        )
    `
	conn.Exec(sql)
	conn.Exec("insert into test_fb3(b) values (true)")
	conn.Exec("insert into test_fb3(b) values (false)")
    var b bool
	err = conn.QueryRow("select * from test_fb3 where b is true").Scan(&b)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if b != true{
		conn.Exec("Invalid boolean value")
	}
	err = conn.QueryRow("select * from test_fb3 where b is false").Scan(&b)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if b != false{
		conn.Exec("Invalid boolean value")
	}

	stmt, _ := conn.Prepare("select * from test_fb3 where b=?")
	err = stmt.QueryRow(true).Scan(&b)
	if err != nil {
		t.Fatalf("Error QueryRow: %v", err)
	}
	if b != false{
		conn.Exec("Invalid boolean value")
	}

	defer conn.Close()
}
*/
<|endoftext|>


<commit_before>// Copyright 2021 The Oto 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.

//go:build !android && !darwin && !js && !windows
// +build !android,!darwin,!js,!windows

package oto

// #cgo pkg-config: alsa
//
// #include <alsa/asoundlib.h>
import "C"

import (
	"fmt"
	"strings"
	"sync"
	"time"
	"unsafe"
)

type context struct {
	sampleRate      int
	channelNum      int
	bitDepthInBytes int

	suspended bool

	handle        *C.snd_pcm_t
	supportsPause bool

	cond *sync.Cond

	players *players
	err     atomicError
}

var theContext *context

func alsaError(name string, err C.int) error {
	return fmt.Errorf("oto: ALSA error at %s: %s", name, C.GoString(C.snd_strerror(err)))
}

func deviceCandidates() []string {
	const getAllDevices = -1

	cPCMInterfaceName := C.CString("pcm")
	defer C.free(unsafe.Pointer(cPCMInterfaceName))

	var hints *unsafe.Pointer
	err := C.snd_device_name_hint(getAllDevices, cPCMInterfaceName, &hints)
	if err != 0 {
		return []string{"default"}
	}
	defer C.snd_device_name_free_hint(hints)

	var devices []string

	cIoHintName := C.CString("IOID")
	defer C.free(unsafe.Pointer(cIoHintName))
	cNameHintName := C.CString("NAME")
	defer C.free(unsafe.Pointer(cNameHintName))

	for it := hints; *it != nil; it = (*unsafe.Pointer)(unsafe.Pointer(uintptr(unsafe.Pointer(it)) + unsafe.Sizeof(uintptr(0)))) {
		io := C.snd_device_name_get_hint(*it, cIoHintName)
		defer func() {
			if io != nil {
				C.free(unsafe.Pointer(io))
			}
		}()
		if io != nil && C.GoString(io) == "Input" {
			continue
		}

		name := C.snd_device_name_get_hint(*it, cNameHintName)
		defer func() {
			if name != nil {
				C.free(unsafe.Pointer(name))
			}
		}()
		if name == nil {
			continue
		}
		goName := C.GoString(name)
		if goName == "null" {
			continue
		}
		if goName == "default" {
			continue
		}
		devices = append(devices, goName)
	}

	devices = append([]string{"default"}, devices...)

	return devices
}

func newContext(sampleRate, channelNum, bitDepthInBytes int) (*context, chan struct{}, error) {
	ready := make(chan struct{})
	close(ready)

	c := &context{
		sampleRate:      sampleRate,
		channelNum:      channelNum,
		bitDepthInBytes: bitDepthInBytes,
		cond:            sync.NewCond(&sync.Mutex{}),
		players:         newPlayers(),
	}
	theContext = c

	// Open a default ALSA audio device for blocking stream playback
	type openError struct {
		device string
		err    C.int
	}
	var openErrs []openError
	var found bool

	for _, name := range deviceCandidates() {
		cname := C.CString(name)
		defer C.free(unsafe.Pointer(cname))
		if err := C.snd_pcm_open(&c.handle, cname, C.SND_PCM_STREAM_PLAYBACK, 0); err < 0 {
			openErrs = append(openErrs, openError{
				device: name,
				err:    err,
			})
			continue
		}
		found = true
		break
	}
	if !found {
		var msgs []string
		for _, e := range openErrs {
			msgs = append(msgs, fmt.Sprintf("%q: %s", e.device, C.GoString(C.snd_strerror(e.err))))
		}
		return nil, nil, fmt.Errorf("oto: ALSA error at snd_pcm_open: %s", strings.Join(msgs, ", "))
	}

	periodSize := C.snd_pcm_uframes_t(1024)
	bufferSize := periodSize * 2
	if err := c.alsaPcmHwParams(sampleRate, channelNum, &bufferSize, &periodSize); err != nil {
		return nil, nil, err
	}

	go func() {
		buf32 := make([]float32, int(periodSize)*c.channelNum)
		for {
			if !c.readAndWrite(buf32) {
				return
			}
		}
	}()

	return c, ready, nil
}

func (c *context) alsaPcmHwParams(sampleRate, channelNum int, bufferSize, periodSize *C.snd_pcm_uframes_t) error {
	var params *C.snd_pcm_hw_params_t
	C.snd_pcm_hw_params_malloc(&params)
	defer C.free(unsafe.Pointer(params))

	if err := C.snd_pcm_hw_params_any(c.handle, params); err < 0 {
		return alsaError("snd_pcm_hw_params_any", err)
	}
	if err := C.snd_pcm_hw_params_set_access(c.handle, params, C.SND_PCM_ACCESS_RW_INTERLEAVED); err < 0 {
		return alsaError("snd_pcm_hw_params_set_access", err)
	}
	if err := C.snd_pcm_hw_params_set_format(c.handle, params, C.SND_PCM_FORMAT_FLOAT_LE); err < 0 {
		return alsaError("snd_pcm_hw_params_set_format", err)
	}
	if err := C.snd_pcm_hw_params_set_channels(c.handle, params, C.unsigned(channelNum)); err < 0 {
		return alsaError("snd_pcm_hw_params_set_channels", err)
	}
	if err := C.snd_pcm_hw_params_set_rate_resample(c.handle, params, 1); err < 0 {
		return alsaError("snd_pcm_hw_params_set_rate_resample", err)
	}
	sr := C.unsigned(sampleRate)
	if err := C.snd_pcm_hw_params_set_rate_near(c.handle, params, &sr, nil); err < 0 {
		return alsaError("snd_pcm_hw_params_set_rate_near", err)
	}
	if err := C.snd_pcm_hw_params_set_buffer_size_near(c.handle, params, bufferSize); err < 0 {
		return alsaError("snd_pcm_hw_params_set_buffer_size_near", err)
	}
	if err := C.snd_pcm_hw_params_set_period_size_near(c.handle, params, periodSize, nil); err < 0 {
		return alsaError("snd_pcm_hw_params_set_period_size_near", err)
	}
	if err := C.snd_pcm_hw_params(c.handle, params); err < 0 {
		return alsaError("snd_pcm_hw_params", err)
	}
	c.supportsPause = C.snd_pcm_hw_params_can_pause(params) == 1
	return nil
}

func (c *context) readAndWrite(buf32 []float32) bool {
	c.cond.L.Lock()
	defer c.cond.L.Unlock()

	for c.suspended && c.err.Load() == nil {
		c.cond.Wait()
	}
	if c.err.Load() != nil {
		return false
	}

	c.players.read(buf32)

	for len(buf32) > 0 {
		n := C.snd_pcm_writei(c.handle, unsafe.Pointer(&buf32[0]), C.snd_pcm_uframes_t(len(buf32)/c.channelNum))
		if n < 0 {
			n = C.long(C.snd_pcm_recover(c.handle, C.int(n), 1))
		}
		if n < 0 {
			c.err.TryStore(alsaError("snd_pcm_writei or snd_pcm_recover", C.int(n)))
			return false
		}
		buf32 = buf32[int(n)*c.channelNum:]
	}
	return true
}

func (c *context) Suspend() error {
	c.cond.L.Lock()
	defer c.cond.L.Unlock()

	if err := c.err.Load(); err != nil {
		return err.(error)
	}

	c.suspended = true
	if c.supportsPause {
		if err := C.snd_pcm_pause(c.handle, 1); err < 0 {
			return alsaError("snd_pcm_pause", err)
		}
		return nil
	}

	if err := C.snd_pcm_drop(c.handle); err < 0 {
		return alsaError("snd_pcm_drop", err)
	}
	return nil
}

func (c *context) Resume() error {
	c.cond.L.Lock()
	defer c.cond.L.Unlock()

	if err := c.err.Load(); err != nil {
		return err.(error)
	}

	defer func() {
		c.suspended = false
		c.cond.Signal()
	}()

	if c.supportsPause {
		if err := C.snd_pcm_pause(c.handle, 0); err < 0 {
			return alsaError("snd_pcm_pause", err)
		}
		return nil
	}

try:
	if err := C.snd_pcm_resume(c.handle); err < 0 {
		if err == -C.EAGAIN {
			time.Sleep(100 * time.Millisecond)
			goto try
		}
		if err == -C.ENOSYS {
			if err := C.snd_pcm_prepare(c.handle); err < 0 {
				return alsaError("snd_pcm_prepare", err)
			}
			return nil
		}
		return alsaError("snd_pcm_resume", err)
	}
	return nil
}

func (c *context) Err() error {
	if err := c.err.Load(); err != nil {
		return err.(error)
	}
	return nil
}
<commit_msg>unix: refactoring<commit_after>// Copyright 2021 The Oto 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.

//go:build !android && !darwin && !js && !windows
// +build !android,!darwin,!js,!windows

package oto

// #cgo pkg-config: alsa
//
// #include <alsa/asoundlib.h>
import "C"

import (
	"fmt"
	"strings"
	"sync"
	"time"
	"unsafe"
)

type context struct {
	sampleRate      int
	channelNum      int
	bitDepthInBytes int

	suspended bool

	handle        *C.snd_pcm_t
	supportsPause bool

	cond *sync.Cond

	players *players
	err     atomicError
}

var theContext *context

func alsaError(name string, err C.int) error {
	return fmt.Errorf("oto: ALSA error at %s: %s", name, C.GoString(C.snd_strerror(err)))
}

func deviceCandidates() []string {
	const getAllDevices = -1

	cPCMInterfaceName := C.CString("pcm")
	defer C.free(unsafe.Pointer(cPCMInterfaceName))

	var hints *unsafe.Pointer
	err := C.snd_device_name_hint(getAllDevices, cPCMInterfaceName, &hints)
	if err != 0 {
		return []string{"default"}
	}
	defer C.snd_device_name_free_hint(hints)

	var devices []string

	cIoHintName := C.CString("IOID")
	defer C.free(unsafe.Pointer(cIoHintName))
	cNameHintName := C.CString("NAME")
	defer C.free(unsafe.Pointer(cNameHintName))

	for it := hints; *it != nil; it = (*unsafe.Pointer)(unsafe.Pointer(uintptr(unsafe.Pointer(it)) + unsafe.Sizeof(uintptr(0)))) {
		io := C.snd_device_name_get_hint(*it, cIoHintName)
		defer func() {
			if io != nil {
				C.free(unsafe.Pointer(io))
			}
		}()
		if C.GoString(io) == "Input" {
			continue
		}

		name := C.snd_device_name_get_hint(*it, cNameHintName)
		defer func() {
			if name != nil {
				C.free(unsafe.Pointer(name))
			}
		}()
		if name == nil {
			continue
		}
		goName := C.GoString(name)
		if goName == "null" {
			continue
		}
		if goName == "default" {
			continue
		}
		devices = append(devices, goName)
	}

	devices = append([]string{"default"}, devices...)

	return devices
}

func newContext(sampleRate, channelNum, bitDepthInBytes int) (*context, chan struct{}, error) {
	ready := make(chan struct{})
	close(ready)

	c := &context{
		sampleRate:      sampleRate,
		channelNum:      channelNum,
		bitDepthInBytes: bitDepthInBytes,
		cond:            sync.NewCond(&sync.Mutex{}),
		players:         newPlayers(),
	}
	theContext = c

	// Open a default ALSA audio device for blocking stream playback
	type openError struct {
		device string
		err    C.int
	}
	var openErrs []openError
	var found bool

	for _, name := range deviceCandidates() {
		cname := C.CString(name)
		defer C.free(unsafe.Pointer(cname))
		if err := C.snd_pcm_open(&c.handle, cname, C.SND_PCM_STREAM_PLAYBACK, 0); err < 0 {
			openErrs = append(openErrs, openError{
				device: name,
				err:    err,
			})
			continue
		}
		found = true
		break
	}
	if !found {
		var msgs []string
		for _, e := range openErrs {
			msgs = append(msgs, fmt.Sprintf("%q: %s", e.device, C.GoString(C.snd_strerror(e.err))))
		}
		return nil, nil, fmt.Errorf("oto: ALSA error at snd_pcm_open: %s", strings.Join(msgs, ", "))
	}

	periodSize := C.snd_pcm_uframes_t(1024)
	bufferSize := periodSize * 2
	if err := c.alsaPcmHwParams(sampleRate, channelNum, &bufferSize, &periodSize); err != nil {
		return nil, nil, err
	}

	go func() {
		buf32 := make([]float32, int(periodSize)*c.channelNum)
		for {
			if !c.readAndWrite(buf32) {
				return
			}
		}
	}()

	return c, ready, nil
}

func (c *context) alsaPcmHwParams(sampleRate, channelNum int, bufferSize, periodSize *C.snd_pcm_uframes_t) error {
	var params *C.snd_pcm_hw_params_t
	C.snd_pcm_hw_params_malloc(&params)
	defer C.free(unsafe.Pointer(params))

	if err := C.snd_pcm_hw_params_any(c.handle, params); err < 0 {
		return alsaError("snd_pcm_hw_params_any", err)
	}
	if err := C.snd_pcm_hw_params_set_access(c.handle, params, C.SND_PCM_ACCESS_RW_INTERLEAVED); err < 0 {
		return alsaError("snd_pcm_hw_params_set_access", err)
	}
	if err := C.snd_pcm_hw_params_set_format(c.handle, params, C.SND_PCM_FORMAT_FLOAT_LE); err < 0 {
		return alsaError("snd_pcm_hw_params_set_format", err)
	}
	if err := C.snd_pcm_hw_params_set_channels(c.handle, params, C.unsigned(channelNum)); err < 0 {
		return alsaError("snd_pcm_hw_params_set_channels", err)
	}
	if err := C.snd_pcm_hw_params_set_rate_resample(c.handle, params, 1); err < 0 {
		return alsaError("snd_pcm_hw_params_set_rate_resample", err)
	}
	sr := C.unsigned(sampleRate)
	if err := C.snd_pcm_hw_params_set_rate_near(c.handle, params, &sr, nil); err < 0 {
		return alsaError("snd_pcm_hw_params_set_rate_near", err)
	}
	if err := C.snd_pcm_hw_params_set_buffer_size_near(c.handle, params, bufferSize); err < 0 {
		return alsaError("snd_pcm_hw_params_set_buffer_size_near", err)
	}
	if err := C.snd_pcm_hw_params_set_period_size_near(c.handle, params, periodSize, nil); err < 0 {
		return alsaError("snd_pcm_hw_params_set_period_size_near", err)
	}
	if err := C.snd_pcm_hw_params(c.handle, params); err < 0 {
		return alsaError("snd_pcm_hw_params", err)
	}
	c.supportsPause = C.snd_pcm_hw_params_can_pause(params) == 1
	return nil
}

func (c *context) readAndWrite(buf32 []float32) bool {
	c.cond.L.Lock()
	defer c.cond.L.Unlock()

	for c.suspended && c.err.Load() == nil {
		c.cond.Wait()
	}
	if c.err.Load() != nil {
		return false
	}

	c.players.read(buf32)

	for len(buf32) > 0 {
		n := C.snd_pcm_writei(c.handle, unsafe.Pointer(&buf32[0]), C.snd_pcm_uframes_t(len(buf32)/c.channelNum))
		if n < 0 {
			n = C.long(C.snd_pcm_recover(c.handle, C.int(n), 1))
		}
		if n < 0 {
			c.err.TryStore(alsaError("snd_pcm_writei or snd_pcm_recover", C.int(n)))
			return false
		}
		buf32 = buf32[int(n)*c.channelNum:]
	}
	return true
}

func (c *context) Suspend() error {
	c.cond.L.Lock()
	defer c.cond.L.Unlock()

	if err := c.err.Load(); err != nil {
		return err.(error)
	}

	c.suspended = true
	if c.supportsPause {
		if err := C.snd_pcm_pause(c.handle, 1); err < 0 {
			return alsaError("snd_pcm_pause", err)
		}
		return nil
	}

	if err := C.snd_pcm_drop(c.handle); err < 0 {
		return alsaError("snd_pcm_drop", err)
	}
	return nil
}

func (c *context) Resume() error {
	c.cond.L.Lock()
	defer c.cond.L.Unlock()

	if err := c.err.Load(); err != nil {
		return err.(error)
	}

	defer func() {
		c.suspended = false
		c.cond.Signal()
	}()

	if c.supportsPause {
		if err := C.snd_pcm_pause(c.handle, 0); err < 0 {
			return alsaError("snd_pcm_pause", err)
		}
		return nil
	}

try:
	if err := C.snd_pcm_resume(c.handle); err < 0 {
		if err == -C.EAGAIN {
			time.Sleep(100 * time.Millisecond)
			goto try
		}
		if err == -C.ENOSYS {
			if err := C.snd_pcm_prepare(c.handle); err < 0 {
				return alsaError("snd_pcm_prepare", err)
			}
			return nil
		}
		return alsaError("snd_pcm_resume", err)
	}
	return nil
}

func (c *context) Err() error {
	if err := c.err.Load(); err != nil {
		return err.(error)
	}
	return nil
}
<|endoftext|>