<commit_before>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 cassandra

import (
	r "reflect"
	"github.com/willfaught/gockle"
	"github.com/ligato/cn-infra/db/sql"
)

// NewBrokerUsingSession is a constructor. Use it like this:
//
// session := gockle.NewSession(gocql.NewCluster("172.17.0.1"))
// defer db.Close()
// db := NewBrokerUsingSession(session)
// db.ListValues(...)
func NewBrokerUsingSession(gocqlSession gockle.Session) *BrokerCassa {
	return &BrokerCassa{session: gocqlSession}
}

// BrokerCassa implements interface db.Broker. This implementation simplifies work with gocql in the way
// that it is not need to write "SQL" queries. But the "SQL" is not really hidden, one can use it if needed.
// The "SQL" queries are generated from the go structures (see more details in Put, Delete, Key, GetValue, ListValues).
type BrokerCassa struct {
	session gockle.Session
}

// ValIterator is an iterator returned by ListValues call
type ValIterator struct {
	Delegate gockle.Iterator
}

// ErrIterator is an iterator that stops immediately and just returns last error on Close()
type ErrIterator struct {
	LastError error
}

// Put - see the description in interface sql.Broker.Put().
// Put generates statement & binding for gocql Exec()
func (pdb *BrokerCassa) Put(where sql.Expression, pointerToAStruct interface{} /*TODO TTL, opts ...keyval.PutOption*/) error {
	statement, bindings, err := PutExpToString(where, pointerToAStruct)
	if err != nil {
		return err
	}
	return pdb.session.Exec(statement, bindings)
}

// Exec - see the description in interface sql.Broker.ExecPut()
// Exec runs statement (AS-IS) using gocql
func (pdb *BrokerCassa) Exec(statement string, binding ...interface{}) error {
	return pdb.session.Exec(statement, binding...)
}

// Delete - see the description in interface sql.Broker.ExecPut()
// Delete generates statement & binding for gocql Exec()
func (pdb *BrokerCassa) Delete(fromWhere sql.Expression) error {
	statement, bindings, err := ExpToString(fromWhere)
	if err != nil {
		return err
	}
	return pdb.session.Exec("DELETE"+statement, bindings)
}

// GetValue - see the description in interface sql.Broker.GetValue()
// GetValue just iterate once for ListValues()
func (pdb *BrokerCassa) GetValue(query sql.Expression, reqObj interface{}) (found bool, err error) {
	it := pdb.ListValues(query)
	stop := it.GetNext(reqObj)
	return !stop, it.Close()
}

// ListValues retrieves an iterator for elements stored under the provided key.
// ListValues runs query (AS-IS) using gocql Scan Iterator.
func (pdb *BrokerCassa) ListValues(query sql.Expression) sql.ValIterator {
	queryStr, binding, err := SelectExpToString(query)
	if err != nil {
		return &ErrIterator{err}
	}

	it := pdb.session.ScanIterator(queryStr, binding)
	return &ValIterator{it}
}

// GetNext returns the following item from the result set. If data was returned, found is set to true.
// argument "outVal" can be:
// - pointer to structure
// - map
func (it *ValIterator) GetNext(outVal interface{}) (stop bool) {
	if m, ok := outVal.(map[string]interface{}); ok {
		ok = it.Delegate.ScanMap(m)
		return !ok //if not ok than stop
	}

	ptrs := structFieldPtrs(outVal)
	ok := it.Delegate.Scan(ptrs...)
	return !ok //if not ok than stop
}

// structFieldPtrs iterates struct fields and return slice of pointers to field values
func structFieldPtrs(val interface{}) []interface{} {
	rVal := r.Indirect(r.ValueOf(val))
	ptrs := []interface{}{}
	for i := 0; i < rVal.NumField(); i++ {
		field := rVal.Field(i)

		switch field.Kind() {
		case r.Chan, r.Func /*TODO func*/ , r.Map, r.Ptr, r.Interface, r.Slice:
			if field.IsNil() {
				p := r.New(field.Type().Elem())
				field.Set(p)
				ptrs = append(ptrs, p.Interface())
			} else {
				ptrs = append(ptrs, field.Interface())
			}
			//case r.Ptr, r.Interface, r.Array, r.Map, r.SliceIt, r.UnsafePointer, r.Chan /*TODO slice, map...*/ :
		default:
			if field.CanAddr() {
				ptrs = append(ptrs, field.Addr().Interface())
			} else if field.IsValid() {
				ptrs = append(ptrs, field.Interface())
			} else {
				panic("invalid field")
			}
		}
	}

	return ptrs
}

// Close the iterator. Note, the error is important (may occure during marshalling/un-marshalling)
func (it *ValIterator) Close() error {
	return it.Delegate.Close()
}

// GetNext returns the following item from the result set. If data was returned, found is set to true.
// argument "outVal" can be:
// - pointer to structure
// - map
func (it *ErrIterator) GetNext(outVal interface{}) (stop bool) {
	return true
}

// Close the iterator. Note, the error is important (may occure during marshalling/un-marshalling)
func (it *ErrIterator) Close() error {
	return it.LastError
}
<commit_msg>ODPM-419 fix passing binding in session Exec()<commit_after>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// 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 cassandra

import (
	r "reflect"
	"github.com/willfaught/gockle"
	"github.com/ligato/cn-infra/db/sql"
)

// NewBrokerUsingSession is a constructor. Use it like this:
//
// session := gockle.NewSession(gocql.NewCluster("172.17.0.1"))
// defer db.Close()
// db := NewBrokerUsingSession(session)
// db.ListValues(...)
func NewBrokerUsingSession(gocqlSession gockle.Session) *BrokerCassa {
	return &BrokerCassa{session: gocqlSession}
}

// BrokerCassa implements interface db.Broker. This implementation simplifies work with gocql in the way
// that it is not need to write "SQL" queries. But the "SQL" is not really hidden, one can use it if needed.
// The "SQL" queries are generated from the go structures (see more details in Put, Delete, Key, GetValue, ListValues).
type BrokerCassa struct {
	session gockle.Session
}

// ValIterator is an iterator returned by ListValues call
type ValIterator struct {
	Delegate gockle.Iterator
}

// ErrIterator is an iterator that stops immediately and just returns last error on Close()
type ErrIterator struct {
	LastError error
}

// Put - see the description in interface sql.Broker.Put().
// Put generates statement & binding for gocql Exec()
func (pdb *BrokerCassa) Put(where sql.Expression, pointerToAStruct interface{} /*TODO TTL, opts ...keyval.PutOption*/) error {
	statement, bindings, err := PutExpToString(where, pointerToAStruct)

	if err != nil {
		return err
	}
	return pdb.session.Exec(statement, bindings...)
}

// Exec - see the description in interface sql.Broker.ExecPut()
// Exec runs statement (AS-IS) using gocql
func (pdb *BrokerCassa) Exec(statement string, binding ...interface{}) error {
	return pdb.session.Exec(statement, binding...)
}

// Delete - see the description in interface sql.Broker.ExecPut()
// Delete generates statement & binding for gocql Exec()
func (pdb *BrokerCassa) Delete(fromWhere sql.Expression) error {
	statement, bindings, err := ExpToString(fromWhere)
	if err != nil {
		return err
	}
	return pdb.session.Exec("DELETE"+statement, bindings...)
}

// GetValue - see the description in interface sql.Broker.GetValue()
// GetValue just iterate once for ListValues()
func (pdb *BrokerCassa) GetValue(query sql.Expression, reqObj interface{}) (found bool, err error) {
	it := pdb.ListValues(query)
	stop := it.GetNext(reqObj)
	return !stop, it.Close()
}

// ListValues retrieves an iterator for elements stored under the provided key.
// ListValues runs query (AS-IS) using gocql Scan Iterator.
func (pdb *BrokerCassa) ListValues(query sql.Expression) sql.ValIterator {
	queryStr, binding, err := SelectExpToString(query)
	if err != nil {
		return &ErrIterator{err}
	}

	it := pdb.session.ScanIterator(queryStr, binding)
	return &ValIterator{it}
}

// GetNext returns the following item from the result set. If data was returned, found is set to true.
// argument "outVal" can be:
// - pointer to structure
// - map
func (it *ValIterator) GetNext(outVal interface{}) (stop bool) {
	if m, ok := outVal.(map[string]interface{}); ok {
		ok = it.Delegate.ScanMap(m)
		return !ok //if not ok than stop
	}

	ptrs := structFieldPtrs(outVal)
	ok := it.Delegate.Scan(ptrs...)
	return !ok //if not ok than stop
}

// structFieldPtrs iterates struct fields and return slice of pointers to field values
func structFieldPtrs(val interface{}) []interface{} {
	rVal := r.Indirect(r.ValueOf(val))
	ptrs := []interface{}{}
	for i := 0; i < rVal.NumField(); i++ {
		field := rVal.Field(i)

		switch field.Kind() {
		case r.Chan, r.Func /*TODO func*/ , r.Map, r.Ptr, r.Interface, r.Slice:
			if field.IsNil() {
				p := r.New(field.Type().Elem())
				field.Set(p)
				ptrs = append(ptrs, p.Interface())
			} else {
				ptrs = append(ptrs, field.Interface())
			}
			//case r.Ptr, r.Interface, r.Array, r.Map, r.SliceIt, r.UnsafePointer, r.Chan /*TODO slice, map...*/ :
		default:
			if field.CanAddr() {
				ptrs = append(ptrs, field.Addr().Interface())
			} else if field.IsValid() {
				ptrs = append(ptrs, field.Interface())
			} else {
				panic("invalid field")
			}
		}
	}

	return ptrs
}

// Close the iterator. Note, the error is important (may occure during marshalling/un-marshalling)
func (it *ValIterator) Close() error {
	return it.Delegate.Close()
}

// GetNext returns the following item from the result set. If data was returned, found is set to true.
// argument "outVal" can be:
// - pointer to structure
// - map
func (it *ErrIterator) GetNext(outVal interface{}) (stop bool) {
	return true
}

// Close the iterator. Note, the error is important (may occure during marshalling/un-marshalling)
func (it *ErrIterator) Close() error {
	return it.LastError
}
<|endoftext|>


<commit_before>package collection

import (
	"encoding/json"
	"fmt"
	"github.com/docker/libcontainer"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"
)

// TODO move to collector config
var (
	docker_folder string = "/var/lib/docker/execdriver/native/"
)

type containerCollector struct {
	Collector
}

func NewContainerCollector() *containerCollector {
	c := new(containerCollector)
	return c
}

func getState(state_config string) *libcontainer.State {
	f, err := os.Open(state_config)
	if err != nil {
		fmt.Printf("failed to open %s - %s\n", state_config, err)
	}
	defer f.Close()

	d := json.NewDecoder(f)
	retConfig := new(libcontainer.State)
	d.Decode(retConfig)
	return retConfig
}

func getConfig(container_config string) *libcontainer.Config {
	f, err := os.Open(container_config)
	if err != nil {
		fmt.Printf("failed to open %s - %s\n", container_config, err)
	}
	defer f.Close()

	d := json.NewDecoder(f)
	retConfig := new(libcontainer.Config)
	d.Decode(retConfig)
	return retConfig
}

// TODO libcontainer update removed support for collection of CPU by removing sampling. Need to reimplement locally.
// func getCpuMetrics(stats *libcontainer.ContainerStats, c *libcontainer.Config, s *libcontainer.State) Metric {
// 	m := Metric{}
// 	// Hostname for container
// 	m.Host = GetHostname()
// 	m.Namespace = []string{"container", c.Hostname, "cpu"}
// 	m.Collector = "libcontainer"
// 	m.LastUpdate = time.Now()
// 	m.Values = map[string]metricType{}
// 	m.Values["percent_usage"] = stats.CgroupStats.CpuStats.CpuUsage.PercentUsage
// 	pc := stats.CgroupStats.CpuStats.CpuUsage.PercpuUsage
// 	var sum uint64 = 0
// 	for _, x := range pc {
// 		sum += x
// 	}
// 	for i, x := range pc {
// 		s := fmt.Sprintf("core%d_ratio", i)
// 		m.Values[s] = fmt.Sprintf("%0.3f", float64(x)/float64(sum))
// 	}
// 	//	metrics = append(metrics, m)
// 	return m
// }

func getNetMetrics(stats *libcontainer.ContainerStats, c *libcontainer.Config, s *libcontainer.State) Metric {
	values := map[string]metricType{}
	values["tx_bytes"] = stats.NetworkStats.TxBytes
	values["rx_bytes"] = stats.NetworkStats.RxBytes
	values["tx_packets"] = stats.NetworkStats.TxPackets
	values["rx_packets"] = stats.NetworkStats.RxPackets
	values["tx_dropped"] = stats.NetworkStats.TxDropped
	values["rx_dropped"] = stats.NetworkStats.RxDropped
	values["tx_errors"] = stats.NetworkStats.TxErrors
	values["rx_errors"] = stats.NetworkStats.RxErrors
	return Metric{
		Host:       GetHostname(),
		Namespace:  []string{"container", c.Hostname, "net"},
		LastUpdate: time.Now(),
		Values:     values,
		Collector:  "libcontainer",
		MetricType: Polling,
	}
}

func getBlkMetrics(stats *libcontainer.ContainerStats, c *libcontainer.Config, s *libcontainer.State) Metric {
	return Metric{}
}

func getContainerMetric(container_path string) ([]Metric, error) {
	s := getState(filepath.Join(container_path, "state.json"))
	c := getConfig(filepath.Join(container_path, "container.json"))
	stats, err := libcontainer.GetStats(c, s)

	values := map[string]metricType{}
	values["start_time"] = s.InitStartTime
	values["pid"] = s.InitPid
	values["veth_host"] = s.NetworkState.VethHost
	values["veth_child"] = s.NetworkState.VethChild
	// State metric
	m := Metric{
		Host:       GetHostname(),
		Namespace:  []string{"container", c.Hostname, "state"},
		LastUpdate: time.Now(),
		Values:     values,
		Collector:  "libcontainer",
		MetricType: Polling,
	}
	//
	// cpu_m := getCpuMetrics(stats, c, s)
	net_m := getNetMetrics(stats, c, s)
	metrics := []Metric{m, cpu_m, net_m}
	return metrics, err
}

// TODO switch to static Metric List
func (x *containerCollector) GetMetricList() []Metric {
	folders, _ := ioutil.ReadDir(docker_folder)
	container_count := 0
	container_ids := []string{}
	metrics := []Metric{}
	for _, folder := range folders {
		if folder.IsDir() {
			m, err := getContainerMetric(filepath.Join(docker_folder, folder.Name()))
			if err == nil {
				container_count++
				container_ids = append(container_ids, folder.Name()[0:11])
				metrics = append(metrics, m...)
			}
		}
	}
	// Global container metric
	values := map[string]metricType{}
	values["count"] = container_count
	values["ids"] = container_ids

	m := Metric{
		Host:       GetHostname(),
		Namespace:  []string{"container", "global"},
		LastUpdate: time.Now(),
		Values:     values,
		Collector:  "libcontainer",
		MetricType: Polling,
	}

	// Insert global metrics at the start
	metrics = append(metrics[:0], append([]Metric{m}, metrics[0:]...)...)
	return metrics
}

func (x *containerCollector) GetMetricValues() []Metric {
	return x.GetMetricList()
}
<commit_msg>rebase me<commit_after>package collection

import (
	"encoding/json"
	"fmt"
	"github.com/docker/libcontainer"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"
)

// TODO move to collector config
var (
	docker_folder string = "/var/lib/docker/execdriver/native/"
)

type containerCollector struct {
	Collector
}

func NewContainerCollector() *containerCollector {
	c := new(containerCollector)
	return c
}

func getState(state_config string) *libcontainer.State {
	f, err := os.Open(state_config)
	if err != nil {
		fmt.Printf("failed to open %s - %s\n", state_config, err)
	}
	defer f.Close()

	d := json.NewDecoder(f)
	retConfig := new(libcontainer.State)
	d.Decode(retConfig)
	return retConfig
}

func getConfig(container_config string) *libcontainer.Config {
	f, err := os.Open(container_config)
	if err != nil {
		fmt.Printf("failed to open %s - %s\n", container_config, err)
	}
	defer f.Close()

	d := json.NewDecoder(f)
	retConfig := new(libcontainer.Config)
	d.Decode(retConfig)
	return retConfig
}

// TODO libcontainer update removed support for collection of CPU by removing sampling. Need to reimplement locally.
// func getCpuMetrics(stats *libcontainer.ContainerStats, c *libcontainer.Config, s *libcontainer.State) Metric {
// 	m := Metric{}
// 	// Hostname for container
// 	m.Host = GetHostname()
// 	m.Namespace = []string{"container", c.Hostname, "cpu"}
// 	m.Collector = "libcontainer"
// 	m.LastUpdate = time.Now()
// 	m.Values = map[string]metricType{}
// 	m.Values["percent_usage"] = stats.CgroupStats.CpuStats.CpuUsage.PercentUsage
// 	pc := stats.CgroupStats.CpuStats.CpuUsage.PercpuUsage
// 	var sum uint64 = 0
// 	for _, x := range pc {
// 		sum += x
// 	}
// 	for i, x := range pc {
// 		s := fmt.Sprintf("core%d_ratio", i)
// 		m.Values[s] = fmt.Sprintf("%0.3f", float64(x)/float64(sum))
// 	}
// 	//	metrics = append(metrics, m)
// 	return m
// }

func getNetMetrics(stats *libcontainer.ContainerStats, c *libcontainer.Config, s *libcontainer.State) Metric {
	values := map[string]metricType{}
	values["tx_bytes"] = stats.NetworkStats.TxBytes
	values["rx_bytes"] = stats.NetworkStats.RxBytes
	values["tx_packets"] = stats.NetworkStats.TxPackets
	values["rx_packets"] = stats.NetworkStats.RxPackets
	values["tx_dropped"] = stats.NetworkStats.TxDropped
	values["rx_dropped"] = stats.NetworkStats.RxDropped
	values["tx_errors"] = stats.NetworkStats.TxErrors
	values["rx_errors"] = stats.NetworkStats.RxErrors
	return Metric{
		Host:       GetHostname(),
		Namespace:  []string{"container", c.Hostname, "net"},
		LastUpdate: time.Now(),
		Values:     values,
		Collector:  "libcontainer",
		MetricType: Polling,
	}
}

func getBlkMetrics(stats *libcontainer.ContainerStats, c *libcontainer.Config, s *libcontainer.State) Metric {
	return Metric{}
}

func getContainerMetric(container_path string) ([]Metric, error) {
	s := getState(filepath.Join(container_path, "state.json"))
	c := getConfig(filepath.Join(container_path, "container.json"))
	stats, err := libcontainer.GetStats(c, s)

	values := map[string]metricType{}
	values["start_time"] = s.InitStartTime
	values["pid"] = s.InitPid
	values["veth_host"] = s.NetworkState.VethHost
	values["veth_child"] = s.NetworkState.VethChild
	// State metric
	m := Metric{
		Host:       GetHostname(),
		Namespace:  []string{"container", c.Hostname, "state"},
		LastUpdate: time.Now(),
		Values:     values,
		Collector:  "libcontainer",
		MetricType: Polling,
	}
	//
	// cpu_m := getCpuMetrics(stats, c, s)
	net_m := getNetMetrics(stats, c, s)
	metrics := []Metric{m, net_m}
	return metrics, err
}

// TODO switch to static Metric List
func (x *containerCollector) GetMetricList() []Metric {
	folders, _ := ioutil.ReadDir(docker_folder)
	container_count := 0
	container_ids := []string{}
	metrics := []Metric{}
	for _, folder := range folders {
		if folder.IsDir() {
			m, err := getContainerMetric(filepath.Join(docker_folder, folder.Name()))
			if err == nil {
				container_count++
				container_ids = append(container_ids, folder.Name()[0:11])
				metrics = append(metrics, m...)
			}
		}
	}
	// Global container metric
	values := map[string]metricType{}
	values["count"] = container_count
	values["ids"] = container_ids

	m := Metric{
		Host:       GetHostname(),
		Namespace:  []string{"container", "global"},
		LastUpdate: time.Now(),
		Values:     values,
		Collector:  "libcontainer",
		MetricType: Polling,
	}

	// Insert global metrics at the start
	metrics = append(metrics[:0], append([]Metric{m}, metrics[0:]...)...)
	return metrics
}

func (x *containerCollector) GetMetricValues() []Metric {
	return x.GetMetricList()
}
<|endoftext|>


<commit_before>package collector

import(
    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
    "time"
)

type ServerStatus struct {
  Uptime             float64                  `bson:"uptime"`
  UptimeEstimate     float64                  `bson:"uptimeEstimate"`
  LocalTime          time.Time              `bson:"localTime"`

  Asserts            map[string]float64       `bson:"asserts"`

  Dur                *DurStats              `bson:"dur"`

  BackgroundFlushing *FlushStats            `bson:"backgroundFlushing"`

  Connections        *ConnectionStats       `bson:"connections"`

  ExtraInfo          *ExtraInfo             `bson:"extra_info"`

  GlobalLock         *GlobalLockStats       `bson:"globalLock"`

  IndexCounter       *IndexCounterStats     `bson:"indexCounters"`

  Locks              map[string]LockStats   `bson:"locks,omitempty"`

  Network            *NetworkStats          `bson:"network"`

  Opcounters         *OpcountStats          `bson:"opcounters"`
  OpcountersRepl     *OpcountStats          `bson:"opcountersRepl"`
  Mem                *MemStats              `bson:"mem"`
}

// Dur
type DurTiming struct {
  Dt               float64 `bson:"dt"`
  PrepLogBuffer    float64 `bson:"prepLogBuffer"`
  WriteToJournal   float64 `bson:"writeToJournal"`
  WriteToDataFiles float64 `bson:"writeToDataFiles"`
  RemapPrivateView float64 `bson:"remapPrivateView"`
}

type DurStats struct {
  Commits            float64 `bson:"commits"`
  JournaledMB        float64 `bson:"journaledMB"`
  WriteToDataFilesMB float64 `bson:"writeToDataFilesMB"`
  Compression        float64 `bson:"compression"`
  CommitsInWriteLock float64 `bson:"commitsInWriteLock"`
  EarlyCommits       float64 `bson:"earlyCommits"`
  TimeMs             DurTiming `bson:"timeMs"`
}

// Flush
type FlushStats struct {
  Flushes      float64     `bson:"flushes"`
  TotalMs      float64     `bson:"total_ms"`
  AverageMs    float64   `bson:"average_ms"`
  LastMs       float64     `bson:"last_ms"`
  LastFinished time.Time `bson:"last_finished"`
}

// Connection
type ConnectionStats struct {
  Current      float64 `bson:"current"`
  Available    float64 `bson:"available"`
  TotalCreated float64 `bson:"totalCreated"`
}

// ExtraInfo
type ExtraInfo struct {
  PageFaults *float64 `bson:"page_faults"`
}

// GlobalLock
type QueueStats struct {
  Total   float64 `bson:"total"`
  Readers float64 `bson:"readers"`
  Writers float64 `bson:"writers"`
}

type ClientStats struct {
  Total   float64 `bson:"total"`
  Readers float64 `bson:"readers"`
  Writers float64 `bson:"writers"`
}

type GlobalLockStats struct {
  TotalTime     float64        `bson:"totalTime"`
  LockTime      float64        `bson:"lockTime"`
  CurrentQueue  *QueueStats  `bson:"currentQueue"`
  ActiveClients *ClientStats `bson:"activeClients"`
}

//IndexCounter
type IndexCounterStats struct {
  Accesses  float64 `bson:"accesses"`
  Hits      float64 `bson:"hits"`
  Misses    float64 `bson:"misses"`
  Resets    float64 `bson:"resets"`
  MissRatio float64 `bson:"missRatio"`
}

//Lock
type ReadWriteLockTimes struct {
  Read       float64 `bson:"R"`
  Write      float64 `bson:"W"`
  ReadLower  float64 `bson:"r"`
  WriteLower float64 `bson:"w"`
}

type LockStats struct {
  TimeLockedMicros    ReadWriteLockTimes `bson:"timeLockedMicros"`
  TimeAcquiringMicros ReadWriteLockTimes `bson:"timeAcquiringMicros"`
}

//Network
type NetworkStats struct {
  BytesIn     float64 `bson:"bytesIn"`
  BytesOut    float64 `bson:"bytesOut"`
  NumRequests float64 `bson:"numRequests"`
}

//Opcount and OpcountersRepl
type OpcountStats struct {
    Insert  float64 `bson:"insert" type:"gauge"`
    Query   float64 `bson:"query" type:"gauge"`
    Update  float64 `bson:"update" type:"gauge"`
    Delete  float64 `bson:"delete" type:"gauge"`
    GetMore float64 `bson:"getmore" type:"gauge"`
    Command float64 `bson:"command" type:"gauge"`
}

//Mem
type MemStats struct {
  Bits              float64       `bson:"bits"`
  Resident          float64       `bson:"resident"`
  Virtual           float64       `bson:"virtual"`
  Supported         interface{}   `bson:"supported"`
  Mapped            float64       `bson:"mapped"`
  MappedWithJournal float64       `bson:"mappedWithJournal"`
}

func NewServerStatus() *ServerStatus {
    result := &ServerStatus{}

    session, err := mgo.Dial("localhost")
    if err != nil {
        panic(err)
    }

    session.SetMode(mgo.Eventual, true)
    session.SetSocketTimeout(0)
    defer func() {
        println("Closing connection to database.")
        session.Close()
    }()

    err = session.DB("admin").Run(bson.D{{"serverStatus", 1}, {"recordStats", 0}}, result)

    return result
}

<commit_msg>Adds tag 'type' to the majority of serverStatus() data<commit_after>package collector

import(
    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
    "time"
)

type ServerStatus struct {
    Uptime             float64                `bson:"uptime" type:"counter"`
    UptimeEstimate     float64                `bson:"uptimeEstimate" type:"counter"`
    LocalTime          time.Time              `bson:"localTime" type:"counter"`

    Asserts            *AssertsStats          `bson:"asserts"`

    Dur                *DurStats              `bson:"dur"`

    BackgroundFlushing *FlushStats            `bson:"backgroundFlushing"`

    Connections        *ConnectionStats       `bson:"connections"`

    ExtraInfo          *ExtraInfo             `bson:"extra_info"`

    GlobalLock         *GlobalLockStats       `bson:"globalLock"`

    IndexCounter       *IndexCounterStats     `bson:"indexCounters"`

    Locks              map[string]LockStats   `bson:"locks,omitempty"`

    Network            *NetworkStats          `bson:"network"`

    Opcounters         *OpcountStats          `bson:"opcounters"`
    OpcountersRepl     *OpcountStats          `bson:"opcountersRepl"`
    Mem                *MemStats              `bson:"mem"`
}

type AssertsStats struct {
    Regular            float64                `bson:"regular" type:"counter"`
    Warning            float64                `bson:"warning type:"counter""`
    Msg                float64                `bson:"msg type:"counter""`
    User               float64                `bson:"user type:"counter""`
    Rollovers          float64                `bson:"rollovers" type:"counter"`
}

// Dur
type DurTiming struct {
    Dt                 float64                `bson:"dt" type:"summary"`
    PrepLogBuffer      float64                `bson:"prepLogBuffer" type:"summary"`
    WriteToJournal     float64                `bson:"writeToJournal" type:"summary"`
    WriteToDataFiles   float64                `bson:"writeToDataFiles" type:"summary"`
    RemapPrivateView   float64                `bson:"remapPrivateView" type:"summary"`
}

type DurStats struct {
    Commits            float64              `bson:"commits" type:"gauge"`
    JournaledMB        float64              `bson:"journaledMB" type:"gauge"`
    WriteToDataFilesMB float64              `bson:"writeToDataFilesMB" type:"gauge"`
    Compression        float64              `bson:"compression" type:"gauge"`
    CommitsInWriteLock float64              `bson:"commitsInWriteLock" type:"gauge"`
    EarlyCommits       float64              `bson:"earlyCommits" type:"summary"`
    TimeMs           DurTiming              `bson:"timeMs"`
}

// Flush
type FlushStats struct {
    Flushes            float64              `bson:"flushes" type:"counter"`
    TotalMs            float64              `bson:"total_ms" type:"counter"`
    AverageMs          float64              `bson:"average_ms" type:"gauge"`
    LastMs             float64              `bson:"last_ms" type:"gauge"`
    LastFinished     time.Time              `bson:"last_finished" type:"gauge"`
}

// Connection
type ConnectionStats struct {
    Current            float64              `bson:"current" type:"gauge"`
    Available          float64              `bson:"available" type:"gauge"`
    TotalCreated       float64              `bson:"totalCreated" type:"counter"`
}

// ExtraInfo
type ExtraInfo struct {
    HeapUsageBytes     float64              `bson:"heap_usage_bytes" type:"gauge"`
    PageFaults         float64              `bson:"page_faults" type:"gauge"`
}

// GlobalLock
type ClientStats struct {
    Total                float64            `bson:"total" type:"gauge"`
    Readers              float64            `bson:"readers" type:"gauge"`
    Writers              float64            `bson:"writers" type:"gauge"`
}

type QueueStats struct {
    Total                float64            `bson:"total" type:"gauge"`
    Readers              float64            `bson:"readers" type:"gauge"`
    Writers              float64            `bson:"writers" type:"gauge"`
}

type GlobalLockStats struct {
    TotalTime             float64           `bson:"totalTime" type:"counter"`
    LockTime              float64           `bson:"lockTime" type:"counter"`
    Ratio                 float64           `bson:"ratio" type:"gauge"`
    CurrentQueue          *QueueStats       `bson:"currentQueue"`
    ActiveClients         *ClientStats      `bson:"activeClients"`
}

//IndexCounter
type IndexCounterStats struct {
    Accesses              float64           `bson:"accesses type:"counter""`
    Hits                  float64           `bson:"hits" type:"counter"`
    Misses                float64           `bson:"misses" type:"counter"`
    Resets                float64           `bson:"resets" type:"gauge"`
    MissRatio             float64           `bson:"missRatio" type:"gauge"`
}

//Lock
type ReadWriteLockTimes struct {
    Read                  float64           `bson:"R" type:"counter"`
    Write                 float64           `bson:"W" type:"counter"`
    ReadLower             float64           `bson:"r" type:"counter"`
    WriteLower            float64           `bson:"w" type:"counter"`
}

type LockStats struct {
    TimeLockedMicros    ReadWriteLockTimes  `bson:"timeLockedMicros"`
    TimeAcquiringMicros ReadWriteLockTimes  `bson:"timeAcquiringMicros"`
}

//Network
type NetworkStats struct {
    BytesIn             float64             `bson:"bytesIn" type:"gauge"`
    BytesOut            float64             `bson:"bytesOut" type:"gauge"`
    NumRequests         float64             `bson:"numRequests" type:"gauge"`
}

//Opcount and OpcountersRepl
type OpcountStats struct {
    Insert              float64             `bson:"insert" type:"gauge"`
    Query               float64             `bson:"query" type:"gauge"`
    Update              float64             `bson:"update" type:"gauge"`
    Delete              float64             `bson:"delete" type:"gauge"`
    GetMore             float64             `bson:"getmore" type:"gauge"`
    Command             float64             `bson:"command" type:"gauge"`
}

//Mem
type MemStats struct {
    Bits                float64             `bson:"bits" type:"counter"`
    Resident            float64             `bson:"resident" type:"counter"`
    Virtual             float64             `bson:"virtual" type:"gauge"`
    Supported           interface{}         `bson:"supported"`
    Mapped              float64             `bson:"mapped" type:"gauge"`
    MappedWithJournal   float64             `bson:"mappedWithJournal" type:"counter"`
}

func NewServerStatus() *ServerStatus {
    result := &ServerStatus{}

    session, err := mgo.Dial("localhost")
    if err != nil {
        panic(err)
    }

    session.SetMode(mgo.Eventual, true)
    session.SetSocketTimeout(0)
    defer func() {
        println("Closing connection to database.")
        session.Close()
    }()

    err = session.DB("admin").Run(bson.D{{"serverStatus", 1}, {"recordStats", 0}}, result)

    return result
}

<|endoftext|>


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

/*
	Package model defines the basic
	data structures of the docs engine.
*/
package model

import (
	"bufio"
	"crypto/sha1"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
)

type RepositoryItem struct {
	Path       string
	Files      []RepositoryItemFile
	ChildItems []RepositoryItem
	Type       string
}

// Create a new repository item
func NewRepositoryItem(itemType string, path string, files []RepositoryItemFile, childItems []RepositoryItem) RepositoryItem {
	return RepositoryItem{
		Path:       path,
		Files:      files,
		ChildItems: childItems,
		Type:       itemType,
	}
}

// Render this repository item
func (item *RepositoryItem) Render() {

	// render child items
	for _, child := range item.ChildItems {
		child.Render()
	}

	// the path of the rendered repostory item
	renderedItemPath := item.GetRenderedItemPath()

	// check if rendering is required
	itemHashCode := item.GetHash()
	renderedItemHashCode := item.GetRenderedItemHash()

	// Abort if the hash has not changed
	if itemHashCode == renderedItemHashCode {
		return
	}

	content := "<!-- " + item.GetHash() + " -->"
	_ = ioutil.WriteFile(renderedItemPath, []byte(content), 0644)
}

// Get the hash code of the rendered item
func (item *RepositoryItem) GetRenderedItemHash() string {
	renderedItemPath := item.GetRenderedItemPath()

	file, err := os.Open(renderedItemPath)
	if err != nil {
		// file does not exist or cannot be accessed
		return ""
	}

	fileReader := bufio.NewReader(file)
	firstLineBytes, _ := fileReader.ReadBytes('\n')
	if firstLineBytes == nil {
		// first line cannot be read
		return ""
	}

	// extract hash from line
	hashCodeRegexp := regexp.MustCompile("<!-- (\\w+) -->")
	matches := hashCodeRegexp.FindStringSubmatch(string(firstLineBytes))
	if len(matches) != 2 {
		return ""
	}

	extractedHashcode := matches[1]

	return string(extractedHashcode)
}

// Get the filepath of the rendered repository item
func (item *RepositoryItem) GetRenderedItemPath() string {
	itemDirectory := filepath.Dir(item.Path)
	renderedFilePath := filepath.Join(itemDirectory, item.Type+".html")
	return renderedFilePath
}

func (item *RepositoryItem) GetHash() string {
	itemBytes, readFileErr := ioutil.ReadFile(item.Path)
	if readFileErr != nil {
		return ""
	}

	sha1 := sha1.New()
	sha1.Write(itemBytes)

	return fmt.Sprintf("%x", string(sha1.Sum(nil)[0:6]))
}

// Get a string representation of the current repository item
func (item *RepositoryItem) String() string {
	s := item.Path + "(Type: " + item.Type + ", Hash: " + item.GetHash() + ")\n"

	s += "\n"
	s += "Files:\n"
	if len(item.Files) > 0 {
		for _, file := range item.Files {
			s += " - " + file.Path + "\n"
		}
	} else {
		s += "<none>\n"
	}

	s += "\n"
	s += "ChildItems:\n"
	if len(item.ChildItems) > 0 {
		for _, child := range item.ChildItems {
			s += child.String()
		}
	} else {
		s += "<none>\n"
	}
	s += "\n"

	return s
}
<commit_msg>Created a function which extracts the title from repository item markdown<commit_after>// Copyright 2013 Andreas Koch. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
	Package model defines the basic
	data structures of the docs engine.
*/
package model

import (
	"bufio"
	"bytes"
	"crypto/sha1"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
)

type RepositoryItem struct {
	Path       string
	Files      []RepositoryItemFile
	ChildItems []RepositoryItem
	Type       string
}

// Create a new repository item
func NewRepositoryItem(itemType string, path string, files []RepositoryItemFile, childItems []RepositoryItem) RepositoryItem {
	return RepositoryItem{
		Path:       path,
		Files:      files,
		ChildItems: childItems,
		Type:       itemType,
	}
}

// Render this repository item
func (item *RepositoryItem) Render() {

	// render child items
	for _, child := range item.ChildItems {
		child.Render()
	}

	// the path of the rendered repostory item
	renderedItemPath := item.GetRenderedItemPath()

	// check if rendering is required
	itemHashCode := item.GetHash()
	renderedItemHashCode := item.GetRenderedItemHash()

	// Abort if the hash has not changed
	if itemHashCode == renderedItemHashCode {
		return
	}

	doc := item.getParsedDocument()

	content := "<!-- " + item.GetHash() + " -->"
	content += "\nTitle: " + doc["title"]

	_ = ioutil.WriteFile(renderedItemPath, []byte(content), 0644)
}

func (item *RepositoryItem) getParsedDocument() map[string]string {
	bytes := item.getBytes()
	doc := make(map[string]string)

	doc["title"] = getTitle(bytes)

	return doc
}

func getTitle(content []byte) string {
	buffer := bytes.NewBuffer(content)

	titleRegexp := regexp.MustCompile("\\s*#\\s*(.+)")
	for line, err := buffer.ReadString(10); err != io.EOF; {
		matches := titleRegexp.FindStringSubmatch(line)

		if len(matches) == 2 {
			return matches[1]
		}
	}

	return "No Title"
}

// Get the bytes of this repository item
func (item *RepositoryItem) getBytes() []byte {
	bytes, err := ioutil.ReadFile(item.Path)
	if err != nil {
		return make([]byte, 0)
	}

	return bytes
}

// Get the hash code of the rendered item
func (item *RepositoryItem) GetRenderedItemHash() string {
	renderedItemPath := item.GetRenderedItemPath()

	file, err := os.Open(renderedItemPath)
	if err != nil {
		// file does not exist or cannot be accessed
		return ""
	}

	fileReader := bufio.NewReader(file)
	firstLineBytes, _ := fileReader.ReadBytes('\n')
	if firstLineBytes == nil {
		// first line cannot be read
		return ""
	}

	// extract hash from line
	hashCodeRegexp := regexp.MustCompile("<!-- (\\w+) -->")
	matches := hashCodeRegexp.FindStringSubmatch(string(firstLineBytes))
	if len(matches) != 2 {
		return ""
	}

	extractedHashcode := matches[1]

	return string(extractedHashcode)
}

// Get the filepath of the rendered repository item
func (item *RepositoryItem) GetRenderedItemPath() string {
	itemDirectory := filepath.Dir(item.Path)
	renderedFilePath := filepath.Join(itemDirectory, item.Type+".html")
	return renderedFilePath
}

func (item *RepositoryItem) GetHash() string {
	itemBytes, readFileErr := ioutil.ReadFile(item.Path)
	if readFileErr != nil {
		return ""
	}

	sha1 := sha1.New()
	sha1.Write(itemBytes)

	return fmt.Sprintf("%x", string(sha1.Sum(nil)[0:6]))
}

// Get a string representation of the current repository item
func (item *RepositoryItem) String() string {
	s := item.Path + "(Type: " + item.Type + ", Hash: " + item.GetHash() + ")\n"

	s += "\n"
	s += "Files:\n"
	if len(item.Files) > 0 {
		for _, file := range item.Files {
			s += " - " + file.Path + "\n"
		}
	} else {
		s += "<none>\n"
	}

	s += "\n"
	s += "ChildItems:\n"
	if len(item.ChildItems) > 0 {
		for _, child := range item.ChildItems {
			s += child.String()
		}
	} else {
		s += "<none>\n"
	}
	s += "\n"

	return s
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"strings"
)

const (
	raw     = "http[s]{0,1}:\\/\\/([a-zA-Z0-9]{0,}\\.)?%v\\/[a-zA-Z0-9\\/_]{0,}"
	relraw  = " href=[\"']{1}[\\.\\/a-zA-Z0-9_]{1,}[\"']{1}"
	teststr = "http://tibyte.net/index.html https://google.de/tschuee http://google.de/hallo"
)

func getDomain(dom string, rabs *regexp.Regexp, rrel *regexp.Regexp) ([]string, error) {
	var protocol string
	ans, err := http.Get(fmt.Sprintf("http://%v", dom))
	protocol = "http://"
	if err != nil {
		ans, err = http.Get(fmt.Sprintf("https://%v", dom))
		protocol = "https://"
		if err != nil {
			fmt.Printf("Domain [%v] doesn't exist\n", dom)
			//panic(err)
			return nil, nil //TODO: return error
		}
	}
	defer ans.Body.Close()
	text, _ := ioutil.ReadAll(ans.Body)
	longabs := rabs.FindAllString(string(text), -1)
	longrel := rrel.FindAllString(string(text), -1)
	for k, v := range longrel {
		longrel[k] = v[7 : len(v)-1]
		if longrel[k][0] == '/' {
			longrel[k] = fmt.Sprintf("%v%v%v", protocol, dom, longrel[k])
		} else {
			longrel[k] = fmt.Sprintf("%v%v/%v", protocol, dom, longrel[k])
		}
	}
	// TODO: make this a map!
	res := make([]string, len(longabs)+len(longrel))
	count := 0
	for _, v := range longabs {
		res[count] = v
		count++
	}
	for _, v := range longrel {
		res[count] = v
		count++
	}
	return res, nil
}

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: crawl <domain>\ne.g: crawl example.org")
		return
	}
	url := os.Args[1]
	savurl := strings.Replace(strings.Replace(url, ".", "\\.", -1), "/", "\\/", -1)
	reg := fmt.Sprintf(raw, savurl)
	r, err := regexp.Compile(reg)
	if err != nil {
		fmt.Println("Could not compile regexp")
		//panic(err)
		return
	}
	rrel, _ := regexp.Compile(relraw)
	//fmt.Printf("Crawling %v with:\n%v\n%v\n", url, reg, relraw)
	links, _ := getDomain(url, r, rrel)
	for _, l := range links {
		fmt.Println(l)
	}
}
<commit_msg>closer but still very experimental!<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"strings"
)

const (
	raw     = "http[s]{0,1}:\\/\\/([a-zA-Z0-9]{0,}\\.)?%v\\/[a-zA-Z0-9\\/_]{0,}"
	relraw  = " href=[\"']{1}[\\.\\/a-zA-Z0-9_]{1,}[\"']{1}"
	teststr = "http://tibyte.net/index.html https://google.de/tschuee http://google.de/hallo"
)

type crawlerError string
type webspace map[string]int
type addc chan string

func (w webspace) String() string {
	ans := ""
	for k, v := range w {
		ans = fmt.Sprintf("%v%v", ans, fmt.Sprintf("(%vx) %s\n", v, k))
	}
	return ans
}

func (e crawlerError) Error() string {
	return fmt.Sprintf("Crawl error: %s", string(e))
}

func cutdomain(s string) string {
	for strings.HasSuffix(s, "/") {
		s = s[:len(s)-1]
	}
	return s
}

func getDomain(dom string, rabs *regexp.Regexp, rrel *regexp.Regexp) ([]string, error) {
	if strings.HasPrefix(dom, "https://") {
		dom = dom[8:]
	}
	if strings.HasPrefix(dom, "http://") {
		dom = dom[7:]
	}
	for strings.HasSuffix(dom, "/") {
		dom = dom[:len(dom)-1]
	}
	var protocol string
	ans, err := http.Get(fmt.Sprintf("http://%v", dom))
	protocol = "http://"
	if err != nil {
		ans, err = http.Get(fmt.Sprintf("https://%v", dom))
		protocol = "https://"
		if err != nil {
			fmt.Printf("Domain [%v] doesn't exist\n", dom)
			fmt.Println(err)
			return nil, crawlerError("http and https not supported")
		}
	}
	defer ans.Body.Close()
	text, _ := ioutil.ReadAll(ans.Body)
	longabs := rabs.FindAllString(string(text), -1)
	longrel := rrel.FindAllString(string(text), -1)
	if i := strings.Index(dom, "/"); i != -1 {
		dom = dom[:i]
	}
	for k, v := range longrel {
		longrel[k] = v[7 : len(v)-1]
		if longrel[k][0] == '/' {
			longrel[k] = fmt.Sprintf("%v%v%v", protocol, dom, longrel[k])
		} else {
			longrel[k] = fmt.Sprintf("%v%v/%v", protocol, dom, longrel[k])
		}
	}
	// TODO: make this a map!
	res := make([]string, len(longabs)+len(longrel))
	count := 0
	for _, v := range longabs {
		res[count] = cutdomain(v)
		count++
	}
	for _, v := range longrel {
		res[count] = cutdomain(v)
		count++
	}
	return res, nil
}

func fill(addr string, c *addc, r1, r2 *regexp.Regexp) {
	links, err := getDomain(addr, r1, r2)
	if err != nil {
		fmt.Printf("Could not read %v\n", addr)
		*c <- "none"
		return
	}
	for _, l := range links {
		*c <- l
	}
}

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: crawl <domain>\ne.g: crawl example.org")
		return
	}
	url := os.Args[1]
	savurl := strings.Replace(strings.Replace(url, ".", "\\.", -1), "/", "\\/", -1)
	reg := fmt.Sprintf(raw, savurl)
	r, err := regexp.Compile(reg)
	if err != nil {
		fmt.Println("Could not compile regexp")
		//panic(err)
		return
	}
	rrel, _ := regexp.Compile(relraw)
	//fmt.Printf("Crawling %v with:\n%v\n%v\n", url, reg, relraw)
	links, _ := getDomain(url, r, rrel)
	maxsize := 100
	collection := make(webspace, maxsize)
	for _, v := range links {
		n, ok := collection[v]
		if ok {
			collection[v] = n + 1
		} else {
			collection[v] = 1
		}
	}
	lres := make(addc, 500)
	iter := 100
	start := 0
	end := len(collection)
	for i := 0; i < iter; i++ {
		fmt.Printf("%v. iteration (%v links)\n", i+1, end)
		new := end - start
		for k := range collection {
			if start < end {
				fmt.Println(start, end)
				go fill(k, &lres, r, rrel)
				start++
			} else {
				continue
			}
		}
		for index := 0; index < new; index++ {
			ns := <-lres
			fmt.Println(ns)
			if ns == "none" {
				continue
			}
			n, ok := collection[ns]
			if ok {
				collection[ns] = n + 1
			} else {
				collection[ns] = 1
				fmt.Println(ns)
			}
		}
		end = len(collection)
	}
	close(lres)
	fmt.Println(collection)
}
<|endoftext|>


<commit_before>package catena

import (
	"sync"
)

// A Series is an ordered set of points
// for a source and metric over a range
// of time.
type Series struct {
	// First timestamp
	Start int64 `json:"start"`

	// Last timestamp
	End int64 `json:"end"`

	Source string `json:"source"`
	Metric string `json:"metric"`

	Points []Point `json:"points"`
}

// A QueryDesc is a description of a
// query. It specifies a source, metric,
// start, and end timestamps.
type QueryDesc struct {
	Source string `json:"source"`
	Metric string `json:"metric"`
	Start  int64  `json:"start"`
	End    int64  `json:"end"`
}

// A QueryResponse is returned after querying
// the DB with a QueryDesc.
type QueryResponse struct {
	Series []Series `json:"series"`
}

// Query fetches series matching the QueryDescs
// and returns a QueryResponse.
func (db *DB) Query(descs []QueryDesc) QueryResponse {
	db.partitionsLock.Lock()
	defer db.partitionsLock.Unlock()

	response := QueryResponse{
		Series: []Series{},
	}

	type sourceMetricKey struct {
		source string
		metric string
	}

	seriesChan := make(chan Series, len(descs))
	seriesWg := sync.WaitGroup{}
	seriesWg.Add(len(descs))

	go func() {
		seriesWg.Wait()
		close(seriesChan)
	}()

	for _, d := range descs {
		go func(desc QueryDesc) {
			defer seriesWg.Done()

			// Get list of partitions to query
			partitions := []partition{}

			for _, part := range db.partitions {
				if part.minTimestamp() >= desc.Start {
					if part.minTimestamp() <= desc.End {
						partitions = append(partitions, part)
						continue
					}
				} else {
					if part.maxTimestamp() >= desc.Start {
						partitions = append(partitions, part)
						continue
					}
				}
			}

			logger.Println("partitions to query:")
			for _, part := range partitions {
				logger.Println("  ", part.filename(),
					"with ranges\n", "    ",
					part.minTimestamp(), "-", part.maxTimestamp())
			}

			series := Series{
				Source: desc.Source,
				Metric: desc.Metric,
			}

			pointsChan := make(chan []Point)
			pointsWg := sync.WaitGroup{}
			pointsWg.Add(len(partitions))

			go func() {
				pointsWg.Wait()
				close(pointsChan)
			}()

			for _, p := range partitions {
				go func(part partition) {
					defer pointsWg.Done()

					logger.Println("querying", part.filename())
					points, err := part.fetchPoints(desc.Source, desc.Metric, desc.Start, desc.End)
					if err != nil {
						logger.Println(err)
						return
					}

					if len(points) == 0 {
						logger.Println()
						return
					}

					pointsChan <- points
				}(p)
			}

			for points := range pointsChan {
				series.Points = append(series.Points, points...)
			}

			if len(series.Points) == 0 {
				return
			}

			series.Start = series.Points[0].Timestamp
			series.End = series.Points[len(series.Points)-1].Timestamp

			seriesChan <- series
		}(d)
	}

	for series := range seriesChan {
		response.Series = append(response.Series, series)
	}

	return response
}

// Sources returns a list of sources present during the given interval.
func (db *DB) Sources(start, end int64) []string {
	db.partitionsLock.Lock()
	defer db.partitionsLock.Unlock()

	// Get list of partitions to query
	partitions := []partition{}

	for _, part := range db.partitions {
		if part.minTimestamp() >= start {
			if part.minTimestamp() <= end {
				partitions = append(partitions, part)
				continue
			}
		} else {
			if part.maxTimestamp() >= start {
				partitions = append(partitions, part)
				continue
			}
		}
	}

	sources := []string{}
	sourcesMap := map[string]bool{}

	for _, part := range partitions {
		for _, src := range part.getSources() {
			sourcesMap[src] = true
		}
	}

	for src := range sourcesMap {
		sources = append(sources, src)
	}

	return sources
}

// Metrics returns a list of metrics present for the given source during the given interval.
func (db *DB) Metrics(source string, start, end int64) []string {
	db.partitionsLock.Lock()
	defer db.partitionsLock.Unlock()

	// Get list of partitions to query
	partitions := []partition{}

	for _, part := range db.partitions {
		if part.minTimestamp() >= start {
			if part.minTimestamp() <= end {
				partitions = append(partitions, part)
				continue
			}
		} else {
			if part.maxTimestamp() >= start {
				partitions = append(partitions, part)
				continue
			}
		}
	}

	metrics := []string{}
	metricsMap := map[string]bool{}

	for _, part := range partitions {
		for _, met := range part.getMetrics(source) {
			metricsMap[met] = true
		}
	}

	for met := range metricsMap {
		metrics = append(metrics, met)
	}

	return metrics
}
<commit_msg>Use RLock/RUnlock for reads<commit_after>package catena

import (
	"sync"
)

// A Series is an ordered set of points
// for a source and metric over a range
// of time.
type Series struct {
	// First timestamp
	Start int64 `json:"start"`

	// Last timestamp
	End int64 `json:"end"`

	Source string `json:"source"`
	Metric string `json:"metric"`

	Points []Point `json:"points"`
}

// A QueryDesc is a description of a
// query. It specifies a source, metric,
// start, and end timestamps.
type QueryDesc struct {
	Source string `json:"source"`
	Metric string `json:"metric"`
	Start  int64  `json:"start"`
	End    int64  `json:"end"`
}

// A QueryResponse is returned after querying
// the DB with a QueryDesc.
type QueryResponse struct {
	Series []Series `json:"series"`
}

// Query fetches series matching the QueryDescs
// and returns a QueryResponse.
func (db *DB) Query(descs []QueryDesc) QueryResponse {
	db.partitionsLock.RLock()
	defer db.partitionsLock.RUnlock()

	response := QueryResponse{
		Series: []Series{},
	}

	type sourceMetricKey struct {
		source string
		metric string
	}

	seriesChan := make(chan Series, len(descs))
	seriesWg := sync.WaitGroup{}
	seriesWg.Add(len(descs))

	go func() {
		seriesWg.Wait()
		close(seriesChan)
	}()

	for _, d := range descs {
		go func(desc QueryDesc) {
			defer seriesWg.Done()

			// Get list of partitions to query
			partitions := []partition{}

			for _, part := range db.partitions {
				if part.minTimestamp() >= desc.Start {
					if part.minTimestamp() <= desc.End {
						partitions = append(partitions, part)
						continue
					}
				} else {
					if part.maxTimestamp() >= desc.Start {
						partitions = append(partitions, part)
						continue
					}
				}
			}

			logger.Println("partitions to query:")
			for _, part := range partitions {
				logger.Println("  ", part.filename(),
					"with ranges\n", "    ",
					part.minTimestamp(), "-", part.maxTimestamp())
			}

			series := Series{
				Source: desc.Source,
				Metric: desc.Metric,
			}

			pointsChan := make(chan []Point)
			pointsWg := sync.WaitGroup{}
			pointsWg.Add(len(partitions))

			go func() {
				pointsWg.Wait()
				close(pointsChan)
			}()

			for _, p := range partitions {
				go func(part partition) {
					defer pointsWg.Done()

					logger.Println("querying", part.filename())
					points, err := part.fetchPoints(desc.Source, desc.Metric, desc.Start, desc.End)
					if err != nil {
						logger.Println(err)
						return
					}

					if len(points) == 0 {
						logger.Println()
						return
					}

					pointsChan <- points
				}(p)
			}

			for points := range pointsChan {
				series.Points = append(series.Points, points...)
			}

			if len(series.Points) == 0 {
				return
			}

			series.Start = series.Points[0].Timestamp
			series.End = series.Points[len(series.Points)-1].Timestamp

			seriesChan <- series
		}(d)
	}

	for series := range seriesChan {
		response.Series = append(response.Series, series)
	}

	return response
}

// Sources returns a list of sources present during the given interval.
func (db *DB) Sources(start, end int64) []string {
	db.partitionsLock.RLock()
	defer db.partitionsLock.RUnlock()

	// Get list of partitions to query
	partitions := []partition{}

	for _, part := range db.partitions {
		if part.minTimestamp() >= start {
			if part.minTimestamp() <= end {
				partitions = append(partitions, part)
				continue
			}
		} else {
			if part.maxTimestamp() >= start {
				partitions = append(partitions, part)
				continue
			}
		}
	}

	sources := []string{}
	sourcesMap := map[string]bool{}

	for _, part := range partitions {
		for _, src := range part.getSources() {
			sourcesMap[src] = true
		}
	}

	for src := range sourcesMap {
		sources = append(sources, src)
	}

	return sources
}

// Metrics returns a list of metrics present for the given source during the given interval.
func (db *DB) Metrics(source string, start, end int64) []string {
	db.partitionsLock.RLock()
	defer db.partitionsLock.RUnlock()

	// Get list of partitions to query
	partitions := []partition{}

	for _, part := range db.partitions {
		if part.minTimestamp() >= start {
			if part.minTimestamp() <= end {
				partitions = append(partitions, part)
				continue
			}
		} else {
			if part.maxTimestamp() >= start {
				partitions = append(partitions, part)
				continue
			}
		}
	}

	metrics := []string{}
	metricsMap := map[string]bool{}

	for _, part := range partitions {
		for _, met := range part.getMetrics(source) {
			metricsMap[met] = true
		}
	}

	for met := range metricsMap {
		metrics = append(metrics, met)
	}

	return metrics
}
<|endoftext|>


<commit_before>// Copyright 2014, Rogue Ethic, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Contributor(s):
//   Christian Vozar (christian@rogueethic.com)

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"
)

const (
	HipChatApiUrl     = "https://api.hipchat.com"
	HipChatApiVersion = "v2"
)

type HipChatUser struct {
	Name         string       `json:"name,omitempty"`
	Title        string       `json:"title,omitempty"`
	Presence     presenceInfo `json:"presence,omitempty"`
	MentionName  string       `json:"mention_name,omitempty"`
	Timezone     string       `json:"timezone,omitempty"`
	Email        string       `json:"email,omitempty"`
	IsGroupAdmin bool         `json:"is_group_admin"`
}

type presenceInfo struct {
	Status string `json:"status, show"`
	Show   string `json:"show, show"`
}

func main() {
	flagVersion := flag.Bool("version", false, "Display application version.")
	flagUser := flag.String("user", "", "Atlassian HipChat ID or Email of user to update.")
	flagAuthToken := flag.String("token", "", "Atlassian HipChat API v2 authentication token.")
	flag.Parse()

	// Handle no command-line paramters
	if flag.NFlag() == 0 {
		flag.PrintDefaults()
		os.Exit(0)
	}

	// Output version
	if *flagVersion {
		fmt.Println("iTunes to Atlassian HipChat Status", Version)
		os.Exit(0)
	}

	userInformation := viewHipChatUser(*flagUser, *flagAuthToken)
	userInformation.Presence.Status = getItunesInformation()
	if userInformation.Presence.Show == "" {
		userInformation.Presence.Show = "chat"
	}
	updateHipChatUser(userInformation, *flagUser, *flagAuthToken)
}

func updateHipChatUser(u HipChatUser, e, a string) {
	messageUri := fmt.Sprintf("%s/%s/user/%s?auth_token=%s", HipChatApiUrl, HipChatApiVersion, e, a)

	messagePayload, err := json.Marshal(u)
	if err != nil {
		log.Fatal(err)
	}

	body := strings.NewReader(string(messagePayload))

	httpClient := &http.Client{}
	req, err := http.NewRequest("PUT", messageUri, body)
	req.Header.Add("content-type", "application/json")

	_, err = httpClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
}

func viewHipChatUser(e, a string) HipChatUser {
	var hipChatData HipChatUser

	messageUri := fmt.Sprintf("%s/%s/user/%s?auth_token=%s", HipChatApiUrl, HipChatApiVersion, e, a)
	res, err := http.Get(messageUri)
	if err != nil {
		log.Fatal(err)
	}

	body, err := ioutil.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		log.Fatal(err)
	}

	err = json.Unmarshal(body, &hipChatData)

	return hipChatData
}

func getItunesInformation() string {
	appleScriptRuntime := "osascript"
	arg0 := "-e"
	cmd := exec.Command(appleScriptRuntime, arg0, `tell application "iTunes"
set trackname to name of current track
set artistname to artist of current track
set albumname to album of current track

if artistname is null then
set artistshow to ""
else if artistname is "" then
set artistshow to ""
else
set artistshow to " | " & artistname & ""
end if

set output to trackname & artistshow
end tell`)

	out, err := cmd.Output()
	if err != nil {
		return ""
	}

	iTunesInformation := strings.TrimSpace(string(out))

	// HipChat status cannot exceed 50 characters.
	if len(iTunesInformation) > 50 {
		return iTunesInformation[0:46] + "..."
	}

	return iTunesInformation
}
<commit_msg>Fix for non-running iTunes<commit_after>// Copyright 2014, Rogue Ethic, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Contributor(s):
//   Christian Vozar (christian@rogueethic.com)

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"
)

const (
	HipChatApiUrl     = "https://api.hipchat.com"
	HipChatApiVersion = "v2"
)

type HipChatUser struct {
	Name         string       `json:"name,omitempty"`
	Title        string       `json:"title,omitempty"`
	Presence     presenceInfo `json:"presence,omitempty"`
	MentionName  string       `json:"mention_name,omitempty"`
	Timezone     string       `json:"timezone,omitempty"`
	Email        string       `json:"email,omitempty"`
	IsGroupAdmin bool         `json:"is_group_admin"`
}

type presenceInfo struct {
	Status string `json:"status, show"`
	Show   string `json:"show, show"`
}

func main() {
	flagVersion := flag.Bool("version", false, "Display application version.")
	flagUser := flag.String("user", "", "Atlassian HipChat ID or Email of user to update.")
	flagAuthToken := flag.String("token", "", "Atlassian HipChat API v2 authentication token.")
	flag.Parse()

	// Handle no command-line paramters
	if flag.NFlag() == 0 {
		flag.PrintDefaults()
		os.Exit(0)
	}

	// Output version
	if *flagVersion {
		fmt.Println("iTunes to Atlassian HipChat Status", Version)
		os.Exit(0)
	}

	userInformation := viewHipChatUser(*flagUser, *flagAuthToken)
	userInformation.Presence.Status = getItunesInformation()
	if userInformation.Presence.Show == "" {
		userInformation.Presence.Show = "chat"
	}
	updateHipChatUser(userInformation, *flagUser, *flagAuthToken)
}

func updateHipChatUser(u HipChatUser, e, a string) {
	messageUri := fmt.Sprintf("%s/%s/user/%s?auth_token=%s", HipChatApiUrl, HipChatApiVersion, e, a)

	messagePayload, err := json.Marshal(u)
	if err != nil {
		log.Fatal(err)
	}

	body := strings.NewReader(string(messagePayload))

	httpClient := &http.Client{}
	req, err := http.NewRequest("PUT", messageUri, body)
	req.Header.Add("content-type", "application/json")

	_, err = httpClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
}

func viewHipChatUser(e, a string) HipChatUser {
	var hipChatData HipChatUser

	messageUri := fmt.Sprintf("%s/%s/user/%s?auth_token=%s", HipChatApiUrl, HipChatApiVersion, e, a)
	res, err := http.Get(messageUri)
	if err != nil {
		log.Fatal(err)
	}

	body, err := ioutil.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		log.Fatal(err)
	}

	err = json.Unmarshal(body, &hipChatData)

	return hipChatData
}

func getItunesInformation() string {
	appleScriptRuntime := "osascript"
	arg0 := "-e"
	cmd := exec.Command(appleScriptRuntime, arg0, `tell application "iTunes"
if it is running then
set trackname to name of current track
set artistname to artist of current track
set albumname to album of current track

if artistname is null then
set artistshow to ""
else if artistname is "" then
set artistshow to ""
else
set artistshow to " | " & artistname & ""
end if

set output to trackname & artistshow
end if
end tell`)

	out, err := cmd.Output()
	if err != nil {
		return ""
	}

	iTunesInformation := strings.TrimSpace(string(out))

	// HipChat status cannot exceed 50 characters.
	if len(iTunesInformation) > 50 {
		return iTunesInformation[0:46] + "..."
	}

	return iTunesInformation
}
<|endoftext|>


<commit_before>package definition

import (
	"log"
	"os"

	"github.com/bronzdoc/symbiote/template"
)

type Resource interface {
	Create(map[string]interface{})
	Name() string
	Children() []Resource
	Id() string
}

type Directory struct {
	name     string
	id       string
	children []Resource
}

func (d *Directory) Create(options map[string]interface{}) {
	os.Mkdir(d.id, 0777)
}

func (d *Directory) Name() string {
	return d.name
}

func (d *Directory) Children() []Resource {
	return d.children
}

func (d *Directory) Id() string {
	return d.id
}

type File struct {
	name string
	id   string
}

func (f *File) Create(options map[string]interface{}) {
	file, err := os.Create(f.id)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	if f.hasTemplate() {
		f.createTemplate(file, options["vars"].(map[string]string))
	}
}

func (f *File) hasTemplate() bool {
	_, err := os.Stat(f.id)
	return err == nil
}

func (f *File) createTemplate(file *os.File, vars map[string]string) {
	_, err := template.New(f.name, vars).Create(file)
	if err != nil {
		log.Fatal(err)
	}
}

func (f *File) Name() string {
	return f.name
}

func (f *File) Children() []Resource {
	return nil
}

func (f *File) Id() string {
	return f.id
}
<commit_msg>Fixed hasTemplate loigic CreateTemplate now has access to the template path trough an option<commit_after>package definition

import (
	"github.com/bronzdoc/droid/template"
	"log"
	"os"
)

type Resource interface {
	Create(map[string]interface{})
	Name() string
	Children() []Resource
	Id() string
}

type Directory struct {
	name     string
	id       string
	children []Resource
}

func (d *Directory) Create(options map[string]interface{}) {
	os.Mkdir(d.id, 0776)
}

func (d *Directory) Name() string {
	return d.name
}

func (d *Directory) Children() []Resource {
	return d.children
}

func (d *Directory) Id() string {
	return d.id
}

type File struct {
	name string
	id   string
}

func (f *File) Create(options map[string]interface{}) {
	file, err := os.Create(f.id)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	// Check if there is a template for the file
	templates_path := options["templates_path"].(string)
	if f.hasTemplate(templates_path) {
		vars := options["vars"].(map[string]string)
		f.createTemplate(
			file,
			templates_path,
			vars,
		)
	}
}

func (f *File) hasTemplate(templates_path string) bool {
	_, err := os.Stat(templates_path + "/" + f.name)
	return err == nil
}

func (f *File) createTemplate(file *os.File, templates_path string, vars map[string]string) {
	_, err := template.New(f.name, templates_path, vars).Create(file)
	if err != nil {
		log.Fatal(err)
	}
}

func (f *File) Name() string {
	return f.name
}

func (f *File) Children() []Resource {
	return nil
}

func (f *File) Id() string {
	return f.id
}
<|endoftext|>


<commit_before>// Copyright (c) 2012, Jorge Acereda Maciá. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can
// be found in the LICENSE file.

// Package cv provides an OpenGL canvas and IO handling. This is the
// low-level package, you probably want the canvas package instead.
package cv

/*
#cgo CFLAGS: -DCV_NO_MAIN -DCV_EXPLICIT_ENTRY
#cgo darwin LDFLAGS: -framework AppKit -lobjc
#cgo linux CFLAGS: -I/usr/X11R6/include
#cgo linux LDFLAGS: -L/usr/X11R6/lib -lGL -lX11
#cgo windows CFLAGS: -fno-stack-check -fno-stack-protector -mno-stack-arg-probe
#cgo windows LDFLAGS: -lgdi32 -lopengl32
#include "cv.h"

static void run() {
  intptr_t gohandle(ev *);
  cvRun((intptr_t(*)(const ev *))gohandle);
}
*/
import "C"

import (
	"code.google.com/p/glcv-go/key"
	"runtime"
	"unsafe"
)

// Helper function for HINT_NAME event.
func String(s string) uintptr {
	return uintptr(unsafe.Pointer(C.CString(s)))
}

var handler func(e *Event) uintptr

// Run starts the event loop using the passed event handler.
func Run(h func(e *Event) uintptr) {
	handler = h
	C.run()
}

// MosueX returns the current X mouse position.
func MouseX() int {
	return int(C.cvMouseX())
}

// MouseY returns the current Y mouse position.
func MouseY() int {
	return int(C.cvMouseY())
}

// Width returns the current canvas width.
func Width() int {
	return int(C.cvWidth())
}

// Height returns the current canvas height.
func Height() int {
	return int(C.cvHeight())
}

// Pressed returns if the key is pressed.
func Pressed(k key.Id) bool {
	return C.cvPressed(C.cvkey(k)) == 1
}

// Released returs if the key just been released.
func Released(k key.Id) bool {
	return C.cvReleased(C.cvkey(k)) == 1
}

// Quits requests the application to leave.
func Quit() {
	C.cvQuit()
}

// SetCursor establishes the cursor bitmap.
func SetCursor(bitmap []byte, hotx, hoty int) {
	C.cvSetCursor((*C.uint8_t)(unsafe.Pointer(&bitmap[0])),
		C.int(hotx), C.int(hoty))
}

// DefaultCursor establishes the default cursor bitmap.
func DefaultCursor() {
	C.cvDefaultCursor()
}

// HideCursor makes the mouse cursor invisible.
func HideCursor() {
	C.cvHideCursor()
}

// Fullscreen switches the canvas to fullscreen mode.
func Fullscreen() {
	C.cvFullscreen()
}

// Windowed switches the canvas to windowed mode.
func Windowed() {
	C.cvWindowed()
}

//export gohandle
func gohandle(e *C.ev) C.intptr_t {
	return C.intptr_t(handler((*Event)(e)))
}

func init() {
	runtime.LockOSThread()
}

func KeyName(k key.Id) string {
	return C.GoString(C.keyName(C.cvkey(k)))
}
<commit_msg>Link against Xcursor<commit_after>// Copyright (c) 2012, Jorge Acereda Maciá. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can
// be found in the LICENSE file.

// Package cv provides an OpenGL canvas and IO handling. This is the
// low-level package, you probably want the canvas package instead.
package cv

/*
#cgo CFLAGS: -DCV_NO_MAIN -DCV_EXPLICIT_ENTRY
#cgo darwin LDFLAGS: -framework AppKit -lobjc
#cgo linux CFLAGS: -I/usr/X11R6/include
#cgo linux LDFLAGS: -L/usr/X11R6/lib -lGL -lX11 -lXcursor
#cgo windows CFLAGS: -fno-stack-check -fno-stack-protector -mno-stack-arg-probe
#cgo windows LDFLAGS: -lgdi32 -lopengl32
#include "cv.h"

static void run() {
  intptr_t gohandle(ev *);
  cvRun((intptr_t(*)(const ev *))gohandle);
}
*/
import "C"

import (
	"code.google.com/p/glcv-go/key"
	"runtime"
	"unsafe"
)

// Helper function for HINT_NAME event.
func String(s string) uintptr {
	return uintptr(unsafe.Pointer(C.CString(s)))
}

var handler func(e *Event) uintptr

// Run starts the event loop using the passed event handler.
func Run(h func(e *Event) uintptr) {
	handler = h
	C.run()
}

// MosueX returns the current X mouse position.
func MouseX() int {
	return int(C.cvMouseX())
}

// MouseY returns the current Y mouse position.
func MouseY() int {
	return int(C.cvMouseY())
}

// Width returns the current canvas width.
func Width() int {
	return int(C.cvWidth())
}

// Height returns the current canvas height.
func Height() int {
	return int(C.cvHeight())
}

// Pressed returns if the key is pressed.
func Pressed(k key.Id) bool {
	return C.cvPressed(C.cvkey(k)) == 1
}

// Released returs if the key just been released.
func Released(k key.Id) bool {
	return C.cvReleased(C.cvkey(k)) == 1
}

// Quits requests the application to leave.
func Quit() {
	C.cvQuit()
}

// SetCursor establishes the cursor bitmap.
func SetCursor(bitmap []byte, hotx, hoty int) {
	C.cvSetCursor((*C.uint8_t)(unsafe.Pointer(&bitmap[0])),
		C.int(hotx), C.int(hoty))
}

// DefaultCursor establishes the default cursor bitmap.
func DefaultCursor() {
	C.cvDefaultCursor()
}

// HideCursor makes the mouse cursor invisible.
func HideCursor() {
	C.cvHideCursor()
}

// Fullscreen switches the canvas to fullscreen mode.
func Fullscreen() {
	C.cvFullscreen()
}

// Windowed switches the canvas to windowed mode.
func Windowed() {
	C.cvWindowed()
}

//export gohandle
func gohandle(e *C.ev) C.intptr_t {
	return C.intptr_t(handler((*Event)(e)))
}

func init() {
	runtime.LockOSThread()
}

func KeyName(k key.Id) string {
	return C.GoString(C.keyName(C.cvkey(k)))
}
<|endoftext|>


<commit_before>package trdsql

import (
	"io"
	"reflect"
	"strings"
	"testing"
)

func TestNewJSONPATHReader(t *testing.T) {
	type args struct {
		reader io.Reader
		opts   *ReadOpts
	}
	tests := []struct {
		name    string
		args    args
		want    *JSONPATHReader
		wantErr bool
	}{
		{
			name: "empty",
			args: args{
				reader: strings.NewReader(""),
				opts:   NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   nil,
				preRead: nil,
			},
			wantErr: false,
		},
		{
			name: "invalidJSON",
			args: args{
				reader: strings.NewReader("t"),
				opts:   NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   nil,
				preRead: nil,
			},
			wantErr: true,
		},
		{
			name: "emptyJSON",
			args: args{
				reader: strings.NewReader("{}"),
				opts:   NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   nil,
				preRead: []map[string]string{{}},
			},
			wantErr: false,
		},
		{
			name: "test1",
			args: args{
				reader: strings.NewReader(`[{"c1":"1","c2":"Orange"},{"c1":"2","c2":"Melon"},{"c1":"3","c2":"Apple"}]`),
				opts:   NewReadOpts(InPreRead(3)),
			},
			want: &JSONPATHReader{
				names:   []string{"c1", "c2"},
				preRead: []map[string]string{{"c1": "1", "c2": "Orange"}, {"c1": "2", "c2": "Melon"}, {"c1": "3", "c2": "Apple"}},
			},
			wantErr: false,
		},
		{
			name: "testPath",
			args: args{
				reader: strings.NewReader(`[{"c1":"1","c2":"Orange"},{"c1":"2","c2":"Melon"},{"c1":"3","c2":"Apple"}]`),
				opts:   NewReadOpts(InPath("0")),
			},
			want: &JSONPATHReader{
				names:   []string{"c1", "c2"},
				preRead: []map[string]string{{"c1": "1", "c2": "Orange"}},
			},
			wantErr: false,
		},
		{
			name: "test2",
			args: args{
				reader: strings.NewReader(`
{"c1":"1","c2":"Orange"}
{"c1":"2","c2":"Melon"}
{"c1":"3","c2":"Apple"}`),
				opts: NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   []string{"c1", "c2"},
				preRead: []map[string]string{{"c1": "1", "c2": "Orange"}},
			},
			wantErr: false,
		},
		{
			name: "testArray",
			args: args{
				reader: strings.NewReader(`[["a"],["b"]]`),
				opts:   NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   []string{"c1"},
				preRead: []map[string]string{{"c1": "[\"a\"]"}, {"c1": "[\"b\"]"}},
			},
			wantErr: false,
		},
		{
			name: "testArray2",
			args: args{
				reader: strings.NewReader(`[["a","b"],["c","d"]]`),
				opts:   NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   []string{"c1"},
				preRead: []map[string]string{{"c1": "[\"a\",\"b\"]"}, {"c1": "[\"c\",\"d\"]"}},
			},
			wantErr: false,
		},
		{
			name: "testArray3",
			args: args{
				reader: strings.NewReader(`["a","b"]`),
				opts:   NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   []string{"c1"},
				preRead: []map[string]string{{"c1": "a"}, {"c1": "b"}},
			},
			wantErr: false,
		},
		{
			name: "testObject",
			args: args{
				reader: strings.NewReader(`{"a":"b"}`),
				opts:   NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   []string{"a"},
				preRead: []map[string]string{{"a": "b"}},
			},
			wantErr: false,
		},
		{
			name: "diffColumn",
			args: args{
				reader: strings.NewReader(`
{"id":"1","name":"Orange"}
{"id":"2","name":"Melon"}
{"id":"3","name":"Apple"}
{"id":"4","name":"Banana","color":"Yellow"}`),
				opts: NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   []string{"id", "name"},
				preRead: []map[string]string{{"id": "1", "name": "Orange"}},
			},
			wantErr: false,
		},
		{
			name: "diffColumn2",
			args: args{
				reader: strings.NewReader(`
{"id":"1","name":"Orange"}
{"id":"2","name":"Melon"}
{"id":"3","name":"Apple"}
{"id":"4","name":"Banana","color":"Yellow"}`),
				opts: NewReadOpts(InPreRead(5)),
			},
			want: &JSONPATHReader{
				names: []string{"id", "name", "color"},
				preRead: []map[string]string{
					{"id": "1", "name": "Orange"},
					{"id": "2", "name": "Melon"},
					{"id": "3", "name": "Apple"},
					{"id": "4", "name": "Banana", "color": "Yellow"},
				},
			},
			wantErr: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := NewJSONPATHReader(tt.args.reader, tt.args.opts)
			if (err != nil) != tt.wantErr {
				t.Errorf("NewJSONPATHReader() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !arraySortEqual(t, got.names, tt.want.names) {
				t.Errorf("NewJSONPATHReader() = %v, want %v", got.names, tt.want.names)
			}
			if !reflect.DeepEqual(got.preRead, tt.want.preRead) {
				t.Errorf("NewJSONPATHReader() = %v, want %v", got.preRead, tt.want.preRead)
			}
		})
	}
}
<commit_msg>Added json path test<commit_after>package trdsql

import (
	"io"
	"reflect"
	"strings"
	"testing"
)

func TestNewJSONPATHReader(t *testing.T) {
	type args struct {
		reader io.Reader
		opts   *ReadOpts
	}
	tests := []struct {
		name    string
		args    args
		want    *JSONPATHReader
		wantErr bool
	}{
		{
			name: "empty",
			args: args{
				reader: strings.NewReader(""),
				opts:   NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   nil,
				preRead: nil,
			},
			wantErr: false,
		},
		{
			name: "invalidJSON",
			args: args{
				reader: strings.NewReader("t"),
				opts:   NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   nil,
				preRead: nil,
			},
			wantErr: true,
		},
		{
			name: "emptyJSON",
			args: args{
				reader: strings.NewReader("{}"),
				opts:   NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   nil,
				preRead: []map[string]string{{}},
			},
			wantErr: false,
		},
		{
			name: "test1",
			args: args{
				reader: strings.NewReader(`[{"c1":"1","c2":"Orange"},{"c1":"2","c2":"Melon"},{"c1":"3","c2":"Apple"}]`),
				opts:   NewReadOpts(InPreRead(3)),
			},
			want: &JSONPATHReader{
				names:   []string{"c1", "c2"},
				preRead: []map[string]string{{"c1": "1", "c2": "Orange"}, {"c1": "2", "c2": "Melon"}, {"c1": "3", "c2": "Apple"}},
			},
			wantErr: false,
		},
		{
			name: "test2",
			args: args{
				reader: strings.NewReader(`
{"c1":"1","c2":"Orange"}
{"c1":"2","c2":"Melon"}
{"c1":"3","c2":"Apple"}`),
				opts: NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   []string{"c1", "c2"},
				preRead: []map[string]string{{"c1": "1", "c2": "Orange"}},
			},
			wantErr: false,
		},
		{
			name: "testArray",
			args: args{
				reader: strings.NewReader(`[["a"],["b"]]`),
				opts:   NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   []string{"c1"},
				preRead: []map[string]string{{"c1": "[\"a\"]"}, {"c1": "[\"b\"]"}},
			},
			wantErr: false,
		},
		{
			name: "testArray2",
			args: args{
				reader: strings.NewReader(`[["a","b"],["c","d"]]`),
				opts:   NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   []string{"c1"},
				preRead: []map[string]string{{"c1": "[\"a\",\"b\"]"}, {"c1": "[\"c\",\"d\"]"}},
			},
			wantErr: false,
		},
		{
			name: "testArray3",
			args: args{
				reader: strings.NewReader(`["a","b"]`),
				opts:   NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   []string{"c1"},
				preRead: []map[string]string{{"c1": "a"}, {"c1": "b"}},
			},
			wantErr: false,
		},
		{
			name: "testObject",
			args: args{
				reader: strings.NewReader(`{"a":"b"}`),
				opts:   NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   []string{"a"},
				preRead: []map[string]string{{"a": "b"}},
			},
			wantErr: false,
		},
		{
			name: "diffColumn",
			args: args{
				reader: strings.NewReader(`
{"id":"1","name":"Orange"}
{"id":"2","name":"Melon"}
{"id":"3","name":"Apple"}
{"id":"4","name":"Banana","color":"Yellow"}`),
				opts: NewReadOpts(),
			},
			want: &JSONPATHReader{
				names:   []string{"id", "name"},
				preRead: []map[string]string{{"id": "1", "name": "Orange"}},
			},
			wantErr: false,
		},
		{
			name: "diffColumn2",
			args: args{
				reader: strings.NewReader(`
{"id":"1","name":"Orange"}
{"id":"2","name":"Melon"}
{"id":"3","name":"Apple"}
{"id":"4","name":"Banana","color":"Yellow"}`),
				opts: NewReadOpts(InPreRead(5)),
			},
			want: &JSONPATHReader{
				names: []string{"id", "name", "color"},
				preRead: []map[string]string{
					{"id": "1", "name": "Orange"},
					{"id": "2", "name": "Melon"},
					{"id": "3", "name": "Apple"},
					{"id": "4", "name": "Banana", "color": "Yellow"},
				},
			},
			wantErr: false,
		},
		{
			name: "testPath",
			args: args{
				reader: strings.NewReader(`[{"c1":"1","c2":"Orange"},{"c1":"2","c2":"Melon"},{"c1":"3","c2":"Apple"}]`),
				opts:   NewReadOpts(InPath("0")),
			},
			want: &JSONPATHReader{
				names:   []string{"c1", "c2"},
				preRead: []map[string]string{{"c1": "1", "c2": "Orange"}},
			},
			wantErr: false,
		},
		{
			name: "testPath2",
			args: args{
				reader: strings.NewReader(`{"employees":[
					{"name":"Shyam", "email":"shyamjaiswal@gmail.com"},
					{"name":"Bob", "email":"bob32@gmail.com"},
					{"name":"Jai", "email":"jai87@gmail.com"}
				]}`),
				opts: NewReadOpts(InPath("employees")),
			},
			want: &JSONPATHReader{
				names: []string{"name", "email"},
				preRead: []map[string]string{
					{"name": "Shyam", "email": "shyamjaiswal@gmail.com"},
					{"name": "Bob", "email": "bob32@gmail.com"},
					{"name": "Jai", "email": "jai87@gmail.com"},
				},
			},
			wantErr: false,
		},
		{
			name: "testPath3",
			args: args{
				reader: strings.NewReader(`{"menu": {
					"id": "file",
					"value": "File",
					"popup": {
					  "menuitem": [
						{"value": "New", "onclick": "CreateDoc()"},
						{"value": "Open", "onclick": "OpenDoc()"},
						{"value": "Save", "onclick": "SaveDoc()"}
					  ]
					}
				  }}`),
				opts: NewReadOpts(InPath("menu.popup.menuitem")),
			},
			want: &JSONPATHReader{
				names: []string{"value", "onclick"},
				preRead: []map[string]string{
					{"value": "New", "onclick": "CreateDoc()"},
					{"value": "Open", "onclick": "OpenDoc()"},
					{"value": "Save", "onclick": "SaveDoc()"},
				},
			},
			wantErr: false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := NewJSONPATHReader(tt.args.reader, tt.args.opts)
			if (err != nil) != tt.wantErr {
				t.Errorf("NewJSONPATHReader() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !arraySortEqual(t, got.names, tt.want.names) {
				t.Errorf("NewJSONPATHReader() = %v, want %v", got.names, tt.want.names)
			}
			if !reflect.DeepEqual(got.preRead, tt.want.preRead) {
				t.Errorf("NewJSONPATHReader() = %v, want %v", got.preRead, tt.want.preRead)
			}
		})
	}
}
<|endoftext|>


<commit_before>package collector

import (
	"context"
	"fmt"
	"time"

	"github.com/digitalocean/godo"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
	"github.com/prometheus/client_golang/prometheus"
)

// DropletCollector collects metrics about all droplets.
type DropletCollector struct {
	logger  log.Logger
	errors  *prometheus.CounterVec
	client  *godo.Client
	timeout time.Duration

	Up           *prometheus.Desc
	CPUs         *prometheus.Desc
	Memory       *prometheus.Desc
	Disk         *prometheus.Desc
	PriceHourly  *prometheus.Desc
	PriceMonthly *prometheus.Desc
}

// NewDropletCollector returns a new DropletCollector.
func NewDropletCollector(logger log.Logger, errors *prometheus.CounterVec, client *godo.Client, timeout time.Duration) *DropletCollector {
	errors.WithLabelValues("droplet").Add(0)

	labels := []string{"id", "name", "region"}
	return &DropletCollector{
		logger:  logger,
		errors:  errors,
		client:  client,
		timeout: timeout,

		Up: prometheus.NewDesc(
			"digitalocean_droplet_up",
			"If 1 the droplet is up and running, 0 otherwise",
			labels, nil,
		),
		CPUs: prometheus.NewDesc(
			"digitalocean_droplet_cpus",
			"Droplet's number of CPUs",
			labels, nil,
		),
		Memory: prometheus.NewDesc(
			"digitalocean_droplet_memory_bytes",
			"Droplet's memory in bytes",
			labels, nil,
		),
		Disk: prometheus.NewDesc(
			"digitalocean_droplet_disk_bytes",
			"Droplet's disk in bytes",
			labels, nil,
		),
		PriceHourly: prometheus.NewDesc(
			"digitalocean_droplet_price_hourly",
			"Price of the Droplet billed hourly in dollars",
			labels, nil,
		),
		PriceMonthly: prometheus.NewDesc(
			"digitalocean_droplet_price_monthly",
			"Price of the Droplet billed monthly in dollars",
			labels, nil,
		),
	}
}

// Describe sends the super-set of all possible descriptors of metrics
// collected by this Collector.
func (c *DropletCollector) Describe(ch chan<- *prometheus.Desc) {
	ch <- c.Up
	ch <- c.CPUs
	ch <- c.Memory
	ch <- c.Disk
	ch <- c.PriceHourly
	ch <- c.PriceMonthly
}

// Collect is called by the Prometheus registry when collecting metrics.
func (c *DropletCollector) Collect(ch chan<- prometheus.Metric) {
	ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
	defer cancel()

	// create a list to hold our droplets
	droplets := []godo.Droplet{}

	// create options. initially, these will be blank
	opt := &godo.ListOptions{}

	for {
		dropletsPage, resp, err := c.client.Droplets.List(ctx, opt)
		if err != nil {
			c.errors.WithLabelValues("droplet").Add(1)
			level.Warn(c.logger).Log(
				"msg", "can't list droplets",
				"err", err,
			)
		}

		// append the current page's droplets to our list
		for _, d := range dropletsPage {
			droplets = append(droplets, d)
		}

		// if we are at the last page, break out the for loop
		if resp.Links == nil || resp.Links.IsLastPage() {
			break
		}

		page, err := resp.Links.CurrentPage()
		if err != nil {
			c.errors.WithLabelValues("droplet").Add(1)
			level.Warn(c.logger).Log(
				"msg", "can't read current page",
				"err", err,
			)
		}

		opt.Page = page + 1
	}

	for _, droplet := range droplets {
		labels := []string{
			fmt.Sprintf("%d", droplet.ID),
			droplet.Name,
			droplet.Region.Slug,
		}

		var active float64
		if droplet.Status == "active" {
			active = 1.0
		}
		ch <- prometheus.MustNewConstMetric(
			c.Up,
			prometheus.GaugeValue,
			active,
			labels...,
		)
		ch <- prometheus.MustNewConstMetric(
			c.CPUs,
			prometheus.GaugeValue,
			float64(droplet.Vcpus),
			labels...,
		)
		ch <- prometheus.MustNewConstMetric(
			c.Memory,
			prometheus.GaugeValue,
			float64(droplet.Memory*1024*1024),
			labels...,
		)
		ch <- prometheus.MustNewConstMetric(
			c.Disk,
			prometheus.GaugeValue,
			float64(droplet.Disk*1000*1000*1000),
			labels...,
		)
		ch <- prometheus.MustNewConstMetric(
			c.PriceHourly,
			prometheus.GaugeValue,
			float64(droplet.Size.PriceHourly),
			labels...,
		)
		ch <- prometheus.MustNewConstMetric(
			c.PriceMonthly,
			prometheus.GaugeValue,
			float64(droplet.Size.PriceMonthly),
			labels...,
		)
	}
}
<commit_msg>Fix panic in droplet collector if pagination fails<commit_after>package collector

import (
	"context"
	"fmt"
	"time"

	"github.com/digitalocean/godo"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
	"github.com/prometheus/client_golang/prometheus"
)

// DropletCollector collects metrics about all droplets.
type DropletCollector struct {
	logger  log.Logger
	errors  *prometheus.CounterVec
	client  *godo.Client
	timeout time.Duration

	Up           *prometheus.Desc
	CPUs         *prometheus.Desc
	Memory       *prometheus.Desc
	Disk         *prometheus.Desc
	PriceHourly  *prometheus.Desc
	PriceMonthly *prometheus.Desc
}

// NewDropletCollector returns a new DropletCollector.
func NewDropletCollector(logger log.Logger, errors *prometheus.CounterVec, client *godo.Client, timeout time.Duration) *DropletCollector {
	errors.WithLabelValues("droplet").Add(0)

	labels := []string{"id", "name", "region"}
	return &DropletCollector{
		logger:  logger,
		errors:  errors,
		client:  client,
		timeout: timeout,

		Up: prometheus.NewDesc(
			"digitalocean_droplet_up",
			"If 1 the droplet is up and running, 0 otherwise",
			labels, nil,
		),
		CPUs: prometheus.NewDesc(
			"digitalocean_droplet_cpus",
			"Droplet's number of CPUs",
			labels, nil,
		),
		Memory: prometheus.NewDesc(
			"digitalocean_droplet_memory_bytes",
			"Droplet's memory in bytes",
			labels, nil,
		),
		Disk: prometheus.NewDesc(
			"digitalocean_droplet_disk_bytes",
			"Droplet's disk in bytes",
			labels, nil,
		),
		PriceHourly: prometheus.NewDesc(
			"digitalocean_droplet_price_hourly",
			"Price of the Droplet billed hourly in dollars",
			labels, nil,
		),
		PriceMonthly: prometheus.NewDesc(
			"digitalocean_droplet_price_monthly",
			"Price of the Droplet billed monthly in dollars",
			labels, nil,
		),
	}
}

// Describe sends the super-set of all possible descriptors of metrics
// collected by this Collector.
func (c *DropletCollector) Describe(ch chan<- *prometheus.Desc) {
	ch <- c.Up
	ch <- c.CPUs
	ch <- c.Memory
	ch <- c.Disk
	ch <- c.PriceHourly
	ch <- c.PriceMonthly
}

// Collect is called by the Prometheus registry when collecting metrics.
func (c *DropletCollector) Collect(ch chan<- prometheus.Metric) {
	ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
	defer cancel()

	// create a list to hold our droplets
	droplets := []godo.Droplet{}

	// create options. initially, these will be blank
	opt := &godo.ListOptions{}

	for {
		dropletsPage, resp, err := c.client.Droplets.List(ctx, opt)
		if err != nil {
			c.errors.WithLabelValues("droplet").Add(1)
			level.Warn(c.logger).Log(
				"msg", "can't list droplets",
				"err", err,
			)
			return
		}

		// append the current page's droplets to our list
		for _, d := range dropletsPage {
			droplets = append(droplets, d)
		}

		// if we are at the last page, break out the for loop
		if resp.Links == nil || resp.Links.IsLastPage() {
			break
		}

		page, err := resp.Links.CurrentPage()
		if err != nil {
			c.errors.WithLabelValues("droplet").Add(1)
			level.Warn(c.logger).Log(
				"msg", "can't read current page",
				"err", err,
			)
		}

		opt.Page = page + 1
	}

	for _, droplet := range droplets {
		labels := []string{
			fmt.Sprintf("%d", droplet.ID),
			droplet.Name,
			droplet.Region.Slug,
		}

		var active float64
		if droplet.Status == "active" {
			active = 1.0
		}
		ch <- prometheus.MustNewConstMetric(
			c.Up,
			prometheus.GaugeValue,
			active,
			labels...,
		)
		ch <- prometheus.MustNewConstMetric(
			c.CPUs,
			prometheus.GaugeValue,
			float64(droplet.Vcpus),
			labels...,
		)
		ch <- prometheus.MustNewConstMetric(
			c.Memory,
			prometheus.GaugeValue,
			float64(droplet.Memory*1024*1024),
			labels...,
		)
		ch <- prometheus.MustNewConstMetric(
			c.Disk,
			prometheus.GaugeValue,
			float64(droplet.Disk*1000*1000*1000),
			labels...,
		)
		ch <- prometheus.MustNewConstMetric(
			c.PriceHourly,
			prometheus.GaugeValue,
			float64(droplet.Size.PriceHourly),
			labels...,
		)
		ch <- prometheus.MustNewConstMetric(
			c.PriceMonthly,
			prometheus.GaugeValue,
			float64(droplet.Size.PriceMonthly),
			labels...,
		)
	}
}
<|endoftext|>


<commit_before>// Copyright 2018 The Hugo Authors. All rights reserved.
//
// 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 commands

import (
	"bytes"
	"errors"
	"path/filepath"
	"strings"

	"github.com/gohugoio/hugo/parser/metadecoders"

	_errors "github.com/pkg/errors"

	"github.com/gohugoio/hugo/create"
	"github.com/gohugoio/hugo/helpers"
	"github.com/gohugoio/hugo/hugofs"
	"github.com/gohugoio/hugo/parser"
	"github.com/spf13/cobra"
	jww "github.com/spf13/jwalterweatherman"
	"github.com/spf13/viper"
)

var _ cmder = (*newSiteCmd)(nil)

type newSiteCmd struct {
	configFormat string

	*baseCmd
}

func newNewSiteCmd() *newSiteCmd {
	ccmd := &newSiteCmd{}

	cmd := &cobra.Command{
		Use:   "site [path]",
		Short: "Create a new site (skeleton)",
		Long: `Create a new site in the provided directory.
The new site will have the correct structure, but no content or theme yet.
Use ` + "`hugo new [contentPath]`" + ` to create new content.`,
		RunE: ccmd.newSite,
	}

	cmd.Flags().StringVarP(&ccmd.configFormat, "format", "f", "toml", "config & frontmatter format")
	cmd.Flags().Bool("force", false, "init inside non-empty directory")

	ccmd.baseCmd = newBaseCmd(cmd)

	return ccmd

}

func (n *newSiteCmd) doNewSite(fs *hugofs.Fs, basepath string, force bool) error {
	archeTypePath := filepath.Join(basepath, "archetypes")
	dirs := []string{
		filepath.Join(basepath, "layouts"),
		filepath.Join(basepath, "content"),
		archeTypePath,
		filepath.Join(basepath, "static"),
		filepath.Join(basepath, "data"),
		filepath.Join(basepath, "themes"),
	}

	if exists, _ := helpers.Exists(basepath, fs.Source); exists {
		if isDir, _ := helpers.IsDir(basepath, fs.Source); !isDir {
			return errors.New(basepath + " already exists but not a directory")
		}

		isEmpty, _ := helpers.IsEmpty(basepath, fs.Source)

		switch {
		case !isEmpty && !force:
			return errors.New(basepath + " already exists and is not empty")

		case !isEmpty && force:
			all := append(dirs, filepath.Join(basepath, "config."+n.configFormat))
			for _, path := range all {
				if exists, _ := helpers.Exists(path, fs.Source); exists {
					return errors.New(path + " already exists")
				}
			}
		}
	}

	for _, dir := range dirs {
		if err := fs.Source.MkdirAll(dir, 0777); err != nil {
			return _errors.Wrap(err, "Failed to create dir")
		}
	}

	createConfig(fs, basepath, n.configFormat)

	// Create a default archetype file.
	helpers.SafeWriteToDisk(filepath.Join(archeTypePath, "default.md"),
		strings.NewReader(create.ArchetypeTemplateTemplate), fs.Source)

	jww.FEEDBACK.Printf("Congratulations! Your new Hugo site is created in %s.\n\n", basepath)
	jww.FEEDBACK.Println(nextStepsText())

	return nil
}

// newSite creates a new Hugo site and initializes a structured Hugo directory.
func (n *newSiteCmd) newSite(cmd *cobra.Command, args []string) error {
	if len(args) < 1 {
		return newUserError("path needs to be provided")
	}

	createpath, err := filepath.Abs(filepath.Clean(args[0]))
	if err != nil {
		return newUserError(err)
	}

	forceNew, _ := cmd.Flags().GetBool("force")

	return n.doNewSite(hugofs.NewDefault(viper.New()), createpath, forceNew)
}

func createConfig(fs *hugofs.Fs, inpath string, kind string) (err error) {
	in := map[string]string{
		"baseURL":      "http://example.org/",
		"title":        "My New Hugo Site",
		"languageCode": "en-us",
	}

	var buf bytes.Buffer
	err = parser.InterfaceToConfig(in, metadecoders.FormatFromString(kind), &buf)
	if err != nil {
		return err
	}

	return helpers.WriteToDisk(filepath.Join(inpath, "config."+kind), &buf, fs.Source)
}

func nextStepsText() string {
	var nextStepsText bytes.Buffer

	nextStepsText.WriteString(`Just a few more steps and you're ready to go:

1. Download a theme into the same-named folder.
   Choose a theme from https://themes.gohugo.io/, or
   create your own with the "hugo new theme <THEMENAME>" command.
2. Perhaps you want to add some content. You can add single files
   with "hugo new `)

	nextStepsText.WriteString(filepath.Join("<SECTIONNAME>", "<FILENAME>.<FORMAT>"))

	nextStepsText.WriteString(`".
3. Start the built-in live server via "hugo server".

Visit https://gohugo.io/ for quickstart guide and full documentation.`)

	return nextStepsText.String()
}
<commit_msg>commands: Remove comma after URL in new site output<commit_after>// Copyright 2018 The Hugo Authors. All rights reserved.
//
// 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 commands

import (
	"bytes"
	"errors"
	"path/filepath"
	"strings"

	"github.com/gohugoio/hugo/parser/metadecoders"

	_errors "github.com/pkg/errors"

	"github.com/gohugoio/hugo/create"
	"github.com/gohugoio/hugo/helpers"
	"github.com/gohugoio/hugo/hugofs"
	"github.com/gohugoio/hugo/parser"
	"github.com/spf13/cobra"
	jww "github.com/spf13/jwalterweatherman"
	"github.com/spf13/viper"
)

var _ cmder = (*newSiteCmd)(nil)

type newSiteCmd struct {
	configFormat string

	*baseCmd
}

func newNewSiteCmd() *newSiteCmd {
	ccmd := &newSiteCmd{}

	cmd := &cobra.Command{
		Use:   "site [path]",
		Short: "Create a new site (skeleton)",
		Long: `Create a new site in the provided directory.
The new site will have the correct structure, but no content or theme yet.
Use ` + "`hugo new [contentPath]`" + ` to create new content.`,
		RunE: ccmd.newSite,
	}

	cmd.Flags().StringVarP(&ccmd.configFormat, "format", "f", "toml", "config & frontmatter format")
	cmd.Flags().Bool("force", false, "init inside non-empty directory")

	ccmd.baseCmd = newBaseCmd(cmd)

	return ccmd

}

func (n *newSiteCmd) doNewSite(fs *hugofs.Fs, basepath string, force bool) error {
	archeTypePath := filepath.Join(basepath, "archetypes")
	dirs := []string{
		filepath.Join(basepath, "layouts"),
		filepath.Join(basepath, "content"),
		archeTypePath,
		filepath.Join(basepath, "static"),
		filepath.Join(basepath, "data"),
		filepath.Join(basepath, "themes"),
	}

	if exists, _ := helpers.Exists(basepath, fs.Source); exists {
		if isDir, _ := helpers.IsDir(basepath, fs.Source); !isDir {
			return errors.New(basepath + " already exists but not a directory")
		}

		isEmpty, _ := helpers.IsEmpty(basepath, fs.Source)

		switch {
		case !isEmpty && !force:
			return errors.New(basepath + " already exists and is not empty")

		case !isEmpty && force:
			all := append(dirs, filepath.Join(basepath, "config."+n.configFormat))
			for _, path := range all {
				if exists, _ := helpers.Exists(path, fs.Source); exists {
					return errors.New(path + " already exists")
				}
			}
		}
	}

	for _, dir := range dirs {
		if err := fs.Source.MkdirAll(dir, 0777); err != nil {
			return _errors.Wrap(err, "Failed to create dir")
		}
	}

	createConfig(fs, basepath, n.configFormat)

	// Create a default archetype file.
	helpers.SafeWriteToDisk(filepath.Join(archeTypePath, "default.md"),
		strings.NewReader(create.ArchetypeTemplateTemplate), fs.Source)

	jww.FEEDBACK.Printf("Congratulations! Your new Hugo site is created in %s.\n\n", basepath)
	jww.FEEDBACK.Println(nextStepsText())

	return nil
}

// newSite creates a new Hugo site and initializes a structured Hugo directory.
func (n *newSiteCmd) newSite(cmd *cobra.Command, args []string) error {
	if len(args) < 1 {
		return newUserError("path needs to be provided")
	}

	createpath, err := filepath.Abs(filepath.Clean(args[0]))
	if err != nil {
		return newUserError(err)
	}

	forceNew, _ := cmd.Flags().GetBool("force")

	return n.doNewSite(hugofs.NewDefault(viper.New()), createpath, forceNew)
}

func createConfig(fs *hugofs.Fs, inpath string, kind string) (err error) {
	in := map[string]string{
		"baseURL":      "http://example.org/",
		"title":        "My New Hugo Site",
		"languageCode": "en-us",
	}

	var buf bytes.Buffer
	err = parser.InterfaceToConfig(in, metadecoders.FormatFromString(kind), &buf)
	if err != nil {
		return err
	}

	return helpers.WriteToDisk(filepath.Join(inpath, "config."+kind), &buf, fs.Source)
}

func nextStepsText() string {
	var nextStepsText bytes.Buffer

	nextStepsText.WriteString(`Just a few more steps and you're ready to go:

1. Download a theme into the same-named folder.
   Choose a theme from https://themes.gohugo.io/ or
   create your own with the "hugo new theme <THEMENAME>" command.
2. Perhaps you want to add some content. You can add single files
   with "hugo new `)

	nextStepsText.WriteString(filepath.Join("<SECTIONNAME>", "<FILENAME>.<FORMAT>"))

	nextStepsText.WriteString(`".
3. Start the built-in live server via "hugo server".

Visit https://gohugo.io/ for quickstart guide and full documentation.`)

	return nextStepsText.String()
}
<|endoftext|>