<commit_before>package render

import (
	"path/filepath"

	"github.com/cbroglie/mustache"

	"github.com/erik/gruppo/model"
)

// TODO: This should be configured somehow
const (
	templateDir string = "./templates"
)

type Context struct {
	Title string
	Post  model.PostData
}

func Render(page string, theme string, ctx *Context) (string, error) {
	mustache.AllowMissingVariables = false

	p := &mustache.FileProvider{
		Paths:      []string{filepath.Join(templateDir, theme)},
		Extensions: []string{"", ".html.tmpl", ".tmpl"},
	}

	f := filepath.Join(templateDir, theme, page+".html.tmpl")
	tmpl, err := mustache.ParseFilePartials(f, p)

	if err != nil {
		return "", err
	}

	return tmpl.Render(ctx)
}
<commit_msg>Fix missed rename<commit_after>package render

import (
	"path/filepath"

	"github.com/cbroglie/mustache"

	"github.com/erik/gruppo/model"
)

// TODO: This should be configured somehow
const (
	templateDir string = "./templates"
)

type Context struct {
	Title string
	Post  model.Post
}

func Render(page string, theme string, ctx *Context) (string, error) {
	mustache.AllowMissingVariables = false

	p := &mustache.FileProvider{
		Paths:      []string{filepath.Join(templateDir, theme)},
		Extensions: []string{"", ".html.tmpl", ".tmpl"},
	}

	f := filepath.Join(templateDir, theme, page+".html.tmpl")
	tmpl, err := mustache.ParseFilePartials(f, p)

	if err != nil {
		return "", err
	}

	return tmpl.Render(ctx)
}
<|endoftext|>


<commit_before>// Copyright 2016 Mender Software AS
//
//    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 main

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
)

// error messages
var (
	ErrLoggerNotInitialized = errors.New("logger not initialized")
)

type FileLogger struct {
	logFileName string
	logFile     io.WriteCloser
}

// NewFileLogger creates instance of file logger; it is initialized
// just before logging is started
func NewFileLogger(name string) *FileLogger {
	// open log file
	logFile, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
	if err != nil {
		// if we can not open file for logging; return nil
		return nil
	}

	// return FileLogger only when logging is possible (we can open log file)
	return &FileLogger{
		logFileName: name,
		logFile:     logFile,
	}
}

func (fl *FileLogger) Write(log []byte) (int, error) {
	return fl.logFile.Write(log)
}

func (fl *FileLogger) Deinit() error {
	return fl.logFile.Close()
}

type DeploymentLogManager struct {
	logLocation  string
	deploymentID string
	logger       *FileLogger
	// how many log files we are keeping in log directory before rotating
	maxLogFiles int
	// it is easy to add logging hook, but not so much remove it;
	// we need a mechanism for emabling and disabling logging
	loggingEnabled bool
}

const baseLogFileName = "deployments"
const logFileNameScheme = baseLogFileName + ".%04d.%s.log"

func NewDeploymentLogManager(logDirLocation string) *DeploymentLogManager {
	return &DeploymentLogManager{
		logLocation: logDirLocation,
		// file logger needs to be instanciated just before writing logs
		//logger:
		// for now we can hardcode this
		maxLogFiles:    5,
		loggingEnabled: false,
	}
}

func (dlm DeploymentLogManager) WriteLog(log []byte) error {
	if dlm.logger == nil {
		return ErrLoggerNotInitialized
	}
	_, err := dlm.logger.Write(log)
	return err
}

func (dlm *DeploymentLogManager) Enable(deploymentID string) error {
	if dlm.loggingEnabled {
		return nil
	}

	dlm.deploymentID = deploymentID

	// we might have new deployment so might need to rotate files
	dlm.Rotate()

	// instanciate logger
	logFileName := fmt.Sprintf(logFileNameScheme, 1, deploymentID)
	dlm.logger = NewFileLogger(filepath.Join(dlm.logLocation, logFileName))
	if dlm.logger == nil {
		return ErrLoggerNotInitialized
	}

	dlm.loggingEnabled = true
	return nil
}

func (dlm *DeploymentLogManager) Disable() error {
	if !dlm.loggingEnabled {
		return nil
	}

	if err := dlm.logger.Deinit(); err != nil {
		return err
	}

	dlm.loggingEnabled = false
	return nil
}

func (dlm DeploymentLogManager) getSortedLogFiles() ([]string, error) {

	// list all the log files in log directory
	logFiles, err :=
		filepath.Glob(filepath.Join(dlm.logLocation, baseLogFileName+".*"))
	if err != nil {
		return nil, err
	}

	sort.Sort(sort.Reverse(sort.StringSlice(logFiles)))
	return logFiles, nil
}

//log naming convention: <base_name>.%04d.<deployment_id>.log
func (dlm DeploymentLogManager) rotateLogFileName(name string) string {
	logFileName := filepath.Base(name)
	nameChunks := strings.Split(logFileName, ".")

	if len(nameChunks) != 4 {
		// we have malformed file name or file is not a log file
		return name
	}
	seq, err := strconv.Atoi(nameChunks[1])
	if err == nil {
		// IDEA: this will allow handling 9999 log files correctly
		// for more we need to change implementation of getSortedLogFiles()
		return fmt.Sprintf(logFileNameScheme, (seq + 1), nameChunks[2])
	}
	return name
}

func (dlm DeploymentLogManager) Rotate() {
	logFiles, err := dlm.getSortedLogFiles()
	if err != nil {
		// can not rotate
		return
	}

	// check if we need to delete oldest file
	for len(logFiles) > dlm.maxLogFiles {
		os.Remove(logFiles[0])
		logFiles = append(logFiles[1:])
	}

	// rename log files; only those not removed
	for i := range logFiles {
		os.Rename(logFiles[i], dlm.rotateLogFileName(logFiles[i]))
	}
}

func (dlm DeploymentLogManager) findLogsForSpecificID(deploymentID string) (string, error) {
	logFiles, err := dlm.getSortedLogFiles()
	if err != nil {
		return "", err
	}

	// look for the file containing given deployment id
	for _, file := range logFiles {
		if strings.Contains(file, deploymentID) {
			return file, nil
		}
	}
	return "", nil
}

func (dlm DeploymentLogManager) GetLogs(deploymentID string) ([]byte, error) {
	logFileName, err := dlm.findLogsForSpecificID(deploymentID)
	if err != nil {
		return nil, err
	}

	logF, err := os.Open(logFileName)
	if err != nil {
		return nil, err
	}

	logs, err := ioutil.ReadAll(logF)
	if err != nil {
		return nil, err
	}
	return logs, nil
}
<commit_msg>Make sure deployments logs are validated and returned as JSON string.<commit_after>// Copyright 2016 Mender Software AS
//
//    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 main

import (
	"bufio"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
)

// error messages
var (
	ErrLoggerNotInitialized = errors.New("logger not initialized")
)

type FileLogger struct {
	logFileName string
	logFile     io.WriteCloser
}

// NewFileLogger creates instance of file logger; it is initialized
// just before logging is started
func NewFileLogger(name string) *FileLogger {
	// open log file
	logFile, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
	if err != nil {
		// if we can not open file for logging; return nil
		return nil
	}

	// return FileLogger only when logging is possible (we can open log file)
	return &FileLogger{
		logFileName: name,
		logFile:     logFile,
	}
}

func (fl *FileLogger) Write(log []byte) (int, error) {
	return fl.logFile.Write(log)
}

func (fl *FileLogger) Deinit() error {
	return fl.logFile.Close()
}

type DeploymentLogManager struct {
	logLocation  string
	deploymentID string
	logger       *FileLogger
	// how many log files we are keeping in log directory before rotating
	maxLogFiles int
	// it is easy to add logging hook, but not so much remove it;
	// we need a mechanism for emabling and disabling logging
	loggingEnabled bool
}

const baseLogFileName = "deployments"
const logFileNameScheme = baseLogFileName + ".%04d.%s.log"

func NewDeploymentLogManager(logDirLocation string) *DeploymentLogManager {
	return &DeploymentLogManager{
		logLocation: logDirLocation,
		// file logger needs to be instanciated just before writing logs
		//logger:
		// for now we can hardcode this
		maxLogFiles:    5,
		loggingEnabled: false,
	}
}

func (dlm DeploymentLogManager) WriteLog(log []byte) error {
	if dlm.logger == nil {
		return ErrLoggerNotInitialized
	}
	_, err := dlm.logger.Write(log)
	return err
}

func (dlm *DeploymentLogManager) Enable(deploymentID string) error {
	if dlm.loggingEnabled {
		return nil
	}

	dlm.deploymentID = deploymentID

	// we might have new deployment so might need to rotate files
	dlm.Rotate()

	// instanciate logger
	logFileName := fmt.Sprintf(logFileNameScheme, 1, deploymentID)
	dlm.logger = NewFileLogger(filepath.Join(dlm.logLocation, logFileName))
	if dlm.logger == nil {
		return ErrLoggerNotInitialized
	}

	dlm.loggingEnabled = true
	return nil
}

func (dlm *DeploymentLogManager) Disable() error {
	if !dlm.loggingEnabled {
		return nil
	}

	if err := dlm.logger.Deinit(); err != nil {
		return err
	}

	dlm.loggingEnabled = false
	return nil
}

func (dlm DeploymentLogManager) getSortedLogFiles() ([]string, error) {

	// list all the log files in log directory
	logFiles, err :=
		filepath.Glob(filepath.Join(dlm.logLocation, baseLogFileName+".*"))
	if err != nil {
		return nil, err
	}

	sort.Sort(sort.Reverse(sort.StringSlice(logFiles)))
	return logFiles, nil
}

//log naming convention: <base_name>.%04d.<deployment_id>.log
func (dlm DeploymentLogManager) rotateLogFileName(name string) string {
	logFileName := filepath.Base(name)
	nameChunks := strings.Split(logFileName, ".")

	if len(nameChunks) != 4 {
		// we have malformed file name or file is not a log file
		return name
	}
	seq, err := strconv.Atoi(nameChunks[1])
	if err == nil {
		// IDEA: this will allow handling 9999 log files correctly
		// for more we need to change implementation of getSortedLogFiles()
		return fmt.Sprintf(logFileNameScheme, (seq + 1), nameChunks[2])
	}
	return name
}

func (dlm DeploymentLogManager) Rotate() {
	logFiles, err := dlm.getSortedLogFiles()
	if err != nil {
		// can not rotate
		return
	}

	// check if we need to delete oldest file
	for len(logFiles) > dlm.maxLogFiles {
		os.Remove(logFiles[0])
		logFiles = append(logFiles[1:])
	}

	// rename log files; only those not removed
	for i := range logFiles {
		os.Rename(logFiles[i], dlm.rotateLogFileName(logFiles[i]))
	}
}

func (dlm DeploymentLogManager) findLogsForSpecificID(deploymentID string) (string, error) {
	logFiles, err := dlm.getSortedLogFiles()
	if err != nil {
		return "", err
	}

	// look for the file containing given deployment id
	for _, file := range logFiles {
		if strings.Contains(file, deploymentID) {
			return file, nil
		}
	}
	return "", nil
}

// GetLogs is returnig logs as a JSON string. Function is having the same
// signature as json.Marshal() ([]byte, error)
func (dlm DeploymentLogManager) GetLogs(deploymentID string) ([]byte, error) {
	logFileName, err := dlm.findLogsForSpecificID(deploymentID)
	if err != nil {
		return nil, err
	}

	logF, err := os.Open(logFileName)
	if err != nil {
		return nil, err
	}

	defer logF.Close()

	// read log file line by line
	scanner := bufio.NewScanner(logF)

	var logsList []json.RawMessage
	for scanner.Scan() {
		var logLine json.RawMessage
		err = json.Unmarshal([]byte(scanner.Text()), &logLine)
		if err != nil {
			// we have broken JSON log; just skip it for now
			continue
		}
		// here we should have a list of verified JSON logs
		logsList = append(logsList, logLine)
	}

	if err = scanner.Err(); err != nil {
		return nil, err
	}

	return json.Marshal(logsList)
}
<|endoftext|>


<commit_before>package server

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/siddontang/go/log"
	"github.com/siddontang/go/num"
	"github.com/siddontang/go/sync2"
	goledis "github.com/siddontang/ledisdb/client/go/ledis"
	"github.com/siddontang/ledisdb/ledis"
	"github.com/siddontang/ledisdb/rpl"
	"net"
	"os"
	"path"
	"strings"
	"sync"
	"time"
)

var (
	errConnectMaster = errors.New("connect master error")
	errReplClosed    = errors.New("replication is closed")
)

const (
	// slave needs to connect to its master
	replConnectState int32 = iota + 1
	// slave-master connection is in progress
	replConnectingState
	// perform the synchronization
	replSyncState
	// slave is online
	replConnectedState
)

type master struct {
	sync.Mutex

	conn *goledis.Conn

	app *App

	quit chan struct{}

	addr string

	wg sync.WaitGroup

	syncBuf bytes.Buffer

	state sync2.AtomicInt32
}

func newMaster(app *App) *master {
	m := new(master)
	m.app = app

	m.quit = make(chan struct{}, 1)

	m.state.Set(replConnectState)

	return m
}

func (m *master) Close() {
	m.quit <- struct{}{}

	m.closeConn()

	m.wg.Wait()

	select {
	case <-m.quit:
	default:
	}

	m.state.Set(replConnectState)
}

func (m *master) resetConn() error {
	if len(m.addr) == 0 {
		return fmt.Errorf("no assign master addr")
	}

	if m.conn != nil {
		m.conn.Close()
	}

	m.conn = goledis.NewConn(m.addr)

	return nil
}

func (m *master) closeConn() {
	if m.conn != nil {
		//for replication, we send quit command to close gracefully
		m.conn.Send("quit")

		m.conn.Close()
	}
}

func (m *master) stopReplication() error {
	m.Close()

	return nil
}

func (m *master) startReplication(masterAddr string, restart bool) error {
	//stop last replcation, if avaliable
	m.Close()

	m.addr = masterAddr

	m.app.cfg.SetReadonly(true)

	m.wg.Add(1)
	go m.runReplication(restart)
	return nil
}

func (m *master) runReplication(restart bool) {
	defer func() {
		m.state.Set(replConnectState)
		m.wg.Done()
	}()

	m.state.Set(replConnectingState)
	if err := m.resetConn(); err != nil {
		log.Errorf("reset conn error %s", err.Error())
		return
	}

	for {
		select {
		case <-m.quit:
			return
		default:
			if _, err := m.conn.Do("ping"); err != nil {
				log.Errorf("ping master %s error %s, try 2s later", m.addr, err.Error())
				time.Sleep(2 * time.Second)
				continue
			}
		}

		m.state.Set(replConnectedState)

		if err := m.replConf(); err != nil {
			log.Errorf("replconf error %s", err.Error())
			return
		}

		if restart {
			m.state.Set(replSyncState)
			if err := m.fullSync(); err != nil {
				log.Errorf("restart fullsync error %s", err.Error())
				return
			}
		}

		for {
			select {
			case <-m.quit:
				return
			default:
				m.state.Set(replConnectedState)
				if err := m.sync(); err != nil {
					log.Errorf("sync error %s", err.Error())
					return
				}
			}
		}
	}

	return
}

func (m *master) replConf() error {
	_, port, err := net.SplitHostPort(m.app.cfg.Addr)
	if err != nil {
		return err
	}

	if s, err := goledis.String(m.conn.Do("replconf", "listening-port", port)); err != nil {
		return err
	} else if strings.ToUpper(s) != "OK" {
		return fmt.Errorf("not ok but %s", s)
	}

	return nil
}

func (m *master) fullSync() error {
	log.Info("begin full sync")

	if err := m.conn.Send("fullsync"); err != nil {
		return err
	}

	dumpPath := path.Join(m.app.cfg.DataDir, "master.dump")
	f, err := os.OpenFile(dumpPath, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}

	defer os.Remove(dumpPath)

	err = m.conn.ReceiveBulkTo(f)
	f.Close()
	if err != nil {
		log.Errorf("read dump data error %s", err.Error())
		return err
	}

	if _, err = m.app.ldb.LoadDumpFile(dumpPath); err != nil {
		log.Errorf("load dump file error %s", err.Error())
		return err
	}

	return nil
}

func (m *master) nextSyncLogID() (uint64, error) {
	s, err := m.app.ldb.ReplicationStat()
	if err != nil {
		return 0, err
	}

	if s.LastID > s.CommitID {
		return s.LastID + 1, nil
	} else {
		return s.CommitID + 1, nil
	}
}

func (m *master) sync() error {
	var err error
	var syncID uint64
	if syncID, err = m.nextSyncLogID(); err != nil {
		return err
	}

	if err := m.conn.Send("sync", syncID); err != nil {
		return err
	}

	m.syncBuf.Reset()

	if err = m.conn.ReceiveBulkTo(&m.syncBuf); err != nil {
		switch err.Error() {
		case ledis.ErrLogMissed.Error():
			return m.fullSync()
		case ledis.ErrRplNotSupport.Error():
			m.stopReplication()
			return nil
		default:
			return err
		}
	}

	buf := m.syncBuf.Bytes()

	if len(buf) < 8 {
		return fmt.Errorf("inavlid sync size %d", len(buf))
	}

	m.app.info.Replication.MasterLastLogID.Set(num.BytesToUint64(buf))

	var t bytes.Buffer
	m.app.info.dumpReplication(&t)

	buf = buf[8:]

	if len(buf) == 0 {
		return nil
	}

	m.state.Set(replSyncState)
	if err = m.app.ldb.StoreLogsFromData(buf); err != nil {
		return err
	}

	return nil

}

func (app *App) slaveof(masterAddr string, restart bool, readonly bool) error {
	app.m.Lock()
	defer app.m.Unlock()

	//in master mode and no slaveof, only set readonly
	if len(app.cfg.SlaveOf) == 0 && len(masterAddr) == 0 {
		app.cfg.SetReadonly(readonly)
		return nil
	}

	if !app.ldb.ReplicationUsed() {
		return fmt.Errorf("slaveof must enable replication")
	}

	app.cfg.SlaveOf = masterAddr

	if len(masterAddr) == 0 {
		if err := app.m.stopReplication(); err != nil {
			return err
		}

		app.cfg.SetReadonly(readonly)
	} else {
		return app.m.startReplication(masterAddr, restart)
	}

	return nil
}

func (app *App) tryReSlaveof() error {
	app.m.Lock()
	defer app.m.Unlock()

	if !app.ldb.ReplicationUsed() {
		return nil
	}

	if len(app.cfg.SlaveOf) == 0 {
		return nil
	} else {
		return app.m.startReplication(app.cfg.SlaveOf, true)
	}
}

func (app *App) addSlave(c *client) {
	addr := c.slaveListeningAddr

	app.slock.Lock()
	defer app.slock.Unlock()

	app.slaves[addr] = c
}

func (app *App) removeSlave(c *client, activeQuit bool) {
	addr := c.slaveListeningAddr

	app.slock.Lock()
	defer app.slock.Unlock()

	if _, ok := app.slaves[addr]; ok {
		delete(app.slaves, addr)
		log.Infof("remove slave %s", addr)
		if activeQuit {
			asyncNotifyUint64(app.slaveSyncAck, c.lastLogID.Get())
		}
	}
}

func (app *App) slaveAck(c *client) {
	addr := c.slaveListeningAddr

	app.slock.Lock()
	defer app.slock.Unlock()

	if _, ok := app.slaves[addr]; !ok {
		//slave not add
		return
	}

	asyncNotifyUint64(app.slaveSyncAck, c.lastLogID.Get())
}

func asyncNotifyUint64(ch chan uint64, v uint64) {
	select {
	case ch <- v:
	default:
	}
}

func (app *App) publishNewLog(l *rpl.Log) {
	if !app.cfg.Replication.Sync {
		//no sync replication, we will do async
		return
	}

	app.info.Replication.PubLogNum.Add(1)

	app.slock.Lock()

	slaveNum := len(app.slaves)

	total := (slaveNum + 1) / 2
	if app.cfg.Replication.WaitMaxSlaveAcks > 0 {
		total = num.MinInt(total, app.cfg.Replication.WaitMaxSlaveAcks)
	}

	n := 0
	logId := l.ID
	for _, s := range app.slaves {
		lastLogID := s.lastLogID.Get()
		if lastLogID == logId {
			//slave has already owned this log
			n++
		} else if lastLogID > logId {
			log.Errorf("invalid slave %s, lastlogid %d > %d", s.slaveListeningAddr, lastLogID, logId)
		}
	}

	app.slock.Unlock()

	if n >= total {
		//at least total slaves have owned this log
		return
	}

	startTime := time.Now()
	done := make(chan struct{}, 1)
	go func() {
		n := 0
		for i := 0; i < slaveNum; i++ {
			id := <-app.slaveSyncAck
			if id < logId {
				log.Infof("some slave may close with last logid %d < %d", id, logId)
			} else {
				n++
				if n >= total {
					break
				}
			}
		}
		done <- struct{}{}
	}()

	select {
	case <-done:
	case <-time.After(time.Duration(app.cfg.Replication.WaitSyncTime) * time.Millisecond):
		log.Info("replication wait timeout")
	}

	stopTime := time.Now()
	app.info.Replication.PubLogAckNum.Add(1)
	app.info.Replication.PubLogTotalAckTime.Add(stopTime.Sub(startTime))
}
<commit_msg>slave support reconnecting<commit_after>package server

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/siddontang/go/log"
	"github.com/siddontang/go/num"
	"github.com/siddontang/go/sync2"
	goledis "github.com/siddontang/ledisdb/client/go/ledis"
	"github.com/siddontang/ledisdb/ledis"
	"github.com/siddontang/ledisdb/rpl"
	"net"
	"os"
	"path"
	"strings"
	"sync"
	"time"
)

var (
	errConnectMaster = errors.New("connect master error")
	errReplClosed    = errors.New("replication is closed")
)

const (
	// slave needs to connect to its master
	replConnectState int32 = iota + 1
	// slave-master connection is in progress
	replConnectingState
	// perform the synchronization
	replSyncState
	// slave is online
	replConnectedState
)

type master struct {
	sync.Mutex

	conn *goledis.Conn

	app *App

	quit chan struct{}

	addr string

	wg sync.WaitGroup

	syncBuf bytes.Buffer

	state sync2.AtomicInt32
}

func newMaster(app *App) *master {
	m := new(master)
	m.app = app

	m.quit = make(chan struct{}, 1)

	m.state.Set(replConnectState)

	return m
}

func (m *master) Close() {
	m.quit <- struct{}{}

	m.closeConn()

	m.wg.Wait()

	select {
	case <-m.quit:
	default:
	}

	m.state.Set(replConnectState)
}

func (m *master) resetConn() error {
	if len(m.addr) == 0 {
		return fmt.Errorf("no assign master addr")
	}

	if m.conn != nil {
		m.conn.Close()
	}

	m.conn = goledis.NewConn(m.addr)

	return nil
}

func (m *master) closeConn() {
	if m.conn != nil {
		//for replication, we send quit command to close gracefully
		m.conn.Send("quit")

		m.conn.Close()
	}
}

func (m *master) stopReplication() error {
	m.Close()

	return nil
}

func (m *master) startReplication(masterAddr string, restart bool) error {
	//stop last replcation, if avaliable
	m.Close()

	m.addr = masterAddr

	m.app.cfg.SetReadonly(true)

	m.wg.Add(1)
	go m.runReplication(restart)
	return nil
}

func (m *master) needQuit() bool {
	select {
	case <-m.quit:
		return true
	default:
		return false
	}
}

func (m *master) runReplication(restart bool) {
	defer func() {
		m.state.Set(replConnectState)
		m.wg.Done()
	}()

	if err := m.resetConn(); err != nil {
		log.Errorf("reset conn error %s", err.Error())
		return
	}

	for {
		m.state.Set(replConnectState)

		if _, err := m.conn.Do("ping"); err != nil {
			log.Errorf("ping master %s error %s, try 3s later", m.addr, err.Error())
			time.Sleep(3 * time.Second)
			continue
		}

		if m.needQuit() {
			return
		}

		m.state.Set(replConnectedState)

		if err := m.replConf(); err != nil {
			log.Errorf("replconf error %s", err.Error())
			continue
		}

		if restart {
			if err := m.fullSync(); err != nil {
				log.Errorf("restart fullsync error %s", err.Error())
				continue
			}
			m.state.Set(replConnectedState)
		}

		for {
			if err := m.sync(); err != nil {
				log.Errorf("sync error %s", err.Error())
				break
			}
			m.state.Set(replConnectedState)

			if m.needQuit() {
				return
			}
		}
	}

	return
}

func (m *master) replConf() error {
	_, port, err := net.SplitHostPort(m.app.cfg.Addr)
	if err != nil {
		return err
	}

	if s, err := goledis.String(m.conn.Do("replconf", "listening-port", port)); err != nil {
		return err
	} else if strings.ToUpper(s) != "OK" {
		return fmt.Errorf("not ok but %s", s)
	}

	return nil
}

func (m *master) fullSync() error {
	log.Info("begin full sync")

	if err := m.conn.Send("fullsync"); err != nil {
		return err
	}

	m.state.Set(replSyncState)

	dumpPath := path.Join(m.app.cfg.DataDir, "master.dump")
	f, err := os.OpenFile(dumpPath, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}

	defer os.Remove(dumpPath)

	err = m.conn.ReceiveBulkTo(f)
	f.Close()
	if err != nil {
		log.Errorf("read dump data error %s", err.Error())
		return err
	}

	if _, err = m.app.ldb.LoadDumpFile(dumpPath); err != nil {
		log.Errorf("load dump file error %s", err.Error())
		return err
	}

	return nil
}

func (m *master) nextSyncLogID() (uint64, error) {
	s, err := m.app.ldb.ReplicationStat()
	if err != nil {
		return 0, err
	}

	if s.LastID > s.CommitID {
		return s.LastID + 1, nil
	} else {
		return s.CommitID + 1, nil
	}
}

func (m *master) sync() error {
	var err error
	var syncID uint64
	if syncID, err = m.nextSyncLogID(); err != nil {
		return err
	}

	if err := m.conn.Send("sync", syncID); err != nil {
		return err
	}

	m.state.Set(replSyncState)

	m.syncBuf.Reset()

	if err = m.conn.ReceiveBulkTo(&m.syncBuf); err != nil {
		switch err.Error() {
		case ledis.ErrLogMissed.Error():
			return m.fullSync()
		case ledis.ErrRplNotSupport.Error():
			m.stopReplication()
			return nil
		default:
			return err
		}
	}

	buf := m.syncBuf.Bytes()

	if len(buf) < 8 {
		return fmt.Errorf("inavlid sync size %d", len(buf))
	}

	m.app.info.Replication.MasterLastLogID.Set(num.BytesToUint64(buf))

	var t bytes.Buffer
	m.app.info.dumpReplication(&t)

	buf = buf[8:]

	if len(buf) == 0 {
		return nil
	}

	if err = m.app.ldb.StoreLogsFromData(buf); err != nil {
		return err
	}

	return nil

}

func (app *App) slaveof(masterAddr string, restart bool, readonly bool) error {
	app.m.Lock()
	defer app.m.Unlock()

	//in master mode and no slaveof, only set readonly
	if len(app.cfg.SlaveOf) == 0 && len(masterAddr) == 0 {
		app.cfg.SetReadonly(readonly)
		return nil
	}

	if !app.ldb.ReplicationUsed() {
		return fmt.Errorf("slaveof must enable replication")
	}

	app.cfg.SlaveOf = masterAddr

	if len(masterAddr) == 0 {
		if err := app.m.stopReplication(); err != nil {
			return err
		}

		app.cfg.SetReadonly(readonly)
	} else {
		return app.m.startReplication(masterAddr, restart)
	}

	return nil
}

func (app *App) tryReSlaveof() error {
	app.m.Lock()
	defer app.m.Unlock()

	if !app.ldb.ReplicationUsed() {
		return nil
	}

	if len(app.cfg.SlaveOf) == 0 {
		return nil
	} else {
		return app.m.startReplication(app.cfg.SlaveOf, true)
	}
}

func (app *App) addSlave(c *client) {
	addr := c.slaveListeningAddr

	app.slock.Lock()
	defer app.slock.Unlock()

	app.slaves[addr] = c
}

func (app *App) removeSlave(c *client, activeQuit bool) {
	addr := c.slaveListeningAddr

	app.slock.Lock()
	defer app.slock.Unlock()

	if _, ok := app.slaves[addr]; ok {
		delete(app.slaves, addr)
		log.Infof("remove slave %s", addr)
		if activeQuit {
			asyncNotifyUint64(app.slaveSyncAck, c.lastLogID.Get())
		}
	}
}

func (app *App) slaveAck(c *client) {
	addr := c.slaveListeningAddr

	app.slock.Lock()
	defer app.slock.Unlock()

	if _, ok := app.slaves[addr]; !ok {
		//slave not add
		return
	}

	asyncNotifyUint64(app.slaveSyncAck, c.lastLogID.Get())
}

func asyncNotifyUint64(ch chan uint64, v uint64) {
	select {
	case ch <- v:
	default:
	}
}

func (app *App) publishNewLog(l *rpl.Log) {
	if !app.cfg.Replication.Sync {
		//no sync replication, we will do async
		return
	}

	app.info.Replication.PubLogNum.Add(1)

	app.slock.Lock()

	slaveNum := len(app.slaves)

	total := (slaveNum + 1) / 2
	if app.cfg.Replication.WaitMaxSlaveAcks > 0 {
		total = num.MinInt(total, app.cfg.Replication.WaitMaxSlaveAcks)
	}

	n := 0
	logId := l.ID
	for _, s := range app.slaves {
		lastLogID := s.lastLogID.Get()
		if lastLogID == logId {
			//slave has already owned this log
			n++
		} else if lastLogID > logId {
			log.Errorf("invalid slave %s, lastlogid %d > %d", s.slaveListeningAddr, lastLogID, logId)
		}
	}

	app.slock.Unlock()

	if n >= total {
		//at least total slaves have owned this log
		return
	}

	startTime := time.Now()
	done := make(chan struct{}, 1)
	go func() {
		n := 0
		for i := 0; i < slaveNum; i++ {
			id := <-app.slaveSyncAck
			if id < logId {
				log.Infof("some slave may close with last logid %d < %d", id, logId)
			} else {
				n++
				if n >= total {
					break
				}
			}
		}
		done <- struct{}{}
	}()

	select {
	case <-done:
	case <-time.After(time.Duration(app.cfg.Replication.WaitSyncTime) * time.Millisecond):
		log.Info("replication wait timeout")
	}

	stopTime := time.Now()
	app.info.Replication.PubLogAckNum.Add(1)
	app.info.Replication.PubLogTotalAckTime.Add(stopTime.Sub(startTime))
}
<|endoftext|>


<commit_before><commit_msg>Demonstration of PDF size reduction with ghostscript<commit_after><|endoftext|>


<commit_before>package server

import (
	"net/http"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/adolphlwq/tinyurl/entity"
	"github.com/gin-gonic/gin"
)

// ShortenURL shorten origin url and save to db
func ShortenURL(c *gin.Context, sp *ServiceProvider) {
	originUrl := c.PostForm("origin_url")

	if originUrl == "" {
		c.JSON(http.StatusBadRequest, gin.H{
			"message": "please provide origin_url.",
		})
		return
	}
	// check longurl
	logrus.Infof("check if origin %s has existed in db.\n", originUrl)
	var url entity.URL
	sp.MysqlClient.DB.Where("origin_uel = ?", originUrl).First(&url)
	if url.OriginUrl == "" {
		url.CreateTime = time.Now().UTC()
		url.OriginUrl = originUrl
		url.ShortPath = "not implement"
		c.JSON(http.StatusOK, gin.H{
			"short_path": url.ShortPath,
		})
	} else {
		c.JSON(http.StatusOK, gin.H{
			"short_path": url.ShortPath,
		})
	}
}
<commit_msg>fix typos<commit_after>package server

import (
	"net/http"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/adolphlwq/tinyurl/entity"
	"github.com/gin-gonic/gin"
)

// ShortenURL shorten origin url and save to db
func ShortenURL(c *gin.Context, sp *ServiceProvider) {
	originUrl := c.PostForm("origin_url")

	if originUrl == "" {
		c.JSON(http.StatusBadRequest, gin.H{
			"message": "please provide origin_url.",
		})
		return
	}
	// check longurl
	logrus.Infof("check if origin %s has existed in db.\n", originUrl)
	var url entity.URL
	sp.MysqlClient.DB.Where("origin_url = ?", originUrl).First(&url)
	if url.OriginUrl == "" {
		url.CreateTime = time.Now().UTC()
		url.OriginUrl = originUrl
		url.ShortPath = "not implement"
		c.JSON(http.StatusOK, gin.H{
			"short_path": url.ShortPath,
		})
	} else {
		c.JSON(http.StatusOK, gin.H{
			"short_path": url.ShortPath,
		})
	}
}
<|endoftext|>


<commit_before>// Package github implements a simple client to consume gitlab API.
package gogitlab

import (
	"bytes"
	"crypto/tls"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

const (
	dasboard_feed_path = "/dashboard.atom"
)

type Gitlab struct {
	BaseUrl      string
	ApiPath      string
	RepoFeedPath string
	Token        string
	Client       *http.Client
}

const (
	dateLayout = "2006-01-02T15:04:05-07:00"
)

var (
	skipCertVerify = flag.Bool("gitlab.skip-cert-check", false,
		`If set to true, gitlab client will skip certificate checking for https, possibly exposing your system to MITM attack.`)
)

func NewGitlab(baseUrl, apiPath, token string) *Gitlab {
	config := &tls.Config{InsecureSkipVerify: *skipCertVerify}
	tr := &http.Transport{TLSClientConfig: config}
	client := &http.Client{Transport: tr}

	return &Gitlab{
		BaseUrl: baseUrl,
		ApiPath: apiPath,
		Token:   token,
		Client:  client,
	}
}

func (g *Gitlab) ResourceUrl(url string, params map[string]string) string {

	if params != nil {
		for key, val := range params {
			url = strings.Replace(url, key, val, -1)
		}
	}

	url = g.BaseUrl + g.ApiPath + url + "?private_token=" + g.Token
	return url
}

func (g *Gitlab) buildAndExecRequest(method, url string, body []byte) ([]byte, error) {

	var req *http.Request
	var err error

	if body != nil {
		reader := bytes.NewReader(body)
		req, err = http.NewRequest(method, url, reader)
	} else {
		req, err = http.NewRequest(method, url, nil)
	}
	if err != nil {
		panic("Error while building gitlab request")
	}

	resp, err := g.Client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("Client.Do error: %q", err)
	}
	defer resp.Body.Close()
	contents, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("%s", err)
	}

	if resp.StatusCode >= 400 {
		err = fmt.Errorf("*Gitlab.buildAndExecRequest failed: <%d> %s", resp.StatusCode, req.URL)
	}

	return contents, err
}

func (g *Gitlab) ResourceUrlRaw(u string, params map[string]string) (string, string) {

	if params != nil {
		for key, val := range params {
			u = strings.Replace(u, key, val, -1)
		}
	}

	path := u
	u = g.BaseUrl + g.ApiPath + path + "?private_token=" + g.Token
	p, err := url.Parse(u)
	if err != nil {
		return u, ""
	}
	opaque := "//" + p.Host + g.ApiPath + path
	return u, opaque
}

func (g *Gitlab) buildAndExecRequestRaw(method, url, opaque string, body []byte) ([]byte, error) {

	var req *http.Request
	var err error

	if body != nil {
		reader := bytes.NewReader(body)
		req, err = http.NewRequest(method, url, reader)
	} else {
		req, err = http.NewRequest(method, url, nil)
	}
	if err != nil {
		panic("Error while building gitlab request")
	}

	if len(opaque) > 0 {
		req.URL.Opaque = opaque
	}

	resp, err := g.Client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("Client.Do error: %q", err)
	}
	defer resp.Body.Close()
	contents, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("%s", err)
	}

	if resp.StatusCode >= 400 {
		err = fmt.Errorf("*Gitlab.buildAndExecRequestRaw failed: <%d> %s", resp.StatusCode, req.URL)
	}

	return contents, err
}
<commit_msg>Retain DefaultTransport behavior<commit_after>// Package github implements a simple client to consume gitlab API.
package gogitlab

import (
	"bytes"
	"crypto/tls"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

const (
	dasboard_feed_path = "/dashboard.atom"
)

type Gitlab struct {
	BaseUrl      string
	ApiPath      string
	RepoFeedPath string
	Token        string
	Client       *http.Client
}

const (
	dateLayout = "2006-01-02T15:04:05-07:00"
)

var (
	skipCertVerify = flag.Bool("gitlab.skip-cert-check", false,
		`If set to true, gitlab client will skip certificate checking for https, possibly exposing your system to MITM attack.`)
)

func NewGitlab(baseUrl, apiPath, token string) *Gitlab {
	config := &tls.Config{InsecureSkipVerify: *skipCertVerify}
	tr := &http.Transport{
		Proxy:           http.ProxyFromEnvironment,
		TLSClientConfig: config,
	}
	client := &http.Client{Transport: tr}

	return &Gitlab{
		BaseUrl: baseUrl,
		ApiPath: apiPath,
		Token:   token,
		Client:  client,
	}
}

func (g *Gitlab) ResourceUrl(url string, params map[string]string) string {

	if params != nil {
		for key, val := range params {
			url = strings.Replace(url, key, val, -1)
		}
	}

	url = g.BaseUrl + g.ApiPath + url + "?private_token=" + g.Token
	return url
}

func (g *Gitlab) buildAndExecRequest(method, url string, body []byte) ([]byte, error) {

	var req *http.Request
	var err error

	if body != nil {
		reader := bytes.NewReader(body)
		req, err = http.NewRequest(method, url, reader)
	} else {
		req, err = http.NewRequest(method, url, nil)
	}
	if err != nil {
		panic("Error while building gitlab request")
	}

	resp, err := g.Client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("Client.Do error: %q", err)
	}
	defer resp.Body.Close()
	contents, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("%s", err)
	}

	if resp.StatusCode >= 400 {
		err = fmt.Errorf("*Gitlab.buildAndExecRequest failed: <%d> %s", resp.StatusCode, req.URL)
	}

	return contents, err
}

func (g *Gitlab) ResourceUrlRaw(u string, params map[string]string) (string, string) {

	if params != nil {
		for key, val := range params {
			u = strings.Replace(u, key, val, -1)
		}
	}

	path := u
	u = g.BaseUrl + g.ApiPath + path + "?private_token=" + g.Token
	p, err := url.Parse(u)
	if err != nil {
		return u, ""
	}
	opaque := "//" + p.Host + g.ApiPath + path
	return u, opaque
}

func (g *Gitlab) buildAndExecRequestRaw(method, url, opaque string, body []byte) ([]byte, error) {

	var req *http.Request
	var err error

	if body != nil {
		reader := bytes.NewReader(body)
		req, err = http.NewRequest(method, url, reader)
	} else {
		req, err = http.NewRequest(method, url, nil)
	}
	if err != nil {
		panic("Error while building gitlab request")
	}

	if len(opaque) > 0 {
		req.URL.Opaque = opaque
	}

	resp, err := g.Client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("Client.Do error: %q", err)
	}
	defer resp.Body.Close()
	contents, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("%s", err)
	}

	if resp.StatusCode >= 400 {
		err = fmt.Errorf("*Gitlab.buildAndExecRequestRaw failed: <%d> %s", resp.StatusCode, req.URL)
	}

	return contents, err
}
<|endoftext|>


<commit_before>package main

import "math"
import "fmt"
import "image"
import "os"
import "image/color"
import "image/png"

// TODO: see if the circle artifact is a result of saving to a png file
// TODO: is it shading the back of the sphere at that point

// vector can represent a point as well, if interpreted as
//  a vector from the origin to a point or 'absolute position vector'.
//  otherwise it represents a 'relative position vector'
type vector struct {
	x, y, z float64
}

type ray struct {
	start vector
	direction vector
}

type camera struct {
	eye vector
	look_at vector
	up vector
}

type screen struct {
	w,h float64
	xres, yres int
}

type sphere struct {
	center vector
	radius float64
	red,green,blue uint16
}

type scene struct {
	items []sceneItem
}

type sceneItem interface {
	intersected(c_ray *ray) (float64, bool)   // returns the t for the intersection, if it occured
	getColor(t float64, c_ray *ray, light *vector) (uint16, uint16, uint16) // get the color at intersection point
}

func (the_scene *scene) getColor(c_ray *ray, light *vector) (uint16, uint16, uint16) {
	t_closest := 0.0
	var closest_item sceneItem = nil
	for _, value := range the_scene.items {
		t, is_hit := value.intersected(c_ray)
		if is_hit == false {
			continue
		}
		if closest_item == nil || (t > 0 && t < t_closest) {
			t_closest = t
			closest_item = value
		}
	}

	if closest_item == nil {
		return 0.0, 0.0, 0.0
	}

	return closest_item.getColor(t_closest, c_ray, light)
}

func getLightedColor(red, green, blue uint16, t float64, c_ray *ray, light, center *vector) (uint16, uint16, uint16){
	dir := c_ray.direction.scalarMult(t)
	point_on_sphere := c_ray.start.add(&dir)

	normal := point_on_sphere.sub(center)
	unormal := normal.unit()

	point_on_sphere_to_light := light.sub(&point_on_sphere)
	upoint_on_sphere_to_light := point_on_sphere_to_light.unit()

	scale := unormal.dot(&upoint_on_sphere_to_light)
	if scale < 0.0 {
		scale = 0.0
	}

	red_light := uint16(scale*float64(red))
	green_light := uint16(scale*float64(green))
	blue_light := uint16(scale*float64(blue))
	return red_light, green_light, blue_light
}

func (s *sphere) getColor(t float64, c_ray *ray, light *vector) (uint16, uint16, uint16) {
	return getLightedColor(s.red,s.green,s.blue,t,c_ray, light, &s.center)
}

func (s *sphere) intersected(c_ray *ray) (float64, bool)  {
	a := c_ray.direction.x * c_ray.direction.x +
		c_ray.direction.y * c_ray.direction.y +
		c_ray.direction.z * c_ray.direction.z
	b := 2.0*((c_ray.start.x-s.center.x)*c_ray.direction.x +
		(c_ray.start.y-s.center.y)*c_ray.direction.y +
		(c_ray.start.z-s.center.z)*c_ray.direction.z)
	c := (c_ray.start.x-s.center.x) * (c_ray.start.x-s.center.x) +
		(c_ray.start.y-s.center.y) * (c_ray.start.y-s.center.y) +
		(c_ray.start.z-s.center.z) * (c_ray.start.z-s.center.z) -
		s.radius * s.radius

	is_hit:=false
	i_test:=b*b-4.0*a*c
	t1,t2,t_closest:=0.0,0.0,0.0
	if i_test >= 0.0 {
		is_hit=true
		t1=(-b+math.Sqrt(i_test))/(2.0*a)
		t2=(-b-math.Sqrt(i_test))/(2.0*a)
		if t1 <= 0.0 && t2 <= 0.0 {
			is_hit=false  // it hit behind or on the viewer
		}else if t1 > 0.0 && t2 > 0.0 {
			if t1<t2 {
				t_closest=t1
			}else{
				t_closest=t2
			}
		} else if t1 > 0.0 {
			t_closest = t1
		} else if t2 > 0.0 {
			t_closest = t2
		}
	}

	return t_closest, is_hit
}

func (v *vector) sub(v1 *vector) vector {
	return vector{v.x-v1.x, v.y-v1.y, v.z-v1.z}
}

func (v *vector) add(v1 *vector) vector {
	return vector{v.x+v1.x, v.y+v1.y, v.z+v1.z}
}

func (v *vector) scalarMult (c float64) vector {
	return vector{c * v.x, c * v.y, c * v.z}
}

func (v *vector) lengthSq() float64 {
	return v.x * v.x  + v.y * v.y + v.z * v.z
}

func (v *vector) length() float64 {
	return math.Sqrt(v.lengthSq())
}

func (v *vector) unit() vector {
	l := v.length()
	return vector{v.x/l, v.y/l, v.z/l}
}

func (v *vector) dot(v1 *vector) float64 {
	return v.x * v1.x + v.y * v1.y + v.z * v1.z
}

func (v1 *vector) cross(v2 *vector) vector {
	return vector{v1.y * v2.z - v2.y * v1.z,
		v2.x * v1.z - v1.x * v2.z,
		v1.x * v2.y - v2.x * v1.y}
}

func get_local_coordinate_system(eye, look_at, up *vector) (*vector, *vector) {
	a_to_e := eye.sub(look_at)
	w := a_to_e.unit()
	up_X_a_to_e := up.cross(&a_to_e)
	u := up_X_a_to_e.unit()
	v := w.cross(&u)
	return &u, &v
}

func get_scene() (*scene) {
	s := sphere{vector{-25.0, 15.0, -15.0}, 10.0, 0, 0, 65535}
	s2 := sphere{vector{5.0, 15.0, -15.0}, 15.0, 0, 65535, 0}
	s3 := sphere{vector{-5.0, -15.0, -15.0}, 15.0, 65535, 0, 0}
	the_scene:=new(scene)
	the_scene.items=make([]sceneItem,3)
	the_scene.items[0]=&s
	the_scene.items[1]=&s2
	the_scene.items[2]=&s3
	return the_scene
}

func get_current_ray (i, j int, the_screen *screen, u, v, look_at, eye *vector) (*ray) {
	cu := (((2.0*float64(i) + 1.0)/(2.0 * float64(the_screen.xres))) - 0.5) * the_screen.w
	cv := (((2.0*float64(j) + 1.0)/(2.0 * float64(the_screen.yres))) - 0.5) * the_screen.h
	ucu := u.scalarMult(cu)
	ucv := v.scalarMult(cv)
	a_plus_ucu := look_at.add(&ucu)
	Pij := a_plus_ucu.add(&ucv)
	e_to_Pij := Pij.sub(eye)
	current_ray := ray{*eye, e_to_Pij.unit()}
	return &current_ray
}

func main() {
	g_screen := screen{100,100,1000,1000}
	g_camera := camera{vector{0,0,1000}, vector{0,0,0}, vector{0,1,0}}
	g_light := vector{1000,0,1000}

	f, err := os.OpenFile("x.png", os.O_CREATE | os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	m := image.NewRGBA64(image.Rect(0,0,g_screen.xres,g_screen.yres))
	the_scene:=get_scene()
	u, v := get_local_coordinate_system(&g_camera.eye, &g_camera.look_at, &g_camera.up)
	for i:=0; i < g_screen.xres; i++ {
		for j:=0; j < g_screen.yres; j++ {
			current_ray:=get_current_ray(i, j, &g_screen, u, v, &g_camera.look_at, &g_camera.eye)
			// shoot the ray into the scene
			red,green,blue:=the_scene.getColor(current_ray, &g_light)
			m.Set(i,j,color.RGBA64{red,green,blue,65535})
		}
	}
	if err=png.Encode(f,m); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}<commit_msg>added shadows and ambient light<commit_after>package main

import "math"
import "fmt"
import "image"
import "os"
import "image/color"
import "image/png"

// TODO: see if the circle artifact is a result of saving to a png file
// TODO: is it shading the back of the sphere at that point

// vector can represent a point as well, if interpreted as
//  a vector from the origin to a point or 'absolute position vector'.
//  otherwise it represents a 'relative position vector'
type vector struct {
	x, y, z float64
}

type ray struct {
	start vector
	direction vector
}

type camera struct {
	eye vector
	look_at vector
	up vector
}

type screen struct {
	w,h float64
	xres, yres int
}

type sphere struct {
	center vector
	radius float64
	red,green,blue uint16
}

type scene struct {
	items []sceneItem
}

type sceneItem interface {
	intersected(c_ray *ray) (float64, bool)   // returns the t for the intersection, if it occured
	getColor(the_scene *scene, t float64, c_ray *ray, light *vector) (uint16, uint16, uint16) // get the color at intersection point
}

func (the_scene *scene) getColor(c_ray *ray, light *vector) (uint16, uint16, uint16) {
	t_closest := 0.0
	var closest_item sceneItem = nil
	for _, value := range the_scene.items {
		t, is_hit := value.intersected(c_ray)
		if is_hit == false {
			continue
		}
		if closest_item == nil || (t > 0 && t < t_closest) {
			t_closest = t
			closest_item = value
		}
	}

	if closest_item == nil {
		return 0.0, 0.0, 0.0
	}

	return closest_item.getColor(the_scene, t_closest, c_ray, light)
}

func (s *sphere) getColor(the_scene *scene, t float64, c_ray *ray, light *vector) (uint16, uint16, uint16) {
	// get the normal
	dir := c_ray.direction.scalarMult(t)
	point_on_sphere := c_ray.start.add(&dir)

	normal := point_on_sphere.sub(&s.center)
	unormal := normal.unit()

	// check for light obstructions
	point_on_sphere_to_light := light.sub(&point_on_sphere)
	upoint_on_sphere_to_light := point_on_sphere_to_light.unit()

	is_obstructed:=false
	var red_light,green_light,blue_light float64=0.0,0.0,0.0
	for _, value := range the_scene.items {
		_, is_hit := value.intersected(&ray{point_on_sphere, upoint_on_sphere_to_light})
		if is_hit {
			is_obstructed=true
			red_light,green_light,blue_light=0.0,0.0,0.0
		}
	}

	if is_obstructed == false {
		//calculate the light contribution
		scale := unormal.dot(&upoint_on_sphere_to_light)
		if scale < 0.0 {
			scale = 0.0
		}

		red_light = scale*float64(s.red)
		green_light = scale*float64(s.green)
		blue_light = scale*float64(s.blue)
	}
	return uint16(ceiling(red_light + 0.1*float64(s.red),65535)),
	uint16(ceiling(green_light + 0.1*float64(s.green),65535)),
	uint16(ceiling(blue_light + 0.1*float64(s.blue),65535))
}

var buffer_val float64 = .00001
func in_buffer(val float64) float64{
	if val < buffer_val {
		val = 0.0
	}
	return val
}

func (s *sphere) intersected(c_ray *ray) (float64, bool)  {
	a := c_ray.direction.x * c_ray.direction.x +
		c_ray.direction.y * c_ray.direction.y +
		c_ray.direction.z * c_ray.direction.z
	b := 2.0*((c_ray.start.x-s.center.x)*c_ray.direction.x +
		(c_ray.start.y-s.center.y)*c_ray.direction.y +
		(c_ray.start.z-s.center.z)*c_ray.direction.z)
	c := (c_ray.start.x-s.center.x) * (c_ray.start.x-s.center.x) +
		(c_ray.start.y-s.center.y) * (c_ray.start.y-s.center.y) +
		(c_ray.start.z-s.center.z) * (c_ray.start.z-s.center.z) -
		s.radius * s.radius

	is_hit:=false
	i_test:=b*b-4.0*a*c
	t1,t2,t_closest:=0.0,0.0,0.0
	if i_test >= 0.0 {
		is_hit=true
		t1=(-b+math.Sqrt(i_test))/(2.0*a)
		t2=(-b-math.Sqrt(i_test))/(2.0*a)
		t1=in_buffer(t1)
		t2=in_buffer(t2)
		if t1 <= 0.0 && t2 <= 0.0 {
			is_hit=false  // it hit behind or on the viewer
		}else if t1 > 0.0 && t2 > 0.0 {
			if t1<t2 {
				t_closest=t1
			}else{
				t_closest=t2
			}
		} else if t1 > 0.0 {
			t_closest = t1
		} else if t2 > 0.0 {
			t_closest = t2
		}
	}

	return t_closest, is_hit
}

func (v *vector) sub(v1 *vector) vector {
	return vector{v.x-v1.x, v.y-v1.y, v.z-v1.z}
}

func (v *vector) add(v1 *vector) vector {
	return vector{v.x+v1.x, v.y+v1.y, v.z+v1.z}
}

func (v *vector) scalarMult (c float64) vector {
	return vector{c * v.x, c * v.y, c * v.z}
}

func (v *vector) lengthSq() float64 {
	return v.x * v.x  + v.y * v.y + v.z * v.z
}

func (v *vector) length() float64 {
	return math.Sqrt(v.lengthSq())
}

func (v *vector) unit() vector {
	l := v.length()
	return vector{v.x/l, v.y/l, v.z/l}
}

func (v *vector) dot(v1 *vector) float64 {
	return v.x * v1.x + v.y * v1.y + v.z * v1.z
}

func (v1 *vector) cross(v2 *vector) vector {
	return vector{v1.y * v2.z - v2.y * v1.z,
		v2.x * v1.z - v1.x * v2.z,
		v1.x * v2.y - v2.x * v1.y}
}

func ceiling(value float64, top_value float64) float64{
	if value > top_value {
		value=top_value
	}
	return value
}

func get_local_coordinate_system(eye, look_at, up *vector) (*vector, *vector) {
	a_to_e := eye.sub(look_at)
	w := a_to_e.unit()
	up_X_a_to_e := up.cross(&a_to_e)
	u := up_X_a_to_e.unit()
	v := w.cross(&u)
	return &u, &v
}

func get_scene() (*scene) {
	s := sphere{vector{-25.0, 15.0, -10.0}, 10.0, 0, 0, 65535}
	s2 := sphere{vector{5.0, 15.0, -15.0}, 15.0, 0, 65535, 0}
	s3 := sphere{vector{-5.0, -15.0, -15.0}, 15.0, 65535, 0, 0}
	the_scene:=new(scene)
	the_scene.items=make([]sceneItem,3)
	the_scene.items[0]=&s
	the_scene.items[1]=&s2
	the_scene.items[2]=&s3
	return the_scene
}

func get_current_ray (i, j int, the_screen *screen, u, v, look_at, eye *vector) (*ray) {
	cu := (((2.0*float64(i) + 1.0)/(2.0 * float64(the_screen.xres))) - 0.5) * the_screen.w
	cv := (((2.0*float64(j) + 1.0)/(2.0 * float64(the_screen.yres))) - 0.5) * the_screen.h
	ucu := u.scalarMult(cu)
	ucv := v.scalarMult(cv)
	a_plus_ucu := look_at.add(&ucu)
	Pij := a_plus_ucu.add(&ucv)
	e_to_Pij := Pij.sub(eye)
	current_ray := ray{*eye, e_to_Pij.unit()}
	return &current_ray
}

func main() {
	g_screen := screen{100,100,1000,1000}
	g_camera := camera{vector{0,0,1000}, vector{0,0,0}, vector{0,1,0}}
	g_light := vector{-1000.0,0.0,15.0}

	f, err := os.OpenFile("x.png", os.O_CREATE | os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	m := image.NewRGBA64(image.Rect(0,0,g_screen.xres,g_screen.yres))
	the_scene:=get_scene()
	u, v := get_local_coordinate_system(&g_camera.eye, &g_camera.look_at, &g_camera.up)
	for i:=0; i < g_screen.xres; i++ {
		for j:=0; j < g_screen.yres; j++ {
			current_ray:=get_current_ray(i, j, &g_screen, u, v, &g_camera.look_at, &g_camera.eye)
			// shoot the ray into the scene
			red,green,blue:=the_scene.getColor(current_ray, &g_light)
			m.Set(i,j,color.RGBA64{red,green,blue,65535})
		}
	}
	if err=png.Encode(f,m); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"json"
	"io/ioutil"
	"time"
	"bytes"
	stfl "github.com/akrennmair/go-stfl"
	oauth "github.com/hokapoka/goauth"
)

func main() {

	tapi := NewTwitterAPI("sDggzGbHbyAfl5fJ87XOCA", "MOCQDL7ot7qIxMwYL5x1mMAqiYBYxNTxPWS6tc6hw")

	at, aterr := LoadAccessToken()

	if aterr == nil {
		tapi.SetAccessToken(at)
	} else {
		auth_url, err := tapi.GetRequestAuthorizationURL()
		if err != nil {
			fmt.Println(err.String())
			return
		}

		var pin string
		fmt.Printf("Open %s\n", auth_url)
		fmt.Printf("PIN Number: ")
		fmt.Scanln(&pin)

		tapi.SetPIN(pin)

		if saveerr := SaveAccessToken(tapi.GetAccessToken()); saveerr != nil {
			fmt.Printf("saving access token failed: %s\n", saveerr.String())
			return
		}
	}

	newtweetchan := make(chan []Tweet, 1)
	viewchan := make(chan []Tweet, 1)

	go func() {
		last_id := int64(0)

		for {

			home_tl, err := tapi.HomeTimeline(50, last_id)

			if err != nil {
				//fmt.Println(err.String())
				//TODO: signal error
			} else {
				if len(home_tl.Tweets) > 0 {
					newtweetchan <- home_tl.Tweets
					if home_tl.Tweets[0].Id != nil {
						last_id = *home_tl.Tweets[0].Id
					}
				}
			}

			time.Sleep(20e9)
		}
	}()

	go func() {
		tweets := []Tweet{}

		for {
			select {
			case newtweets := <-newtweetchan:
				//fmt.Fprintf(os.Stderr, "received %d tweets in controller\n", len(newtweets))
				tweets = append(newtweets, tweets...)
				viewchan <- newtweets
			}
		}

	}()

	form := stfl.Create("<ui.stfl>")
	form.Set("program", os.Args[0])

	go func() {

		for {
			select {
			case newtweets := <-viewchan:
				//fmt.Fprintf(os.Stderr, "received %d tweets in view\n", len(newtweets))
				str := formatTweets(newtweets)
				//fmt.Fprintf(os.Stderr, "formatted new tweets: %s\n", str)
				form.Modify("tweets", "insert_inner", str)
				form.Run(-1)
			}
		}
	}()

	event := ""
	for event != "q" {
		event = form.Run(0)
	}

	stfl.Reset()

//	foo, posterr := goauthcon.Post(
//		"http://api.twitter.com/1/statuses/update.json",
//		oauth.Params{
//			&oauth.Pair{
//				Key:"status",
//				Value:"Test posting using Gockel prototype",
//			},
//		}, at )
//
//	fmt.Printf("foo = %v\n", foo)
//
//	if posterr != nil {
//		fmt.Println(err.String())
//		return
//	}
//
//	fmt.Println("Twitter Status is updated")
}

func SaveAccessToken(at *oauth.AccessToken) os.Error {
	data, marshalerr := json.Marshal(at)
	if marshalerr != nil {
		return marshalerr
	}

	f, ferr := os.OpenFile("access_token.json", os.O_WRONLY | os.O_CREATE, 0600)
	if ferr != nil {
		return ferr
	}
	defer f.Close()

	_, werr := f.Write(data)
	if werr != nil {
		return werr
	}

	return nil
}

func LoadAccessToken() (*oauth.AccessToken, os.Error) {
	f, ferr := os.Open("access_token.json")
	if ferr != nil {
		return nil, ferr
	}
	defer f.Close()

	data, readerr := ioutil.ReadAll(f)
	if readerr != nil {
		return nil, readerr
	}

	at := &oauth.AccessToken{}

	err := json.Unmarshal(data, at)
	if err != nil {
		return nil, err
	}

	return at, nil
}

func formatTweets(tweets []Tweet) string {
	buf := bytes.NewBufferString("{list")

	for _, t := range tweets {
		tweetline := fmt.Sprintf("[%16s] %s", "@" + *t.User.Screen_name, *t.Text)
		buf.WriteString("{listitem text:")
		buf.WriteString(stfl.Quote(tweetline))
		buf.WriteString("}")
	}

	buf.WriteString("}")
	return string(buf.Bytes())
}
<commit_msg>initialize STFL so that the correct locale is set.<commit_after>package main

import (
	"fmt"
	"os"
	"json"
	"io/ioutil"
	"time"
	"bytes"
	stfl "github.com/akrennmair/go-stfl"
	oauth "github.com/hokapoka/goauth"
)

func main() {

	tapi := NewTwitterAPI("sDggzGbHbyAfl5fJ87XOCA", "MOCQDL7ot7qIxMwYL5x1mMAqiYBYxNTxPWS6tc6hw")

	at, aterr := LoadAccessToken()

	if aterr == nil {
		tapi.SetAccessToken(at)
	} else {
		auth_url, err := tapi.GetRequestAuthorizationURL()
		if err != nil {
			fmt.Println(err.String())
			return
		}

		var pin string
		fmt.Printf("Open %s\n", auth_url)
		fmt.Printf("PIN Number: ")
		fmt.Scanln(&pin)

		tapi.SetPIN(pin)

		if saveerr := SaveAccessToken(tapi.GetAccessToken()); saveerr != nil {
			fmt.Printf("saving access token failed: %s\n", saveerr.String())
			return
		}
	}

	newtweetchan := make(chan []Tweet, 1)
	viewchan := make(chan []Tweet, 1)

	go func() {
		last_id := int64(0)

		for {

			home_tl, err := tapi.HomeTimeline(50, last_id)

			if err != nil {
				//fmt.Println(err.String())
				//TODO: signal error
			} else {
				if len(home_tl.Tweets) > 0 {
					newtweetchan <- home_tl.Tweets
					if home_tl.Tweets[0].Id != nil {
						last_id = *home_tl.Tweets[0].Id
					}
				}
			}

			time.Sleep(20e9)
		}
	}()

	go func() {
		tweets := []Tweet{}

		for {
			select {
			case newtweets := <-newtweetchan:
				//fmt.Fprintf(os.Stderr, "received %d tweets in controller\n", len(newtweets))
				tweets = append(newtweets, tweets...)
				viewchan <- newtweets
			}
		}

	}()

	stfl.Init()
	form := stfl.Create("<ui.stfl>")
	form.Set("program", os.Args[0])

	go func() {

		for {
			select {
			case newtweets := <-viewchan:
				//fmt.Fprintf(os.Stderr, "received %d tweets in view\n", len(newtweets))
				str := formatTweets(newtweets)
				//fmt.Fprintf(os.Stderr, "formatted new tweets: %s\n", str)
				form.Modify("tweets", "insert_inner", str)
				form.Run(-1)
			}
		}
	}()

	event := ""
	for event != "q" {
		event = form.Run(0)
	}

	stfl.Reset()

//	foo, posterr := goauthcon.Post(
//		"http://api.twitter.com/1/statuses/update.json",
//		oauth.Params{
//			&oauth.Pair{
//				Key:"status",
//				Value:"Test posting using Gockel prototype",
//			},
//		}, at )
//
//	fmt.Printf("foo = %v\n", foo)
//
//	if posterr != nil {
//		fmt.Println(err.String())
//		return
//	}
//
//	fmt.Println("Twitter Status is updated")
}

func SaveAccessToken(at *oauth.AccessToken) os.Error {
	data, marshalerr := json.Marshal(at)
	if marshalerr != nil {
		return marshalerr
	}

	f, ferr := os.OpenFile("access_token.json", os.O_WRONLY | os.O_CREATE, 0600)
	if ferr != nil {
		return ferr
	}
	defer f.Close()

	_, werr := f.Write(data)
	if werr != nil {
		return werr
	}

	return nil
}

func LoadAccessToken() (*oauth.AccessToken, os.Error) {
	f, ferr := os.Open("access_token.json")
	if ferr != nil {
		return nil, ferr
	}
	defer f.Close()

	data, readerr := ioutil.ReadAll(f)
	if readerr != nil {
		return nil, readerr
	}

	at := &oauth.AccessToken{}

	err := json.Unmarshal(data, at)
	if err != nil {
		return nil, err
	}

	return at, nil
}

func formatTweets(tweets []Tweet) string {
	buf := bytes.NewBufferString("{list")

	for _, t := range tweets {
		tweetline := fmt.Sprintf("[%16s] %s", "@" + *t.User.Screen_name, *t.Text)
		buf.WriteString("{listitem text:")
		buf.WriteString(stfl.Quote(tweetline))
		buf.WriteString("}")
	}

	buf.WriteString("}")
	return string(buf.Bytes())
}
<|endoftext|>


<commit_before>package metadata

import (
	"testing"

	. "pkg.re/check.v1"
)

// ////////////////////////////////////////////////////////////////////////////////// //

type ProviderSuite struct{}

func Test(t *testing.T) { TestingT(t) }

var _ = Suite(&ProviderSuite{})

// ////////////////////////////////////////////////////////////////////////////////// //

// TestAddProvider checks adding new provider to version struct
func (p *ProviderSuite) TestAddProvider(c *C) {

	p1 := NewMetadataProvider(
		"virtualbox",
		"checksum1",
		"sha256",
		"http://localhost:8080/virtualbox.box",
	)

	p2 := NewMetadataProvider(
		"vmware",
		"checksum2",
		"sha256",
		"http://localhost:8080/vmware.box",
	)

	p3 := NewMetadataProvider(
		"virtualbox",
		"checksum3",
		"sha256",
		"http://localhost:8080/virtualbox.box",
	)

	v1 := NewMetadataVersion("1.0.0", make(VMetadataProvidersList, 0))

	v1.AddProvider(p1)
	v1.AddProvider(p2)

	c.Assert(2, Equals, v1.CountProviders())

	v1.AddProvider(p3)

	c.Assert(2, Equals, v1.CountProviders())
}

//
func (p *ProviderSuite) TestRemoveProvider(c *C) {

	p1 := NewMetadataProvider(
		"virtualbox",
		"checksum1",
		"sha256",
		"http://localhost:8080/virtualbox.box",
	)

	p2 := NewMetadataProvider(
		"vmware",
		"checksum2",
		"sha256",
		"http://localhost:8080/vmware.box",
	)

	v1 := NewMetadataVersion("1.0.0", make(VMetadataProvidersList, 0))

	v1.AddProvider(p1)
	v1.AddProvider(p2)

	v1.RemoveProvider(p1)
	v1.RemoveProvider(p2)

	c.Assert(0, Equals, v1.CountProviders())
}
<commit_msg>Add TestFilterProvider test.<commit_after>package metadata

import (
	"testing"

	. "pkg.re/check.v1"
)

// ////////////////////////////////////////////////////////////////////////////////// //

type ProviderSuite struct{}

func Test(t *testing.T) { TestingT(t) }

var _ = Suite(&ProviderSuite{})

// ////////////////////////////////////////////////////////////////////////////////// //

// TestFilterProvides checks FilterProvider function
func (p *ProviderSuite) TestFilterProvider(c *C) {

	p1 := NewMetadataProvider(
		"virtualbox",
		"checksum1",
		"sha256",
		"http://localhost:8080/virtualbox.box",
	)

	p2 := NewMetadataProvider(
		"vmware",
		"checksum2",
		"sha256",
		"http://localhost:8080/vmware.box",
	)

	p3 := NewMetadataProvider(
		"custom",
		"checksum3",
		"sha256",
		"http://localhost:8080/custom.box",
	)

	v1 := NewMetadataVersion("1.0.0", make(VMetadataProvidersList, 0))

	v1.AddProvider(p1)
	v1.AddProvider(p2)
	v1.AddProvider(p3)

	v1.FilterProvider(p2, isEqualProviders)

	v2 := NewMetadataVersion("1.0.0", make(VMetadataProvidersList, 0))

	v2.AddProvider(p1)
	v2.AddProvider(p3)

	v2.FilterProvider(p2, isEqualProviders)

	c.Assert(1, Equals, v1.CountProviders())
	c.Assert(0, Equals, v2.CountProviders())
}

// TestAddProvider checks adding new provider to version struct
func (p *ProviderSuite) TestAddProvider(c *C) {

	p1 := NewMetadataProvider(
		"virtualbox",
		"checksum1",
		"sha256",
		"http://localhost:8080/virtualbox.box",
	)

	p2 := NewMetadataProvider(
		"vmware",
		"checksum2",
		"sha256",
		"http://localhost:8080/vmware.box",
	)

	p3 := NewMetadataProvider(
		"virtualbox",
		"checksum3",
		"sha256",
		"http://localhost:8080/virtualbox.box",
	)

	v1 := NewMetadataVersion("1.0.0", make(VMetadataProvidersList, 0))

	v1.AddProvider(p1)
	v1.AddProvider(p2)

	c.Assert(2, Equals, v1.CountProviders())

	v1.AddProvider(p3)

	c.Assert(2, Equals, v1.CountProviders())
}

// TestRemoveProvider checks removing provider from the version struct
func (p *ProviderSuite) TestRemoveProvider(c *C) {

	p1 := NewMetadataProvider(
		"virtualbox",
		"checksum1",
		"sha256",
		"http://localhost:8080/virtualbox.box",
	)

	p2 := NewMetadataProvider(
		"vmware",
		"checksum2",
		"sha256",
		"http://localhost:8080/vmware.box",
	)

	v1 := NewMetadataVersion("1.0.0", make(VMetadataProvidersList, 0))

	v1.AddProvider(p1)
	v1.AddProvider(p2)

	v1.RemoveProvider(p1)
	v1.RemoveProvider(p2)

	c.Assert(0, Equals, v1.CountProviders())
}
<|endoftext|>


<commit_before>package middleware

import (
	"testing"

	"github.com/neptulon/cmap"
	"github.com/neptulon/neptulon"
)

func TestResLog(t *testing.T) {
	err := Logger(&neptulon.ReqCtx{
		Session: cmap.New(),
		ID:      "1234",
		Method:  "wow.method",
		Res:     "my response",
	})

	if err != nil {
		t.Fatal("unexpected error return value")
	}
}

func TestErrResLog(t *testing.T) {
	err := Logger(&neptulon.ReqCtx{
		Session: cmap.New(),
		ID:      "1234",
		Method:  "wow.method",
		Err:     &neptulon.ResError{Code: 98765},
	})

	if err != nil {
		t.Fatal("unexpected error return value")
	}
}

func TestCustLog(t *testing.T) {
	s := cmap.New()
	s.Set(CustResLogDataKey, "custom log output")

	err := Logger(&neptulon.ReqCtx{
		Session: s,
		ID:      "1234",
		Method:  "wow.method",
		Res:     "my response",
	})

	if err != nil {
		t.Fatal("unexpected error return value")
	}
}
<commit_msg>check log output during log tests<commit_after>package middleware

import (
	"bytes"
	"log"
	"os"
	"strings"
	"testing"

	"github.com/neptulon/cmap"
	"github.com/neptulon/neptulon"
)

func captureOutput(f func()) string {
	var buf bytes.Buffer
	log.SetOutput(&buf)
	f()
	log.SetOutput(os.Stderr)
	return buf.String()
}

func TestResLog(t *testing.T) {
	ctx := &neptulon.ReqCtx{
		Session: cmap.New(),
		ID:      "1234",
		Method:  "wow.method",
		Res:     "my response",
		Err:     &neptulon.ResError{Code: 98765},
	}

	out := captureOutput(func() {
		err := Logger(ctx)
		if err != nil {
			t.Fatal("didn't expect error from logger")
		}
	})

	if !strings.Contains(out, "my response") || strings.Contains(out, "98765") {
		log.Fatalf("malformed log output: %v", out)
	}
}

func TestErrResLog(t *testing.T) {
	ctx := &neptulon.ReqCtx{
		Session: cmap.New(),
		ID:      "1234",
		Method:  "wow.method",
		Err:     &neptulon.ResError{Code: 98765},
	}

	out := captureOutput(func() {
		err := Logger(ctx)
		if err != nil {
			t.Fatal("didn't expect error from logger")
		}
	})

	if strings.Contains(out, "my response") || !strings.Contains(out, "98765") {
		log.Fatalf("malformed log output: %v", out)
	}
}

func TestCustLog(t *testing.T) {
	s := cmap.New()
	s.Set(CustResLogDataKey, "custom log output")

	ctx := &neptulon.ReqCtx{
		Session: s,
		ID:      "1234",
		Method:  "wow.method",
		Res:     "my response",
		Err:     &neptulon.ResError{Code: 98765},
	}

	out := captureOutput(func() {
		err := Logger(ctx)
		if err != nil {
			t.Fatal("didn't expect error from logger")
		}
	})

	if strings.Contains(out, "my response") || strings.Contains(out, "98765") {
		log.Fatalf("malformed log output: %v", out)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"log"
	"time"
)

type Client struct {
	writer http.ResponseWriter
	channel chan <- string
}

func handleMessages(messageChan <- chan string, addChan <- chan Client, removeChan <- chan Client) {
	// clients := make(map[http.ResponseWriter] chan <- string)

	for {
		select {
		case message := <- messageChan:
			log.Print("New message: ", message)
		case client := <- addChan:
			log.Print("Client connected: ", client)
		case client := <- removeChan:
			log.Print("Client disconnected: ", client)
		}
	}
}

func handleStream(messageChan chan <- string, addChan chan <- Client, removeChan chan <- Client, writer http.ResponseWriter, request *http.Request) {
	writer.Header().Set("Content-Type", "text/event-stream")
	writer.Header().Set("Access-Control-Allow-Origin", "*")
	writer.WriteHeader(200)

	channel := make(chan string)
	client  := Client{writer, channel}

	addChan <- client

	for {
		if _, error := writer.Write([]byte("test\r\n")); error != nil {
			log.Print("Write: ", error)
			break
		}
		writer.(http.Flusher).Flush()
		time.Sleep(time.Second)
	}

	removeChan <- client
}

func main() {
	messagesChan := make(chan string)
	addChan      := make(chan Client)
	removeChan   := make(chan Client)

	go handleMessages(messagesChan, addChan, removeChan)

	http.HandleFunc("/", func (writer http.ResponseWriter, request *http.Request) {
		http.ServeFile(writer, request, "static/index.html")
	})
	http.HandleFunc("/static/", func (writer http.ResponseWriter, request *http.Request) {
		http.ServeFile(writer, request, request.URL.Path[1:])
	})
	http.HandleFunc("/stream", func (writer http.ResponseWriter, request *http.Request) {
		handleStream(messagesChan, addChan, removeChan, writer, request)
	})

	log.Print("Starting server on :8080")

	if error := http.ListenAndServe(":8080", nil); error != nil {
		log.Fatal("ListenAndServe: ", error)
	}
}
<commit_msg>added messages handler<commit_after>package main

import (
	"net/http"
	"log"
)

type Client struct {
	writer http.ResponseWriter
	channel chan <- string
}

func handleMessages(messageChan <- chan string, addChan <- chan Client, removeChan <- chan Client) {
	clients := make(map[http.ResponseWriter] chan <- string)

	for {
		select {
		case message := <- messageChan:
			log.Print("New message: ", message)
			for _, channel := range clients {
				// TODO: use buffered channel?
				go func () {
					channel <- message
				}()
			}
		case client := <- addChan:
			log.Print("Client connected: ", client)
			clients[client.writer] = client.channel
		case client := <- removeChan:
			log.Print("Client disconnected: ", client)
			delete(clients, client.writer)
		}
	}
}

func handleStream(messageChan chan <- string, addChan chan <- Client, removeChan chan <- Client, writer http.ResponseWriter, request *http.Request) {
	writer.Header().Set("Content-Type", "text/event-stream")
	writer.Header().Set("Access-Control-Allow-Origin", "*")
	writer.WriteHeader(200)

	channel := make(chan string)
	client  := Client{writer, channel}

	addChan <- client

	for {
		message := <- channel
		if _, error := writer.Write([]byte(message + "\r\n")); error != nil {
			log.Print("Write: ", error)
			break
		}
		writer.(http.Flusher).Flush()
	}

	removeChan <- client
}

func handleMessage(messageChan chan <- string, writer http.ResponseWriter, request *http.Request) {
	request.ParseForm()
	message := request.FormValue("message")
	messageChan <- message
	writer.WriteHeader(200)
}

func main() {
	messagesChan := make(chan string)
	addChan      := make(chan Client)
	removeChan   := make(chan Client)

	go handleMessages(messagesChan, addChan, removeChan)

	http.HandleFunc("/", func (writer http.ResponseWriter, request *http.Request) {
		http.ServeFile(writer, request, "static/index.html")
	})
	http.HandleFunc("/static/", func (writer http.ResponseWriter, request *http.Request) {
		http.ServeFile(writer, request, request.URL.Path[1:])
	})
	http.HandleFunc("/stream", func (writer http.ResponseWriter, request *http.Request) {
		handleStream(messagesChan, addChan, removeChan, writer, request)
	})
	http.HandleFunc("/messages", func (writer http.ResponseWriter, request *http.Request) {
		handleMessage(messagesChan, writer, request)
	})

	log.Print("Starting server on :8080")

	http.ListenAndServe(":8080", nil)
}
<|endoftext|>


<commit_before>package signer

import (
	"bytes"
	"crypto/x509"
	"encoding/asn1"
	"encoding/hex"
	"fmt"
	"reflect"
	"testing"

	"github.com/cloudflare/cfssl/config"
)

func TestAppendIf(t *testing.T) {
	s := ""
	a := make([]string, 0, 5)
	appendIf(s, &a)
	if len(a) != 0 {
		t.Fatal("appendIf should not append to a with an empty s")
	}
	s = "test"
	appendIf(s, &a)
	if len(a[0]) != 4 {
		t.Fatal("appendIf should append s to a")
	}
}

func TestSplitHosts(t *testing.T) {
	list := SplitHosts("")
	if list != nil {
		t.Fatal("SplitHost should return nil with empty input")
	}

	list = SplitHosts("single.domain")
	if len(list) != 1 {
		t.Fatal("SplitHost fails to split single domain")
	}

	list = SplitHosts("comma,separated,values")
	if len(list) != 3 {
		t.Fatal("SplitHost fails to split multiple domains")
	}
	if list[0] != "comma" || list[1] != "separated" || list[2] != "values" {
		t.Fatal("SplitHost fails to split multiple domains")
	}
}

func TestAddPolicies(t *testing.T) {
	var cert x509.Certificate
	addPolicies(&cert, []config.CertificatePolicy{
		config.CertificatePolicy{
			ID: config.OID{1, 2, 3, 4},
		},
	})

	if len(cert.ExtraExtensions) != 1 {
		t.Fatal("No extension added")
	}
	ext := cert.ExtraExtensions[0]
	if !reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 32}) {
		t.Fatal(fmt.Sprintf("Wrong OID for policy qualifier %v", ext.Id))
	}
	if ext.Critical {
		t.Fatal("Policy qualifier marked critical")
	}
	expectedBytes, _ := hex.DecodeString("3009300706032a03043000")
	if !bytes.Equal(ext.Value, expectedBytes) {
		t.Fatal(fmt.Sprintf("Value didn't match expected bytes: %s vs %s",
			hex.EncodeToString(ext.Value), hex.EncodeToString(expectedBytes)))
	}
}

func TestAddPoliciesWithQualifiers(t *testing.T) {
	var cert x509.Certificate
	addPolicies(&cert, []config.CertificatePolicy{
		config.CertificatePolicy{
			ID: config.OID{1, 2, 3, 4},
			Qualifiers: []config.CertificatePolicyQualifier{
				config.CertificatePolicyQualifier{
					Type:  "id-qt-cps",
					Value: "http://example.com/cps",
				},
				config.CertificatePolicyQualifier{
					Type:  "id-qt-unotice",
					Value: "Do What Thou Wilt",
				},
			},
		},
	})

	if len(cert.ExtraExtensions) != 1 {
		t.Fatal("No extension added")
	}
	ext := cert.ExtraExtensions[0]
	if !reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 32}) {
		t.Fatal(fmt.Sprintf("Wrong OID for policy qualifier %v", ext.Id))
	}
	if ext.Critical {
		t.Fatal("Policy qualifier marked critical")
	}
	expectedBytes, _ := hex.DecodeString("304e304c06032a03043045302206082b060105050702011616687474703a2f2f6578616d706c652e636f6d2f637073301f06082b0601050507020230130c11446f20576861742054686f752057696c74")
	if !bytes.Equal(ext.Value, expectedBytes) {
		t.Fatal(fmt.Sprintf("Value didn't match expected bytes: %s vs %s",
			hex.EncodeToString(ext.Value), hex.EncodeToString(expectedBytes)))
	}
}
<commit_msg>Fix govet error<commit_after>package signer

import (
	"bytes"
	"crypto/x509"
	"encoding/asn1"
	"encoding/hex"
	"fmt"
	"reflect"
	"testing"

	"github.com/cloudflare/cfssl/config"
)

func TestAppendIf(t *testing.T) {
	s := ""
	a := make([]string, 0, 5)
	appendIf(s, &a)
	if len(a) != 0 {
		t.Fatal("appendIf should not append to a with an empty s")
	}
	s = "test"
	appendIf(s, &a)
	if len(a[0]) != 4 {
		t.Fatal("appendIf should append s to a")
	}
}

func TestSplitHosts(t *testing.T) {
	list := SplitHosts("")
	if list != nil {
		t.Fatal("SplitHost should return nil with empty input")
	}

	list = SplitHosts("single.domain")
	if len(list) != 1 {
		t.Fatal("SplitHost fails to split single domain")
	}

	list = SplitHosts("comma,separated,values")
	if len(list) != 3 {
		t.Fatal("SplitHost fails to split multiple domains")
	}
	if list[0] != "comma" || list[1] != "separated" || list[2] != "values" {
		t.Fatal("SplitHost fails to split multiple domains")
	}
}

func TestAddPolicies(t *testing.T) {
	var cert x509.Certificate
	addPolicies(&cert, []config.CertificatePolicy{
		config.CertificatePolicy{
			ID: config.OID([]int{1, 2, 3, 4}),
		},
	})

	if len(cert.ExtraExtensions) != 1 {
		t.Fatal("No extension added")
	}
	ext := cert.ExtraExtensions[0]
	if !reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 32}) {
		t.Fatal(fmt.Sprintf("Wrong OID for policy qualifier %v", ext.Id))
	}
	if ext.Critical {
		t.Fatal("Policy qualifier marked critical")
	}
	expectedBytes, _ := hex.DecodeString("3009300706032a03043000")
	if !bytes.Equal(ext.Value, expectedBytes) {
		t.Fatal(fmt.Sprintf("Value didn't match expected bytes: %s vs %s",
			hex.EncodeToString(ext.Value), hex.EncodeToString(expectedBytes)))
	}
}

func TestAddPoliciesWithQualifiers(t *testing.T) {
	var cert x509.Certificate
	addPolicies(&cert, []config.CertificatePolicy{
		config.CertificatePolicy{
			ID: config.OID([]int{1, 2, 3, 4}),
			Qualifiers: []config.CertificatePolicyQualifier{
				config.CertificatePolicyQualifier{
					Type:  "id-qt-cps",
					Value: "http://example.com/cps",
				},
				config.CertificatePolicyQualifier{
					Type:  "id-qt-unotice",
					Value: "Do What Thou Wilt",
				},
			},
		},
	})

	if len(cert.ExtraExtensions) != 1 {
		t.Fatal("No extension added")
	}
	ext := cert.ExtraExtensions[0]
	if !reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 32}) {
		t.Fatal(fmt.Sprintf("Wrong OID for policy qualifier %v", ext.Id))
	}
	if ext.Critical {
		t.Fatal("Policy qualifier marked critical")
	}
	expectedBytes, _ := hex.DecodeString("304e304c06032a03043045302206082b060105050702011616687474703a2f2f6578616d706c652e636f6d2f637073301f06082b0601050507020230130c11446f20576861742054686f752057696c74")
	if !bytes.Equal(ext.Value, expectedBytes) {
		t.Fatal(fmt.Sprintf("Value didn't match expected bytes: %s vs %s",
			hex.EncodeToString(ext.Value), hex.EncodeToString(expectedBytes)))
	}
}
<|endoftext|>


<commit_before>package gogadgets

import (
	"time"
)

//Heater represnts an electic heating element.  It
//provides a way to heat up something to a target
//temperature. In order to use this there must be
//a thermometer in the same Location.
type Heater struct {
	target   float64
	current  float64
	duration time.Duration
	status   bool
	gpio     OutputDevice
	update   chan Message
	stop     chan bool
}

func NewHeater(pin *Pin) (OutputDevice, error) {
	var h *Heater
	var err error
	g, err := NewGPIO(pin)
	if err == nil {
		h = &Heater{
			gpio:    g,
			current: 0.0,
			target:  100.0,
		}
	}
	return h, err
}

func (h *Heater) Update(msg *Message) {
	if h.status && msg.Name == "temperature" {
		h.update <- *msg
	}
}

func (h *Heater) On(val *Value) error {
	fmt.Println("heater on")
	if val != nil {
		target, ok := val.ToFloat()
		if ok {
			h.target = target
		}
	}
	h.status = true
	h.update = make(chan Message)
	h.stop = make(chan bool)
	if h.target > 0.0 {
		go h.watchTemperature(h.update, h.stop)
	}
	return nil
}

func (h *Heater) Status() interface{} {
	return h.status
}

func (h *Heater) Off() error {
	if h.status {
		h.stop <- true
	}
	return nil
}

func (h *Heater) watchTemperature(update <-chan Message, stop <-chan bool) {
	h.gpio.On(nil)
	keepGoing := true
	h.duration = time.Duration(60 * time.Second)
	for keepGoing {
		select {
		case msg := <-update:
			current, ok := msg.Value.ToFloat()
			if ok {
				h.current = current
				h.toggle()
			}
		case <-stop:
			h.gpio.Off()
			keepGoing = false
		case <-time.After(h.duration):
			h.toggle()
		}
	}
}

func (h *Heater) toggle() {
	on, off := h.getDurations()
	status := h.gpio.Status().(bool)
	if on == 0 && off != 0 {
		h.gpio.Off()
		h.duration = off
	} else if status && off != 0 {
		h.gpio.Off()
		h.duration = off
	} else if !status && on != 0 {
		h.gpio.On(nil)
		h.duration = on
	}
}

//Once the heater approaches the target temperature the electricity
//is applied PWM style so the target temperature isn't overshot.
func (h *Heater) getDurations() (on time.Duration, off time.Duration) {
	diff := h.target - h.current
	if diff >= 2.0 {
		on = time.Duration(60.0 * float64(time.Second))
	} else if diff >= 1.0 {
		on = time.Duration(0.5 * float64(time.Second))
		off = time.Duration(0.5 * float64(time.Second))
	} else if diff > 0.0 {
		on = time.Duration(0.25 * float64(time.Second))
		off = time.Duration(0.75 * float64(time.Second))
	} else if diff <= 0.0 {
		off = time.Duration(60.0 * float64(time.Second))
	}
	return on, off
}
<commit_msg>dont watch temperature if no target<commit_after>package gogadgets

import (
	"time"
)

//Heater represnts an electic heating element.  It
//provides a way to heat up something to a target
//temperature. In order to use this there must be
//a thermometer in the same Location.
type Heater struct {
	target   float64
	current  float64
	duration time.Duration
	status   bool
	gpio     OutputDevice
	update   chan Message
	stop     chan bool
}

func NewHeater(pin *Pin) (OutputDevice, error) {
	var h *Heater
	var err error
	g, err := NewGPIO(pin)
	if err == nil {
		h = &Heater{
			gpio:    g,
			current: 0.0,
			target:  100.0,
		}
	}
	return h, err
}

func (h *Heater) Update(msg *Message) {
	if h.status && msg.Name == "temperature" {
		h.update <- *msg
	}
}

func (h *Heater) On(val *Value) error {
	fmt.Println("heater on")
	if val != nil {
		target, ok := val.ToFloat()
		if ok {
			h.target = target
		}
	}
	h.status = true
	h.update = make(chan Message)
	h.stop = make(chan bool)
	if h.target > 0.0 {
		go h.watchTemperature(h.update, h.stop)
	}
	return nil
}

func (h *Heater) Status() interface{} {
	return h.status
}

func (h *Heater) Off() error {
	if h.status {
		h.stop <- true
	}
	h.target = 0.0
	return nil
}

func (h *Heater) watchTemperature(update <-chan Message, stop <-chan bool) {
	h.gpio.On(nil)
	keepGoing := true
	h.duration = time.Duration(60 * time.Second)
	for keepGoing {
		select {
		case msg := <-update:
			current, ok := msg.Value.ToFloat()
			if ok {
				h.current = current
				h.toggle()
			}
		case <-stop:
			h.gpio.Off()
			keepGoing = false
		case <-time.After(h.duration):
			h.toggle()
		}
	}
}

func (h *Heater) toggle() {
	on, off := h.getDurations()
	status := h.gpio.Status().(bool)
	if on == 0 && off != 0 {
		h.gpio.Off()
		h.duration = off
	} else if status && off != 0 {
		h.gpio.Off()
		h.duration = off
	} else if !status && on != 0 {
		h.gpio.On(nil)
		h.duration = on
	}
}

//Once the heater approaches the target temperature the electricity
//is applied PWM style so the target temperature isn't overshot.
func (h *Heater) getDurations() (on time.Duration, off time.Duration) {
	diff := h.target - h.current
	if diff >= 2.0 {
		on = time.Duration(60.0 * float64(time.Second))
	} else if diff >= 1.0 {
		on = time.Duration(0.5 * float64(time.Second))
		off = time.Duration(0.5 * float64(time.Second))
	} else if diff > 0.0 {
		on = time.Duration(0.25 * float64(time.Second))
		off = time.Duration(0.75 * float64(time.Second))
	} else if diff <= 0.0 {
		off = time.Duration(60.0 * float64(time.Second))
	}
	return on, off
}
<|endoftext|>


<commit_before>package faker

import (
	"bytes"
	"github.com/raitucarp/faker/locales"
	"math/rand"
	"reflect"
	"strconv"
	"strings"
	"text/template"
	"time"
	"regexp"
)

func Fake(s string) (result string, err error) {
	s = strings.Replace(s, "#{", "#{sample ", -1)
	t := template.New("fake")
	t = t.Funcs(template.FuncMap{
		"sample": sample,
	})
	t = t.Delims("#{", "}")
	t, err = t.Parse(s)
	if err != nil {
		return
	}

	var b bytes.Buffer

	err = t.Execute(&b, data)
	if err != nil {
		return
	}

	return b.String(), nil
}

// get data from EN, and return error if not found
func defaultLocaleData(step ...string) (values []string) {
	immutable := reflect.ValueOf(defaultData)
	data := immutable.FieldByName(locales.EN).Interface()

	// field name length
	fieldLength := len(step) - 1

	for index, name := range step {

		immutable := reflect.ValueOf(data)
		val := immutable.FieldByName(name)

		if val.Kind().String() == "invalid" {
			return
		}

		if index == fieldLength {
			return val.Interface().([]string)
		} else {
			data = val.Interface()
		}
	}

	return
}

func round(val float64) int {
	if val < 0 {
		return int(val - 0.5)
	}
	return int(val + 0.5)
}

func call(field ...string) (result map[string]string) {
	// clone of data
	dat := data

	// field name length
	fieldLength := len(field) - 1

	// iterate field args
	for index, name := range field {
		immutable := reflect.ValueOf(dat)
		if index == fieldLength {
			method := immutable.MethodByName(name)
			if method.IsValid() {
				r := method.Call([]reflect.Value{})

				result = r[0].Interface().(map[string]string)
				return
			} else {
				return
			}
		} else {
			val := immutable.FieldByName(name)
			dat = val.Interface()
		}
	}
	return
}

func getData(field ...string) (values []string) {
	// clone of data
	dat := data

	// field name length
	fieldLength := len(field) - 1

	// so far step
	var step []string

	// iterate field args
	for index, name := range field {
		step = append(step, name)
		immutable := reflect.ValueOf(dat)
		val := immutable.FieldByName(name)

		// try to get data from en locale
		if val.Kind().String() == "invalid" {
			d := defaultLocaleData(step...)

			// final decision, if not found
			// return zero slice
			if len(d) <= 0 {
				return
			} else {
				return d
			}
		}

		if index == fieldLength {

			return val.Interface().([]string)
		} else {
			dat = val.Interface()
		}
	}

	return
}

func sample(list []string) string {
	if len(list) <= 0 {
		return ""
	}

	r := random(0, len(list))

	return list[r]
}

func random(min, max int) int {
	rand.Seed(time.Now().Unix() + int64(rand.Int()))
	return rand.Intn(max-min) + min
}

func typeof(p ...interface{}) (types []reflect.Kind) {

	for i := 0; i < len(p); i++ {
		t := reflect.TypeOf(p[i]).Kind()
		types = append(types, t)
	}
	return
}

func replaceSymbolsWithNumber(s string, symbol rune) (result string) {
	for _, v := range s {
		if v == symbol {
			r := rand.Intn(9)
			result += strconv.Itoa(r)
		} else {
			result += string(v)
		}
	}
	return
}

func replaceSymbols(symbol string) (s string) {
	alpha := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

	for i := 0; i < len(symbol); i++ {
		if string(symbol[i]) == "#" {
			s += strconv.Itoa(rand.Intn(9))
		} else if string(symbol[i]) == "?" {
			list := strings.Split(alpha, "")
			s += sample(list)
		} else {
			s += string(symbol[i])
		}
	}
	return s
}

func Slugify(s string) string {
	r := regexp.MustCompile(`\s`)
	newString := r.ReplaceAllString(s, `-`)

	r2 := regexp.MustCompile(`[^\w\.\-]+`)
	result := r2.ReplaceAllString(newString, "")

	return result
}
<commit_msg>go fmt<commit_after>package faker

import (
	"bytes"
	"github.com/raitucarp/faker/locales"
	"math/rand"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"text/template"
	"time"
)

func Fake(s string) (result string, err error) {
	s = strings.Replace(s, "#{", "#{sample ", -1)
	t := template.New("fake")
	t = t.Funcs(template.FuncMap{
		"sample": sample,
	})
	t = t.Delims("#{", "}")
	t, err = t.Parse(s)
	if err != nil {
		return
	}

	var b bytes.Buffer

	err = t.Execute(&b, data)
	if err != nil {
		return
	}

	return b.String(), nil
}

// get data from EN, and return error if not found
func defaultLocaleData(step ...string) (values []string) {
	immutable := reflect.ValueOf(defaultData)
	data := immutable.FieldByName(locales.EN).Interface()

	// field name length
	fieldLength := len(step) - 1

	for index, name := range step {

		immutable := reflect.ValueOf(data)
		val := immutable.FieldByName(name)

		if val.Kind().String() == "invalid" {
			return
		}

		if index == fieldLength {
			return val.Interface().([]string)
		} else {
			data = val.Interface()
		}
	}

	return
}

func round(val float64) int {
	if val < 0 {
		return int(val - 0.5)
	}
	return int(val + 0.5)
}

func call(field ...string) (result map[string]string) {
	// clone of data
	dat := data

	// field name length
	fieldLength := len(field) - 1

	// iterate field args
	for index, name := range field {
		immutable := reflect.ValueOf(dat)
		if index == fieldLength {
			method := immutable.MethodByName(name)
			if method.IsValid() {
				r := method.Call([]reflect.Value{})

				result = r[0].Interface().(map[string]string)
				return
			} else {
				return
			}
		} else {
			val := immutable.FieldByName(name)
			dat = val.Interface()
		}
	}
	return
}

func getData(field ...string) (values []string) {
	// clone of data
	dat := data

	// field name length
	fieldLength := len(field) - 1

	// so far step
	var step []string

	// iterate field args
	for index, name := range field {
		step = append(step, name)
		immutable := reflect.ValueOf(dat)
		val := immutable.FieldByName(name)

		// try to get data from en locale
		if val.Kind().String() == "invalid" {
			d := defaultLocaleData(step...)

			// final decision, if not found
			// return zero slice
			if len(d) <= 0 {
				return
			} else {
				return d
			}
		}

		if index == fieldLength {

			return val.Interface().([]string)
		} else {
			dat = val.Interface()
		}
	}

	return
}

func sample(list []string) string {
	if len(list) <= 0 {
		return ""
	}

	r := random(0, len(list))

	return list[r]
}

func random(min, max int) int {
	rand.Seed(time.Now().Unix() + int64(rand.Int()))
	return rand.Intn(max-min) + min
}

func typeof(p ...interface{}) (types []reflect.Kind) {

	for i := 0; i < len(p); i++ {
		t := reflect.TypeOf(p[i]).Kind()
		types = append(types, t)
	}
	return
}

func replaceSymbolsWithNumber(s string, symbol rune) (result string) {
	for _, v := range s {
		if v == symbol {
			r := rand.Intn(9)
			result += strconv.Itoa(r)
		} else {
			result += string(v)
		}
	}
	return
}

func replaceSymbols(symbol string) (s string) {
	alpha := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

	for i := 0; i < len(symbol); i++ {
		if string(symbol[i]) == "#" {
			s += strconv.Itoa(rand.Intn(9))
		} else if string(symbol[i]) == "?" {
			list := strings.Split(alpha, "")
			s += sample(list)
		} else {
			s += string(symbol[i])
		}
	}
	return s
}

func Slugify(s string) string {
	r := regexp.MustCompile(`\s`)
	newString := r.ReplaceAllString(s, `-`)

	r2 := regexp.MustCompile(`[^\w\.\-]+`)
	result := r2.ReplaceAllString(newString, "")

	return result
}
<|endoftext|>


<commit_before>package siri

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/af83/edwig/logger"
	"github.com/jbowtie/gokogiri/xml"
)

type XMLStructure struct {
	node xml.Node
}

type ResponseXMLStructure struct {
	XMLStructure

	address                   string
	producerRef               string
	requestMessageRef         string
	responseMessageIdentifier string
	responseTimestamp         time.Time
}

func (xmlStruct *XMLStructure) findNode(localName string) xml.Node {
	xpath := fmt.Sprintf("//*[local-name()='%s']", localName)
	nodes, err := xmlStruct.node.Search(xpath)
	if err != nil {
		logger.Log.Panicf("Error while parsing XML: %v", err)
	}
	if len(nodes) == 0 {
		return nil
	}
	return nodes[0]
}

func (xmlStruct *XMLStructure) findNodes(localName string) []xml.Node {
	xpath := fmt.Sprintf("//*[local-name()='%s']", localName)
	nodes, err := xmlStruct.node.Search(xpath)
	if err != nil {
		logger.Log.Panicf("Error while parsing XML: %v", err)
	}
	if len(nodes) == 0 {
		return nil
	}
	return nodes
}

// TODO: See how to handle errors
func (xmlStruct *XMLStructure) findStringChildContent(localName string) string {
	node := xmlStruct.findNode(localName)
	if node == nil {
		return ""
	}
	return strings.TrimSpace(node.Content())
}

func (xmlStruct *XMLStructure) findTimeChildContent(localName string) time.Time {
	node := xmlStruct.findNode(localName)
	if node == nil {
		return time.Time{}
	}
	t, err := time.Parse("2006-01-02T15:04:05.000Z07:00", strings.TrimSpace(node.Content()))
	if err != nil {
		logger.Log.Panicf("Error while parsing XML: %v", err)
	}
	return t
}

func (xmlStruct *XMLStructure) findBoolChildContent(localName string) bool {
	node := xmlStruct.findNode(localName)
	if node == nil {
		return false
	}
	s, err := strconv.ParseBool(strings.TrimSpace(node.Content()))
	if err != nil {
		logger.Log.Panicf("Error while parsing XML: %v", err)
	}
	return s
}

func (xmlStruct *XMLStructure) findIntChildContent(localName string) int {
	node := xmlStruct.findNode(localName)
	if node == nil {
		return 0
	}
	s, err := strconv.Atoi(strings.TrimSpace(node.Content()))
	if err != nil {
		logger.Log.Panicf("Error while parsing XML: %v", err)
	}
	return s
}

func (xmlStruct *XMLStructure) RawXML() string {
	return xmlStruct.node.String()
}

func (response *ResponseXMLStructure) Address() string {
	if response.address == "" {
		response.address = response.findStringChildContent("Address")
	}
	return response.address
}

func (response *ResponseXMLStructure) ProducerRef() string {
	if response.producerRef == "" {
		response.producerRef = response.findStringChildContent("ProducerRef")
	}
	return response.producerRef
}
func (response *ResponseXMLStructure) RequestMessageRef() string {
	if response.requestMessageRef == "" {
		response.requestMessageRef = response.findStringChildContent("RequestMessageRef")
	}
	return response.requestMessageRef
}

func (response *ResponseXMLStructure) ResponseMessageIdentifier() string {
	if response.responseMessageIdentifier == "" {
		response.responseMessageIdentifier = response.findStringChildContent("ResponseMessageIdentifier")
	}
	return response.responseMessageIdentifier
}

func (response *ResponseXMLStructure) ResponseTimestamp() time.Time {
	if response.responseTimestamp.IsZero() {
		response.responseTimestamp = response.findTimeChildContent("ResponseTimestamp")
	}
	return response.responseTimestamp
}
<commit_msg>fix xpath in xml strucutre find methods<commit_after>package siri

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/af83/edwig/logger"
	"github.com/jbowtie/gokogiri/xml"
)

type XMLStructure struct {
	node xml.Node
}

type ResponseXMLStructure struct {
	XMLStructure

	address                   string
	producerRef               string
	requestMessageRef         string
	responseMessageIdentifier string
	responseTimestamp         time.Time
}

func (xmlStruct *XMLStructure) findNode(localName string) xml.Node {
	xpath := fmt.Sprintf(".//*[local-name()='%s']", localName)
	nodes, err := xmlStruct.node.Search(xpath)
	if err != nil {
		logger.Log.Panicf("Error while parsing XML: %v", err)
	}
	if len(nodes) == 0 {
		return nil
	}
	return nodes[0]
}

func (xmlStruct *XMLStructure) findNodes(localName string) []xml.Node {
	xpath := fmt.Sprintf(".//*[local-name()='%s']", localName)
	nodes, err := xmlStruct.node.Search(xpath)
	if err != nil {
		logger.Log.Panicf("Error while parsing XML: %v", err)
	}
	if len(nodes) == 0 {
		return nil
	}
	return nodes
}

// TODO: See how to handle errors
func (xmlStruct *XMLStructure) findStringChildContent(localName string) string {
	node := xmlStruct.findNode(localName)
	if node == nil {
		return ""
	}
	return strings.TrimSpace(node.Content())
}

func (xmlStruct *XMLStructure) findTimeChildContent(localName string) time.Time {
	node := xmlStruct.findNode(localName)
	if node == nil {
		return time.Time{}
	}
	t, err := time.Parse("2006-01-02T15:04:05.000Z07:00", strings.TrimSpace(node.Content()))
	if err != nil {
		logger.Log.Panicf("Error while parsing XML: %v", err)
	}
	return t
}

func (xmlStruct *XMLStructure) findBoolChildContent(localName string) bool {
	node := xmlStruct.findNode(localName)
	if node == nil {
		return false
	}
	s, err := strconv.ParseBool(strings.TrimSpace(node.Content()))
	if err != nil {
		logger.Log.Panicf("Error while parsing XML: %v", err)
	}
	return s
}

func (xmlStruct *XMLStructure) findIntChildContent(localName string) int {
	node := xmlStruct.findNode(localName)
	if node == nil {
		return 0
	}
	s, err := strconv.Atoi(strings.TrimSpace(node.Content()))
	if err != nil {
		logger.Log.Panicf("Error while parsing XML: %v", err)
	}
	return s
}

func (xmlStruct *XMLStructure) RawXML() string {
	return xmlStruct.node.String()
}

func (response *ResponseXMLStructure) Address() string {
	if response.address == "" {
		response.address = response.findStringChildContent("Address")
	}
	return response.address
}

func (response *ResponseXMLStructure) ProducerRef() string {
	if response.producerRef == "" {
		response.producerRef = response.findStringChildContent("ProducerRef")
	}
	return response.producerRef
}
func (response *ResponseXMLStructure) RequestMessageRef() string {
	if response.requestMessageRef == "" {
		response.requestMessageRef = response.findStringChildContent("RequestMessageRef")
	}
	return response.requestMessageRef
}

func (response *ResponseXMLStructure) ResponseMessageIdentifier() string {
	if response.responseMessageIdentifier == "" {
		response.responseMessageIdentifier = response.findStringChildContent("ResponseMessageIdentifier")
	}
	return response.responseMessageIdentifier
}

func (response *ResponseXMLStructure) ResponseTimestamp() time.Time {
	if response.responseTimestamp.IsZero() {
		response.responseTimestamp = response.findTimeChildContent("ResponseTimestamp")
	}
	return response.responseTimestamp
}
<|endoftext|>


<commit_before>package httpseverywhere

import (
	"net/url"
	"sync"
	"sync/atomic"
	"time"

	"github.com/armon/go-radix"
	"github.com/getlantern/golog"
	"github.com/getlantern/mtime"
)

// Rewrite changes an HTTP URL to rewrite.
type Rewrite func(url *url.URL) (string, bool)

type httpse struct {
	log             golog.Logger
	initOnce        sync.Once
	wildcardTargets atomic.Value // *radix.Tree
	plainTargets    atomic.Value // map[string]*ruleset
	stats           *httpseStats
	statsCh         chan *timing
}

type httpseStats struct {
	runs      int64
	totalTime int64
	max       int64
	maxHost   string
}

type timing struct {
	host string
	dur  time.Duration
}

// Default returns a lazily-initialized Rewrite using the default rules
func Default() Rewrite {
	h := newEmpty()
	h.initAsync()
	return h.rewrite
}

func newEmpty() *httpse {
	h := &httpse{
		log:     golog.LoggerFor("httpse"),
		stats:   &httpseStats{},
		statsCh: make(chan *timing),
	}
	go h.readTimings()
	h.wildcardTargets.Store(radix.New())
	h.plainTargets.Store(make(map[string]*ruleset))
	return h
}

func (h *httpse) init() {
	d := newDeserializer()
	plain, wildcard, err := d.newRulesets()
	if err != nil {
		return
	}
	h.plainTargets.Store(plain)
	h.wildcardTargets.Store(wildcard)
}

func (h *httpse) initAsync() {
	h.initOnce.Do(func() {
		go h.init()
	})
}

func (h *httpse) rewrite(url *url.URL) (string, bool) {
	if url.Scheme != "http" {
		return "", false
	}

	start := mtime.Now()
	defer func() {
		h.statsCh <- &timing{
			dur:  mtime.Now().Sub(start),
			host: url.String(),
		}
	}()
	if val, ok := h.plainTargets.Load().(map[string]*ruleset)[url.Host]; ok {
		if r, hit := h.rewriteWithRuleset(url, val); hit {
			return r, hit
		}
	}
	// Check prefixes (with reversing the URL host)
	if _, val, match := h.wildcardTargets.Load().(*radix.Tree).LongestPrefix(reverse(url.Host)); match {
		if r, hit := h.rewriteWithRuleset(url, val.(*ruleset)); hit {
			return r, hit
		}
	}

	// Check suffixes last because there are far fewer suffix rules.
	if _, val, match := h.wildcardTargets.Load().(*radix.Tree).LongestPrefix(url.Host); match {
		return h.rewriteWithRuleset(url, val.(*ruleset))
	}

	return "", false
}

// rewriteWithRuleset converts the given URL to HTTPS if there is an associated
// rule for it.
func (h *httpse) rewriteWithRuleset(fullURL *url.URL, r *ruleset) (string, bool) {
	url := fullURL.String()
	for _, exclude := range r.exclusion {
		if exclude.pattern.MatchString(url) {
			return "", false
		}
	}
	for _, rule := range r.rule {
		if rule.from.MatchString(url) {
			return rule.from.ReplaceAllString(url, rule.to), true
		}
	}
	return "", false
}

func reverse(input string) string {
	n := 0
	runes := make([]rune, len(input)+1)
	// Add a dot prefix to make sure we're only operating on subdomains
	runes[0] = '.'
	runes = runes[1:]
	for _, r := range input {
		runes[n] = r
		n++
	}
	runes = runes[0:n]
	// Reverse
	for i := 0; i < n/2; i++ {
		runes[i], runes[n-1-i] = runes[n-1-i], runes[i]
	}
	// Convert back to UTF-8.
	return string(runes)
}

func (h *httpse) readTimings() {
	for t := range h.statsCh {
		h.addTiming(t)
	}
}

func (h *httpse) addTiming(t *timing) {
	ms := t.dur.Nanoseconds() / int64(time.Millisecond)
	h.stats.runs++
	h.stats.totalTime += ms
	if ms > h.stats.max {
		h.stats.max = ms
		h.stats.maxHost = t.host
	}
	h.log.Debugf("Average running time: %vms", float64(h.stats.totalTime/h.stats.runs))
	h.log.Debugf("Max running time: %vms for host: %v", h.stats.max, h.stats.maxHost)
}
<commit_msg>made channel buffered<commit_after>package httpseverywhere

import (
	"net/url"
	"sync"
	"sync/atomic"
	"time"

	"github.com/armon/go-radix"
	"github.com/getlantern/golog"
	"github.com/getlantern/mtime"
)

// Rewrite changes an HTTP URL to rewrite.
type Rewrite func(url *url.URL) (string, bool)

type httpse struct {
	log             golog.Logger
	initOnce        sync.Once
	wildcardTargets atomic.Value // *radix.Tree
	plainTargets    atomic.Value // map[string]*ruleset
	stats           *httpseStats
	statsCh         chan *timing
}

type httpseStats struct {
	runs      int64
	totalTime int64
	max       int64
	maxHost   string
}

type timing struct {
	host string
	dur  time.Duration
}

// Default returns a lazily-initialized Rewrite using the default rules
func Default() Rewrite {
	h := newEmpty()
	h.initAsync()
	return h.rewrite
}

func newEmpty() *httpse {
	h := &httpse{
		log:     golog.LoggerFor("httpse"),
		stats:   &httpseStats{},
		statsCh: make(chan *timing, 100),
	}
	go h.readTimings()
	h.wildcardTargets.Store(radix.New())
	h.plainTargets.Store(make(map[string]*ruleset))
	return h
}

func (h *httpse) init() {
	d := newDeserializer()
	plain, wildcard, err := d.newRulesets()
	if err != nil {
		return
	}
	h.plainTargets.Store(plain)
	h.wildcardTargets.Store(wildcard)
}

func (h *httpse) initAsync() {
	h.initOnce.Do(func() {
		go h.init()
	})
}

func (h *httpse) rewrite(url *url.URL) (string, bool) {
	if url.Scheme != "http" {
		return "", false
	}

	start := mtime.Now()
	defer func() {
		h.statsCh <- &timing{
			dur:  mtime.Now().Sub(start),
			host: url.String(),
		}
	}()
	if val, ok := h.plainTargets.Load().(map[string]*ruleset)[url.Host]; ok {
		if r, hit := h.rewriteWithRuleset(url, val); hit {
			return r, hit
		}
	}
	// Check prefixes (with reversing the URL host)
	if _, val, match := h.wildcardTargets.Load().(*radix.Tree).LongestPrefix(reverse(url.Host)); match {
		if r, hit := h.rewriteWithRuleset(url, val.(*ruleset)); hit {
			return r, hit
		}
	}

	// Check suffixes last because there are far fewer suffix rules.
	if _, val, match := h.wildcardTargets.Load().(*radix.Tree).LongestPrefix(url.Host); match {
		return h.rewriteWithRuleset(url, val.(*ruleset))
	}

	return "", false
}

// rewriteWithRuleset converts the given URL to HTTPS if there is an associated
// rule for it.
func (h *httpse) rewriteWithRuleset(fullURL *url.URL, r *ruleset) (string, bool) {
	url := fullURL.String()
	for _, exclude := range r.exclusion {
		if exclude.pattern.MatchString(url) {
			return "", false
		}
	}
	for _, rule := range r.rule {
		if rule.from.MatchString(url) {
			return rule.from.ReplaceAllString(url, rule.to), true
		}
	}
	return "", false
}

func reverse(input string) string {
	n := 0
	runes := make([]rune, len(input)+1)
	// Add a dot prefix to make sure we're only operating on subdomains
	runes[0] = '.'
	runes = runes[1:]
	for _, r := range input {
		runes[n] = r
		n++
	}
	runes = runes[0:n]
	// Reverse
	for i := 0; i < n/2; i++ {
		runes[i], runes[n-1-i] = runes[n-1-i], runes[i]
	}
	// Convert back to UTF-8.
	return string(runes)
}

func (h *httpse) readTimings() {
	for t := range h.statsCh {
		h.addTiming(t)
	}
}

func (h *httpse) addTiming(t *timing) {
	ms := t.dur.Nanoseconds() / int64(time.Millisecond)
	h.stats.runs++
	h.stats.totalTime += ms
	if ms > h.stats.max {
		h.stats.max = ms
		h.stats.maxHost = t.host
	}
	h.log.Debugf("Average running time: %vms", float64(h.stats.totalTime/h.stats.runs))
	h.log.Debugf("Max running time: %vms for host: %v", h.stats.max, h.stats.maxHost)
}
<|endoftext|>


<commit_before>package main

import (

)

func main() {

}<commit_msg>Hello World, print to screen example<commit_after>package main

import (
	"fmt"
	"os"
)

func main() {
	fmt.Fprintf(os.Stdout, "Hello World\n")
}<|endoftext|>