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

package telemetrylogs // import "go.opentelemetry.io/collector/service/internal/telemetrylogs"

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"go.uber.org/zap/zapgrpc"
	"google.golang.org/grpc/grpclog"

	"go.opentelemetry.io/collector/config"
)

func NewLogger(cfg config.ServiceTelemetryLogs, options []zap.Option) (*zap.Logger, error) {
	// Copied from NewProductionConfig.
	zapCfg := &zap.Config{
		Level:       zap.NewAtomicLevelAt(cfg.Level),
		Development: cfg.Development,
		Sampling: &zap.SamplingConfig{
			Initial:    100,
			Thereafter: 100,
		},
		Encoding:          cfg.Encoding,
		EncoderConfig:     zap.NewProductionEncoderConfig(),
		OutputPaths:       cfg.OutputPaths,
		ErrorOutputPaths:  cfg.ErrorOutputPaths,
		DisableCaller:     cfg.DisableCaller,
		DisableStacktrace: cfg.DisableStacktrace,
		InitialFields:     cfg.InitialFields,
	}

	if zapCfg.Encoding == "console" {
		// Human-readable timestamps for console format of logs.
		zapCfg.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
	}

	logger, err := zapCfg.Build(options...)
	if err != nil {
		return nil, err
	}

	return logger, nil
}

// SetColGRPCLogger constructs a zapgrpc.Logger instance, and installs it as grpc logger, cloned from baseLogger with
// exact configuration. The minimum level of gRPC logs is set to WARN should the loglevel of the collector is set to
// INFO to avoid copious logging from grpc framework.
func SetColGRPCLogger(baseLogger *zap.Logger, loglevel zapcore.Level) *zapgrpc.Logger {
	logger := zapgrpc.NewLogger(baseLogger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core {
		var c zapcore.Core
		if loglevel == zap.InfoLevel {
			// NewIncreaseLevelCore errors only if the new log level is less than the initial core level.
			// In this case it never happens as WARN is always greater than INFO, therefore ignoring it.
			c, _ = zapcore.NewIncreaseLevelCore(core, zap.WarnLevel)
		} else {
			c = core
		}
		return c.With([]zapcore.Field{zap.Bool("grpc_log", true)})
	})))

	grpclog.SetLoggerV2(logger)
	return logger
}
<commit_msg>fix nil error introduced in SetColGRPCLogger (#4598)<commit_after>// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package telemetrylogs // import "go.opentelemetry.io/collector/service/internal/telemetrylogs"

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"go.uber.org/zap/zapgrpc"
	"google.golang.org/grpc/grpclog"

	"go.opentelemetry.io/collector/config"
)

func NewLogger(cfg config.ServiceTelemetryLogs, options []zap.Option) (*zap.Logger, error) {
	// Copied from NewProductionConfig.
	zapCfg := &zap.Config{
		Level:       zap.NewAtomicLevelAt(cfg.Level),
		Development: cfg.Development,
		Sampling: &zap.SamplingConfig{
			Initial:    100,
			Thereafter: 100,
		},
		Encoding:          cfg.Encoding,
		EncoderConfig:     zap.NewProductionEncoderConfig(),
		OutputPaths:       cfg.OutputPaths,
		ErrorOutputPaths:  cfg.ErrorOutputPaths,
		DisableCaller:     cfg.DisableCaller,
		DisableStacktrace: cfg.DisableStacktrace,
		InitialFields:     cfg.InitialFields,
	}

	if zapCfg.Encoding == "console" {
		// Human-readable timestamps for console format of logs.
		zapCfg.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
	}

	logger, err := zapCfg.Build(options...)
	if err != nil {
		return nil, err
	}

	return logger, nil
}

// SetColGRPCLogger constructs a zapgrpc.Logger instance, and installs it as grpc logger, cloned from baseLogger with
// exact configuration. The minimum level of gRPC logs is set to WARN should the loglevel of the collector is set to
// INFO to avoid copious logging from grpc framework.
func SetColGRPCLogger(baseLogger *zap.Logger, loglevel zapcore.Level) *zapgrpc.Logger {
	logger := zapgrpc.NewLogger(baseLogger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core {
		var c zapcore.Core
		if loglevel == zap.InfoLevel {
			var err error
			// NewIncreaseLevelCore errors only if the new log level is less than the initial core level.
			// In this case it never happens as WARN is always greater than INFO, therefore ignoring it.
			c, err = zapcore.NewIncreaseLevelCore(core, zap.WarnLevel)
			// In case of an error changing the level, move on, this happens when using the NopCore
			if err != nil {
				c = core
			}
		} else {
			c = core
		}
		return c.With([]zapcore.Field{zap.Bool("grpc_log", true)})
	})))

	grpclog.SetLoggerV2(logger)
	return logger
}
<|endoftext|>


<commit_before>package mstate_test

import (
	. "launchpad.net/gocheck"
	"launchpad.net/juju-core/charm"
	state "launchpad.net/juju-core/mstate"
)

type ServiceSuite struct {
	ConnSuite
	charm   *state.Charm
	service *state.Service
}

var _ = Suite(&ServiceSuite{})

func (s *ServiceSuite) SetUpTest(c *C) {
	s.ConnSuite.SetUpTest(c)
	s.charm = s.AddTestingCharm(c, "dummy")
	var err error
	s.service, err = s.State.AddService("mysql", s.charm)
	c.Assert(err, IsNil)
}

func (s *ServiceSuite) TestServiceCharm(c *C) {
	// Check that getting and setting the service charm URL works correctly.
	testcurl, err := s.service.CharmURL()
	c.Assert(err, IsNil)
	c.Assert(testcurl.String(), Equals, s.charm.URL().String())

	// TODO BUG https://bugs.launchpad.net/juju-core/+bug/1020318
	testcurl = charm.MustParseURL("local:myseries/mydummy-1")
	err = s.service.SetCharmURL(testcurl)
	c.Assert(err, IsNil)
	testcurl, err = s.service.CharmURL()
	c.Assert(err, IsNil)
	c.Assert(testcurl.String(), Equals, "local:myseries/mydummy-1")
}

func (s *ServiceSuite) TestServiceRefesh(c *C) {
	s1, err := s.State.Service(s.service.Name())
	c.Assert(err, IsNil)

	newcurl := charm.MustParseURL("local:myseries/mydummy-1")
	err = s.service.SetCharmURL(newcurl)
	c.Assert(err, IsNil)

	testcurl, err := s1.CharmURL()
	c.Assert(err, IsNil)
	c.Assert(testcurl.String(), Equals, s.charm.URL().String())

	err = s1.Refresh()
	testcurl, err = s1.CharmURL()
	c.Assert(err, IsNil)
	c.Assert(testcurl.String(), Equals, "local:myseries/mydummy-1")
}

func (s *ServiceSuite) TestAddUnit(c *C) {
	// Check that principal units can be added on their own.
	unitZero, err := s.service.AddUnit()
	c.Assert(err, IsNil)
	c.Assert(unitZero.Name(), Equals, "mysql/0")
	principal := unitZero.IsPrincipal()
	c.Assert(principal, Equals, true)
	unitOne, err := s.service.AddUnit()
	c.Assert(err, IsNil)
	c.Assert(unitOne.Name(), Equals, "mysql/1")
	principal = unitOne.IsPrincipal()
	c.Assert(principal, Equals, true)

	// Check that principal units cannot be added to principal units.
	_, err = s.service.AddUnitSubordinateTo(unitZero)
	c.Assert(err, ErrorMatches, `cannot add unit of principal service "mysql" as a subordinate of "mysql/0"`)

	// Assign the principal unit to a machine.
	m, err := s.State.AddMachine()
	c.Assert(err, IsNil)
	err = unitZero.AssignToMachine(m)
	c.Assert(err, IsNil)

	// Add a subordinate service.
	subCharm := s.AddTestingCharm(c, "logging")
	logging, err := s.State.AddService("logging", subCharm)
	c.Assert(err, IsNil)

	// Check that subordinate units can be added to principal units
	subZero, err := logging.AddUnitSubordinateTo(unitZero)
	c.Assert(err, IsNil)
	c.Assert(subZero.Name(), Equals, "logging/0")
	principal = subZero.IsPrincipal()
	c.Assert(principal, Equals, false)

	// Check the subordinate unit has been assigned its principal's machine.
	id, err := subZero.AssignedMachineId()
	c.Assert(err, IsNil)
	c.Assert(id, Equals, m.Id())

	// Check that subordinate units must be added to other units.
	_, err = logging.AddUnit()
	c.Assert(err, ErrorMatches, `cannot directly add units to subordinate service "logging"`)

	// Check that subordinate units cannnot be added to subordinate units.
	_, err = logging.AddUnitSubordinateTo(subZero)
	c.Assert(err, ErrorMatches, "a subordinate unit must be added to a principal unit")
}

func (s *ServiceSuite) TestReadUnit(c *C) {
	_, err := s.service.AddUnit()
	c.Assert(err, IsNil)
	_, err = s.service.AddUnit()
	c.Assert(err, IsNil)
	// Check that retrieving a unit works correctly.
	unit, err := s.service.Unit("mysql/0")
	c.Assert(err, IsNil)
	c.Assert(unit.Name(), Equals, "mysql/0")

	// Check that retrieving a non-existent or an invalidly
	// named unit fail nicely.
	unit, err = s.service.Unit("mysql")
	c.Assert(err, ErrorMatches, `cannot get unit "mysql" from service "mysql":.*`)
	unit, err = s.service.Unit("mysql/0/0")
	c.Assert(err, ErrorMatches, `cannot get unit "mysql/0/0" from service "mysql": .*`)
	unit, err = s.service.Unit("pressword/0")
	c.Assert(err, ErrorMatches, `cannot get unit "pressword/0" from service "mysql": .*`)

	// Add another service to check units are not misattributed.
	mysql, err := s.State.AddService("wordpress", s.charm)
	c.Assert(err, IsNil)
	_, err = mysql.AddUnit()
	c.Assert(err, IsNil)

	// BUG(aram): use error strings from state.
	unit, err = s.service.Unit("wordpress/0")
	c.Assert(err, ErrorMatches, `cannot get unit "wordpress/0" from service "mysql": .*`)

	// Check that retrieving all units works.
	units, err := s.service.AllUnits()
	c.Assert(err, IsNil)
	c.Assert(len(units), Equals, 2)
	c.Assert(units[0].Name(), Equals, "mysql/0")
	c.Assert(units[1].Name(), Equals, "mysql/1")
}

func (s *ServiceSuite) TestRemoveUnit(c *C) {
	_, err := s.service.AddUnit()
	c.Assert(err, IsNil)
	_, err = s.service.AddUnit()
	c.Assert(err, IsNil)

	// Check that removing a unit works.
	unit, err := s.service.Unit("mysql/0")
	c.Assert(err, IsNil)
	err = s.service.RemoveUnit(unit)
	c.Assert(err, IsNil)

	units, err := s.service.AllUnits()
	c.Assert(err, IsNil)
	c.Assert(units, HasLen, 1)
	c.Assert(units[0].Name(), Equals, "mysql/1")

	// Check that removing a non-existent unit fails nicely.
	// TODO(aram): improve error message.
	// BUG(aram): use error strings from state.
	err = s.service.RemoveUnit(unit)
	c.Assert(err, ErrorMatches, `cannot remove unit "mysql/0": .*`)
}
<commit_msg>mstate: use charm.URLs in TestServiceRefesh instead of strings<commit_after>package mstate_test

import (
	. "launchpad.net/gocheck"
	"launchpad.net/juju-core/charm"
	state "launchpad.net/juju-core/mstate"
)

type ServiceSuite struct {
	ConnSuite
	charm   *state.Charm
	service *state.Service
}

var _ = Suite(&ServiceSuite{})

func (s *ServiceSuite) SetUpTest(c *C) {
	s.ConnSuite.SetUpTest(c)
	s.charm = s.AddTestingCharm(c, "dummy")
	var err error
	s.service, err = s.State.AddService("mysql", s.charm)
	c.Assert(err, IsNil)
}

func (s *ServiceSuite) TestServiceCharm(c *C) {
	// Check that getting and setting the service charm URL works correctly.
	testcurl, err := s.service.CharmURL()
	c.Assert(err, IsNil)
	c.Assert(testcurl.String(), Equals, s.charm.URL().String())

	// TODO BUG https://bugs.launchpad.net/juju-core/+bug/1020318
	testcurl = charm.MustParseURL("local:myseries/mydummy-1")
	err = s.service.SetCharmURL(testcurl)
	c.Assert(err, IsNil)
	testcurl, err = s.service.CharmURL()
	c.Assert(err, IsNil)
	c.Assert(testcurl.String(), Equals, "local:myseries/mydummy-1")
}

func (s *ServiceSuite) TestServiceRefesh(c *C) {
	s1, err := s.State.Service(s.service.Name())
	c.Assert(err, IsNil)

	newcurl := charm.MustParseURL("local:myseries/mydummy-1")
	err = s.service.SetCharmURL(newcurl)
	c.Assert(err, IsNil)

	testcurl, err := s1.CharmURL()
	c.Assert(err, IsNil)
	c.Assert(testcurl, DeepEquals, s.charm.URL())

	err = s1.Refresh()
	testcurl, err = s1.CharmURL()
	c.Assert(err, IsNil)
	c.Assert(testcurl, DeepEquals, newcurl)
}

func (s *ServiceSuite) TestAddUnit(c *C) {
	// Check that principal units can be added on their own.
	unitZero, err := s.service.AddUnit()
	c.Assert(err, IsNil)
	c.Assert(unitZero.Name(), Equals, "mysql/0")
	principal := unitZero.IsPrincipal()
	c.Assert(principal, Equals, true)
	unitOne, err := s.service.AddUnit()
	c.Assert(err, IsNil)
	c.Assert(unitOne.Name(), Equals, "mysql/1")
	principal = unitOne.IsPrincipal()
	c.Assert(principal, Equals, true)

	// Check that principal units cannot be added to principal units.
	_, err = s.service.AddUnitSubordinateTo(unitZero)
	c.Assert(err, ErrorMatches, `cannot add unit of principal service "mysql" as a subordinate of "mysql/0"`)

	// Assign the principal unit to a machine.
	m, err := s.State.AddMachine()
	c.Assert(err, IsNil)
	err = unitZero.AssignToMachine(m)
	c.Assert(err, IsNil)

	// Add a subordinate service.
	subCharm := s.AddTestingCharm(c, "logging")
	logging, err := s.State.AddService("logging", subCharm)
	c.Assert(err, IsNil)

	// Check that subordinate units can be added to principal units
	subZero, err := logging.AddUnitSubordinateTo(unitZero)
	c.Assert(err, IsNil)
	c.Assert(subZero.Name(), Equals, "logging/0")
	principal = subZero.IsPrincipal()
	c.Assert(principal, Equals, false)

	// Check the subordinate unit has been assigned its principal's machine.
	id, err := subZero.AssignedMachineId()
	c.Assert(err, IsNil)
	c.Assert(id, Equals, m.Id())

	// Check that subordinate units must be added to other units.
	_, err = logging.AddUnit()
	c.Assert(err, ErrorMatches, `cannot directly add units to subordinate service "logging"`)

	// Check that subordinate units cannnot be added to subordinate units.
	_, err = logging.AddUnitSubordinateTo(subZero)
	c.Assert(err, ErrorMatches, "a subordinate unit must be added to a principal unit")
}

func (s *ServiceSuite) TestReadUnit(c *C) {
	_, err := s.service.AddUnit()
	c.Assert(err, IsNil)
	_, err = s.service.AddUnit()
	c.Assert(err, IsNil)
	// Check that retrieving a unit works correctly.
	unit, err := s.service.Unit("mysql/0")
	c.Assert(err, IsNil)
	c.Assert(unit.Name(), Equals, "mysql/0")

	// Check that retrieving a non-existent or an invalidly
	// named unit fail nicely.
	unit, err = s.service.Unit("mysql")
	c.Assert(err, ErrorMatches, `cannot get unit "mysql" from service "mysql":.*`)
	unit, err = s.service.Unit("mysql/0/0")
	c.Assert(err, ErrorMatches, `cannot get unit "mysql/0/0" from service "mysql": .*`)
	unit, err = s.service.Unit("pressword/0")
	c.Assert(err, ErrorMatches, `cannot get unit "pressword/0" from service "mysql": .*`)

	// Add another service to check units are not misattributed.
	mysql, err := s.State.AddService("wordpress", s.charm)
	c.Assert(err, IsNil)
	_, err = mysql.AddUnit()
	c.Assert(err, IsNil)

	// BUG(aram): use error strings from state.
	unit, err = s.service.Unit("wordpress/0")
	c.Assert(err, ErrorMatches, `cannot get unit "wordpress/0" from service "mysql": .*`)

	// Check that retrieving all units works.
	units, err := s.service.AllUnits()
	c.Assert(err, IsNil)
	c.Assert(len(units), Equals, 2)
	c.Assert(units[0].Name(), Equals, "mysql/0")
	c.Assert(units[1].Name(), Equals, "mysql/1")
}

func (s *ServiceSuite) TestRemoveUnit(c *C) {
	_, err := s.service.AddUnit()
	c.Assert(err, IsNil)
	_, err = s.service.AddUnit()
	c.Assert(err, IsNil)

	// Check that removing a unit works.
	unit, err := s.service.Unit("mysql/0")
	c.Assert(err, IsNil)
	err = s.service.RemoveUnit(unit)
	c.Assert(err, IsNil)

	units, err := s.service.AllUnits()
	c.Assert(err, IsNil)
	c.Assert(units, HasLen, 1)
	c.Assert(units[0].Name(), Equals, "mysql/1")

	// Check that removing a non-existent unit fails nicely.
	// TODO(aram): improve error message.
	// BUG(aram): use error strings from state.
	err = s.service.RemoveUnit(unit)
	c.Assert(err, ErrorMatches, `cannot remove unit "mysql/0": .*`)
}
<|endoftext|>


<commit_before>package message

import (
	"GoOnchain/common"
	"GoOnchain/common/log"
	. "GoOnchain/net/protocol"
	"bytes"
	"crypto/sha256"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
)

type Messager interface {
	Verify([]byte) error
	Serialization() ([]byte, error)
	Deserialization([]byte) error
	Handle(Noder) error
}

// The network communication message header
type msgHdr struct {
	Magic    uint32
	//ID	 uint64
	CMD      [MSGCMDLEN]byte // The message type
	Length   uint32
	Checksum [CHECKSUMLEN]byte
}

// The message body and header
type msgCont struct {
	hdr msgHdr
	p   interface{}
}

type varStr struct {
	len uint
	buf []byte
}

type filteradd struct {
	msgHdr
	//TBD
}

type filterclear struct {
	msgHdr
	//TBD
}

type filterload struct {
	msgHdr
	//TBD
}

// Alloc different message stucture
// @t the message name or type
// @len the message length only valid for varible length structure
//
// Return:
// @messager the messager interface
// @error  error code
// FixMe fix the ugly multiple return.
func AllocMsg(t string, length int) Messager {
	switch t {
	case "msgheader":
		var msg msgHdr
		return &msg
	case "version":
		var msg version
		// TODO fill the header and type
		copy(msg.Hdr.CMD[0:len(t)], t)
		return &msg
	case "verack":
		var msg verACK
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "getheaders":
		var msg headersReq
		// TODO fill the header and type
		copy(msg.hdr.CMD[0:len(t)], t)
		return &msg
	case "headers":
		var msg blkHeader
		copy(msg.hdr.CMD[0:len(t)], t)
		return &msg
	case "getaddr":
		var msg addrReq
		copy(msg.Hdr.CMD[0:len(t)], t)
		return &msg
	case "addr":
		var msg addr
		copy(msg.hdr.CMD[0:len(t)], t)
		return &msg
	case "inv":
		var msg Inv
		copy(msg.Hdr.CMD[0:len(t)], t)
		// the 1 is the inv type lenght
		msg.P.Blk = make([]byte, length-MSGHDRLEN-1)
		return &msg
	case "getdata":
		var msg dataReq
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "block":
		var msg block
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "tx":
		var msg trn
		copy(msg.msgHdr.CMD[0:len(t)], t)
		//if (message.Payload.Length <= 1024 * 1024)
		//OnInventoryReceived(Transaction.DeserializeFrom(message.Payload));
		return &msg
	case "consensus":
		var msg consensus
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "filteradd":
		var msg filteradd
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "filterclear":
		var msg filterclear
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "filterload":
		var msg filterload
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "getblocks":
		var msg blockReq
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "mempool":
		var msg memPool
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "alert":
		errors.New("Not supported message type")
		return nil
	case "merkleblock":
		errors.New("Not supported message type")
		return nil
	case "notfound":
		errors.New("Not supported message type")
		return nil
	case "ping":
		errors.New("Not supported message type")
		return nil
	case "pong":
		errors.New("Not supported message type")
		return nil
	case "reject":
		errors.New("Not supported message type")
		return nil
	default:
		errors.New("Unknown message type")
		return nil
	}
}

func MsgType(buf []byte) (string, error) {
	cmd := buf[CMDOFFSET : CMDOFFSET+MSGCMDLEN]
	n := bytes.IndexByte(cmd, 0)
	if n < 0 || n >= MSGCMDLEN {
		return "", errors.New("Unexpected length of CMD command")
	}
	s := string(cmd[:n])
	return s, nil
}

// TODO combine all of message alloc in one function via interface
func NewMsg(t string, n Noder) ([]byte, error) {
	switch t {
	case "version":
		return NewVersion(n)
	case "verack":
		return NewVerack()
	case "getheaders":
		return NewHeadersReq(n)
	case "getaddr":
		return newGetAddr()

	default:
		return nil, errors.New("Unknown message type")
	}
}

// FIXME the length exceed int32 case?
func HandleNodeMsg(node Noder, buf []byte, len int) error {
	if len < MSGHDRLEN {
		log.Warn("Unexpected size of received message")
		return errors.New("Unexpected size of received message")
	}

	str := hex.EncodeToString(buf[:len])
	log.Debug("Received data len: ", len, "\n", str)

	s, err := MsgType(buf)
	if err != nil {
		fmt.Println(err.Error())
		return err
	}

	msg := AllocMsg(s, len)
	if msg == nil {
		fmt.Println(err.Error())
		return err
	}
	// Todo attach a ndoe pointer to each message
	// Todo drop the message when verify/deseria packet error
	msg.Deserialization(buf[:len])
	msg.Verify(buf[:len])
	str := hex.EncodeToString(buf[:len])
	log.Debug("Received data len: ", len, "\n", str)
	return msg.Handle(node)
}

func magicVerify(magic uint32) bool {
	if magic != NETMAGIC {
		return false
	}
	return true
}

func PayloadLen(buf []byte) int {
	var h msgHdr
	h.Deserialization(buf)
	return int(h.Length)
}

func checkSum(p []byte) []byte {
	t := sha256.Sum256(p)
	s := sha256.Sum256(t[:])

	// Currently we only need the front 4 bytes as checksum
	return s[:CHECKSUMLEN]
}

func reverse(input []byte) []byte {
	if len(input) == 0 {
		return input
	}
	return append(reverse(input[1:]), input[0])
}

func (hdr *msgHdr) init(cmd string, checksum []byte, length uint32) {
	hdr.Magic = NETMAGIC
	copy(hdr.CMD[0:uint32(len(cmd))], cmd)
	copy(hdr.Checksum[:], checksum[:CHECKSUMLEN])
	hdr.Length = length
	//hdr.ID = id
}

// Verify the message header information
// @p payload of the message
func (hdr msgHdr) Verify(buf []byte) error {
	if magicVerify(hdr.Magic) == false {
		log.Warn(fmt.Sprintf("Unmatched magic number 0x%0x", hdr.Magic))
		return errors.New("Unmatched magic number")
	}
	log.Debug(fmt.Sprintf("Magic number 0x%0x", hdr.Magic))
	checkSum := checkSum(buf)
	if bytes.Equal(hdr.Checksum[:], checkSum[:]) == false {
		str1 := hex.EncodeToString(hdr.Checksum[:])
		str2 := hex.EncodeToString(checkSum[:])
		log.Warn(fmt.Sprintf("Message Checksum error, Received checksum %s Wanted checksum: %s",
			str1, str2))
		return errors.New("Message Checksum error")
	}

	return nil
}

func (msg *msgHdr) Deserialization(p []byte) error {

	buf := bytes.NewBuffer(p[0:MSGHDRLEN])
	err := binary.Read(buf, binary.LittleEndian, msg)
	return err
}

// FIXME how to avoid duplicate serial/deserial function as
// most of them are the same
func (hdr msgHdr) Serialization() ([]byte, error) {
	var buf bytes.Buffer
	err := binary.Write(&buf, binary.LittleEndian, hdr)
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), err
}

func (hdr msgHdr) Handle(n Noder) error {
	common.Trace()
	// TBD
	return nil
}
<commit_msg>Fixing the message header deserialization issue when receive block<commit_after>package message

import (
	"GoOnchain/common"
	"GoOnchain/common/log"
	. "GoOnchain/net/protocol"
	"bytes"
	"crypto/sha256"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
)

type Messager interface {
	Verify([]byte) error
	Serialization() ([]byte, error)
	Deserialization([]byte) error
	Handle(Noder) error
}

// The network communication message header
type msgHdr struct {
	Magic    uint32
	//ID	 uint64
	CMD      [MSGCMDLEN]byte // The message type
	Length   uint32
	Checksum [CHECKSUMLEN]byte
}

// The message body and header
type msgCont struct {
	hdr msgHdr
	p   interface{}
}

type varStr struct {
	len uint
	buf []byte
}

type filteradd struct {
	msgHdr
	//TBD
}

type filterclear struct {
	msgHdr
	//TBD
}

type filterload struct {
	msgHdr
	//TBD
}

// Alloc different message stucture
// @t the message name or type
// @len the message length only valid for varible length structure
//
// Return:
// @messager the messager interface
// @error  error code
// FixMe fix the ugly multiple return.
func AllocMsg(t string, length int) Messager {
	switch t {
	case "msgheader":
		var msg msgHdr
		return &msg
	case "version":
		var msg version
		// TODO fill the header and type
		copy(msg.Hdr.CMD[0:len(t)], t)
		return &msg
	case "verack":
		var msg verACK
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "getheaders":
		var msg headersReq
		// TODO fill the header and type
		copy(msg.hdr.CMD[0:len(t)], t)
		return &msg
	case "headers":
		var msg blkHeader
		copy(msg.hdr.CMD[0:len(t)], t)
		return &msg
	case "getaddr":
		var msg addrReq
		copy(msg.Hdr.CMD[0:len(t)], t)
		return &msg
	case "addr":
		var msg addr
		copy(msg.hdr.CMD[0:len(t)], t)
		return &msg
	case "inv":
		var msg Inv
		copy(msg.Hdr.CMD[0:len(t)], t)
		// the 1 is the inv type lenght
		msg.P.Blk = make([]byte, length-MSGHDRLEN-1)
		return &msg
	case "getdata":
		var msg dataReq
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "block":
		var msg block
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "tx":
		var msg trn
		copy(msg.msgHdr.CMD[0:len(t)], t)
		//if (message.Payload.Length <= 1024 * 1024)
		//OnInventoryReceived(Transaction.DeserializeFrom(message.Payload));
		return &msg
	case "consensus":
		var msg consensus
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "filteradd":
		var msg filteradd
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "filterclear":
		var msg filterclear
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "filterload":
		var msg filterload
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "getblocks":
		var msg blockReq
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "mempool":
		var msg memPool
		copy(msg.msgHdr.CMD[0:len(t)], t)
		return &msg
	case "alert":
		errors.New("Not supported message type")
		return nil
	case "merkleblock":
		errors.New("Not supported message type")
		return nil
	case "notfound":
		errors.New("Not supported message type")
		return nil
	case "ping":
		errors.New("Not supported message type")
		return nil
	case "pong":
		errors.New("Not supported message type")
		return nil
	case "reject":
		errors.New("Not supported message type")
		return nil
	default:
		errors.New("Unknown message type")
		return nil
	}
}

func MsgType(buf []byte) (string, error) {
	cmd := buf[CMDOFFSET : CMDOFFSET+MSGCMDLEN]
	n := bytes.IndexByte(cmd, 0)
	if n < 0 || n >= MSGCMDLEN {
		return "", errors.New("Unexpected length of CMD command")
	}
	s := string(cmd[:n])
	return s, nil
}

// TODO combine all of message alloc in one function via interface
func NewMsg(t string, n Noder) ([]byte, error) {
	switch t {
	case "version":
		return NewVersion(n)
	case "verack":
		return NewVerack()
	case "getheaders":
		return NewHeadersReq(n)
	case "getaddr":
		return newGetAddr()

	default:
		return nil, errors.New("Unknown message type")
	}
}

// FIXME the length exceed int32 case?
func HandleNodeMsg(node Noder, buf []byte, len int) error {
	if len < MSGHDRLEN {
		log.Warn("Unexpected size of received message")
		return errors.New("Unexpected size of received message")
	}

	str := hex.EncodeToString(buf[:len])
	log.Debug("Received data len: ", len, "\n", str)

	s, err := MsgType(buf)
	if err != nil {
		fmt.Println(err.Error())
		return err
	}

	msg := AllocMsg(s, len)
	if msg == nil {
		fmt.Println(err.Error())
		return err
	}
	// Todo attach a ndoe pointer to each message
	// Todo drop the message when verify/deseria packet error
	msg.Deserialization(buf[:len])
	msg.Verify(buf[:len])

	return msg.Handle(node)
}

func magicVerify(magic uint32) bool {
	if magic != NETMAGIC {
		return false
	}
	return true
}

func PayloadLen(buf []byte) int {
	var h msgHdr
	h.Deserialization(buf)
	return int(h.Length)
}

func checkSum(p []byte) []byte {
	t := sha256.Sum256(p)
	s := sha256.Sum256(t[:])

	// Currently we only need the front 4 bytes as checksum
	return s[:CHECKSUMLEN]
}

func reverse(input []byte) []byte {
	if len(input) == 0 {
		return input
	}
	return append(reverse(input[1:]), input[0])
}

func (hdr *msgHdr) init(cmd string, checksum []byte, length uint32) {
	hdr.Magic = NETMAGIC
	copy(hdr.CMD[0:uint32(len(cmd))], cmd)
	copy(hdr.Checksum[:], checksum[:CHECKSUMLEN])
	hdr.Length = length
	//hdr.ID = id
}

// Verify the message header information
// @p payload of the message
func (hdr msgHdr) Verify(buf []byte) error {
	if magicVerify(hdr.Magic) == false {
		log.Warn(fmt.Sprintf("Unmatched magic number 0x%0x", hdr.Magic))
		return errors.New("Unmatched magic number")
	}
	log.Debug(fmt.Sprintf("Magic number 0x%0x", hdr.Magic))
	checkSum := checkSum(buf)
	if bytes.Equal(hdr.Checksum[:], checkSum[:]) == false {
		str1 := hex.EncodeToString(hdr.Checksum[:])
		str2 := hex.EncodeToString(checkSum[:])
		log.Warn(fmt.Sprintf("Message Checksum error, Received checksum %s Wanted checksum: %s",
			str1, str2))
		return errors.New("Message Checksum error")
	}

	return nil
}

func (msg *msgHdr) Deserialization(p []byte) error {

	buf := bytes.NewBuffer(p[0:MSGHDRLEN])
	err := binary.Read(buf, binary.LittleEndian, msg)
	return err
}

// FIXME how to avoid duplicate serial/deserial function as
// most of them are the same
func (hdr msgHdr) Serialization() ([]byte, error) {
	var buf bytes.Buffer
	err := binary.Write(&buf, binary.LittleEndian, hdr)
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), err
}

func (hdr msgHdr) Handle(n Noder) error {
	common.Trace()
	// TBD
	return nil
}
<|endoftext|>


<commit_before>package gls

// so, basically, we're going to encode integer tags in base-16 on the stack

import (
	"runtime"
)

const (
	bitWidth = 4
)

func addStackTag(tag uint, context_call func()) {
	if context_call == nil {
		return
	}
	markS(tag, context_call)
}

func markS(tag uint, cb func()) uintptr { return _m(tag, cb) }
func mark0(tag uint, cb func()) uintptr { return _m(tag, cb) }
func mark1(tag uint, cb func()) uintptr { return _m(tag, cb) }
func mark2(tag uint, cb func()) uintptr { return _m(tag, cb) }
func mark3(tag uint, cb func()) uintptr { return _m(tag, cb) }
func mark4(tag uint, cb func()) uintptr { return _m(tag, cb) }
func mark5(tag uint, cb func()) uintptr { return _m(tag, cb) }
func mark6(tag uint, cb func()) uintptr { return _m(tag, cb) }
func mark7(tag uint, cb func()) uintptr { return _m(tag, cb) }
func mark8(tag uint, cb func()) uintptr { return _m(tag, cb) }
func mark9(tag uint, cb func()) uintptr { return _m(tag, cb) }
func markA(tag uint, cb func()) uintptr { return _m(tag, cb) }
func markB(tag uint, cb func()) uintptr { return _m(tag, cb) }
func markC(tag uint, cb func()) uintptr { return _m(tag, cb) }
func markD(tag uint, cb func()) uintptr { return _m(tag, cb) }
func markE(tag uint, cb func()) uintptr { return _m(tag, cb) }
func markF(tag uint, cb func()) uintptr { return _m(tag, cb) }

func _m(tag_remainder uint, cb func()) uintptr {
	if cb == nil {
		pc, _, _, ok := runtime.Caller(1)
		if !ok {
			panic("unable to find caller")
		}
		return runtime.FuncForPC(pc).Entry()
	}
	if tag_remainder == 0 {
		cb()
		return 0
	}
	current_octal_val := tag_remainder & 0xf
	tag_remainder >>= bitWidth
	switch current_octal_val {
	case 0x0:
		return mark0(tag_remainder, cb)
	case 0x1:
		return mark1(tag_remainder, cb)
	case 0x2:
		return mark2(tag_remainder, cb)
	case 0x3:
		return mark3(tag_remainder, cb)
	case 0x4:
		return mark4(tag_remainder, cb)
	case 0x5:
		return mark5(tag_remainder, cb)
	case 0x6:
		return mark6(tag_remainder, cb)
	case 0x7:
		return mark7(tag_remainder, cb)
	case 0x8:
		return mark8(tag_remainder, cb)
	case 0x9:
		return mark9(tag_remainder, cb)
	case 0xa:
		return markA(tag_remainder, cb)
	case 0xb:
		return markB(tag_remainder, cb)
	case 0xc:
		return markC(tag_remainder, cb)
	case 0xd:
		return markD(tag_remainder, cb)
	case 0xe:
		return markE(tag_remainder, cb)
	case 0xf:
		return markF(tag_remainder, cb)
	default:
		panic("programmer failed at base 16")
	}
}

var pc_lookup = map[uintptr]int{
	markS(0, nil): -1,
	mark0(0, nil): 0x0,
	mark1(0, nil): 0x1,
	mark2(0, nil): 0x2,
	mark3(0, nil): 0x3,
	mark4(0, nil): 0x4,
	mark5(0, nil): 0x5,
	mark6(0, nil): 0x6,
	mark7(0, nil): 0x7,
	mark8(0, nil): 0x8,
	mark9(0, nil): 0x9,
	markA(0, nil): 0xa,
	markB(0, nil): 0xb,
	markC(0, nil): 0xc,
	markD(0, nil): 0xd,
	markE(0, nil): 0xe,
	markF(0, nil): 0xf}

func readStackTags(stack []uintptr) (tags []uint) {
	var current_tag uint
	for _, pc := range stack {
		pc = runtime.FuncForPC(pc).Entry()
		val, ok := pc_lookup[pc]
		if !ok {
			continue
		}
		if val < 0 {
			tags = append(tags, current_tag)
			current_tag = 0
			continue
		}
		current_tag <<= bitWidth
		current_tag += uint(val)
	}
	return
}
<commit_msg>Cleanup stack_tags to make the trick more obvious<commit_after>package gls

// so, basically, we're going to encode integer tags in base-16 on the stack

import (
	"reflect"
	"runtime"
)

const (
	bitWidth = 4
)

func addStackTag(tag uint, context_call func()) {
	if context_call == nil {
		return
	}
	markS(tag, context_call)
}

func markS(tag uint, cb func()) { _m(tag, cb) }
func mark0(tag uint, cb func()) { _m(tag, cb) }
func mark1(tag uint, cb func()) { _m(tag, cb) }
func mark2(tag uint, cb func()) { _m(tag, cb) }
func mark3(tag uint, cb func()) { _m(tag, cb) }
func mark4(tag uint, cb func()) { _m(tag, cb) }
func mark5(tag uint, cb func()) { _m(tag, cb) }
func mark6(tag uint, cb func()) { _m(tag, cb) }
func mark7(tag uint, cb func()) { _m(tag, cb) }
func mark8(tag uint, cb func()) { _m(tag, cb) }
func mark9(tag uint, cb func()) { _m(tag, cb) }
func markA(tag uint, cb func()) { _m(tag, cb) }
func markB(tag uint, cb func()) { _m(tag, cb) }
func markC(tag uint, cb func()) { _m(tag, cb) }
func markD(tag uint, cb func()) { _m(tag, cb) }
func markE(tag uint, cb func()) { _m(tag, cb) }
func markF(tag uint, cb func()) { _m(tag, cb) }

var pc_lookup = make(map[uintptr]int8, 17)
var mark_lookup [16]func(uint, func())

func init() {
	setEntries := func(f func(uint, func()), v int8) {
		pc_lookup[reflect.ValueOf(f).Pointer()] = v
		if v >= 0 {
			mark_lookup[v] = f
		}
	}
	setEntries(markS, -0x1)
	setEntries(mark0, 0x0)
	setEntries(mark1, 0x1)
	setEntries(mark2, 0x2)
	setEntries(mark3, 0x3)
	setEntries(mark4, 0x4)
	setEntries(mark5, 0x5)
	setEntries(mark6, 0x6)
	setEntries(mark7, 0x7)
	setEntries(mark8, 0x8)
	setEntries(mark9, 0x9)
	setEntries(markA, 0xa)
	setEntries(markB, 0xb)
	setEntries(markC, 0xc)
	setEntries(markD, 0xd)
	setEntries(markE, 0xe)
	setEntries(markF, 0xf)
}

func _m(tag_remainder uint, cb func()) {
	if tag_remainder == 0 {
		cb()
	} else {
		mark_lookup[tag_remainder&0xf](tag_remainder>>bitWidth, cb)
	}
}

func readStackTags(stack []uintptr) (tags []uint) {
	var current_tag uint
	for _, pc := range stack {
		pc = runtime.FuncForPC(pc).Entry()
		val, ok := pc_lookup[pc]
		if !ok {
			continue
		}
		if val < 0 {
			tags = append(tags, current_tag)
			current_tag = 0
			continue
		}
		current_tag <<= bitWidth
		current_tag += uint(val)
	}
	return
}
<|endoftext|>


<commit_before>// Copyright © 2016 Nick Klauer <klauer@gmail.com>
//
// 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 trackello

import (
	"fmt"

	"github.com/VojtechVitek/go-trello"
	"github.com/fatih/color"
)

// statistics provides a way to show statistical information about a list, card or whatnot by aggregating the updates,
// comments, checklists, and other actions under a specific item.
type statistics struct {
	comments, // represented by a horizontal ellepsis ⋯ 0x22EF
	updates, // represented by a keyboard 0x2328
	creates, // represented by plus +
	checkListItemUpdates int // represented by check mark ✓ 0x2713
}

// AddCalculation will the new action to the Card's statistics.
func (c *Card) AddCalculation(a trello.Action) {
	switch a.Type {
	case "commentCard":
		c.stats.comments++
	case "updateCard", "deleteAttachmentFromCard":
		c.stats.updates++
	case "createCard", "addChecklistToCard", "addAttachmentToCard":
		c.stats.creates++
	case "updateCheckItemStateOnCard":
		c.stats.checkListItemUpdates++
	default:
		fmt.Printf("Unmapped action type: %s.  Defaulting to update\n", a.Type)
		c.stats.updates++
	}
}

// PrintStatistics will print the statistics information out.
// Example format: [ 3 +  2 ≡  0 ✓  1 … ]
func (s *statistics) PrintStatistics() string {
	if s == nil {
		s = &statistics{}
	}
	stats := "[" + color.CyanString("%d +", s.updates)
	stats = stats + color.RedString(" %d ≡", s.comments)
	stats = stats + color.GreenString(" %d ✓", s.checkListItemUpdates)
	stats = stats + color.MagentaString(" %d …", s.creates)
	stats = stats + "]"
	return stats
}
<commit_msg>tweak output to account for double-digit updates<commit_after>// Copyright © 2016 Nick Klauer <klauer@gmail.com>
//
// 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 trackello

import (
	"fmt"

	"github.com/VojtechVitek/go-trello"
	"github.com/fatih/color"
)

// statistics provides a way to show statistical information about a list, card or whatnot by aggregating the updates,
// comments, checklists, and other actions under a specific item.
type statistics struct {
	comments, // represented by a horizontal ellepsis ⋯ 0x22EF
	updates, // represented by a keyboard 0x2328
	creates, // represented by plus +
	checkListItemUpdates int // represented by check mark ✓ 0x2713
}

// AddCalculation will the new action to the Card's statistics.
func (c *Card) AddCalculation(a trello.Action) {
	switch a.Type {
	case "commentCard":
		c.stats.comments++
	case "updateCard", "deleteAttachmentFromCard":
		c.stats.updates++
	case "createCard", "addChecklistToCard", "addAttachmentToCard":
		c.stats.creates++
	case "updateCheckItemStateOnCard":
		c.stats.checkListItemUpdates++
	default:
		fmt.Printf("Unmapped action type: %s.  Defaulting to update\n", a.Type)
		c.stats.updates++
	}
}

// PrintStatistics will print the statistics information out.
// Example format: [ 3 +  2 ≡  0 ✓  1 … ]
func (s *statistics) PrintStatistics() string {
	if s == nil {
		s = &statistics{}
	}
	stats := "[" + color.CyanString("%-2d +", s.updates)
	stats = stats + color.RedString(" %-2d ≡", s.comments)
	stats = stats + color.GreenString(" %-2d ✓", s.checkListItemUpdates)
	stats = stats + color.MagentaString(" %-2d …", s.creates)
	stats = stats + "]"
	return stats
}
<|endoftext|>


<commit_before>package storage

import (
	"database/sql"
	"encoding/base64"
	"errors"
	"fmt"
	log "github.com/golang/glog"
	"github.com/jrupac/goliath/models"
	_ "github.com/lib/pq"
	"strconv"
	"strings"
)

const (
	DIALECT               = "postgres"
	FOLDER_TABLE          = "Folder"
	FOLDER_CHILDREN_TABLE = "FolderChildren"
	FEED_TABLE            = "Feed"
	ARTICLE_TABLE         = "Article"
	MAX_FETCHED_ROWS      = 10000
)

type Database struct {
	db *sql.DB
}

func Open(dbPath string) (*Database, error) {
	db := new(Database)

	d, err := sql.Open(DIALECT, dbPath)
	if err != nil {
		return nil, err
	}

	db.db = d
	return db, nil
}

func (d *Database) Close() error {
	return d.db.Close()
}

func (d *Database) InsertArticle(a models.Article) error {
	var articleId int64
	var count int
	err := d.db.QueryRow(
		`SELECT COUNT(*) FROM `+ARTICLE_TABLE+` WHERE hash = $1`, a.Hash()).Scan(&count)
	if err != nil {
		return err
	}
	if count > 0 {
		log.Infof("Duplicate article entry, skipping.")
		return nil
	}

	err = d.db.QueryRow(
		`INSERT INTO `+ARTICLE_TABLE+`
		(feed, folder, hash, title, summary, content, link, date, read)
		VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id`,
		a.FeedId, a.FolderId, a.Hash(), a.Title, a.Summary, a.Content, a.Link, a.Date, a.Read).Scan(&articleId)
	if err != nil {
		return err
	}
	a.Id = articleId
	return nil
}

func (d *Database) InsertFavicon(feedId int64, mime string, img []byte) error {
	var count int
	err := d.db.QueryRow(
		`SELECT COUNT(*) FROM `+FEED_TABLE+` WHERE id = $1`, feedId).Scan(&count)
	if err != nil {
		return err
	}
	if count == 0 {
		return errors.New(fmt.Sprintf("Original feed not in table: %d", feedId))
	}

	// Convert to a base64 encoded string before inserting
	h := base64.StdEncoding.EncodeToString(img)

	_, err = d.db.Query(
		`UPDATE `+FEED_TABLE+` SET favicon = $1, mime = $2 WHERE id = $3`,
		h, mime, feedId)
	return err
}

func (d *Database) MarkArticle(id int64, status string) error {
	var state bool
	switch status {
	case "saved", "unsaved":
		// Perhaps add support for saving articles in the future.
		return nil
	case "read":
		state = true
	case "unread":
		state = false
	}

	_, err := d.db.Query(`UPDATE `+ARTICLE_TABLE+` SET read = $1 WHERE id = $2`, state, id)
	return err
}

func (d *Database) MarkFeed(id int64, status string) error {
	var state bool
	switch status {
	case "saved", "unsaved":
		// Perhaps add support for saving articles in the future.
		return nil
	case "read":
		state = true
	case "unread":
		state = false
	}

	_, err := d.db.Query(`UPDATE `+ARTICLE_TABLE+` SET read = $1 WHERE feed = $2`, state, id)
	return err
}

func (d *Database) MarkFolder(id int64, status string) error {
	var state bool
	switch status {
	case "saved", "unsaved":
		// Perhaps add support for saving articles in the future.
		return nil
	case "read":
		state = true
	case "unread":
		state = false
	}

	_, err := d.db.Query(`UPDATE `+ARTICLE_TABLE+` SET read = $1 WHERE folder = $2`, state, id)
	return err
}

func (d *Database) GetAllFolders() ([]models.Folder, error) {
	folders := []models.Folder{}
	rows, err := d.db.Query(`SELECT id, name FROM ` + FOLDER_TABLE)
	if err != nil {
		return folders, err
	}
	defer rows.Close()

	for rows.Next() {
		f := models.Folder{}
		if err = rows.Scan(&f.Id, &f.Name); err != nil {
			return folders, err
		}
		folders = append(folders, f)
	}

	return folders, err
}

func (d *Database) GetAllFeeds() ([]models.Feed, error) {
	feeds := []models.Feed{}
	rows, err := d.db.Query(`SELECT id, folder, title, description, url FROM ` + FEED_TABLE)
	if err != nil {
		return feeds, err
	}
	defer rows.Close()

	for rows.Next() {
		f := models.Feed{}
		if err = rows.Scan(&f.Id, &f.FolderId, &f.Title, &f.Description, &f.Url); err != nil {
			return feeds, err
		}
		feeds = append(feeds, f)
	}

	return feeds, err
}

func (d *Database) GetFeedsPerFolder() (map[int64]string, error) {
	agg := map[int64][]string{}
	resp := map[int64]string{}

	// CockroachDB doesn't have a concat-with-separator aggregation function
	rows, err := d.db.Query(`SELECT folder, id FROM ` + FEED_TABLE)
	if err != nil {
		return resp, err
	}
	defer rows.Close()

	var folderId, feed_id int64
	for rows.Next() {
		if err = rows.Scan(&folderId, &feed_id); err != nil {
			return resp, err
		}
		agg[folderId] = append(agg[folderId], strconv.FormatInt(feed_id, 10))
	}

	for k, v := range agg {
		resp[k] = strings.Join(v, ",")
	}
	return resp, err
}

func (d *Database) GetAllFavicons() (map[int64]string, error) {
	favicons := map[int64]string{}
	rows, err := d.db.Query(
		`SELECT id, mime, favicon FROM ` + FEED_TABLE + ` WHERE favicon IS NOT NULL`)
	if err != nil {
		return favicons, err
	}
	defer rows.Close()

	var id int64
	var mime string
	var favicon string
	for rows.Next() {
		if err = rows.Scan(&id, &mime, &favicon); err != nil {
			return favicons, err
		}
		favicons[id] = fmt.Sprintf("%s;base64,%s", mime, favicon)
	}
	return favicons, err
}

func (d *Database) GetUnreadArticles(limit int, since_id int64) ([]models.Article, error) {
	articles := []models.Article{}
	var rows *sql.Rows
	var err error

	if limit == -1 {
		limit = MAX_FETCHED_ROWS
	}
	if since_id == -1 {
		since_id = 0
	}

	rows, err = d.db.Query(
		`SELECT id, feed, folder, title, summary, content, link, date FROM `+ARTICLE_TABLE+`
		WHERE NOT read AND id > $1 LIMIT $2`, since_id, limit)

	if err != nil {
		return articles, err
	}
	defer rows.Close()

	for rows.Next() {
		a := models.Article{}
		if err = rows.Scan(
			&a.Id, &a.FeedId, &a.FolderId, &a.Title, &a.Summary, &a.Content, &a.Link, &a.Date); err != nil {
			return articles, err
		}
		if err != nil {
			return articles, nil
		}
		articles = append(articles, a)
	}
	return articles, err
}

func (d *Database) ImportOpml(opml *models.Opml) error {
	root := opml.Folders
	var rootId int64
	err := d.db.QueryRow(
		`INSERT INTO `+FOLDER_TABLE+`(name) VALUES($1) RETURNING id`, root.Name).Scan(&rootId)
	if err != nil {
		return err
	}
	root.Id = rootId
	return d.importChildren(root)
}

func (d *Database) importChildren(parent models.Folder) error {
	var err error
	var feedId int64
	var count int
	for _, f := range parent.Feed {
		err := d.db.QueryRow(
			`SELECT COUNT(*) FROM `+FEED_TABLE+` WHERE hash = $1`, f.Hash()).Scan(&count)
		if err != nil {
			return err
		}
		if count > 0 {
			log.Infof("Duplicate feed entry, skipping.")
			continue
		}

		err = d.db.QueryRow(
			`INSERT INTO `+FEED_TABLE+`(folder, hash, title, description, url)
			VALUES($1, $2, $3, $4, $5) RETURNING id`,
			parent.Id, f.Hash(), f.Title, f.Description, f.Url).Scan(&feedId)
		if err != nil {
			return err
		}
		f.Id = feedId
		f.FolderId = parent.Id
	}

	var childId int64
	for _, child := range parent.Folders {
		err = d.db.QueryRow(
			`INSERT INTO `+FOLDER_TABLE+`(name) VALUES($1) RETURNING id`, child.Name).Scan(&childId)
		if err != nil {
			return err
		}
		child.Id = childId
		_, err = d.db.Query(
			`INSERT INTO `+FOLDER_CHILDREN_TABLE+`(parent, child) VALUES($1, $2)`, parent.Id, child.Id)
		if err != nil {
			return err
		}
		if err = d.importChildren(child); err != nil {
			return err
		}
	}
	return err
}
<commit_msg>Remove unneeded and incorrect error handling in fetching articles.<commit_after>package storage

import (
	"database/sql"
	"encoding/base64"
	"errors"
	"fmt"
	log "github.com/golang/glog"
	"github.com/jrupac/goliath/models"
	_ "github.com/lib/pq"
	"strconv"
	"strings"
)

const (
	DIALECT               = "postgres"
	FOLDER_TABLE          = "Folder"
	FOLDER_CHILDREN_TABLE = "FolderChildren"
	FEED_TABLE            = "Feed"
	ARTICLE_TABLE         = "Article"
	MAX_FETCHED_ROWS      = 10000
)

type Database struct {
	db *sql.DB
}

func Open(dbPath string) (*Database, error) {
	db := new(Database)

	d, err := sql.Open(DIALECT, dbPath)
	if err != nil {
		return nil, err
	}

	db.db = d
	return db, nil
}

func (d *Database) Close() error {
	return d.db.Close()
}

func (d *Database) InsertArticle(a models.Article) error {
	var articleId int64
	var count int
	err := d.db.QueryRow(
		`SELECT COUNT(*) FROM `+ARTICLE_TABLE+` WHERE hash = $1`, a.Hash()).Scan(&count)
	if err != nil {
		return err
	}
	if count > 0 {
		log.Infof("Duplicate article entry, skipping.")
		return nil
	}

	err = d.db.QueryRow(
		`INSERT INTO `+ARTICLE_TABLE+`
		(feed, folder, hash, title, summary, content, link, date, read)
		VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id`,
		a.FeedId, a.FolderId, a.Hash(), a.Title, a.Summary, a.Content, a.Link, a.Date, a.Read).Scan(&articleId)
	if err != nil {
		return err
	}
	a.Id = articleId
	return nil
}

func (d *Database) InsertFavicon(feedId int64, mime string, img []byte) error {
	var count int
	err := d.db.QueryRow(
		`SELECT COUNT(*) FROM `+FEED_TABLE+` WHERE id = $1`, feedId).Scan(&count)
	if err != nil {
		return err
	}
	if count == 0 {
		return errors.New(fmt.Sprintf("Original feed not in table: %d", feedId))
	}

	// Convert to a base64 encoded string before inserting
	h := base64.StdEncoding.EncodeToString(img)

	_, err = d.db.Query(
		`UPDATE `+FEED_TABLE+` SET favicon = $1, mime = $2 WHERE id = $3`,
		h, mime, feedId)
	return err
}

func (d *Database) MarkArticle(id int64, status string) error {
	var state bool
	switch status {
	case "saved", "unsaved":
		// Perhaps add support for saving articles in the future.
		return nil
	case "read":
		state = true
	case "unread":
		state = false
	}

	_, err := d.db.Query(`UPDATE `+ARTICLE_TABLE+` SET read = $1 WHERE id = $2`, state, id)
	return err
}

func (d *Database) MarkFeed(id int64, status string) error {
	var state bool
	switch status {
	case "saved", "unsaved":
		// Perhaps add support for saving articles in the future.
		return nil
	case "read":
		state = true
	case "unread":
		state = false
	}

	_, err := d.db.Query(`UPDATE `+ARTICLE_TABLE+` SET read = $1 WHERE feed = $2`, state, id)
	return err
}

func (d *Database) MarkFolder(id int64, status string) error {
	var state bool
	switch status {
	case "saved", "unsaved":
		// Perhaps add support for saving articles in the future.
		return nil
	case "read":
		state = true
	case "unread":
		state = false
	}

	_, err := d.db.Query(`UPDATE `+ARTICLE_TABLE+` SET read = $1 WHERE folder = $2`, state, id)
	return err
}

func (d *Database) GetAllFolders() ([]models.Folder, error) {
	folders := []models.Folder{}
	rows, err := d.db.Query(`SELECT id, name FROM ` + FOLDER_TABLE)
	if err != nil {
		return folders, err
	}
	defer rows.Close()

	for rows.Next() {
		f := models.Folder{}
		if err = rows.Scan(&f.Id, &f.Name); err != nil {
			return folders, err
		}
		folders = append(folders, f)
	}

	return folders, err
}

func (d *Database) GetAllFeeds() ([]models.Feed, error) {
	feeds := []models.Feed{}
	rows, err := d.db.Query(`SELECT id, folder, title, description, url FROM ` + FEED_TABLE)
	if err != nil {
		return feeds, err
	}
	defer rows.Close()

	for rows.Next() {
		f := models.Feed{}
		if err = rows.Scan(&f.Id, &f.FolderId, &f.Title, &f.Description, &f.Url); err != nil {
			return feeds, err
		}
		feeds = append(feeds, f)
	}

	return feeds, err
}

func (d *Database) GetFeedsPerFolder() (map[int64]string, error) {
	agg := map[int64][]string{}
	resp := map[int64]string{}

	// CockroachDB doesn't have a concat-with-separator aggregation function
	rows, err := d.db.Query(`SELECT folder, id FROM ` + FEED_TABLE)
	if err != nil {
		return resp, err
	}
	defer rows.Close()

	var folderId, feed_id int64
	for rows.Next() {
		if err = rows.Scan(&folderId, &feed_id); err != nil {
			return resp, err
		}
		agg[folderId] = append(agg[folderId], strconv.FormatInt(feed_id, 10))
	}

	for k, v := range agg {
		resp[k] = strings.Join(v, ",")
	}
	return resp, err
}

func (d *Database) GetAllFavicons() (map[int64]string, error) {
	favicons := map[int64]string{}
	rows, err := d.db.Query(
		`SELECT id, mime, favicon FROM ` + FEED_TABLE + ` WHERE favicon IS NOT NULL`)
	if err != nil {
		return favicons, err
	}
	defer rows.Close()

	var id int64
	var mime string
	var favicon string
	for rows.Next() {
		if err = rows.Scan(&id, &mime, &favicon); err != nil {
			return favicons, err
		}
		favicons[id] = fmt.Sprintf("%s;base64,%s", mime, favicon)
	}
	return favicons, err
}

func (d *Database) GetUnreadArticles(limit int, since_id int64) ([]models.Article, error) {
	articles := []models.Article{}
	var rows *sql.Rows
	var err error

	if limit == -1 {
		limit = MAX_FETCHED_ROWS
	}
	if since_id == -1 {
		since_id = 0
	}

	rows, err = d.db.Query(
		`SELECT id, feed, folder, title, summary, content, link, date FROM `+ARTICLE_TABLE+`
		WHERE NOT read AND id > $1 LIMIT $2`, since_id, limit)

	if err != nil {
		return articles, err
	}
	defer rows.Close()

	for rows.Next() {
		a := models.Article{}
		if err = rows.Scan(
			&a.Id, &a.FeedId, &a.FolderId, &a.Title, &a.Summary, &a.Content, &a.Link, &a.Date); err != nil {
			return articles, err
		}
		articles = append(articles, a)
	}
	return articles, err
}

func (d *Database) ImportOpml(opml *models.Opml) error {
	root := opml.Folders
	var rootId int64
	err := d.db.QueryRow(
		`INSERT INTO `+FOLDER_TABLE+`(name) VALUES($1) RETURNING id`, root.Name).Scan(&rootId)
	if err != nil {
		return err
	}
	root.Id = rootId
	return d.importChildren(root)
}

func (d *Database) importChildren(parent models.Folder) error {
	var err error
	var feedId int64
	var count int
	for _, f := range parent.Feed {
		err := d.db.QueryRow(
			`SELECT COUNT(*) FROM `+FEED_TABLE+` WHERE hash = $1`, f.Hash()).Scan(&count)
		if err != nil {
			return err
		}
		if count > 0 {
			log.Infof("Duplicate feed entry, skipping.")
			continue
		}

		err = d.db.QueryRow(
			`INSERT INTO `+FEED_TABLE+`(folder, hash, title, description, url)
			VALUES($1, $2, $3, $4, $5) RETURNING id`,
			parent.Id, f.Hash(), f.Title, f.Description, f.Url).Scan(&feedId)
		if err != nil {
			return err
		}
		f.Id = feedId
		f.FolderId = parent.Id
	}

	var childId int64
	for _, child := range parent.Folders {
		err = d.db.QueryRow(
			`INSERT INTO `+FOLDER_TABLE+`(name) VALUES($1) RETURNING id`, child.Name).Scan(&childId)
		if err != nil {
			return err
		}
		child.Id = childId
		_, err = d.db.Query(
			`INSERT INTO `+FOLDER_CHILDREN_TABLE+`(parent, child) VALUES($1, $2)`, parent.Id, child.Id)
		if err != nil {
			return err
		}
		if err = d.importChildren(child); err != nil {
			return err
		}
	}
	return err
}
<|endoftext|>


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

package geddit

import (
	"fmt"
)

// Submission represents an individual post from the perspective
// of a subreddit. Remember to check for nil pointers before
// using any pointer fields.
type Submission struct {
	Author       string  `json:"author"`
	Title        string  `json:"title"`
	URL          string  `json:"url"`
	Domain       string  `json:"domain"`
	Subreddit    string  `json:"subreddit"`
	SubredditID  string  `json:"subreddit_id"`
	FullID       string  `json:"name"`
	ID           string  `json:"id"`
	Permalink    string  `json:"permalink"`
	Selftext     string  `json:"selftext"`
	ThumbnailURL string  `json:"thumbnail"`
	DateCreated  float32 `json:"created_utc"`
	NumComments  int     `json:"num_comments"`
	Score        int     `json:"score"`
	Ups          int     `json:"ups"`
	Downs        int     `json:"downs"`
	IsNSFW       bool    `json:"over_18"`
	IsSelf       bool    `json:"is_self"`
	WasClicked   bool    `json:"clicked"`
	IsSaved      bool    `json:"saved"`
	BannedBy     *string `json:"banned_by"`
}

func (h Submission) voteID() string   { return h.FullID }
func (h Submission) deleteID() string { return h.FullID }
func (h Submission) replyID() string  { return h.FullID }

// FullPermalink returns the full URL of a submission.
func (h *Submission) FullPermalink() string {
	return "http://reddit.com" + h.Permalink
}

// String returns the string representation of a submission.
func (h *Submission) String() string {
	plural := ""
	if h.NumComments != 1 {
		plural = "s"
	}
	comments := fmt.Sprintf("%d comment%s", h.NumComments, plural)
	return fmt.Sprintf("%d - %s (%s)", h.Score, h.Title, comments)
}
<commit_msg>Update submission struct<commit_after>// Copyright 2012 Jimmy Zelinskie. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package geddit

import (
	"fmt"
)

// Submission represents an individual post from the perspective
// of a subreddit. Remember to check for nil pointers before
// using any pointer fields.
type Submission struct {
	Author       string  `json:"author"`
	Title        string  `json:"title"`
	URL          string  `json:"url"`
	Domain       string  `json:"domain"`
	Subreddit    string  `json:"subreddit"`
	SubredditID  string  `json:"subreddit_id"`
	FullID       string  `json:"name"`
	ID           string  `json:"id"`
	Permalink    string  `json:"permalink"`
	Selftext     string  `json:"selftext"`
	ThumbnailURL string  `json:"thumbnail"`
	DateCreated  float32 `json:"created_utc"`
	NumComments  int     `json:"num_comments"`
	Score        int     `json:"score"`
	IsNSFW       bool    `json:"over_18"`
	IsSelf       bool    `json:"is_self"`
	WasClicked   bool    `json:"clicked"`
	IsSaved      bool    `json:"saved"`
	IsSticky     bool    `json:"stickied"`
	BannedBy     *string `json:"banned_by"`
}

func (h Submission) voteID() string   { return h.FullID }
func (h Submission) deleteID() string { return h.FullID }
func (h Submission) replyID() string  { return h.FullID }

// FullPermalink returns the full URL of a submission.
func (h *Submission) FullPermalink() string {
	return "http://reddit.com" + h.Permalink
}

// String returns the string representation of a submission.
func (h *Submission) String() string {
	plural := ""
	if h.NumComments != 1 {
		plural = "s"
	}
	comments := fmt.Sprintf("%d comment%s", h.NumComments, plural)
	return fmt.Sprintf("%d - %s (%s)", h.Score, h.Title, comments)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"runtime/pprof"
	"strconv"
	"strings"
	"sync"
	"time"
)

//Ride - basic struct for Mobile controller responce
type Ride struct {
	ID        uint        `json:"id"`
	Number    string      `json:"number"`
	Duration  uint        `json:"duration"`
	Distance  float32     `json:"distance"`
	FactRides []FactRides `json:"fact_rides"`
}

// FactRides - struct for json unmarshal FactRides in responce
type FactRides struct {
	ID         uint        `json:"id"`
	TimeStart  string      `json:"time_start"`
	RidePoints []RidePoint `json:"ride_points"`
}

// RidePoint - struct for json unmarshal RidePoint in responce
type RidePoint struct {
	ID          uint    `json:"id"`
	Number      uint    `json:"number"`
	Lat         float32 `json:"lat"`
	Lng         float32 `json:"lng"`
	AddressText string  `json:"address_text"`
	Status      string  `json:"status"`
	Kind        string  `json:"kind"`
	Order       Order   `json:"order"`
}

// Order - struct for json unmarshal Order in responce
type Order struct {
	ID            uint          `json:"id"`
	Status        string        `json:"status"`
	ServiceType   string        `json:"service_type"`
	ServiceObject ServiceObject `json:"service_object"`
}

// ServiceObject - struct for json unmarshal ServiceObject in responce
type ServiceObject struct {
	ID      uint   `json:"id"`
	Name    string `json:"name"`
	ObjType string `json:"type"`
	TimeT   string `json:"time_t"`
	Phones  string `json:"phones"`
	TimeG1  string `json:"time_g1"`
	TimeG2  string `json:"time_g2"`
}

// Authtokens stores json represent array of tokens
type Authtokens struct {
	Tokens []string `json:"tokens"`
}

// HiveConfig gather all of needed configs
type HiveConfig struct {
	ServerEndpoint string `json:"endpoint_url"`
	TokensPath     string `json:"token_file_path"`
}

// GetConfigJSON func get full path to config.json and store it in HiveConfig struct
func GetConfigJSON(jsonFile string) (cfg HiveConfig, err error) {
	jsonDoc, err := ioutil.ReadFile(jsonFile)
	if err != nil {
		log.Fatalf("Could not read config file: %s ", err)
		return
	}
	err = json.Unmarshal(jsonDoc, &cfg)
	return cfg, err
}

// TabletClient one unit of hive
type TabletClient struct {
	ID         string
	Token      string
	DeviceID   string
	RespObj    Ride
	Rawresp    string
	StatusCode int
	ch         chan string
}

// GetRide create connect amd get ride for that token
func (t *TabletClient) GetRide(wg *sync.WaitGroup, cfg *HiveConfig) (int, error) {
	defer wg.Done()
	endURL := []string{}
	client := &http.Client{}
	endURL = append(endURL, cfg.ServerEndpoint)
	endURL = append(endURL, string(t.DeviceID))
	url := strings.Join(endURL, "")
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return 0, err
	}
	request.Header.Add("HTTP-AUTH-TOKEN", t.Token)
	responce, err := client.Do(request)
	if err != nil {
		log.Fatal(err)
	}
	jsonData, err := ioutil.ReadAll(responce.Body)
	defer responce.Body.Close()
	if err != nil && err != io.EOF {
		fmt.Println("error reading from responce Body", err)
		return 0, err
	}
	t.StatusCode = responce.StatusCode
	if responce.StatusCode == 404 {
		t.Rawresp = string(jsonData)
		return responce.StatusCode, nil
	} else if responce.StatusCode == 200 {
		var answer Ride
		err = json.Unmarshal([]byte(jsonData), &answer)
		if err != nil {
			fmt.Printf("err: %s  with token : %s when unmarhal this %s  \n", err, t.Token, jsonData)
		}
		t.RespObj, t.Rawresp = answer, string(jsonData)
		return responce.StatusCode, nil
	} else {
		t.Rawresp = string(jsonData)
		return responce.StatusCode, nil
	}
}

func (t *TabletClient) ConsumeRidePoints(wg *sync.WaitGroup, cfg *HiveConfig) (bool, error) {
	fmt.Println(os.Stdout, "We have key: %d in Consume,\n Value: %v \n", t.Token, t.RespObj)
	return false, nil
}

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
var memprofile = flag.String("memprofile", "", "write mem profile to file")

func main() {
	start := time.Now()
	fmt.Fprintf(os.Stdout, "We start at: %v\n", start)
	cfg, err := GetConfigJSON("./config.json")
	if err != nil {
		log.Fatal(err)
	}
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			fmt.Println("Error: ", err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}
	if *memprofile != "" {
		f, err := os.Create(*memprofile)
		if err != nil {
			fmt.Println("Error: ", err)
		}
		pprof.WriteHeapProfile(f)
	}
	var wg sync.WaitGroup
	tokens, err := getTokens(cfg.TokensPath)
	hive := make([]TabletClient, 0, 1000)
	if err != nil {
		fmt.Println("error while read tokens.json", err)
	}
	for k, v := range tokens.Tokens[0:] {
		hive = append(hive, TabletClient{ID: v, Token: v, DeviceID: strconv.Itoa(k + 1)})
	}
	fmt.Printf("we have %d tokens \n", len(hive))
	for k := range hive {
		wg.Add(1)
		go hive[k].GetRide(&wg, &cfg)
	}
	wg.Wait()
	for k, v := range hive {
		if v.StatusCode == 200 {
			wg.Add(1)
			go hive[k].ConsumeRidePoints(&wg, &cfg)
		}
	}
	wg.Wait()
	secs := time.Since(start).Seconds()
	fmt.Printf("we all done with: %.5fs \n", secs)
}

func getTokens(path string) (tokens Authtokens, err error) {
	tokens = Authtokens{}
	content, err := ioutil.ReadFile(path)
	if err != nil {
		fmt.Println("error while open file with tokens", err)
		return tokens, err
	}
	err = json.Unmarshal(content, &tokens)
	return tokens, nil
}

func getChatset(responce *http.Response) string {
	contentType := responce.Header.Get("Content-Type")
	if contentType == "" {
		return "UTF-8"
	}
	idx := strings.Index(contentType, "charset:")
	if idx == -1 {
		return "UTF-8"
	}
	return strings.Trim(contentType[idx:], " ")
}
<commit_msg>move ridePoints for consume in map<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"runtime/pprof"
	"strconv"
	"strings"
	"sync"
	"time"
)

//Ride - basic struct for Mobile controller responce
type Ride struct {
	ID        uint        `json:"id"`
	Number    string      `json:"number"`
	Duration  uint        `json:"duration"`
	Distance  float32     `json:"distance"`
	FactRides []FactRides `json:"fact_rides"`
}

// FactRides - struct for json unmarshal FactRides in responce
type FactRides struct {
	ID         uint        `json:"id"`
	TimeStart  string      `json:"time_start"`
	RidePoints []RidePoint `json:"ride_points"`
}

// RidePoint - struct for json unmarshal RidePoint in responce
type RidePoint struct {
	ID          uint    `json:"id"`
	Number      uint    `json:"number"`
	Lat         float32 `json:"lat"`
	Lng         float32 `json:"lng"`
	AddressText string  `json:"address_text"`
	Status      string  `json:"status"`
	Kind        string  `json:"kind"`
	Order       Order   `json:"order"`
}

// Order - struct for json unmarshal Order in responce
type Order struct {
	ID            uint          `json:"id"`
	Status        string        `json:"status"`
	ServiceType   string        `json:"service_type"`
	ServiceObject ServiceObject `json:"service_object"`
}

// ServiceObject - struct for json unmarshal ServiceObject in responce
type ServiceObject struct {
	ID      uint   `json:"id"`
	Name    string `json:"name"`
	ObjType string `json:"type"`
	TimeT   string `json:"time_t"`
	Phones  string `json:"phones"`
	TimeG1  string `json:"time_g1"`
	TimeG2  string `json:"time_g2"`
}

// Authtokens stores json represent array of tokens
type Authtokens struct {
	Tokens []string `json:"tokens"`
}

// HiveConfig gather all of needed configs
type HiveConfig struct {
	ServerEndpoint string `json:"endpoint_url"`
	TokensPath     string `json:"token_file_path"`
}

// GetConfigJSON func get full path to config.json and store it in HiveConfig struct
func GetConfigJSON(jsonFile string) (cfg HiveConfig, err error) {
	jsonDoc, err := ioutil.ReadFile(jsonFile)
	if err != nil {
		log.Fatalf("Could not read config file: %s ", err)
		return
	}
	err = json.Unmarshal(jsonDoc, &cfg)
	return cfg, err
}

// TabletClient one unit of hive
type TabletClient struct {
	ID         string
	Token      string
	DeviceID   string
	RespObj    Ride
	Rawresp    string
	StatusCode int
	ch         chan string
}

// GetRide create connect amd get ride for that token
func (t *TabletClient) GetRide(wg *sync.WaitGroup, cfg *HiveConfig) (int, error) {
	defer wg.Done()
	endURL := []string{}
	client := &http.Client{}
	endURL = append(endURL, cfg.ServerEndpoint)
	endURL = append(endURL, string(t.DeviceID))
	url := strings.Join(endURL, "")
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return 0, err
	}
	request.Header.Add("HTTP-AUTH-TOKEN", t.Token)
	responce, err := client.Do(request)
	if err != nil {
		log.Fatal(err)
	}
	jsonData, err := ioutil.ReadAll(responce.Body)
	defer responce.Body.Close()
	if err != nil && err != io.EOF {
		fmt.Println("error reading from responce Body", err)
		return 0, err
	}
	t.StatusCode = responce.StatusCode
	if responce.StatusCode == 404 {
		t.Rawresp = string(jsonData)
		return responce.StatusCode, nil
	} else if responce.StatusCode == 200 {
		var answer Ride
		err = json.Unmarshal([]byte(jsonData), &answer)
		if err != nil {
			fmt.Printf("err: %s  with token : %s when unmarhal this %s  \n", err, t.Token, jsonData)
		}
		t.RespObj, t.Rawresp = answer, string(jsonData)
		return responce.StatusCode, nil
	} else {
		t.Rawresp = string(jsonData)
		return responce.StatusCode, nil
	}
}

func (t *TabletClient) ConsumeRidePoints(wg *sync.WaitGroup, cfg *HiveConfig) (bool, error) {
	return false, nil
}

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
var memprofile = flag.String("memprofile", "", "write mem profile to file")

func main() {
	start := time.Now()
	fmt.Fprintf(os.Stdout, "We start at: %v\n", start)
	cfg, err := GetConfigJSON("./config.json")
	if err != nil {
		log.Fatal(err)
	}
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			fmt.Println("Error: ", err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}
	if *memprofile != "" {
		f, err := os.Create(*memprofile)
		if err != nil {
			fmt.Println("Error: ", err)
		}
		pprof.WriteHeapProfile(f)
	}
	var wg sync.WaitGroup
	tokens, err := getTokens(cfg.TokensPath)
	hive := make([]TabletClient, 0, 1000)
	if err != nil {
		fmt.Println("error while read tokens.json", err)
	}
	for k, v := range tokens.Tokens[0:] {
		hive = append(hive, TabletClient{ID: v, Token: v, DeviceID: strconv.Itoa(k + 1)})
	}
	fmt.Printf("we have %d tokens \n", len(hive))
	for k := range hive {
		wg.Add(1)
		go hive[k].GetRide(&wg, &cfg)
	}
	wg.Wait()
	ridePoints := make(map[string][]RidePoint)
	for _, tablerClient := range hive {
		for _, factRides := range tablerClient.RespObj.FactRides {
			if len(factRides.RidePoints) != 0 {
				ridePoints[tablerClient.DeviceID] = factRides.RidePoints
			}
		}
	}
	wg.Wait()
	secs := time.Since(start).Seconds()
	fmt.Printf("we all done with: %.5fs \n", secs)
}

func getTokens(path string) (tokens Authtokens, err error) {
	tokens = Authtokens{}
	content, err := ioutil.ReadFile(path)
	if err != nil {
		fmt.Println("error while open file with tokens", err)
		return tokens, err
	}
	err = json.Unmarshal(content, &tokens)
	return tokens, nil
}

func getChatset(responce *http.Response) string {
	contentType := responce.Header.Get("Content-Type")
	if contentType == "" {
		return "UTF-8"
	}
	idx := strings.Index(contentType, "charset:")
	if idx == -1 {
		return "UTF-8"
	}
	return strings.Trim(contentType[idx:], " ")
}
<|endoftext|>


<commit_before>package target

import (
	"fmt"
	"io"
	"net"
	"os"
	"strconv"
	"strings"

	"golang.org/x/crypto/ssh"
	"golang.org/x/crypto/ssh/agent"
)

// Create a target for provisioning via SSH.
func NewSshTarget(addr string) (target *sshTarget, e error) {
	target = &sshTarget{port: 22, user: "root"}

	hostAndPort := strings.SplitN(addr, ":", 2)
	if len(hostAndPort) == 2 {
		addr = hostAndPort[0]
		target.port, e = strconv.Atoi(hostAndPort[1])
		if e != nil {
			return nil, fmt.Errorf("port must be given as integer, got %q", hostAndPort[1])
		}
	}

	userAndAddress := strings.Split(addr, "@")
	switch len(userAndAddress) {
	case 1:
		target.address = addr
	case 2:
		target.user = userAndAddress[0]
		target.address = userAndAddress[1]
	default:
		return nil, fmt.Errorf("expected target address of the form '<user>@<host>', but was given: %s", addr)
	}

	if target.address == "" {
		e = fmt.Errorf("empty address given for target")
	}

	return target, e
}

type sshTarget struct {
	Password string

	user    string
	port    int
	address string

	client *ssh.Client
}

func (target *sshTarget) User() string {
	return target.user
}

func (target *sshTarget) String() string {
	return fmt.Sprintf("%s@%s:%d", target.user, target.address, target.port)
}

func (target *sshTarget) Command(cmd string) (ExecCommand, error) {
	if target.client == nil {
		var e error
		target.client, e = target.buildClient()
		if e != nil {
			return nil, e
		}
	}
	ses, e := target.client.NewSession()
	if e != nil {
		return nil, e
	}
	return &sshCommand{command: cmd, session: ses}, nil
}

func (target *sshTarget) Reset() (e error) {
	if target.client != nil {
		e = target.client.Close()
		target.client = nil
	}
	return e
}

func (target *sshTarget) buildClient() (*ssh.Client, error) {
	var e error
	config := &ssh.ClientConfig{
		User: target.user,
	}
	if target.Password != "" {
		config.Auth = append(config.Auth, ssh.Password(target.Password))
	} else if sshSocket := os.Getenv("SSH_AUTH_SOCK"); sshSocket != "" {
		if agentConn, e := net.Dial("unix", sshSocket); e == nil {
			config.Auth = append(config.Auth, ssh.PublicKeysCallback(agent.NewClient(agentConn).Signers))
		}
	}
	con, e := ssh.Dial("tcp", fmt.Sprintf("%s:%d", target.address, target.port), config)
	if e != nil {
		return nil, e
	}
	return &ssh.Client{Conn: con}, nil
}

type sshCommand struct {
	command string
	session *ssh.Session
}

func (c *sshCommand) Close() error {
	return c.session.Close()
}

func (c *sshCommand) StdinPipe() (io.WriteCloser, error) {
	return c.session.StdinPipe()
}

func (c *sshCommand) StdoutPipe() (io.Reader, error) {
	return c.session.StdoutPipe()
}

func (c *sshCommand) StderrPipe() (io.Reader, error) {
	return c.session.StderrPipe()
}

func (c *sshCommand) SetStdout(w io.Writer) {
	c.session.Stdout = w
}

func (c *sshCommand) SetStderr(w io.Writer) {
	c.session.Stderr = w
}

func (c *sshCommand) SetStdin(r io.Reader) {
	c.session.Stdin = r
}

func (c *sshCommand) Run() error {
	return c.session.Run(c.command)
}

func (c *sshCommand) Wait() error {
	return c.session.Wait()
}

func (c *sshCommand) Start() error {
	return c.session.Start(c.command)
}
<commit_msg>only print IP for ssh target<commit_after>package target

import (
	"fmt"
	"io"
	"net"
	"os"
	"strconv"
	"strings"

	"golang.org/x/crypto/ssh"
	"golang.org/x/crypto/ssh/agent"
)

// Create a target for provisioning via SSH.
func NewSshTarget(addr string) (target *sshTarget, e error) {
	target = &sshTarget{port: 22, user: "root"}

	hostAndPort := strings.SplitN(addr, ":", 2)
	if len(hostAndPort) == 2 {
		addr = hostAndPort[0]
		target.port, e = strconv.Atoi(hostAndPort[1])
		if e != nil {
			return nil, fmt.Errorf("port must be given as integer, got %q", hostAndPort[1])
		}
	}

	userAndAddress := strings.Split(addr, "@")
	switch len(userAndAddress) {
	case 1:
		target.address = addr
	case 2:
		target.user = userAndAddress[0]
		target.address = userAndAddress[1]
	default:
		return nil, fmt.Errorf("expected target address of the form '<user>@<host>', but was given: %s", addr)
	}

	if target.address == "" {
		e = fmt.Errorf("empty address given for target")
	}

	return target, e
}

type sshTarget struct {
	Password string

	user    string
	port    int
	address string

	client *ssh.Client
}

func (target *sshTarget) User() string {
	return target.user
}

func (target *sshTarget) String() string {
	return target.address
}

func (target *sshTarget) Command(cmd string) (ExecCommand, error) {
	if target.client == nil {
		var e error
		target.client, e = target.buildClient()
		if e != nil {
			return nil, e
		}
	}
	ses, e := target.client.NewSession()
	if e != nil {
		return nil, e
	}
	return &sshCommand{command: cmd, session: ses}, nil
}

func (target *sshTarget) Reset() (e error) {
	if target.client != nil {
		e = target.client.Close()
		target.client = nil
	}
	return e
}

func (target *sshTarget) buildClient() (*ssh.Client, error) {
	var e error
	config := &ssh.ClientConfig{
		User: target.user,
	}
	if target.Password != "" {
		config.Auth = append(config.Auth, ssh.Password(target.Password))
	} else if sshSocket := os.Getenv("SSH_AUTH_SOCK"); sshSocket != "" {
		if agentConn, e := net.Dial("unix", sshSocket); e == nil {
			config.Auth = append(config.Auth, ssh.PublicKeysCallback(agent.NewClient(agentConn).Signers))
		}
	}
	con, e := ssh.Dial("tcp", fmt.Sprintf("%s:%d", target.address, target.port), config)
	if e != nil {
		return nil, e
	}
	return &ssh.Client{Conn: con}, nil
}

type sshCommand struct {
	command string
	session *ssh.Session
}

func (c *sshCommand) Close() error {
	return c.session.Close()
}

func (c *sshCommand) StdinPipe() (io.WriteCloser, error) {
	return c.session.StdinPipe()
}

func (c *sshCommand) StdoutPipe() (io.Reader, error) {
	return c.session.StdoutPipe()
}

func (c *sshCommand) StderrPipe() (io.Reader, error) {
	return c.session.StderrPipe()
}

func (c *sshCommand) SetStdout(w io.Writer) {
	c.session.Stdout = w
}

func (c *sshCommand) SetStderr(w io.Writer) {
	c.session.Stderr = w
}

func (c *sshCommand) SetStdin(r io.Reader) {
	c.session.Stdin = r
}

func (c *sshCommand) Run() error {
	return c.session.Run(c.command)
}

func (c *sshCommand) Wait() error {
	return c.session.Wait()
}

func (c *sshCommand) Start() error {
	return c.session.Start(c.command)
}
<|endoftext|>


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

// Package storetest provides the utility functions of config store for
// testing. Shouldn't be imported outside of the test.
package storetest

import (
	"fmt"
	"strings"
	"sync"
	"time"

	multierror "github.com/hashicorp/go-multierror"

	"istio.io/istio/mixer/pkg/config/store"
)

// Memstore is an on-memory store backend. Used only for testing.
type Memstore struct {
	mu    sync.Mutex
	data  map[store.Key]*store.BackEndResource
	wch   chan store.BackendEvent
	donec chan struct{}
}

// NewMemstore creates a new Memstore instance.
func NewMemstore() *Memstore {
	return &Memstore{data: map[store.Key]*store.BackEndResource{}, donec: make(chan struct{})}
}

// Stop implements store.Backend interface.
func (m *Memstore) Stop() {
	close(m.donec)
}

// Init implements store.Backend interface.
func (m *Memstore) Init(kinds []string) error {
	return nil
}

// WaitForSynced implements store.Backend interface
func (m *Memstore) WaitForSynced(time.Duration) error {
	return nil
}

// Watch implements store.Backend interface.
func (m *Memstore) Watch() (<-chan store.BackendEvent, error) {
	// Watch is not supported in the memstore, but sometimes it needs to be invoked.
	c := make(chan store.BackendEvent)
	go func() {
		<-m.donec
		close(c)
	}()
	m.mu.Lock()
	defer m.mu.Unlock()
	m.wch = c
	return c, nil
}

// Get implements store.Backend interface.
func (m *Memstore) Get(key store.Key) (*store.BackEndResource, error) {
	m.mu.Lock()
	defer m.mu.Unlock()
	r, ok := m.data[key]
	if !ok {
		return nil, store.ErrNotFound
	}
	return r, nil
}

// List implements store.Backend interface.
func (m *Memstore) List() map[store.Key]*store.BackEndResource {
	return m.data
}

// Put adds a new resource to the memstore.
func (m *Memstore) Put(r *store.BackEndResource) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.data[r.Key()] = r
	if m.wch != nil {
		m.wch <- store.BackendEvent{Type: store.Update, Key: r.Key(), Value: r}
	}
}

// Delete removes a resource for the specified key from the memstore.
func (m *Memstore) Delete(k store.Key) {
	m.mu.Lock()
	defer m.mu.Unlock()
	delete(m.data, k)
	if m.wch != nil {
		m.wch <- store.BackendEvent{Type: store.Delete, Key: k}
	}
}

// SetupStoreForTest creates an on-memory store backend, initializes its
// data with the specified specs, and returns a new store with the backend.
// Note that this store can't change, Watch does not emit any events.
func SetupStoreForTest(data ...string) (store.Store, error) {
	m := &Memstore{data: map[store.Key]*store.BackEndResource{}, donec: make(chan struct{})}
	var errs error
	for i, d := range data {
		for j, chunk := range strings.Split(d, "\n---\n") {
			chunk = strings.TrimSpace(chunk)
			if len(chunk) == 0 {
				continue
			}
			r, err := store.ParseChunk([]byte(chunk))
			if err != nil {
				errs = multierror.Append(errs, fmt.Errorf("failed to parse at %d/%d: %v", i, j, err))
				continue
			}
			if r == nil {
				continue
			}
			m.data[r.Key()] = r
		}
	}

	if errs != nil {
		return nil, errs
	}
	return store.WithBackend(m), nil
}
<commit_msg>reused dead NewMemstore() function (#8680)<commit_after>// Copyright 2018 Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package storetest provides the utility functions of config store for
// testing. Shouldn't be imported outside of the test.
package storetest

import (
	"fmt"
	"strings"
	"sync"
	"time"

	multierror "github.com/hashicorp/go-multierror"

	"istio.io/istio/mixer/pkg/config/store"
)

// Memstore is an on-memory store backend. Used only for testing.
type Memstore struct {
	mu    sync.Mutex
	data  map[store.Key]*store.BackEndResource
	wch   chan store.BackendEvent
	donec chan struct{}
}

// NewMemstore creates a new Memstore instance.
func NewMemstore() *Memstore {
	return &Memstore{data: map[store.Key]*store.BackEndResource{}, donec: make(chan struct{})}
}

// Stop implements store.Backend interface.
func (m *Memstore) Stop() {
	close(m.donec)
}

// Init implements store.Backend interface.
func (m *Memstore) Init(kinds []string) error {
	return nil
}

// WaitForSynced implements store.Backend interface
func (m *Memstore) WaitForSynced(time.Duration) error {
	return nil
}

// Watch implements store.Backend interface.
func (m *Memstore) Watch() (<-chan store.BackendEvent, error) {
	// Watch is not supported in the memstore, but sometimes it needs to be invoked.
	c := make(chan store.BackendEvent)
	go func() {
		<-m.donec
		close(c)
	}()
	m.mu.Lock()
	defer m.mu.Unlock()
	m.wch = c
	return c, nil
}

// Get implements store.Backend interface.
func (m *Memstore) Get(key store.Key) (*store.BackEndResource, error) {
	m.mu.Lock()
	defer m.mu.Unlock()
	r, ok := m.data[key]
	if !ok {
		return nil, store.ErrNotFound
	}
	return r, nil
}

// List implements store.Backend interface.
func (m *Memstore) List() map[store.Key]*store.BackEndResource {
	return m.data
}

// Put adds a new resource to the memstore.
func (m *Memstore) Put(r *store.BackEndResource) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.data[r.Key()] = r
	if m.wch != nil {
		m.wch <- store.BackendEvent{Type: store.Update, Key: r.Key(), Value: r}
	}
}

// Delete removes a resource for the specified key from the memstore.
func (m *Memstore) Delete(k store.Key) {
	m.mu.Lock()
	defer m.mu.Unlock()
	delete(m.data, k)
	if m.wch != nil {
		m.wch <- store.BackendEvent{Type: store.Delete, Key: k}
	}
}

// SetupStoreForTest creates an on-memory store backend, initializes its
// data with the specified specs, and returns a new store with the backend.
// Note that this store can't change, Watch does not emit any events.
func SetupStoreForTest(data ...string) (store.Store, error) {
	m := NewMemstore()
	var errs error
	for i, d := range data {
		for j, chunk := range strings.Split(d, "\n---\n") {
			chunk = strings.TrimSpace(chunk)
			if len(chunk) == 0 {
				continue
			}
			r, err := store.ParseChunk([]byte(chunk))
			if err != nil {
				errs = multierror.Append(errs, fmt.Errorf("failed to parse at %d/%d: %v", i, j, err))
				continue
			}
			if r == nil {
				continue
			}
			m.data[r.Key()] = r
		}
	}

	if errs != nil {
		return nil, errs
	}
	return store.WithBackend(m), nil
}
<|endoftext|>


<commit_before>package docker

import (
	"bytes"
	"github.com/marxarelli/blubber/config"
)

func Compile(cfg *config.Config, variant string) *bytes.Buffer {
	buffer := new(bytes.Buffer)

	vcfg, err := config.ExpandVariant(cfg, variant)

	if err == nil {
		// write multi-stage sections for each artifact dependency
		for _, artifact := range vcfg.Artifacts {
			if artifact.From != "" {
				dependency, err := config.ExpandVariant(cfg, artifact.From)

				if err == nil {
					CompileStage(buffer, artifact.From, dependency)
				}
			}
		}

		CompileStage(buffer, variant, vcfg)
	}

	return buffer
}

func CompileStage(buffer *bytes.Buffer, stage string, vcfg *config.VariantConfig) {
	Writeln(buffer, "FROM ", vcfg.Base, " AS ", stage)

	Writeln(buffer, "USER root")
	Writeln(buffer, "WORKDIR /srv")
	CompileToCommands(buffer, vcfg.Apt)
	CompileToCommands(buffer, vcfg.Run)

	if vcfg.Run.As != "" {
		Writeln(buffer, "USER ", vcfg.Run.As)
	}

	if vcfg.Run.In != "" {
		Writeln(buffer, "WORKDIR ", vcfg.Run.In)
	}

	if vcfg.CopiesTree {
		Writeln(buffer, "COPY . .")
	}

	CompileToCommands(buffer, vcfg.Npm)

	// Artifact copying
	for _, artifact := range vcfg.Artifacts {
		Write(buffer, "COPY ")

		if artifact.From != "" {
			Write(buffer, "--from=", artifact.From, " ")
		}

		Writeln(buffer, artifact.Source, " ", artifact.Destination)
	}
}

func CompileToCommands(buffer *bytes.Buffer, compileable config.CommandCompileable) {
	for _, command := range compileable.Commands() {
		Writeln(buffer, "RUN ", command)
	}
}

func Write(buffer *bytes.Buffer, strings ...string) {
	for _, str := range strings {
		buffer.WriteString(str)
	}
}

func Writeln(buffer *bytes.Buffer, strings ...string) {
	Write(buffer, strings...)
	buffer.WriteString("\n")
}
<commit_msg>Include entrypoint<commit_after>package docker

import (
	"bytes"
	"strings"
	"github.com/marxarelli/blubber/config"
)

func Compile(cfg *config.Config, variant string) *bytes.Buffer {
	buffer := new(bytes.Buffer)

	vcfg, err := config.ExpandVariant(cfg, variant)

	if err == nil {
		// write multi-stage sections for each artifact dependency
		for _, artifact := range vcfg.Artifacts {
			if artifact.From != "" {
				dependency, err := config.ExpandVariant(cfg, artifact.From)

				if err == nil {
					CompileStage(buffer, artifact.From, dependency)
				}
			}
		}

		CompileStage(buffer, variant, vcfg)
	}

	return buffer
}

func CompileStage(buffer *bytes.Buffer, stage string, vcfg *config.VariantConfig) {
	Writeln(buffer, "FROM ", vcfg.Base, " AS ", stage)

	Writeln(buffer, "USER root")
	Writeln(buffer, "WORKDIR /srv")
	CompileToCommands(buffer, vcfg.Apt)
	CompileToCommands(buffer, vcfg.Run)

	if vcfg.Run.As != "" {
		Writeln(buffer, "USER ", vcfg.Run.As)
	}

	if vcfg.Run.In != "" {
		Writeln(buffer, "WORKDIR ", vcfg.Run.In)
	}

	if vcfg.CopiesTree {
		Writeln(buffer, "COPY . .")
	}

	CompileToCommands(buffer, vcfg.Npm)

	// Artifact copying
	for _, artifact := range vcfg.Artifacts {
		Write(buffer, "COPY ")

		if artifact.From != "" {
			Write(buffer, "--from=", artifact.From, " ")
		}

		Writeln(buffer, artifact.Source, " ", artifact.Destination)
	}

	if len(vcfg.EntryPoint) > 0 {
		Writeln(buffer, "ENTRYPOINT [\"", strings.Join(vcfg.EntryPoint, "\", \""), "\"]")
	}
}

func CompileToCommands(buffer *bytes.Buffer, compileable config.CommandCompileable) {
	for _, command := range compileable.Commands() {
		Writeln(buffer, "RUN ", command)
	}
}

func Write(buffer *bytes.Buffer, strings ...string) {
	for _, str := range strings {
		buffer.WriteString(str)
	}
}

func Writeln(buffer *bytes.Buffer, strings ...string) {
	Write(buffer, strings...)
	buffer.WriteString("\n")
}
<|endoftext|>