<commit_before>package workflowtrigger

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

	"github.com/caicloud/cyclone/pkg/k8s/clientset"
	"github.com/pkg/errors"
	"github.com/robfig/cron"
	"github.com/satori/go.uuid"
	log "github.com/sirupsen/logrus"

	"github.com/caicloud/cyclone/pkg/apis/cyclone/v1alpha1"
)

const (
	KeyTemplate = "%s/%s"
)

type CronTrigger struct {
	Cron                *cron.Cron
	IsRunning           bool
	SuccCount           int
	FailCount           int
	Namespace           string
	WorkflowTriggerName string
	WorkflowRun         *v1alpha1.WorkflowRun
	Manage              *CronTriggerManager
}

type CronTriggerManager struct {
	Client         clientset.Interface
	CronTriggerMap map[string]*CronTrigger
	mutex          sync.Mutex
}

func NewTriggerManager(client clientset.Interface) *CronTriggerManager {
	return &CronTriggerManager{
		Client:         client,
		CronTriggerMap: make(map[string]*CronTrigger),
		mutex:          sync.Mutex{},
	}
}

func (trigger *CronTrigger) getKeyFromTrigger() string {
	return fmt.Sprintf(KeyTemplate, trigger.Namespace, trigger.WorkflowTriggerName)
}

func (m *CronTriggerManager) AddTrigger(trigger *CronTrigger) {
	wftKey := trigger.getKeyFromTrigger()
	m.mutex.Lock()
	defer m.mutex.Unlock()
	if wft, ok := m.CronTriggerMap[wftKey]; ok {
		// this situation may not happen for k8s will do same name check
		log.Warnf("failed to add cronTrigger, already exists: %+v\n", wft)
	} else {
		m.CronTriggerMap[wftKey] = trigger
	}
}

func (m *CronTriggerManager) DeleteTrigger(wftKey string) {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	if wft, ok := m.CronTriggerMap[wftKey]; ok {
		wft.Cron.Stop()
		wft.IsRunning = false
		delete(m.CronTriggerMap, wftKey)
	} else {
		log.Warnf("failed to delete cronTrigger(%s), not exist\n", wftKey)
	}
}

func ToWorkflowTrigger(obj interface{}) (*v1alpha1.WorkflowTrigger, error) {

	wft, ok := obj.(*v1alpha1.WorkflowTrigger)
	if !ok {
		return nil, errors.New(fmt.Sprintf("I want type: WorkflowTrigger, but it is: %T", obj))
	} else {
		return wft, nil
	}
}

func (c *CronTrigger) Run() {

	c.WorkflowRun.Name = c.WorkflowTriggerName + "-" + strings.Replace(uuid.NewV1().String(), "-", "", -1)
	_, err := c.Manage.Client.CycloneV1alpha1().WorkflowRuns(c.Namespace).Create(c.WorkflowRun)
	if err != nil {
		c.FailCount++
		log.Warnf("can not create WorkflowRun: %s", err)
	} else {
		c.SuccCount++
	}
}

func getParaValue(items []v1alpha1.ParameterItem, key string) (string, bool) {
	for _, item := range items {
		if item.Name == key {
			return item.Value, true
		}
	}
	return "", false
}

func (m *CronTriggerManager) CreateCron(wft *v1alpha1.WorkflowTrigger) {

	schedule, has := getParaValue(wft.Spec.Parameters, "schedule")
	if !has {
		log.WithField("wft", wft.Name).Warn("Parameter 'schedule' not set in WorkflowTrigger spec")
		return
	}

	timezone, has := getParaValue(wft.Spec.Parameters, "timezone")
	if !has {
		timezone = "0"
	}

	minuteOffUTC, err := strconv.Atoi(timezone)
	if err != nil {
		log.Warnf("can not parse timezone(%s) to int", timezone)
		minuteOffUTC = 0
	}

	ct := &CronTrigger{
		Namespace:           wft.Namespace,
		WorkflowTriggerName: wft.Name,
	}

	wfr := &v1alpha1.WorkflowRun{
		Spec: wft.Spec.WorkflowRunSpec,
	}

	ct.WorkflowRun = wfr

	c := cron.NewWithLocation(time.FixedZone("userZone", -1*60*minuteOffUTC))
	err = c.AddJob(schedule, ct)
	if err != nil {
		log.Errorf("can not create Cron job: %s", err)
		return
	}

	ct.Cron = c
	ct.Manage = m
	m.AddTrigger(ct)

	if !wft.Spec.Disabled {
		ct.Cron.Start()
		ct.IsRunning = true
	}
}

func (m *CronTriggerManager) UpdateCron(wft *v1alpha1.WorkflowTrigger) {
	m.DeleteCron(wft)
	m.CreateCron(wft)
}

func (m *CronTriggerManager) DeleteCron(wft *v1alpha1.WorkflowTrigger) {
	wftKey := getKeyFromWorkflowTrigger(wft)
	m.DeleteTrigger(wftKey)
}

func getKeyFromWorkflowTrigger(wft *v1alpha1.WorkflowTrigger) string {
	return fmt.Sprintf(KeyTemplate, wft.Namespace, wft.Name)
}
<commit_msg>fix(trigger): description for the new key: timeZoneOffset<commit_after>package workflowtrigger

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

	"github.com/caicloud/cyclone/pkg/k8s/clientset"
	"github.com/pkg/errors"
	"github.com/robfig/cron"
	"github.com/satori/go.uuid"
	log "github.com/sirupsen/logrus"

	"github.com/caicloud/cyclone/pkg/apis/cyclone/v1alpha1"
)

const (
	KeyTemplate = "%s/%s"

	// the time zone difference, in minutes, from current locale (host system settings) to UTC
	// -480 for Asia/Shanghai
	ParamTimeZoneOffset = "timezone"
	ParamSchedule       = "schedule"
)

type CronTrigger struct {
	Cron                *cron.Cron
	IsRunning           bool
	SuccCount           int
	FailCount           int
	Namespace           string
	WorkflowTriggerName string
	WorkflowRun         *v1alpha1.WorkflowRun
	Manage              *CronTriggerManager
}

type CronTriggerManager struct {
	Client         clientset.Interface
	CronTriggerMap map[string]*CronTrigger
	mutex          sync.Mutex
}

func NewTriggerManager(client clientset.Interface) *CronTriggerManager {
	return &CronTriggerManager{
		Client:         client,
		CronTriggerMap: make(map[string]*CronTrigger),
		mutex:          sync.Mutex{},
	}
}

func (trigger *CronTrigger) getKeyFromTrigger() string {
	return fmt.Sprintf(KeyTemplate, trigger.Namespace, trigger.WorkflowTriggerName)
}

func (m *CronTriggerManager) AddTrigger(trigger *CronTrigger) {
	wftKey := trigger.getKeyFromTrigger()
	m.mutex.Lock()
	defer m.mutex.Unlock()
	if wft, ok := m.CronTriggerMap[wftKey]; ok {
		// this situation may not happen for k8s will do same name check
		log.Warnf("failed to add cronTrigger, already exists: %+v\n", wft)
	} else {
		m.CronTriggerMap[wftKey] = trigger
	}
}

func (m *CronTriggerManager) DeleteTrigger(wftKey string) {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	if wft, ok := m.CronTriggerMap[wftKey]; ok {
		wft.Cron.Stop()
		wft.IsRunning = false
		delete(m.CronTriggerMap, wftKey)
	} else {
		log.Warnf("failed to delete cronTrigger(%s), not exist\n", wftKey)
	}
}

func ToWorkflowTrigger(obj interface{}) (*v1alpha1.WorkflowTrigger, error) {

	wft, ok := obj.(*v1alpha1.WorkflowTrigger)
	if !ok {
		return nil, errors.New(fmt.Sprintf("I want type: WorkflowTrigger, but it is: %T", obj))
	} else {
		return wft, nil
	}
}

func (c *CronTrigger) Run() {

	c.WorkflowRun.Name = c.WorkflowTriggerName + "-" + strings.Replace(uuid.NewV1().String(), "-", "", -1)
	_, err := c.Manage.Client.CycloneV1alpha1().WorkflowRuns(c.Namespace).Create(c.WorkflowRun)
	if err != nil {
		c.FailCount++
		log.Warnf("can not create WorkflowRun: %s", err)
	} else {
		c.SuccCount++
	}
}

func getParamValue(items []v1alpha1.ParameterItem, key string) (string, bool) {
	for _, item := range items {
		if item.Name == key {
			return item.Value, true
		}
	}
	return "", false
}

func (m *CronTriggerManager) CreateCron(wft *v1alpha1.WorkflowTrigger) {

	schedule, has := getParamValue(wft.Spec.Parameters, ParamSchedule)
	if !has {
		log.WithField("wft", wft.Name).Warn("Parameter 'schedule' not set in WorkflowTrigger spec")
		return
	}

	timezone, has := getParamValue(wft.Spec.Parameters, ParamTimeZoneOffset)
	if !has {
		timezone = "0"
	}

	minuteOffUTC, err := strconv.Atoi(timezone)
	if err != nil {
		log.Warnf("can not parse timezone(%s) to int", timezone)
		minuteOffUTC = 0
	}

	ct := &CronTrigger{
		Namespace:           wft.Namespace,
		WorkflowTriggerName: wft.Name,
	}

	wfr := &v1alpha1.WorkflowRun{
		Spec: wft.Spec.WorkflowRunSpec,
	}

	ct.WorkflowRun = wfr

	c := cron.NewWithLocation(time.FixedZone("userZone", -1*60*minuteOffUTC))
	err = c.AddJob(schedule, ct)
	if err != nil {
		log.Errorf("can not create Cron job: %s", err)
		return
	}

	ct.Cron = c
	ct.Manage = m
	m.AddTrigger(ct)

	if !wft.Spec.Disabled {
		ct.Cron.Start()
		ct.IsRunning = true
	}
}

func (m *CronTriggerManager) UpdateCron(wft *v1alpha1.WorkflowTrigger) {
	m.DeleteCron(wft)
	m.CreateCron(wft)
}

func (m *CronTriggerManager) DeleteCron(wft *v1alpha1.WorkflowTrigger) {
	wftKey := getKeyFromWorkflowTrigger(wft)
	m.DeleteTrigger(wftKey)
}

func getKeyFromWorkflowTrigger(wft *v1alpha1.WorkflowTrigger) string {
	return fmt.Sprintf(KeyTemplate, wft.Namespace, wft.Name)
}
<|endoftext|>


<commit_before>package workflowtrigger

import (
	"fmt"
	"sync"

	"github.com/robfig/cron"
	log "github.com/sirupsen/logrus"
	errors2 "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/util/rand"

	"github.com/caicloud/cyclone/pkg/apis/cyclone/v1alpha1"
	"github.com/caicloud/cyclone/pkg/k8s/clientset"
	s_common "github.com/caicloud/cyclone/pkg/server/common"
	"github.com/caicloud/cyclone/pkg/workflow/common"
)

const (
	// KeyTemplate ...
	KeyTemplate = "%s/%s"
)

// CronTrigger ...
type CronTrigger struct {
	Cron                *cron.Cron
	IsRunning           bool
	SuccCount           int
	FailCount           int
	Namespace           string
	WorkflowTriggerName string
	WorkflowRun         *v1alpha1.WorkflowRun
	Manage              *CronTriggerManager
}

// CronTriggerManager represents manager for cron triggers.
type CronTriggerManager struct {
	Client         clientset.Interface
	CronTriggerMap map[string]*CronTrigger
	mutex          sync.Mutex
}

// NewTriggerManager returns a cron trigger manager.
func NewTriggerManager(client clientset.Interface) *CronTriggerManager {
	return &CronTriggerManager{
		Client:         client,
		CronTriggerMap: make(map[string]*CronTrigger),
		mutex:          sync.Mutex{},
	}
}

// AddTrigger adds one cron trigger.
func (m *CronTriggerManager) AddTrigger(trigger *CronTrigger) {
	wftKey := trigger.getKeyFromTrigger()
	m.mutex.Lock()
	defer m.mutex.Unlock()
	if wft, ok := m.CronTriggerMap[wftKey]; ok {
		// this situation may not happen for k8s will do same name check
		log.Warnf("failed to add cronTrigger, already exists: %+v\n", wft)
	} else {
		m.CronTriggerMap[wftKey] = trigger
	}
}

// DeleteTrigger deletes one cron trigger.
func (m *CronTriggerManager) DeleteTrigger(wftKey string) {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	if wft, ok := m.CronTriggerMap[wftKey]; ok {
		wft.Cron.Stop()
		wft.IsRunning = false
		delete(m.CronTriggerMap, wftKey)
	} else {
		log.Warnf("failed to delete cronTrigger(%s), not exist\n", wftKey)
	}
}

// ToWorkflowTrigger converts to workflow trigger.
func ToWorkflowTrigger(obj interface{}) (*v1alpha1.WorkflowTrigger, error) {

	wft, ok := obj.(*v1alpha1.WorkflowTrigger)
	if !ok {
		return nil, fmt.Errorf("I want type: WorkflowTrigger, but it is: %T", obj)
	}

	return wft, nil
}

func (t *CronTrigger) getKeyFromTrigger() string {
	return fmt.Sprintf(KeyTemplate, t.Namespace, t.WorkflowTriggerName)
}

// Run triggers the workflows.
func (t *CronTrigger) Run() {
	if t.WorkflowRun.Labels == nil {
		t.WorkflowRun.Labels = make(map[string]string)
	}
	t.WorkflowRun.Labels[common.WorkflowNameLabelName] = t.WorkflowRun.Spec.WorkflowRef.Name
	t.WorkflowRun.Annotations[s_common.AnnotationTrigger] = s_common.CronTimerTrigger

	for {
		t.WorkflowRun.Name = fmt.Sprintf("%s-%s", t.WorkflowTriggerName, rand.String(5))
		_, err := t.Manage.Client.CycloneV1alpha1().WorkflowRuns(t.Namespace).Create(t.WorkflowRun)
		if err != nil {
			if errors2.IsAlreadyExists(err) {
				continue
			} else {
				t.FailCount++
				log.Warnf("can not create WorkflowRun: %s", err)
				break
			}
		} else {
			t.SuccCount++
			break
		}
	}
}

func getParamValue(items []v1alpha1.ParameterItem, key string) (string, bool) {
	for _, item := range items {
		if item.Name == key {
			return item.Value, true
		}
	}
	return "", false
}

// CreateCron creates a cron trigger from workflow trigger, and add it to cron trigger manager.
func (m *CronTriggerManager) CreateCron(wft *v1alpha1.WorkflowTrigger) {
	ct := &CronTrigger{
		Namespace:           wft.Namespace,
		WorkflowTriggerName: wft.Name,
	}

	wfr := &v1alpha1.WorkflowRun{
		Spec: wft.Spec.WorkflowRunSpec,
	}

	ct.WorkflowRun = wfr

	c := cron.New()
	if err := c.AddJob(wft.Spec.Cron.Schedule, ct); err != nil {
		log.Errorf("can not create Cron job: %s", err)
		return
	}

	ct.Cron = c
	ct.Manage = m
	m.AddTrigger(ct)

	if !wft.Spec.Disabled {
		ct.Cron.Start()
		ct.IsRunning = true
	}
}

// UpdateCron updates cron trigger based on workflow trigger.
func (m *CronTriggerManager) UpdateCron(wft *v1alpha1.WorkflowTrigger) {
	m.DeleteCron(wft)
	m.CreateCron(wft)
}

// DeleteCron deletes cron trigger from cron trigger manager.
func (m *CronTriggerManager) DeleteCron(wft *v1alpha1.WorkflowTrigger) {
	wftKey := getKeyFromWorkflowTrigger(wft)
	m.DeleteTrigger(wftKey)
}

func getKeyFromWorkflowTrigger(wft *v1alpha1.WorkflowTrigger) string {
	return fmt.Sprintf(KeyTemplate, wft.Namespace, wft.Name)
}
<commit_msg>fix(engine): fix cron trigger (#870)<commit_after>package workflowtrigger

import (
	"fmt"
	"sync"

	"github.com/robfig/cron"
	log "github.com/sirupsen/logrus"
	errors2 "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/util/rand"

	"github.com/caicloud/cyclone/pkg/apis/cyclone/v1alpha1"
	"github.com/caicloud/cyclone/pkg/k8s/clientset"
	s_common "github.com/caicloud/cyclone/pkg/server/common"
	"github.com/caicloud/cyclone/pkg/workflow/common"
)

const (
	// KeyTemplate ...
	KeyTemplate = "%s/%s"
)

// CronTrigger ...
type CronTrigger struct {
	Cron                *cron.Cron
	IsRunning           bool
	SuccCount           int
	FailCount           int
	Namespace           string
	WorkflowTriggerName string
	WorkflowRun         *v1alpha1.WorkflowRun
	Manage              *CronTriggerManager
}

// CronTriggerManager represents manager for cron triggers.
type CronTriggerManager struct {
	Client         clientset.Interface
	CronTriggerMap map[string]*CronTrigger
	mutex          sync.Mutex
}

// NewTriggerManager returns a cron trigger manager.
func NewTriggerManager(client clientset.Interface) *CronTriggerManager {
	return &CronTriggerManager{
		Client:         client,
		CronTriggerMap: make(map[string]*CronTrigger),
		mutex:          sync.Mutex{},
	}
}

// AddTrigger adds one cron trigger.
func (m *CronTriggerManager) AddTrigger(trigger *CronTrigger) {
	wftKey := trigger.getKeyFromTrigger()
	m.mutex.Lock()
	defer m.mutex.Unlock()
	if wft, ok := m.CronTriggerMap[wftKey]; ok {
		// this situation may not happen for k8s will do same name check
		log.Warnf("failed to add cronTrigger, already exists: %+v\n", wft)
	} else {
		m.CronTriggerMap[wftKey] = trigger
	}
}

// DeleteTrigger deletes one cron trigger.
func (m *CronTriggerManager) DeleteTrigger(wftKey string) {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	if wft, ok := m.CronTriggerMap[wftKey]; ok {
		wft.Cron.Stop()
		wft.IsRunning = false
		delete(m.CronTriggerMap, wftKey)
	} else {
		log.Warnf("failed to delete cronTrigger(%s), not exist\n", wftKey)
	}
}

// ToWorkflowTrigger converts to workflow trigger.
func ToWorkflowTrigger(obj interface{}) (*v1alpha1.WorkflowTrigger, error) {

	wft, ok := obj.(*v1alpha1.WorkflowTrigger)
	if !ok {
		return nil, fmt.Errorf("I want type: WorkflowTrigger, but it is: %T", obj)
	}

	return wft, nil
}

func (t *CronTrigger) getKeyFromTrigger() string {
	return fmt.Sprintf(KeyTemplate, t.Namespace, t.WorkflowTriggerName)
}

// Run triggers the workflows.
func (t *CronTrigger) Run() {
	if t.WorkflowRun.Labels == nil {
		t.WorkflowRun.Labels = make(map[string]string)
	}
	t.WorkflowRun.Labels[common.WorkflowNameLabelName] = t.WorkflowRun.Spec.WorkflowRef.Name
	if t.WorkflowRun.Annotations == nil {
		t.WorkflowRun.Annotations = make(map[string]string)
	}
	t.WorkflowRun.Annotations[s_common.AnnotationTrigger] = s_common.CronTimerTrigger

	for {
		t.WorkflowRun.Name = fmt.Sprintf("%s-%s", t.WorkflowTriggerName, rand.String(5))
		_, err := t.Manage.Client.CycloneV1alpha1().WorkflowRuns(t.Namespace).Create(t.WorkflowRun)
		if err != nil {
			if errors2.IsAlreadyExists(err) {
				continue
			} else {
				t.FailCount++
				log.Warnf("can not create WorkflowRun: %s", err)
				break
			}
		} else {
			t.SuccCount++
			break
		}
	}
}

func getParamValue(items []v1alpha1.ParameterItem, key string) (string, bool) {
	for _, item := range items {
		if item.Name == key {
			return item.Value, true
		}
	}
	return "", false
}

// CreateCron creates a cron trigger from workflow trigger, and add it to cron trigger manager.
func (m *CronTriggerManager) CreateCron(wft *v1alpha1.WorkflowTrigger) {
	ct := &CronTrigger{
		Namespace:           wft.Namespace,
		WorkflowTriggerName: wft.Name,
	}

	wfr := &v1alpha1.WorkflowRun{
		Spec: wft.Spec.WorkflowRunSpec,
	}

	ct.WorkflowRun = wfr

	c := cron.New()
	if err := c.AddJob(wft.Spec.Cron.Schedule, ct); err != nil {
		log.Errorf("can not create Cron job: %s", err)
		return
	}

	ct.Cron = c
	ct.Manage = m
	m.AddTrigger(ct)

	if !wft.Spec.Disabled {
		ct.Cron.Start()
		ct.IsRunning = true
	}
}

// UpdateCron updates cron trigger based on workflow trigger.
func (m *CronTriggerManager) UpdateCron(wft *v1alpha1.WorkflowTrigger) {
	m.DeleteCron(wft)
	m.CreateCron(wft)
}

// DeleteCron deletes cron trigger from cron trigger manager.
func (m *CronTriggerManager) DeleteCron(wft *v1alpha1.WorkflowTrigger) {
	wftKey := getKeyFromWorkflowTrigger(wft)
	m.DeleteTrigger(wftKey)
}

func getKeyFromWorkflowTrigger(wft *v1alpha1.WorkflowTrigger) string {
	return fmt.Sprintf(KeyTemplate, wft.Namespace, wft.Name)
}
<|endoftext|>


<commit_before>package queues
/*
 *  Filename:    priority.go
 *  Package:     queues
 *  Author:      Bryan Matsuo <bmatsuo@soe.ucsc.edu>
 *  Created:     Wed Jul  6 22:18:57 PDT 2011
 *  Description:
 */
import (
    "container/heap"
)

type PrioritizedTask interface {
    Task
    Key() float64
    SetKey(float64)
}
type PTask struct {
    F func(int64)
    P float64
}
func (pt PTask) Func() func(int64) {
    return pt.F
}
func (pt PTask) Key() float64 {
    return pt.P
}
func (pt *PTask) SetKey(k float64) {
    pt.P = k
}

type pQueue struct {
    elements []RegisteredTask
}
func newPQueue() *pQueue {
    var h = new(pQueue)
    h.elements = make([]RegisteredTask, 0, 5)
    return h
}
func (h *pQueue) GetPTask(i int) PrioritizedTask {
    if n := len(h.elements) ; i < 0 || i >= n {
        panic("badindex")
    }
    return h.elements[i].Task().(PrioritizedTask)
}
func (h *pQueue) Len() int {
    return len(h.elements)
}
func (h *pQueue) Less(i, j int) bool {
    return h.GetPTask(i).Key() < h.GetPTask(j).Key()
}
func (h *pQueue) Swap(i, j int) {
    if n := len(h.elements) ; i < 0 || i >=n || j < 0 || j >= n {
        panic("badindex")
    }
    var tmp = h.elements[i]
    h.elements[i] = h.elements[j]
    h.elements[j] = tmp
}
func (h *pQueue) Push(x interface{}) {
    switch x.(type) {
    case PrioritizedTask:
        h.elements = append(h.elements, x.(RegisteredTask))
    default:
        panic("badtype")
    }
}
func (h *pQueue) Pop() interface{} {
    if len(h.elements) <= 0 {
        panic("empty")
    }
    var head = h.elements[0]
    h.elements = h.elements[1:]
    return head
}
func (h *pQueue) FindId(id int64) (int, RegisteredTask) {
    for i, elm := range h.elements {
        if elm.Id() == id {
            return i, elm
        }
    }
    return -1, nil
}

type PriorityQueue struct {
    h  *pQueue
}

func NewPriorityQueue() *PriorityQueue {
    var pq = new(PriorityQueue)
    pq.h = newPQueue()
    // No need to call heap.Init(pq.h) on an empty heap.
    return pq
}

func (pq *PriorityQueue) Len() int {
    return pq.h.Len()
}
func (pq *PriorityQueue) Dequeue() RegisteredTask {
    if pq.Len() <= 0 {
        panic("empty")
    }
    return heap.Pop(pq.h).(RegisteredTask)
}
func (pq *PriorityQueue) Enqueue(task RegisteredTask) {
    switch task.Task().(type) {
    case PrioritizedTask:
        heap.Push(pq.h, task)
    default:
        panic(fmt.Sprintf("nokey %v", task))
    }
}
func (pq *PriorityQueue) SetKey(id int64, k float64) {
    var i, task = pq.h.FindId(id)
    if i < 0 {
        return
    }
    heap.Remove(pq.h, i)
    task.Task().(PrioritizedTask).SetKey(k)
    heap.Push(pq.h, task)
}
<commit_msg>Add forgotten import.<commit_after>package queues
/*
 *  Filename:    priority.go
 *  Package:     queues
 *  Author:      Bryan Matsuo <bmatsuo@soe.ucsc.edu>
 *  Created:     Wed Jul  6 22:18:57 PDT 2011
 *  Description:
 */
import (
    "fmt"
    "container/heap"
)

type PrioritizedTask interface {
    Task
    Key() float64
    SetKey(float64)
}
type PTask struct {
    F func(int64)
    P float64
}
func (pt PTask) Func() func(int64) {
    return pt.F
}
func (pt PTask) Key() float64 {
    return pt.P
}
func (pt *PTask) SetKey(k float64) {
    pt.P = k
}

type pQueue struct {
    elements []RegisteredTask
}
func newPQueue() *pQueue {
    var h = new(pQueue)
    h.elements = make([]RegisteredTask, 0, 5)
    return h
}
func (h *pQueue) GetPTask(i int) PrioritizedTask {
    if n := len(h.elements) ; i < 0 || i >= n {
        panic("badindex")
    }
    return h.elements[i].Task().(PrioritizedTask)
}
func (h *pQueue) Len() int {
    return len(h.elements)
}
func (h *pQueue) Less(i, j int) bool {
    return h.GetPTask(i).Key() < h.GetPTask(j).Key()
}
func (h *pQueue) Swap(i, j int) {
    if n := len(h.elements) ; i < 0 || i >=n || j < 0 || j >= n {
        panic("badindex")
    }
    var tmp = h.elements[i]
    h.elements[i] = h.elements[j]
    h.elements[j] = tmp
}
func (h *pQueue) Push(x interface{}) {
    switch x.(type) {
    case PrioritizedTask:
        h.elements = append(h.elements, x.(RegisteredTask))
    default:
        panic("badtype")
    }
}
func (h *pQueue) Pop() interface{} {
    if len(h.elements) <= 0 {
        panic("empty")
    }
    var head = h.elements[0]
    h.elements = h.elements[1:]
    return head
}
func (h *pQueue) FindId(id int64) (int, RegisteredTask) {
    for i, elm := range h.elements {
        if elm.Id() == id {
            return i, elm
        }
    }
    return -1, nil
}

type PriorityQueue struct {
    h  *pQueue
}

func NewPriorityQueue() *PriorityQueue {
    var pq = new(PriorityQueue)
    pq.h = newPQueue()
    // No need to call heap.Init(pq.h) on an empty heap.
    return pq
}

func (pq *PriorityQueue) Len() int {
    return pq.h.Len()
}
func (pq *PriorityQueue) Dequeue() RegisteredTask {
    if pq.Len() <= 0 {
        panic("empty")
    }
    return heap.Pop(pq.h).(RegisteredTask)
}
func (pq *PriorityQueue) Enqueue(task RegisteredTask) {
    switch task.Task().(type) {
    case PrioritizedTask:
        heap.Push(pq.h, task)
    default:
        panic(fmt.Sprintf("nokey %v", task))
    }
}
func (pq *PriorityQueue) SetKey(id int64, k float64) {
    var i, task = pq.h.FindId(id)
    if i < 0 {
        return
    }
    heap.Remove(pq.h, i)
    task.Task().(PrioritizedTask).SetKey(k)
    heap.Push(pq.h, task)
}
<|endoftext|>


<commit_before>package main

import (
	"testing"

	log "github.com/Sirupsen/logrus"
	"github.com/davecgh/go-spew/spew"
)

type testpair struct {
	value  string
	result string
}

func TestRawTextExtraction(t *testing.T) {
	var tests = []testpair{
		{
			`An undocumented(test)`,
			`An undocumented(test)`,
		},
		{
			`An undocumented `,
			`An undocumented `,
		},
		{
			`Adventurer's clothes`,
			`Adventurer's clothes`,
		},
		{
			`An undocumented if`,
			`An undocumented if`,
		},
		{
			`An undocumented if()`,
			`An undocumented `,
		},
		{
			`if(v[178] \\>= 40)`,
			``,
		},
		{
			`踊れ if(v[178] \\>= 40)`,
			`踊れ `,
		},
		{
			`\\\>\\C[14]…今は使用できません。`,
			`…今は使用できません。`,
		},
		{
			`Basic Switch \u0026 Variable`,
			`Basic Switch  Variable`,
		},
		{
			`Mun「Ha～～～\\\\!`,
			`Mun「Ha～～～`,
		},
		{
			`Marcus「Hey there.……！\\\\!`,
			`Marcus「Hey there.……！`,
		},
		{
			`Yorkie「\"Suddenly it is a question, I have been worried since long ago`,
			`Yorkie「\"Suddenly it is a question, I have been worried since long ago`,
		},
	}

	for _, pair := range tests {
		v := getOnlyText(pair.value)
		if v != pair.result {
			t.Error(
				"For", pair.value,
				"expected", pair.result,
				"got", v,
			)
		}
	}

}

func TestTranslatableTextExtraction(t *testing.T) {
	var tests = []testpair{
		{
			`if(v[178] \\>= 40)`,
			``,
		},
		{
			`踊れ if(v[178] \\>= 40)`,
			`踊れ `,
		},
		{
			`\\\>\\C[14]…今は使用できません。`,
			`今は使用できません`,
		},
		{
			`\\\>…「\\C[14]\\N[2]\\C[0]」は、\\\>　カナーン村の酒場へ帰っていった。`,
			`は、カナーン村の酒場へ帰っていった`,
		},
		{
			`\\\>…「\\C[14]\\N[2]\\C[0]」の同伴時間が\\C[3] 10 \\C[0]を超えていますので、\\\>　「\\C[14]\\N[2]\\C[0]」の欲情度が\\C[3] 100 \\C[0]未満の場合、\\\>　時間経過で上昇していきます。`,
			`の同伴時間が 10 を超えていますので、の欲情度が 100 未満の場合、時間経過で上昇していきます`,
		},
		{
			`%sを %s 回復した！`,
			`を  回復した`,
		},
		{
			`"お金を %s\\\\G 手に入れた！"`,
			`"お金を  手に入れた"`,
		},
		{
			`'\\.'`,
			`''`,
		},
		{
			`【\\C[14]\\N[2]\\C[0]】　\\{アハァァーーーンッ！！`,
			`アハァァーーーンッ`,
		},
		{
			`\\\>…「\\C[10]バッポウ\\C[0]」再出現カウント： \\C[3] \\V[491] \\C[0]\\\>\\\>　\\C[14]※出現場所：キータニ平原\\\>　\\C[14]※カウントが 0 になると再挑戦可能になります。`,
			`バッポウ再出現カウント：   ※出現場所：キータニ平原※カウントが 0 になると再挑戦可能になります`,
		},
		{
			`【\\C[14]骨董屋\\C[0]】　「謎の防具」か。　ほぅ、複数持っているようだな。　一気に鑑定するかい？\\C[3] \\V[982] G\\C[0] 頂くけどな。\\$`,
			`骨董屋謎の防具かほぅ、複数持っているようだな一気に鑑定するかい  G 頂くけどな`,
		},
		{
			`【\\C[14]ザウナー\\C[0]】　\\}…待て待て、この場を乗り切るための詭弁さ。\\{　\\}すまないが、我慢して様子を見ててくれ。\\{　\\}必ず上手くいくさ。`,
			`ザウナー待て待て、この場を乗り切るための詭弁さすまないが、我慢して様子を見ててくれ必ず上手くいくさ`,
		},
		{
			`\\c[3]宿屋の主人\\c[0]ほほ～、シスターとは珍しい！\\lこんな辺鄙な島で布教活動かね？言っとくが、ワシは神など信じないぞ。`,
			`宿屋の主人ほほ、シスターとは珍しいこんな辺鄙な島で布教活動かね言っとくが、ワシは神など信じないぞ`,
		},
		{
			`0\\G 手に入れた！`,
			`0 手に入れた`,
		},
		{
			`\\\>牡丹の命が５回復した。\\|\\.\\^`,
			`牡丹の命が５回復した`,
		},
		{
			`氷結水　(残\\V[29]) en(s[28])`,
			`氷結水残 `,
		},
		{
			`疾風苦無(消費1)　en(v[25] \>= 1)`,
			`疾風苦無消費1`,
		},
		{
			`\\\\B\\\\I\\\\C[4]レジネッタ：\\\\C[0]\\\\/I\\\\/B\nあ……ふぁっ……！\n`,
			`レジネッタ：あふぁっ`,
		},
		{
			`\\\\Bポータルフリントを手に入れた！`,
			`ポータルフリントを手に入れた`,
		},
	}

	for _, pair := range tests {
		items, err := parseText(pair.value)
		if err != nil {
			log.Errorf("%s\ntext: %q", err, pair.value)
			log.Error(spew.Sdump(items))
		}

		var v string

		for _, item := range items {
			if item.typ == itemText {
				v += item.val
			}
		}

		if v != pair.result {
			t.Error(
				"For", pair.value,
				"expected", pair.result,
				"got", v,
			)
		}
	}
}
<commit_msg>Fix test<commit_after>package main

import (
	"testing"

	log "github.com/Sirupsen/logrus"
	"github.com/davecgh/go-spew/spew"
)

type testpair struct {
	value  string
	result string
}

func TestRawTextExtraction(t *testing.T) {
	var tests = []testpair{
		{
			`An undocumented(test)`,
			`An undocumented(test)`,
		},
		{
			`An undocumented `,
			`An undocumented `,
		},
		{
			`Adventurer's clothes`,
			`Adventurer's clothes`,
		},
		{
			`An undocumented if`,
			`An undocumented if`,
		},
		{
			`An undocumented if()`,
			`An undocumented `,
		},
		{
			`if(v[178] \\>= 40)`,
			``,
		},
		{
			`踊れ if(v[178] \\>= 40)`,
			`踊れ `,
		},
		{
			`\\\>\\C[14]…今は使用できません。`,
			`…今は使用できません。`,
		},
		{
			`Basic Switch \u0026 Variable`,
			`Basic Switch  Variable`,
		},
		{
			`Mun「Ha～～～\\\\!`,
			`Mun「Ha～～～`,
		},
		{
			`Marcus「Hey there.……！\\\\!`,
			`Marcus「Hey there.……！`,
		},
		{
			`Yorkie「\"Suddenly it is a question, I have been worried since long ago`,
			`Yorkie「\"Suddenly it is a question, I have been worried since long ago`,
		},
	}

	for _, pair := range tests {
		v := getOnlyText(pair.value)
		if v != pair.result {
			t.Error(
				"For", pair.value,
				"expected", pair.result,
				"got", v,
			)
		}
	}

}

func TestTranslatableTextExtraction(t *testing.T) {
	var tests = []testpair{
		{
			`if(v[178] \\>= 40)`,
			``,
		},
		{
			`踊れ if(v[178] \\>= 40)`,
			`踊れ `,
		},
		{
			`\\\>\\C[14]…今は使用できません。`,
			`今は使用できません`,
		},
		{
			`\\\>…「\\C[14]\\N[2]\\C[0]」は、\\\>　カナーン村の酒場へ帰っていった。`,
			`は、カナーン村の酒場へ帰っていった`,
		},
		{
			`\\\>…「\\C[14]\\N[2]\\C[0]」の同伴時間が\\C[3] 10 \\C[0]を超えていますので、\\\>　「\\C[14]\\N[2]\\C[0]」の欲情度が\\C[3] 100 \\C[0]未満の場合、\\\>　時間経過で上昇していきます。`,
			`の同伴時間が 10 を超えていますので、の欲情度が 100 未満の場合、時間経過で上昇していきます`,
		},
		{
			`%sを %s 回復した！`,
			`を  回復した`,
		},
		{
			`"お金を %s\\\\G 手に入れた！"`,
			`お金を  手に入れた`,
		},
		{
			`'\\.'`,
			`''`,
		},
		{
			`【\\C[14]\\N[2]\\C[0]】　\\{アハァァーーーンッ！！`,
			`アハァァーーーンッ`,
		},
		{
			`\\\>…「\\C[10]バッポウ\\C[0]」再出現カウント： \\C[3] \\V[491] \\C[0]\\\>\\\>　\\C[14]※出現場所：キータニ平原\\\>　\\C[14]※カウントが 0 になると再挑戦可能になります。`,
			`バッポウ再出現カウント：   ※出現場所：キータニ平原※カウントが 0 になると再挑戦可能になります`,
		},
		{
			`【\\C[14]骨董屋\\C[0]】　「謎の防具」か。　ほぅ、複数持っているようだな。　一気に鑑定するかい？\\C[3] \\V[982] G\\C[0] 頂くけどな。\\$`,
			`骨董屋謎の防具かほぅ、複数持っているようだな一気に鑑定するかい  G 頂くけどな`,
		},
		{
			`【\\C[14]ザウナー\\C[0]】　\\}…待て待て、この場を乗り切るための詭弁さ。\\{　\\}すまないが、我慢して様子を見ててくれ。\\{　\\}必ず上手くいくさ。`,
			`ザウナー待て待て、この場を乗り切るための詭弁さすまないが、我慢して様子を見ててくれ必ず上手くいくさ`,
		},
		{
			`\\c[3]宿屋の主人\\c[0]ほほ～、シスターとは珍しい！\\lこんな辺鄙な島で布教活動かね？言っとくが、ワシは神など信じないぞ。`,
			`宿屋の主人ほほ、シスターとは珍しいこんな辺鄙な島で布教活動かね言っとくが、ワシは神など信じないぞ`,
		},
		{
			`0\\G 手に入れた！`,
			`0 手に入れた`,
		},
		{
			`\\\>牡丹の命が５回復した。\\|\\.\\^`,
			`牡丹の命が５回復した`,
		},
		{
			`氷結水　(残\\V[29]) en(s[28])`,
			`氷結水残 `,
		},
		{
			`疾風苦無(消費1)　en(v[25] \>= 1)`,
			`疾風苦無消費1`,
		},
		{
			`\\\\B\\\\I\\\\C[4]レジネッタ：\\\\C[0]\\\\/I\\\\/B\nあ……ふぁっ……！\n`,
			`レジネッタ：あふぁっ`,
		},
		{
			`\\\\Bポータルフリントを手に入れた！`,
			`ポータルフリントを手に入れた`,
		},
	}

	for _, pair := range tests {
		items, err := parseText(pair.value)
		if err != nil {
			log.Errorf("%s\ntext: %q", err, pair.value)
			log.Error(spew.Sdump(items))
		}

		var v string

		for _, item := range items {
			if item.typ == itemText {
				v += item.val
			}
		}

		if v != pair.result {
			t.Error(
				"For", pair.value,
				"expected", pair.result,
				"got", v,
			)
		}
	}
}
<|endoftext|>


<commit_before>package lfs

import (
	"bufio"
	"bytes"
	"crypto/tls"
	"errors"
	"fmt"
	"io"
	"net"
	"net/http"
	"net/http/httputil"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

type transferStats struct {
	HeaderSize int
	BodySize   int
	Start      time.Time
	Stop       time.Time
}

type transfer struct {
	requestStats  *transferStats
	responseStats *transferStats
}

var (
	// TODO should use some locks
	transfers           = make(map[*http.Response]*transfer)
	transferBuckets     = make(map[string][]*http.Response)
	transfersLock       sync.Mutex
	transferBucketsLock sync.Mutex
)

func LogTransfer(key string, res *http.Response) {
	if Config.isLoggingStats {
		transferBucketsLock.Lock()
		transferBuckets[key] = append(transferBuckets[key], res)
		transferBucketsLock.Unlock()
	}
}

type HttpClient struct {
	*http.Client
}

func (c *HttpClient) Do(req *http.Request) (*http.Response, error) {
	traceHttpRequest(req)

	crc := countingRequest(req)
	if req.Body != nil {
		// Only set the body if we have a body, but create the countingRequest
		// anyway to make using zeroed stats easier.
		req.Body = crc
	}

	start := time.Now()
	res, err := c.Client.Do(req)
	if err != nil {
		return res, err
	}

	traceHttpResponse(res)

	cresp := countingResponse(res)
	res.Body = cresp

	if Config.isLoggingStats {
		reqHeaderSize := 0
		resHeaderSize := 0

		if dump, err := httputil.DumpRequest(req, false); err == nil {
			reqHeaderSize = len(dump)
		}

		if dump, err := httputil.DumpResponse(res, false); err == nil {
			resHeaderSize = len(dump)
		}

		reqstats := &transferStats{HeaderSize: reqHeaderSize, BodySize: crc.Count}

		// Response body size cannot be figured until it is read. Do not rely on a Content-Length
		// header because it may not exist or be -1 in the case of chunked responses.
		resstats := &transferStats{HeaderSize: resHeaderSize, Start: start}
		t := &transfer{requestStats: reqstats, responseStats: resstats}
		transfersLock.Lock()
		transfers[res] = t
		transfersLock.Unlock()
	}

	return res, err
}

func (c *Configuration) HttpClient() *HttpClient {
	if c.httpClient != nil {
		return c.httpClient
	}

	tr := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   5 * time.Second,
			KeepAlive: 30 * time.Second,
		}).Dial,
		TLSHandshakeTimeout: 5 * time.Second,
	}

	sslVerify, _ := c.GitConfig("http.sslverify")
	if sslVerify == "false" || Config.GetenvBool("GIT_SSL_NO_VERIFY", false) {
		tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	}

	c.httpClient = &HttpClient{
		&http.Client{Transport: tr, CheckRedirect: checkRedirect},
	}

	return c.httpClient
}

func checkRedirect(req *http.Request, via []*http.Request) error {
	if len(via) >= 3 {
		return errors.New("stopped after 3 redirects")
	}

	oldest := via[0]
	for key, _ := range oldest.Header {
		if key == "Authorization" {
			if req.URL.Scheme != oldest.URL.Scheme || req.URL.Host != oldest.URL.Host {
				continue
			}
		}
		req.Header.Set(key, oldest.Header.Get(key))
	}

	tracerx.Printf("api: redirect %s %s to %s", oldest.Method, oldest.URL, req.URL)

	return nil
}

var tracedTypes = []string{"json", "text", "xml", "html"}

func traceHttpRequest(req *http.Request) {
	tracerx.Printf("HTTP: %s %s", req.Method, req.URL.String())

	if Config.isTracingHttp == false {
		return
	}

	dump, err := httputil.DumpRequest(req, false)
	if err != nil {
		return
	}

	scanner := bufio.NewScanner(bytes.NewBuffer(dump))
	for scanner.Scan() {
		fmt.Fprintf(os.Stderr, "> %s\n", scanner.Text())
	}
}

func traceHttpResponse(res *http.Response) {
	if res == nil {
		return
	}

	tracerx.Printf("HTTP: %d", res.StatusCode)

	if Config.isTracingHttp == false {
		return
	}

	dump, err := httputil.DumpResponse(res, false)
	if err != nil {
		return
	}

	scanner := bufio.NewScanner(bytes.NewBuffer(dump))
	for scanner.Scan() {
		fmt.Fprintf(os.Stderr, "< %s\n", scanner.Text())
	}
}

func countingRequest(req *http.Request) *countingReadCloser {
	return &countingReadCloser{request: req, ReadCloser: req.Body}
}

func countingResponse(res *http.Response) *countingReadCloser {
	return &countingReadCloser{response: res, ReadCloser: res.Body}
}

type countingReadCloser struct {
	Count    int
	request  *http.Request
	response *http.Response
	io.ReadCloser
}

func (c *countingReadCloser) Read(b []byte) (int, error) {
	n, err := c.ReadCloser.Read(b)
	if err != nil && err != io.EOF {
		return n, err
	}

	c.Count += n

	if Config.isTracingHttp {
		contentType := ""
		if c.response != nil { // Response, only print certain kinds of data
			contentType = strings.ToLower(strings.SplitN(c.response.Header.Get("Content-Type"), ";", 2)[0])
		} else {
			contentType = strings.ToLower(strings.SplitN(c.request.Header.Get("Content-Type"), ";", 2)[0])
		}

		for _, tracedType := range tracedTypes {
			if strings.Contains(contentType, tracedType) {
				fmt.Fprint(os.Stderr, string(b[0:n]))
			}
		}
	}

	if err == io.EOF && Config.isLoggingStats {
		// This transfer is done, we're checking it this way so we can also
		// catch transfers where the caller forgets to Close() the Body.
		if c.response != nil {
			transfersLock.Lock()
			if transfer, ok := transfers[c.response]; ok {
				transfer.responseStats.BodySize = c.Count
				transfer.responseStats.Stop = time.Now()
			}
			transfersLock.Unlock()
		}
	}
	return n, err
}

// LogHttpStats is intended to be called after all HTTP operations for the
// commmand have finished. It dumps k/v logs, one line per transfer into
// a log file with the current timestamp.
func LogHttpStats() {
	if !Config.isLoggingStats {
		return
	}

	file, err := statsLogFile()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error logging http stats: %s\n", err)
		return
	}

	fmt.Fprintf(file, "concurrent=%d batch=%v time=%d version=%s\n", Config.ConcurrentTransfers(), Config.BatchTransfer(), time.Now().Unix(), Version)

	for key, responses := range transferBuckets {
		for _, response := range responses {
			stats := transfers[response]
			fmt.Fprintf(file, "key=%s reqheader=%d reqbody=%d resheader=%d resbody=%d restime=%d status=%d url=%s\n",
				key,
				stats.requestStats.HeaderSize,
				stats.requestStats.BodySize,
				stats.responseStats.HeaderSize,
				stats.responseStats.BodySize,
				stats.responseStats.Stop.Sub(stats.responseStats.Start).Nanoseconds(),
				response.StatusCode,
				response.Request.URL)
		}
	}

	fmt.Fprintf(os.Stderr, "HTTP Stats logged to file %s\n", file.Name())
}

func statsLogFile() (*os.File, error) {
	logBase := filepath.Join(LocalLogDir, "http")
	if err := os.MkdirAll(logBase, 0755); err != nil {
		return nil, err
	}

	logFile := fmt.Sprintf("http-%d.log", time.Now().Unix())
	return os.Create(filepath.Join(logBase, logFile))
}
<commit_msg>ンンンンン ンンンン<commit_after>package lfs

import (
	"bufio"
	"bytes"
	"crypto/tls"
	"errors"
	"fmt"
	"io"
	"net"
	"net/http"
	"net/http/httputil"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

type transferStats struct {
	HeaderSize int
	BodySize   int
	Start      time.Time
	Stop       time.Time
}

type transfer struct {
	requestStats  *transferStats
	responseStats *transferStats
}

var (
	// TODO should use some locks
	transfers           = make(map[*http.Response]*transfer)
	transferBuckets     = make(map[string][]*http.Response)
	transfersLock       sync.Mutex
	transferBucketsLock sync.Mutex
)

func LogTransfer(key string, res *http.Response) {
	if Config.isLoggingStats {
		transferBucketsLock.Lock()
		transferBuckets[key] = append(transferBuckets[key], res)
		transferBucketsLock.Unlock()
	}
}

type HttpClient struct {
	*http.Client
}

func (c *HttpClient) Do(req *http.Request) (*http.Response, error) {
	traceHttpRequest(req)

	crc := countingRequest(req)
	if req.Body != nil {
		// Only set the body if we have a body, but create the countingRequest
		// anyway to make using zeroed stats easier.
		req.Body = crc
	}

	start := time.Now()
	res, err := c.Client.Do(req)
	if err != nil {
		return res, err
	}

	traceHttpResponse(res)

	cresp := countingResponse(res)
	res.Body = cresp

	if Config.isLoggingStats {
		reqHeaderSize := 0
		resHeaderSize := 0

		if dump, err := httputil.DumpRequest(req, false); err == nil {
			reqHeaderSize = len(dump)
		}

		if dump, err := httputil.DumpResponse(res, false); err == nil {
			resHeaderSize = len(dump)
		}

		reqstats := &transferStats{HeaderSize: reqHeaderSize, BodySize: crc.Count}

		// Response body size cannot be figured until it is read. Do not rely on a Content-Length
		// header because it may not exist or be -1 in the case of chunked responses.
		resstats := &transferStats{HeaderSize: resHeaderSize, Start: start}
		t := &transfer{requestStats: reqstats, responseStats: resstats}
		transfersLock.Lock()
		transfers[res] = t
		transfersLock.Unlock()
	}

	return res, err
}

func (c *Configuration) HttpClient() *HttpClient {
	if c.httpClient != nil {
		return c.httpClient
	}

	tr := &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   5 * time.Second,
			KeepAlive: 30 * time.Second,
		}).Dial,
		TLSHandshakeTimeout: 5 * time.Second,
	}

	sslVerify, _ := c.GitConfig("http.sslverify")
	if sslVerify == "false" || Config.GetenvBool("GIT_SSL_NO_VERIFY", false) {
		tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	}

	c.httpClient = &HttpClient{
		&http.Client{Transport: tr, CheckRedirect: checkRedirect},
	}

	return c.httpClient
}

func checkRedirect(req *http.Request, via []*http.Request) error {
	if len(via) >= 3 {
		return errors.New("stopped after 3 redirects")
	}

	oldest := via[0]
	for key, _ := range oldest.Header {
		if key == "Authorization" {
			if req.URL.Scheme != oldest.URL.Scheme || req.URL.Host != oldest.URL.Host {
				continue
			}
		}
		req.Header.Set(key, oldest.Header.Get(key))
	}

	tracerx.Printf("api: redirect %s %s to %s", oldest.Method, oldest.URL, req.URL)

	return nil
}

var tracedTypes = []string{"json", "text", "xml", "html"}

func traceHttpRequest(req *http.Request) {
	tracerx.Printf("HTTP: %s %s", req.Method, req.URL.String())

	if Config.isTracingHttp == false {
		return
	}

	dump, err := httputil.DumpRequest(req, false)
	if err != nil {
		return
	}

	traceHttpDump(dump)
}

func traceHttpResponse(res *http.Response) {
	if res == nil {
		return
	}

	tracerx.Printf("HTTP: %d", res.StatusCode)

	if Config.isTracingHttp == false {
		return
	}

	dump, err := httputil.DumpResponse(res, false)
	if err != nil {
		return
	}

	if isTraceableContent(res.Header) {
		fmt.Fprintf(os.Stderr, "\n\n")
	} else {
		fmt.Fprintf(os.Stderr, "\n")
	}

	traceHttpDump(dump)
}

func traceHttpDump(dump []byte) {
	scanner := bufio.NewScanner(bytes.NewBuffer(dump))

	for scanner.Scan() {
		line := scanner.Text()
		if strings.HasPrefix("authorization: basic", strings.ToLower(line)) {
			fmt.Fprintf(os.Stderr, "< Authorization: Basic * * * * *\n")
		} else {
			fmt.Fprintf(os.Stderr, "< %s\n", line)
		}
	}
}

func isTraceableContent(h http.Header) bool {
	ctype := strings.ToLower(strings.SplitN(h.Get("Content-Type"), ";", 2)[0])
	for _, tracedType := range tracedTypes {
		if strings.Contains(ctype, tracedType) {
			return true
		}
	}
	return false
}

func countingRequest(req *http.Request) *countingReadCloser {
	return &countingReadCloser{request: req, ReadCloser: req.Body, isTraceableType: isTraceableContent(req.Header)}
}

func countingResponse(res *http.Response) *countingReadCloser {
	return &countingReadCloser{response: res, ReadCloser: res.Body, isTraceableType: isTraceableContent(res.Header)}
}

type countingReadCloser struct {
	Count           int
	request         *http.Request
	response        *http.Response
	isTraceableType bool
	io.ReadCloser
}

func (c *countingReadCloser) Read(b []byte) (int, error) {
	n, err := c.ReadCloser.Read(b)
	if err != nil && err != io.EOF {
		return n, err
	}

	c.Count += n

	if Config.isTracingHttp && c.isTraceableType {
		fmt.Fprint(os.Stderr, string(b[0:n]))
	}

	if err == io.EOF && Config.isLoggingStats {
		// This transfer is done, we're checking it this way so we can also
		// catch transfers where the caller forgets to Close() the Body.
		if c.response != nil {
			transfersLock.Lock()
			if transfer, ok := transfers[c.response]; ok {
				transfer.responseStats.BodySize = c.Count
				transfer.responseStats.Stop = time.Now()
			}
			transfersLock.Unlock()
		}
	}
	return n, err
}

// LogHttpStats is intended to be called after all HTTP operations for the
// commmand have finished. It dumps k/v logs, one line per transfer into
// a log file with the current timestamp.
func LogHttpStats() {
	if !Config.isLoggingStats {
		return
	}

	file, err := statsLogFile()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error logging http stats: %s\n", err)
		return
	}

	fmt.Fprintf(file, "concurrent=%d batch=%v time=%d version=%s\n", Config.ConcurrentTransfers(), Config.BatchTransfer(), time.Now().Unix(), Version)

	for key, responses := range transferBuckets {
		for _, response := range responses {
			stats := transfers[response]
			fmt.Fprintf(file, "key=%s reqheader=%d reqbody=%d resheader=%d resbody=%d restime=%d status=%d url=%s\n",
				key,
				stats.requestStats.HeaderSize,
				stats.requestStats.BodySize,
				stats.responseStats.HeaderSize,
				stats.responseStats.BodySize,
				stats.responseStats.Stop.Sub(stats.responseStats.Start).Nanoseconds(),
				response.StatusCode,
				response.Request.URL)
		}
	}

	fmt.Fprintf(os.Stderr, "HTTP Stats logged to file %s\n", file.Name())
}

func statsLogFile() (*os.File, error) {
	logBase := filepath.Join(LocalLogDir, "http")
	if err := os.MkdirAll(logBase, 0755); err != nil {
		return nil, err
	}

	logFile := fmt.Sprintf("http-%d.log", time.Now().Unix())
	return os.Create(filepath.Join(logBase, logFile))
}
<|endoftext|>


<commit_before>package lfs

import (
	"crypto/tls"
	"fmt"
	"github.com/rubyist/tracerx"
	"io"
	"net/http"
	"os"
	"strings"
)

func DoHTTP(c *Configuration, req *http.Request) (*http.Response, error) {
	var res *http.Response
	var err error

	var counter *countingBody
	if req.Body != nil {
		counter = newCountingBody(req.Body)
		req.Body = counter
	}

	traceHttpRequest(c, req)

	switch req.Method {
	case "GET", "HEAD":
		res, err = c.RedirectingHttpClient().Do(req)
	default:
		res, err = c.HttpClient().Do(req)
	}

	traceHttpResponse(c, res, counter)

	return res, err
}

func (c *Configuration) HttpClient() *http.Client {
	if c.httpClient == nil {
		c.httpClient = &http.Client{
			Transport: c.RedirectingHttpClient().Transport,
			CheckRedirect: func(req *http.Request, via []*http.Request) error {
				return RedirectError
			},
		}
	}
	return c.httpClient
}

func (c *Configuration) RedirectingHttpClient() *http.Client {
	if c.redirectingHttpClient == nil {
		tr := &http.Transport{}
		sslVerify, _ := c.GitConfig("http.sslverify")
		if sslVerify == "false" || len(os.Getenv("GIT_SSL_NO_VERIFY")) > 0 {
			tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
		}
		c.redirectingHttpClient = &http.Client{Transport: tr}
	}
	return c.redirectingHttpClient
}

var tracedTypes = []string{"json", "text", "xml", "html"}

func traceHttpRequest(c *Configuration, req *http.Request) {
	tracerx.Printf("HTTP: %s %s", req.Method, req.URL.String())

	if c.isTracingHttp == false {
		return
	}

	fmt.Fprintf(os.Stderr, "> %s %s %s\n", req.Method, req.URL.RequestURI(), req.Proto)
	for key, _ := range req.Header {
		fmt.Fprintf(os.Stderr, "> %s: %s\n", key, req.Header.Get(key))
	}
}

func traceHttpResponse(c *Configuration, res *http.Response, counter *countingBody) {
	tracerx.Printf("HTTP: %d", res.StatusCode)

	if c.isTracingHttp == false {
		return
	}

	if counter != nil {
		fmt.Fprintf(os.Stderr, "* upload sent off: %d bytes\n", counter.Size)
	}
	fmt.Fprintf(os.Stderr, "\n")

	fmt.Fprintf(os.Stderr, "< %s %s\n", res.Proto, res.Status)
	for key, _ := range res.Header {
		fmt.Fprintf(os.Stderr, "< %s: %s\n", key, res.Header.Get(key))
	}

	traceBody := false
	ctype := strings.ToLower(strings.SplitN(res.Header.Get("Content-Type"), ";", 2)[0])
	for _, tracedType := range tracedTypes {
		if strings.Contains(ctype, tracedType) {
			traceBody = true
		}
	}

	if traceBody {
		fmt.Fprintf(os.Stderr, "\n")
		res.Body = newTracedBody(res.Body)
	}

	fmt.Fprintf(os.Stderr, "\n")
}

type countingBody struct {
	body io.ReadCloser
	Size int64
}

func (r *countingBody) Read(p []byte) (int, error) {
	n, err := r.body.Read(p)
	r.Size += int64(n)
	return n, err
}

func (r *countingBody) Close() error {
	return r.body.Close()
}

func newCountingBody(body io.ReadCloser) *countingBody {
	return &countingBody{body, 0}
}

type tracedBody struct {
	body io.ReadCloser
}

func (r *tracedBody) Read(p []byte) (int, error) {
	n, err := r.body.Read(p)
	fmt.Fprintf(os.Stderr, "%s\n", string(p[0:n]))
	return n, err
}

func (r *tracedBody) Close() error {
	return r.body.Close()
}

func newTracedBody(body io.ReadCloser) *tracedBody {
	return &tracedBody{body}
}
<commit_msg>embed the structs<commit_after>package lfs

import (
	"crypto/tls"
	"fmt"
	"github.com/rubyist/tracerx"
	"io"
	"net/http"
	"os"
	"strings"
)

func DoHTTP(c *Configuration, req *http.Request) (*http.Response, error) {
	var res *http.Response
	var err error

	var counter *countingBody
	if req.Body != nil {
		counter = newCountingBody(req.Body)
		req.Body = counter
	}

	traceHttpRequest(c, req)

	switch req.Method {
	case "GET", "HEAD":
		res, err = c.RedirectingHttpClient().Do(req)
	default:
		res, err = c.HttpClient().Do(req)
	}

	traceHttpResponse(c, res, counter)

	return res, err
}

func (c *Configuration) HttpClient() *http.Client {
	if c.httpClient == nil {
		c.httpClient = &http.Client{
			Transport: c.RedirectingHttpClient().Transport,
			CheckRedirect: func(req *http.Request, via []*http.Request) error {
				return RedirectError
			},
		}
	}
	return c.httpClient
}

func (c *Configuration) RedirectingHttpClient() *http.Client {
	if c.redirectingHttpClient == nil {
		tr := &http.Transport{}
		sslVerify, _ := c.GitConfig("http.sslverify")
		if sslVerify == "false" || len(os.Getenv("GIT_SSL_NO_VERIFY")) > 0 {
			tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
		}
		c.redirectingHttpClient = &http.Client{Transport: tr}
	}
	return c.redirectingHttpClient
}

var tracedTypes = []string{"json", "text", "xml", "html"}

func traceHttpRequest(c *Configuration, req *http.Request) {
	tracerx.Printf("HTTP: %s %s", req.Method, req.URL.String())

	if c.isTracingHttp == false {
		return
	}

	fmt.Fprintf(os.Stderr, "> %s %s %s\n", req.Method, req.URL.RequestURI(), req.Proto)
	for key, _ := range req.Header {
		fmt.Fprintf(os.Stderr, "> %s: %s\n", key, req.Header.Get(key))
	}
}

func traceHttpResponse(c *Configuration, res *http.Response, counter *countingBody) {
	tracerx.Printf("HTTP: %d", res.StatusCode)

	if c.isTracingHttp == false {
		return
	}

	if counter != nil {
		fmt.Fprintf(os.Stderr, "* upload sent off: %d bytes\n", counter.Size)
	}
	fmt.Fprintf(os.Stderr, "\n")

	fmt.Fprintf(os.Stderr, "< %s %s\n", res.Proto, res.Status)
	for key, _ := range res.Header {
		fmt.Fprintf(os.Stderr, "< %s: %s\n", key, res.Header.Get(key))
	}

	traceBody := false
	ctype := strings.ToLower(strings.SplitN(res.Header.Get("Content-Type"), ";", 2)[0])
	for _, tracedType := range tracedTypes {
		if strings.Contains(ctype, tracedType) {
			traceBody = true
		}
	}

	if traceBody {
		fmt.Fprintf(os.Stderr, "\n")
		res.Body = newTracedBody(res.Body)
	}

	fmt.Fprintf(os.Stderr, "\n")
}

type countingBody struct {
	Size int64
	io.ReadCloser
}

func (r *countingBody) Read(p []byte) (int, error) {
	n, err := r.ReadCloser.Read(p)
	r.Size += int64(n)
	return n, err
}

func (r *countingBody) Close() error {
	return r.ReadCloser.Close()
}

func newCountingBody(body io.ReadCloser) *countingBody {
	return &countingBody{0, body}
}

type tracedBody struct {
	io.ReadCloser
}

func (r *tracedBody) Read(p []byte) (int, error) {
	n, err := r.ReadCloser.Read(p)
	fmt.Fprintf(os.Stderr, "%s\n", string(p[0:n]))
	return n, err
}

func (r *tracedBody) Close() error {
	return r.ReadCloser.Close()
}

func newTracedBody(body io.ReadCloser) *tracedBody {
	return &tracedBody{body}
}
<|endoftext|>


<commit_before>package hash

import (
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/hex"
	"encoding/json"
	"hash/adler32"
	"hash/crc32"

	"golang.org/x/crypto/md4"
	"golang.org/x/crypto/ripemd160"
	"golang.org/x/crypto/sha3"
)

var list = map[string]func(b []byte) string{
	"md4":       MD4,
	"md5":       MD5,
	"sha1":      SHA1,
	"sha224":    SHA224,
	"sha256":    SHA256,
	"sha512":    SHA512,
	"sha384":    SHA384,
	"sha3_224":  Sha3_224,
	"sha3_256":  Sha3_256,
	"sha3_384":  Sha3_384,
	"sha3_512":  Sha3_512,
	"ripemd160": Ripemd160,
	"adler32":   Adler32,
	"crc32":     Crc32,
}

// Get get hash func
func Get(name string) (f func(b []byte) string, ok bool) {
	f, ok = list[name]
	return
}

// MD4 md4
func MD4(a []byte) string {
	h := md4.New()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// MD5 md5
func MD5(a []byte) string {
	h := md5.New()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Md5Object md5(json(interface))
func Md5Object(v interface{}) (string, error) {
	b, err := json.Marshal(v)
	if err != nil {
		return "", err
	}
	return MD5(b), nil
}

// SHA1 sha1
func SHA1(a []byte) string {
	h := sha1.New()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// SHA224 sha224
func SHA224(a []byte) string {
	h := sha256.New224()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// SHA256 sha256
func SHA256(a []byte) string {
	h := sha256.New()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// SHA384 sha384
func SHA384(a []byte) string {
	h := sha512.New384()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// SHA512 sha512
func SHA512(a []byte) string {
	h := sha512.New()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Sha3_224 sha3_224
func Sha3_224(a []byte) string {
	h := sha3.New224()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Sha3_256 sha3_256
func Sha3_256(a []byte) string {
	h := sha3.New256()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Sha3_384 sha3_384
func Sha3_384(a []byte) string {
	h := sha3.New384()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Sha3_512 sha3_512
func Sha3_512(a []byte) string {
	h := sha3.New512()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Ripemd160 Ripemd160
func Ripemd160(a []byte) string {
	h := ripemd160.New()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Adler32 Adler32
func Adler32(a []byte) string {
	h := adler32.New()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Crc32 Crc32
func Crc32(a []byte) string {
	h := crc32.NewIEEE()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}
<commit_msg>新增 Sha1Object<commit_after>package hash

import (
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/hex"
	"encoding/json"
	"hash/adler32"
	"hash/crc32"

	"github.com/vmihailenco/msgpack"
	"golang.org/x/crypto/md4"
	"golang.org/x/crypto/ripemd160"
	"golang.org/x/crypto/sha3"
)

var list = map[string]func(b []byte) string{
	"md4":       MD4,
	"md5":       MD5,
	"sha1":      SHA1,
	"sha224":    SHA224,
	"sha256":    SHA256,
	"sha512":    SHA512,
	"sha384":    SHA384,
	"sha3_224":  Sha3_224,
	"sha3_256":  Sha3_256,
	"sha3_384":  Sha3_384,
	"sha3_512":  Sha3_512,
	"ripemd160": Ripemd160,
	"adler32":   Adler32,
	"crc32":     Crc32,
}

// Get get hash func
func Get(name string) (f func(b []byte) string, ok bool) {
	f, ok = list[name]
	return
}

// MD4 md4
func MD4(a []byte) string {
	h := md4.New()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// MD5 md5
func MD5(a []byte) string {
	h := md5.New()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Md5Object md5(json(interface))
func Md5Object(v interface{}) (string, error) {
	b, err := json.Marshal(v)
	if err != nil {
		return "", err
	}
	return MD5(b), nil
}
func Sha1Object(v interface{}) (string, error) {
	b, err := msgpack.Marshal(v)
	if err != nil {
		return "", err
	}
	return SHA1(b), nil
}

// SHA1 sha1
func SHA1(a []byte) string {
	h := sha1.New()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// SHA224 sha224
func SHA224(a []byte) string {
	h := sha256.New224()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// SHA256 sha256
func SHA256(a []byte) string {
	h := sha256.New()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// SHA384 sha384
func SHA384(a []byte) string {
	h := sha512.New384()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// SHA512 sha512
func SHA512(a []byte) string {
	h := sha512.New()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Sha3_224 sha3_224
func Sha3_224(a []byte) string {
	h := sha3.New224()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Sha3_256 sha3_256
func Sha3_256(a []byte) string {
	h := sha3.New256()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Sha3_384 sha3_384
func Sha3_384(a []byte) string {
	h := sha3.New384()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Sha3_512 sha3_512
func Sha3_512(a []byte) string {
	h := sha3.New512()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Ripemd160 Ripemd160
func Ripemd160(a []byte) string {
	h := ripemd160.New()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Adler32 Adler32
func Adler32(a []byte) string {
	h := adler32.New()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}

// Crc32 Crc32
func Crc32(a []byte) string {
	h := crc32.NewIEEE()
	h.Write(a)
	return hex.EncodeToString(h.Sum(nil))
}
<|endoftext|>


<commit_before>package lib

import (
	"fmt"
	"log"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/jh-bate/fantail-bot/Godeps/_workspace/src/github.com/tucnak/telebot"
)

const said_tag = say_action
const chat_tag = chat_action
const remind_tag = remind_action

type (
	Note struct {
		WhoId       int
		AddedOn     time.Time
		RemindNext  time.Time
		CompletedOn time.Time
		Tag         string
		Text        string
	}

	Notes []*Note
)

func (this *Note) RemindToday() bool {
	today := time.Now()

	if this.RemindNext.Before(today) == false {
		return this.RemindNext.Year() == today.Year() &&
			this.RemindNext.YearDay() == today.YearDay()
	}
	return true
}

func (this *Note) IsCurrent() bool {
	return this.CompletedOn.IsZero()
}

func (this *Note) Complete() {
	this.CompletedOn = time.Now()
	return
}

func (this *Note) UpdateRemindNext() {
	today := time.Now()
	this.RemindNext = today.AddDate(0, 0, 7)
	return
}

func (this *Note) ToString() string {
	return fmt.Sprintf("On %s you said '%s'", this.AddedOn.Format("Mon Jan 2 03:04pm"), this.Text)
}

func (this Notes) FilterBy(tag string) Notes {
	var n Notes
	for i := range this {
		if this[i].CompletedOn.IsZero() && strings.Contains(this[i].Tag, tag) {
			n = append(n, this[i])
		}
	}
	return n
}

func (this Notes) ForNextDays(days int) Notes {
	var r Notes
	t := time.Now()

	t.AddDate(0, 0, days)

	log.Println("getting all before ", t.Format(time.Stamp))

	for i := range this {
		if this[i].RemindNext.Before(t) {
			r = append(r, this[i])
		}
	}
	return r
}

type ByDate Notes

func (this ByDate) Len() int           { return len(this) }
func (this ByDate) Swap(i, j int)      { this[i], this[j] = this[j], this[i] }
func (this ByDate) Less(i, j int) bool { return this[i].AddedOn.Before(this[j].AddedOn) }

func (this Notes) ToString() string {
	str := ""
	if len(this) > 0 {
		str = fmt.Sprintf("%s \n\n", this[0].AddedOn.Format("Mon Jan 2"))
		day := this[0].AddedOn.YearDay()
		for i := range this {
			if day != this[i].AddedOn.YearDay() {
				str += fmt.Sprintf("%s \n\n", this[i].AddedOn.Format("Mon Jan 2"))
			}
			str += fmt.Sprintf("  - %s '%s'", this[i].AddedOn.Format("Mon 03:04pm"), this[i].Text)
		}
	}

	return str
}

func (this Notes) SortByDate() Notes {
	sort.Sort(ByDate(this))
	return this
}

func (this Note) IsEmpty() bool {
	return this.Text == "" && this.Tag == ""
}

func tagFromMsg(msgTxt string) string {
	words := strings.Fields(msgTxt)
	if strings.Contains(words[0], "/") {
		return words[0]
	}
	return ""
}

func NewNote(msg telebot.Message, tags ...string) Note {

	txt := msg.Text

	cmdTag := tagFromMsg(txt)

	//e.g. remove '/say' from the message
	if strings.Contains(txt, cmdTag) {
		txt = strings.TrimSpace(strings.Split(txt, cmdTag)[1])
	}

	return Note{
		WhoId:      msg.Sender.ID,
		AddedOn:    msg.Time(),
		Text:       txt,
		Tag:        strings.Join(append(tags, cmdTag), ","),
		RemindNext: time.Now().AddDate(0, 0, 7)}
}

func NewReminderNote(msg telebot.Message, tags ...string) Note {

	const remind_pos, time_pos, msg_pos = 0, 1, 2
	words := strings.Fields(msg.Text)

	days, err := strconv.Atoi(words[time_pos])

	if err != nil {
		log.Println(fmt.Errorf("Reminder format is %s", remind_action_hint).Error())
		return Note{}
	}

	what := strings.SplitAfterN(msg.Text, words[time_pos], 2)[1]

	if what == "" {
		log.Println(fmt.Errorf("Reminder format is %s", remind_action_hint).Error())
		return Note{}
	}

	return Note{
		WhoId:      msg.Sender.ID,
		AddedOn:    msg.Time(),
		Text:       strings.TrimSpace(what),
		Tag:        strings.Join(append(tags, remind_tag), ","),
		RemindNext: time.Now().AddDate(0, 0, days)}
}
<commit_msg>reset the day<commit_after>package lib

import (
	"fmt"
	"log"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/jh-bate/fantail-bot/Godeps/_workspace/src/github.com/tucnak/telebot"
)

const said_tag = say_action
const chat_tag = chat_action
const remind_tag = remind_action

type (
	Note struct {
		WhoId       int
		AddedOn     time.Time
		RemindNext  time.Time
		CompletedOn time.Time
		Tag         string
		Text        string
	}

	Notes []*Note
)

func (this *Note) RemindToday() bool {
	today := time.Now()

	if this.RemindNext.Before(today) == false {
		return this.RemindNext.Year() == today.Year() &&
			this.RemindNext.YearDay() == today.YearDay()
	}
	return true
}

func (this *Note) IsCurrent() bool {
	return this.CompletedOn.IsZero()
}

func (this *Note) Complete() {
	this.CompletedOn = time.Now()
	return
}

func (this *Note) UpdateRemindNext() {
	today := time.Now()
	this.RemindNext = today.AddDate(0, 0, 7)
	return
}

func (this *Note) ToString() string {
	return fmt.Sprintf("On %s you said '%s'", this.AddedOn.Format("Mon Jan 2 03:04pm"), this.Text)
}

func (this Notes) FilterBy(tag string) Notes {
	var n Notes
	for i := range this {
		if this[i].CompletedOn.IsZero() && strings.Contains(this[i].Tag, tag) {
			n = append(n, this[i])
		}
	}
	return n
}

func (this Notes) ForNextDays(days int) Notes {
	var r Notes
	t := time.Now()

	t.AddDate(0, 0, days)

	log.Println("getting all before ", t.Format(time.Stamp))

	for i := range this {
		if this[i].RemindNext.Before(t) {
			r = append(r, this[i])
		}
	}
	return r
}

type ByDate Notes

func (this ByDate) Len() int           { return len(this) }
func (this ByDate) Swap(i, j int)      { this[i], this[j] = this[j], this[i] }
func (this ByDate) Less(i, j int) bool { return this[i].AddedOn.Before(this[j].AddedOn) }

func (this Notes) ToString() string {
	str := ""
	if len(this) > 0 {
		str = fmt.Sprintf("%s \n\n", this[0].AddedOn.Format("Mon Jan 2"))
		day := this[0].AddedOn.YearDay()
		for i := range this {
			if day != this[i].AddedOn.YearDay() {
				log.Println("its a new day")
				str += fmt.Sprintf("%s \n\n", this[i].AddedOn.Format("Mon Jan 2"))
				day = this[i].AddedOn.YearDay()
			}
			str += fmt.Sprintf("  - %s '%s'", this[i].AddedOn.Format("03:04pm"), this[i].Text)
		}
	}

	return str
}

func (this Notes) SortByDate() Notes {
	sort.Sort(ByDate(this))
	return this
}

func (this Note) IsEmpty() bool {
	return this.Text == "" && this.Tag == ""
}

func tagFromMsg(msgTxt string) string {
	words := strings.Fields(msgTxt)
	if strings.Contains(words[0], "/") {
		return words[0]
	}
	return ""
}

func NewNote(msg telebot.Message, tags ...string) Note {

	txt := msg.Text

	cmdTag := tagFromMsg(txt)

	//e.g. remove '/say' from the message
	if strings.Contains(txt, cmdTag) {
		txt = strings.TrimSpace(strings.Split(txt, cmdTag)[1])
	}

	return Note{
		WhoId:      msg.Sender.ID,
		AddedOn:    msg.Time(),
		Text:       txt,
		Tag:        strings.Join(append(tags, cmdTag), ","),
		RemindNext: time.Now().AddDate(0, 0, 7)}
}

func NewReminderNote(msg telebot.Message, tags ...string) Note {

	const remind_pos, time_pos, msg_pos = 0, 1, 2
	words := strings.Fields(msg.Text)

	days, err := strconv.Atoi(words[time_pos])

	if err != nil {
		log.Println(fmt.Errorf("Reminder format is %s", remind_action_hint).Error())
		return Note{}
	}

	what := strings.SplitAfterN(msg.Text, words[time_pos], 2)[1]

	if what == "" {
		log.Println(fmt.Errorf("Reminder format is %s", remind_action_hint).Error())
		return Note{}
	}

	return Note{
		WhoId:      msg.Sender.ID,
		AddedOn:    msg.Time(),
		Text:       strings.TrimSpace(what),
		Tag:        strings.Join(append(tags, remind_tag), ","),
		RemindNext: time.Now().AddDate(0, 0, days)}
}
<|endoftext|>


<commit_before>// Copyright 2015-present, Cyrill @ Schumacher.fm and the CoreStore contributors
//
// 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 dml

import (
	"context"
	"database/sql"

	"github.com/corestoreio/errors"
)

type stmtWrapper struct {
	stmt interface {
		ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error)
		QueryContext(ctx context.Context, args ...interface{}) (*sql.Rows, error)
		QueryRowContext(ctx context.Context, args ...interface{}) *sql.Row
	}
}

func (sw stmtWrapper) PrepareContext(_ context.Context, sql string) (*sql.Stmt, error) {
	if sql != "" {
		panic(errors.NotAllowed.Newf("[dml] Argument `sql` with %q not allowed because this is a prepared statement", sql))
	}
	return nil, errors.NotImplemented.Newf("[dml] A *sql.Stmt cannot prepare anything")
}

func (sw stmtWrapper) ExecContext(ctx context.Context, sql string, args ...interface{}) (sql.Result, error) {
	if sql != "" {
		panic(errors.NotAllowed.Newf("[dml] Argument `sql` with %q not allowed because this is a prepared statement", sql))
	}
	return sw.stmt.ExecContext(ctx, args...)
}

func (sw stmtWrapper) QueryContext(ctx context.Context, sql string, args ...interface{}) (*sql.Rows, error) {
	if sql != "" {
		panic(errors.NotAllowed.Newf("[dml] Argument `sql` with %q not allowed because this is a prepared statement", sql))
	}
	return sw.stmt.QueryContext(ctx, args...)
}

func (sw stmtWrapper) QueryRowContext(ctx context.Context, sql string, args ...interface{}) *sql.Row {
	if sql != "" {
		panic(errors.NotAllowed.Newf("[dml] Argument `sql` with %q not allowed because this is a prepared statement", sql))
	}
	return sw.stmt.QueryRowContext(ctx, args...)
}

// Stmt wraps a *sql.Stmt (a prepared statement) with a specific SQL query. To
// create a Stmt call the Prepare function of a specific DML type. Stmt is not
// yet safe for concurrent use, despite the underlying *sql.Stmt is. Don't
// forget to call Close!
type Stmt struct {
	base builderCommon
	Stmt *sql.Stmt
}

// WithArgs creates a new argument handler.
func (st *Stmt) WithArgs() *Artisan {
	var args [defaultArgumentsCapacity]argument
	a := &Artisan{
		base:       st.base,
		arguments:  args[:0],
		isPrepared: true,
	}
	a.base.DB = stmtWrapper{stmt: st.Stmt}
	return a
}

// Close closes the statement in the database and frees its resources.
func (st *Stmt) Close() error { return st.Stmt.Close() }
<commit_msg>sql/dml: Update comment, that Stmt.WithArgs is not safe for concurrency<commit_after>// Copyright 2015-present, Cyrill @ Schumacher.fm and the CoreStore contributors
//
// 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 dml

import (
	"context"
	"database/sql"

	"github.com/corestoreio/errors"
)

type stmtWrapper struct {
	stmt interface {
		ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error)
		QueryContext(ctx context.Context, args ...interface{}) (*sql.Rows, error)
		QueryRowContext(ctx context.Context, args ...interface{}) *sql.Row
	}
}

func (sw stmtWrapper) PrepareContext(_ context.Context, sql string) (*sql.Stmt, error) {
	if sql != "" {
		panic(errors.NotAllowed.Newf("[dml] Argument `sql` with %q not allowed because this is a prepared statement", sql))
	}
	return nil, errors.NotImplemented.Newf("[dml] A *sql.Stmt cannot prepare anything")
}

func (sw stmtWrapper) ExecContext(ctx context.Context, sql string, args ...interface{}) (sql.Result, error) {
	if sql != "" {
		panic(errors.NotAllowed.Newf("[dml] Argument `sql` with %q not allowed because this is a prepared statement", sql))
	}
	return sw.stmt.ExecContext(ctx, args...)
}

func (sw stmtWrapper) QueryContext(ctx context.Context, sql string, args ...interface{}) (*sql.Rows, error) {
	if sql != "" {
		panic(errors.NotAllowed.Newf("[dml] Argument `sql` with %q not allowed because this is a prepared statement", sql))
	}
	return sw.stmt.QueryContext(ctx, args...)
}

func (sw stmtWrapper) QueryRowContext(ctx context.Context, sql string, args ...interface{}) *sql.Row {
	if sql != "" {
		panic(errors.NotAllowed.Newf("[dml] Argument `sql` with %q not allowed because this is a prepared statement", sql))
	}
	return sw.stmt.QueryRowContext(ctx, args...)
}

// Stmt wraps a *sql.Stmt (a prepared statement) with a specific SQL query. To
// create a Stmt call the Prepare function of a specific DML type. Stmt is not
// yet safe for concurrent use, despite the underlying *sql.Stmt is. Don't
// forget to call Close!
type Stmt struct {
	base builderCommon
	Stmt *sql.Stmt
}

// WithArgs creates a new argument handler. Not safe for concurrent use.
func (st *Stmt) WithArgs() *Artisan {
	var args [defaultArgumentsCapacity]argument
	a := &Artisan{
		base:       st.base,
		arguments:  args[:0],
		isPrepared: true,
	}
	a.base.DB = stmtWrapper{stmt: st.Stmt}
	return a
}

// Close closes the statement in the database and frees its resources.
func (st *Stmt) Close() error { return st.Stmt.Close() }
<|endoftext|>


<commit_before>package sql

import (
	"bytes"
	"database/sql"
	"encoding/gob"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"

	"github.com/go-sql-driver/mysql"
	"github.com/wangkuiyi/sqlfs"
)

func run(slct string, cfg *mysql.Config) error {
	r, e := newParser().Parse(slct)
	if e != nil {
		return e
	}
	if r.train {
		cwd, e := ioutil.TempDir("/tmp", "sqlflow-training")
		if e != nil {
			return e
		}
		defer os.RemoveAll(cwd)

		fts, e := verify(r, cfg)
		if e != nil {
			return e
		}

		if e := train(r, fts, cfg, cwd); e != nil {
			return e
		}
		m := &model{r, slct}
		if e := m.save(cfg, cwd); e != nil {
			return e
		}
	} else {
		inferParsed := r

		cwd, e := ioutil.TempDir("/tmp", "sqlflow-predicting")
		if e != nil {
			return e
		}
		defer os.RemoveAll(cwd)

		m := &model{parseResult: inferParsed}
		if e := m.load(cfg, cwd); e != nil {
			return e
		}

		trainParsed, e := newParser().Parse(m.TrainSelect)
		if e != nil {
			return e
		}

		if e := verifyColumnNameAndType(trainParsed, inferParsed, cfg); e != nil {
			return e
		}

		if e := preparePredictionTable(inferParsed, cfg); e != nil {
			return e
		}

		if e := infer(trainParsed, inferParsed, cfg, cwd); e != nil {
			return e
		}
	}

	return nil
}

func train(pr *extendedSelect, fts fieldTypes, cfg *mysql.Config, cwd string) (e error) {
	var program bytes.Buffer
	if e := generateTFProgram(&program, pr, fts, cfg); e != nil {
		return e
	}

	cmd := tensorflowCmd(cwd)
	cmd.Stdin = bytes.NewReader(program.Bytes())
	o, e := cmd.CombinedOutput()
	if e != nil {
		return e
	}
	if !strings.Contains(string(o), "Done training") {
		return fmt.Errorf(string(o) + "\nTraining failed")
	}

	return nil
}

type model struct {
	parseResult *extendedSelect // private member will not be gob-encoded.
	TrainSelect string
}

func (m *model) save(cfg *mysql.Config, cwd string) (e error) {
	db, e := sql.Open("mysql", cfg.FormatDSN())
	if e != nil {
		return e
	}
	defer db.Close()

	sqlfn := fmt.Sprintf("sqlflow_models.%s", m.parseResult.save)
	sqlf, e := sqlfs.Create(db, sqlfn)
	if e != nil {
		return fmt.Errorf("Cannot create sqlfs file %s: %v", sqlfn, e)
	}
	defer func() { sqlf.Close() }()

	if e := gob.NewEncoder(sqlf).Encode(m); e != nil {
		return fmt.Errorf("model.save: gob-encoding model failed: %v", e)
	}

	cmd := exec.Command("tar", "czf", "-", "-C", cwd, ".")
	cmd.Stdout = sqlf
	return cmd.Run()
}

func (m *model) load(cfg *mysql.Config, cwd string) (e error) {
	db, e := sql.Open("mysql", cfg.FormatDSN())
	if e != nil {
		return e
	}
	defer db.Close()

	sqlfn := fmt.Sprintf("sqlflow_models.%s", m.parseResult.model)
	sqlf, e := sqlfs.Open(db, sqlfn)
	if e != nil {
		return fmt.Errorf("Cannot open sqlfs file %s: %v", sqlfn, e)
	}
	defer func() { sqlf.Close() }()

	// FIXME(tonyyang-svail): directly decoding from sqlf will cause out of bond
	// error, but it works fine if we loaded the whole chunk to the bytes.Buffer
	// then decode from there. More details at
	// https://github.com/wangkuiyi/sqlflow/issues/122
	var buf bytes.Buffer
	bs, e := ioutil.ReadAll(sqlf)
	if e != nil {
		return e
	}
	buf.Write(bs)
	if e := gob.NewDecoder(&buf).Decode(m); e != nil {
		return fmt.Errorf("model.load: gob-decoding model failed: %v", e)
	}

	cmd := exec.Command("tar", "xzf", "-", "-C", cwd)
	cmd.Stdin = &buf
	return cmd.Run()
}

func preparePredictionTable(pr *extendedSelect, cfg *mysql.Config) (e error) {
	return fmt.Errorf("preparePredictionTable not implemented")
}

func infer(trainParsed, inferParsed *extendedSelect, cfg *mysql.Config, cwd string) (e error) {
	return fmt.Errorf("model.load not implemented")
}
<commit_msg>executor predict: prepare prediction table (#128)<commit_after>package sql

import (
	"bytes"
	"database/sql"
	"encoding/gob"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"

	"github.com/go-sql-driver/mysql"
	"github.com/wangkuiyi/sqlfs"
)

func run(slct string, cfg *mysql.Config) error {
	r, e := newParser().Parse(slct)
	if e != nil {
		return e
	}
	if r.train {
		cwd, e := ioutil.TempDir("/tmp", "sqlflow-training")
		if e != nil {
			return e
		}
		defer os.RemoveAll(cwd)

		fts, e := verify(r, cfg)
		if e != nil {
			return e
		}

		if e := train(r, fts, cfg, cwd); e != nil {
			return e
		}
		m := &model{r, slct}
		if e := m.save(cfg, cwd); e != nil {
			return e
		}
	} else {
		inferParsed := r

		cwd, e := ioutil.TempDir("/tmp", "sqlflow-predicting")
		if e != nil {
			return e
		}
		defer os.RemoveAll(cwd)

		m := &model{parseResult: inferParsed}
		if e := m.load(cfg, cwd); e != nil {
			return e
		}

		trainParsed, e := newParser().Parse(m.TrainSelect)
		if e != nil {
			return e
		}

		if e := verifyColumnNameAndType(trainParsed, inferParsed, cfg); e != nil {
			return e
		}

		if e := createPredictionTable(trainParsed, inferParsed, cfg); e != nil {
			return e
		}

		if e := infer(trainParsed, inferParsed, cfg, cwd); e != nil {
			return e
		}
	}

	return nil
}

func train(pr *extendedSelect, fts fieldTypes, cfg *mysql.Config, cwd string) (e error) {
	var program bytes.Buffer
	if e := generateTFProgram(&program, pr, fts, cfg); e != nil {
		return e
	}

	cmd := tensorflowCmd(cwd)
	cmd.Stdin = bytes.NewReader(program.Bytes())
	o, e := cmd.CombinedOutput()
	if e != nil {
		return e
	}
	if !strings.Contains(string(o), "Done training") {
		return fmt.Errorf(string(o) + "\nTraining failed")
	}

	return nil
}

type model struct {
	parseResult *extendedSelect // private member will not be gob-encoded.
	TrainSelect string
}

func (m *model) save(cfg *mysql.Config, cwd string) (e error) {
	db, e := sql.Open("mysql", cfg.FormatDSN())
	if e != nil {
		return e
	}
	defer db.Close()

	sqlfn := fmt.Sprintf("sqlflow_models.%s", m.parseResult.save)
	sqlf, e := sqlfs.Create(db, sqlfn)
	if e != nil {
		return fmt.Errorf("Cannot create sqlfs file %s: %v", sqlfn, e)
	}
	defer func() { sqlf.Close() }()

	if e := gob.NewEncoder(sqlf).Encode(m); e != nil {
		return fmt.Errorf("model.save: gob-encoding model failed: %v", e)
	}

	cmd := exec.Command("tar", "czf", "-", "-C", cwd, ".")
	cmd.Stdout = sqlf
	return cmd.Run()
}

func (m *model) load(cfg *mysql.Config, cwd string) (e error) {
	db, e := sql.Open("mysql", cfg.FormatDSN())
	if e != nil {
		return e
	}
	defer db.Close()

	sqlfn := fmt.Sprintf("sqlflow_models.%s", m.parseResult.model)
	sqlf, e := sqlfs.Open(db, sqlfn)
	if e != nil {
		return fmt.Errorf("Cannot open sqlfs file %s: %v", sqlfn, e)
	}
	defer func() { sqlf.Close() }()

	// FIXME(tonyyang-svail): directly decoding from sqlf will cause out of bond
	// error, but it works fine if we loaded the whole chunk to the bytes.Buffer
	// then decode from there. More details at
	// https://github.com/wangkuiyi/sqlflow/issues/122
	var buf bytes.Buffer
	bs, e := ioutil.ReadAll(sqlf)
	if e != nil {
		return e
	}
	buf.Write(bs)
	if e := gob.NewDecoder(&buf).Decode(m); e != nil {
		return fmt.Errorf("model.load: gob-decoding model failed: %v", e)
	}

	cmd := exec.Command("tar", "xzf", "-", "-C", cwd)
	cmd.Stdin = &buf
	return cmd.Run()
}

// Create prediction table with appropriate column type.
// If prediction table already exists, it will be overwritten.
func createPredictionTable(trainParsed, inferParsed *extendedSelect, cfg *mysql.Config) (e error) {
	if len(strings.Split(inferParsed.into, ".")) != 3 {
		return fmt.Errorf("invalid inferParsed.into %s. should be DBName.TableName.ColumnName", inferParsed.into)
	}
	tableName := strings.Join(strings.Split(inferParsed.into, ".")[:2], ".")
	columnName := strings.Split(inferParsed.into, ".")[2]

	db, e := sql.Open("mysql", cfg.FormatDSN())
	if e != nil {
		return fmt.Errorf("verify cannot connect to MySQL: %q", e)
	}
	defer db.Close()

	dropStmt := fmt.Sprintf("drop table if exists %s;", tableName)
	if _, e := db.Query(dropStmt); e != nil {
		return fmt.Errorf("failed executing %s: %q", dropStmt, e)
	}

	fts, e := verify(trainParsed, cfg)
	if e != nil {
		return e
	}
	tpy, _ := fts.get(trainParsed.label)

	createStmt := fmt.Sprintf("create table %s (%s %s);", tableName, columnName, tpy)
	if _, e := db.Query(createStmt); e != nil {
		return fmt.Errorf("failed executing %s: %q", createStmt, e)
	}

	return nil
}

func infer(trainParsed, inferParsed *extendedSelect, cfg *mysql.Config, cwd string) (e error) {
	return fmt.Errorf("infer not implemented")
}
<|endoftext|>


<commit_before>package ftdi

import "unsafe"
import "syscall"
import "bytes"
import "time"

func bytesToString(b []byte) string {
	n := bytes.Index(b, []byte{0})
	return string(b[:n])
}

var d2xx = syscall.MustLoadDLL("ftd2xx.dll")

var (
	createDeviceInfoList = d2xx.MustFindProc("FT_CreateDeviceInfoList")
	getDeviceInfoDetail  = d2xx.MustFindProc("FT_GetDeviceInfoDetail")
	ft_open              = d2xx.MustFindProc("FT_Open")
	ft_close             = d2xx.MustFindProc("FT_Close")
	ft_read              = d2xx.MustFindProc("FT_Read")
	ft_write             = d2xx.MustFindProc("FT_Write")
	ft_getStatus         = d2xx.MustFindProc("FT_GetStatus")
	ft_purge             = d2xx.MustFindProc("FT_Purge")
	setBaudRate          = d2xx.MustFindProc("FT_SetBaudRate")
	setBitMode           = d2xx.MustFindProc("FT_SetBitMode")
	setFlowControl       = d2xx.MustFindProc("FT_SetFlowControl")
	setLatency           = d2xx.MustFindProc("FT_SetLatencyTimer")
	setChars             = d2xx.MustFindProc("FT_SetChars")
	setLineProperty      = d2xx.MustFindProc("FT_SetDataCharacteristics")
	setTimeout           = d2xx.MustFindProc("FT_SetTimeouts")
	setTransferSize      = d2xx.MustFindProc("FT_SetUSBParameters")
	resetPort            = d2xx.MustFindProc("FT_ResetPort")
	resetDevice          = d2xx.MustFindProc("FT_ResetDevice")
)

type Device uintptr

type DeviceInfo struct {
	index         uint64
	flags         uint64
	dtype         uint64
	id            uint64
	location      uint64
	SerialNumber string
	Description   string
	handle        uintptr
}

func GetDeviceList() (di []DeviceInfo, e error) {
	var n uint32
	r, _, err := createDeviceInfoList.Call(uintptr(unsafe.Pointer(&n)))
	if r != 0 {
		return di, err
	}

	di = make([]DeviceInfo, n)
	for i := uint32(0); i < n; i++ {
		var d DeviceInfo
		var sn [16]byte
		var description [64]byte
		d.index = uint64(i)
		r, _, e = getDeviceInfoDetail.Call(uintptr(i),
			uintptr(unsafe.Pointer(&(d.flags))),
			uintptr(unsafe.Pointer(&d.dtype)),
			uintptr(unsafe.Pointer(&d.id)),
			uintptr(unsafe.Pointer(&d.location)),
			uintptr(unsafe.Pointer(&sn)),
			uintptr(unsafe.Pointer(&description)),
			uintptr(unsafe.Pointer(&d.handle)))
		if r != 0 {
			return di, e
		}
		d.SerialNumber = bytesToString(sn[:])
		d.Description = bytesToString(description[:])

		di[i] = d
	}
	return di, nil
}

func Open(di DeviceInfo) (d Device, e error) {
	r, _, e := ft_open.Call(uintptr(di.index), uintptr(unsafe.Pointer(&d)))
	if r == 0 {
		return d, nil
	}
	return d, e
}

func (d Device) Close() (e error) {
	r, _, e := ft_close.Call(uintptr(d))
	if r == 0 {
		return nil
	}
	return e
}

// Does this have Posix Counterpart?
func (d Device) GetStatus() (rx_queue, tx_queue, events int32, e error) {
	r, _, e := ft_getStatus.Call(uintptr(d),
		uintptr(unsafe.Pointer(&rx_queue)),
		uintptr(unsafe.Pointer(&tx_queue)),
		uintptr(unsafe.Pointer(&events)))
	if r == 0 {
		return rx_queue, tx_queue, events, nil
	}
	return rx_queue, tx_queue, events, e
}

//TODO: Need EOF logic for a closed device
func (d Device) Read(p []byte) (n int, e error) {
	var bytesRead uint32
	bytesToRead := uint32(len(p))

    // Bugfix: Only read what's available immediately. On windows, you can't
    // trust ft_read to block until the requested amount of data is available.
    // We also insert a delay to force the read to block for more data...
    // ugh... crappy FTDI drivers.
    rx_cnt, _, _, e := d.GetStatus()
    if bytesToRead > uint32(rx_cnt) {
        time.Sleep(20*time.Millisecond)
        bytesToRead = uint32(rx_cnt)
    }

	ptr := &p[0] //A reference to the first element of the underlying "array"
	r, _, e := ft_read.Call(uintptr(d),
		uintptr(unsafe.Pointer(ptr)),
		uintptr(bytesToRead),
		uintptr(unsafe.Pointer(&bytesRead)))
	if r == 0 {
		return int(bytesRead), nil
	}
	return int(bytesRead), e
}

func (d Device) Write(p []byte) (n int, e error) {
	var bytesWritten uint32
	bytesToWrite := uint32(len(p))
	ptr := &p[0] //A reference to the first element of the underlying "array"
	r, _, e := ft_write.Call(uintptr(d),
		uintptr(unsafe.Pointer(ptr)),
		uintptr(bytesToWrite),
		uintptr(unsafe.Pointer(&bytesWritten)))
	if r == 0 {
		return int(bytesWritten), nil
	}
	return int(bytesWritten), e
}

func (d Device) SetBaudRate(baud uint) (e error) {
	r, _, e := setBaudRate.Call(uintptr(d), uintptr(uint32(baud)))
	if r == 0 {
		return nil
	}
	return e
}

// Set the 'event' and 'error' characheters. Disabled if the charachter is '0x00'.
func (d Device) SetChars(event, err byte) (e error) {
	r, _, e := setChars.Call(uintptr(d),
		uintptr(event),
		uintptr(event),
		uintptr(err),
		uintptr(err))
	if r == 0 {
		return nil
	}
	return e
}

func (d Device) SetBitMode(mode BitMode) (e error) {
	r, _, e := setBitMode.Call(uintptr(d),
		uintptr(0x00), // All pins set to input
		uintptr(byte(mode)))
	if r == 0 {
		return nil
	}
	return e
}

func (d Device) SetFlowControl(f FlowControl) (e error) {
	r, _, e := setFlowControl.Call(uintptr(d),
		uintptr(uint16(f)), // All pins set to input
		uintptr(0x11),      // XON Character
		uintptr(0x13))      // XOFF Character
	if r == 0 {
		return nil
	}
	return e
}

// Set latency in milliseconds. Valid between 2 and 255.
func (d Device) SetLatency(latency int) (e error) {
	r, _, e := setLatency.Call(uintptr(d), uintptr(byte(latency)))
	if r == 0 {
		return nil
	}
	return e
}

// Set the transfer size. Valid between 64 and 64k bytes in 64-byte increments.
func (d Device) SetTransferSize(read_size, write_size int) (e error) {
	r, _, e := setTransferSize.Call(uintptr(d),
		uintptr(uint32(read_size)),
		uintptr(uint32(write_size)))
	if r == 0 {
		return nil
	}
	return e
}

func (d Device) SetLineProperty(props LineProperties) (e error) {
	r, _, e := setLineProperty.Call(uintptr(d),
		uintptr(byte(props.Bits)),
		uintptr(byte(props.StopBits)),
		uintptr(byte(props.Parity)))
	if r == 0 {
		return nil
	}
	return e
}

func (d Device) SetTimeout(read_timeout, write_timeout int) (e error) {
	r, _, e := setTimeout.Call(uintptr(d),
		uintptr(uint32(read_timeout)),
		uintptr(uint32(write_timeout)))
	if r == 0 {
		return nil
	}
	return e
}

func (d Device) Reset() (e error) {
	r, _, e := resetDevice.Call(uintptr(d))
	if r == 0 {
		return nil
	}
	return e
}

func (d Device) Purge() (e error) {
	// Purge both RX and TX buffers
	r, _, e := ft_purge.Call(uintptr(d), uintptr(0x01|0x02))
	if r == 0 {
		return nil
	}
	return e
}
<commit_msg>Windows API now treats ftdi.Device as pointer like linux implementation<commit_after>package ftdi

import "unsafe"
import "syscall"
import "bytes"
import "time"

func bytesToString(b []byte) string {
	n := bytes.Index(b, []byte{0})
	return string(b[:n])
}

var d2xx = syscall.MustLoadDLL("ftd2xx.dll")

var (
	createDeviceInfoList = d2xx.MustFindProc("FT_CreateDeviceInfoList")
	getDeviceInfoDetail  = d2xx.MustFindProc("FT_GetDeviceInfoDetail")
	ft_open              = d2xx.MustFindProc("FT_Open")
	ft_close             = d2xx.MustFindProc("FT_Close")
	ft_read              = d2xx.MustFindProc("FT_Read")
	ft_write             = d2xx.MustFindProc("FT_Write")
	ft_getStatus         = d2xx.MustFindProc("FT_GetStatus")
	ft_purge             = d2xx.MustFindProc("FT_Purge")
	setBaudRate          = d2xx.MustFindProc("FT_SetBaudRate")
	setBitMode           = d2xx.MustFindProc("FT_SetBitMode")
	setFlowControl       = d2xx.MustFindProc("FT_SetFlowControl")
	setLatency           = d2xx.MustFindProc("FT_SetLatencyTimer")
	setChars             = d2xx.MustFindProc("FT_SetChars")
	setLineProperty      = d2xx.MustFindProc("FT_SetDataCharacteristics")
	setTimeout           = d2xx.MustFindProc("FT_SetTimeouts")
	setTransferSize      = d2xx.MustFindProc("FT_SetUSBParameters")
	resetPort            = d2xx.MustFindProc("FT_ResetPort")
	resetDevice          = d2xx.MustFindProc("FT_ResetDevice")
)

type Device uintptr

type DeviceInfo struct {
	index         uint64
	flags         uint64
	dtype         uint64
	id            uint64
	location      uint64
	SerialNumber string
	Description   string
	handle        uintptr
}

func GetDeviceList() (di []DeviceInfo, e error) {
	var n uint32
	r, _, err := createDeviceInfoList.Call(uintptr(unsafe.Pointer(&n)))
	if r != 0 {
		return di, err
	}

	di = make([]DeviceInfo, n)
	for i := uint32(0); i < n; i++ {
		var d DeviceInfo
		var sn [16]byte
		var description [64]byte
		d.index = uint64(i)
		r, _, e = getDeviceInfoDetail.Call(uintptr(i),
			uintptr(unsafe.Pointer(&(d.flags))),
			uintptr(unsafe.Pointer(&d.dtype)),
			uintptr(unsafe.Pointer(&d.id)),
			uintptr(unsafe.Pointer(&d.location)),
			uintptr(unsafe.Pointer(&sn)),
			uintptr(unsafe.Pointer(&description)),
			uintptr(unsafe.Pointer(&d.handle)))
		if r != 0 {
			return di, e
		}
		d.SerialNumber = bytesToString(sn[:])
		d.Description = bytesToString(description[:])

		di[i] = d
	}
	return di, nil
}

func Open(di DeviceInfo) (*Device, error) {
	var dev Device
	r, _, e := ft_open.Call(uintptr(di.index), uintptr(unsafe.Pointer(&dev)))
	if r == 0 {
		return &dev, nil
	}
	return nil, e
}

func (d *Device) Close() (e error) {
	r, _, e := ft_close.Call(uintptr(*d))
	if r == 0 {
		return nil
	}
	return e
}

// Does this have Posix Counterpart?
func (d *Device) GetStatus() (rx_queue, tx_queue, events int32, e error) {
	r, _, e := ft_getStatus.Call(uintptr(*d),
		uintptr(unsafe.Pointer(&rx_queue)),
		uintptr(unsafe.Pointer(&tx_queue)),
		uintptr(unsafe.Pointer(&events)))
	if r == 0 {
		return rx_queue, tx_queue, events, nil
	}
	return rx_queue, tx_queue, events, e
}

//TODO: Need EOF logic for a closed device
func (d *Device) Read(p []byte) (n int, e error) {
	var bytesRead uint32
	bytesToRead := uint32(len(p))

    // Bugfix: Only read what's available immediately. On windows, you can't
    // trust ft_read to block until the requested amount of data is available.
    // We also insert a delay to force the read to block for more data...
    // ugh... crappy FTDI drivers.
    rx_cnt, _, _, e := d.GetStatus()
    if bytesToRead > uint32(rx_cnt) {
        time.Sleep(20*time.Millisecond)
        bytesToRead = uint32(rx_cnt)
    }

	ptr := &p[0] //A reference to the first element of the underlying "array"
	r, _, e := ft_read.Call(uintptr(*d),
		uintptr(unsafe.Pointer(ptr)),
		uintptr(bytesToRead),
		uintptr(unsafe.Pointer(&bytesRead)))
	if r == 0 {
		return int(bytesRead), nil
	}
	return int(bytesRead), e
}

func (d *Device) Write(p []byte) (n int, e error) {
	var bytesWritten uint32
	bytesToWrite := uint32(len(p))
	ptr := &p[0] //A reference to the first element of the underlying "array"
	r, _, e := ft_write.Call(uintptr(*d),
		uintptr(unsafe.Pointer(ptr)),
		uintptr(bytesToWrite),
		uintptr(unsafe.Pointer(&bytesWritten)))
	if r == 0 {
		return int(bytesWritten), nil
	}
	return int(bytesWritten), e
}

func (d *Device) SetBaudRate(baud uint) (e error) {
	r, _, e := setBaudRate.Call(uintptr(*d), uintptr(uint32(baud)))
	if r == 0 {
		return nil
	}
	return e
}

// Set the 'event' and 'error' characheters. Disabled if the charachter is '0x00'.
func (d *Device) SetChars(event, err byte) (e error) {
	r, _, e := setChars.Call(uintptr(*d),
		uintptr(event),
		uintptr(event),
		uintptr(err),
		uintptr(err))
	if r == 0 {
		return nil
	}
	return e
}

func (d *Device) SetBitMode(mode BitMode) (e error) {
	r, _, e := setBitMode.Call(uintptr(*d),
		uintptr(0x00), // All pins set to input
		uintptr(byte(mode)))
	if r == 0 {
		return nil
	}
	return e
}

func (d *Device) SetFlowControl(f FlowControl) (e error) {
	r, _, e := setFlowControl.Call(uintptr(*d),
		uintptr(uint16(f)), // All pins set to input
		uintptr(0x11),      // XON Character
		uintptr(0x13))      // XOFF Character
	if r == 0 {
		return nil
	}
	return e
}

// Set latency in milliseconds. Valid between 2 and 255.
func (d *Device) SetLatency(latency int) (e error) {
	r, _, e := setLatency.Call(uintptr(*d), uintptr(byte(latency)))
	if r == 0 {
		return nil
	}
	return e
}

// Set the transfer size. Valid between 64 and 64k bytes in 64-byte increments.
func (d *Device) SetTransferSize(read_size, write_size int) (e error) {
	r, _, e := setTransferSize.Call(uintptr(*d),
		uintptr(uint32(read_size)),
		uintptr(uint32(write_size)))
	if r == 0 {
		return nil
	}
	return e
}

func (d *Device) SetLineProperty(props LineProperties) (e error) {
	r, _, e := setLineProperty.Call(uintptr(*d),
		uintptr(byte(props.Bits)),
		uintptr(byte(props.StopBits)),
		uintptr(byte(props.Parity)))
	if r == 0 {
		return nil
	}
	return e
}

func (d *Device) SetTimeout(read_timeout, write_timeout int) (e error) {
	r, _, e := setTimeout.Call(uintptr(*d),
		uintptr(uint32(read_timeout)),
		uintptr(uint32(write_timeout)))
	if r == 0 {
		return nil
	}
	return e
}

func (d *Device) Reset() (e error) {
	r, _, e := resetDevice.Call(uintptr(*d))
	if r == 0 {
		return nil
	}
	return e
}

func (d *Device) Purge() (e error) {
	// Purge both RX and TX buffers
	r, _, e := ft_purge.Call(uintptr(*d), uintptr(0x01|0x02))
	if r == 0 {
		return nil
	}
	return e
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"strconv"
	"encoding/json"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"github.com/hyperledger/fabric/core/util"
)

type Chaincode struct { }

type ChaincodeFunctions struct {
	stub shim.ChaincodeStubInterface
}

func main() {
	err := shim.Start(new(Chaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

// Init resets all the things
func (t Chaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	if len(args) > 0 {
		return nil, errors.New("Incorrect number of arguments. Expecting 0")
	}
	_ = stub.PutState("dealStatus", []byte("draft")) // Possible Values [draft, open, closed, allocated]
	_ = stub.PutState("orderbook", []byte("{}"))
	return nil, nil
}

func (t Chaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)
	fns := ChaincodeFunctions{stub}
	if function == "addOrder" {
		investor := args[0]
		ioi, err := strconv.ParseFloat(args[1], 64)
		if err != nil {
	        return nil, errors.New("Failed to parse " + args[1] + " as a float64")
    	}
		return fns.AddOrder(investor, ioi)
	} else if function == "allocateOrder" {
		investor := args[0]
		alloc, err := strconv.ParseFloat(args[1], 64)
		if err != nil {
	        return nil, errors.New("Failed to parse " + args[1] + " as a float64")
    	}
		return fns.AllocateOrder(investor, alloc)
	} else if function == "updateDealStatus" {
		status := args[0]
		return fns.UpdateDealStatus(status)
	}
	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation: " + function)
}

func (t Chaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)
	fns := ChaincodeFunctions{stub}
	if function == "getOrder" {
		investor := args[0]
		return fns.GetOrder(investor)
	} else if function == "getOrderbook" {
		return fns.GetOrderbook()
	} else if function == "echo" {
		address := args[0]
		f := "echo"
		arg := args[1]
		return fns.Echo(address, f, arg)
	} else if function == "getDealStatus" {
		return fns.GetDealStatus()
	}
	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query: " + function)
}

type Order struct {
	Investor	string 		`json:"investor"`
	Ioi 		float64 	`json:"ioi"`
	Alloc 		float64		`json:"alloc"`
}

// Public Functions

func (c ChaincodeFunctions) GetDealStatus() ([]byte, error)  {
	dealStatus, _ := c.stub.GetState("dealStatus")
	return dealStatus, nil
}

func (c ChaincodeFunctions) UpdateDealStatus(dealStatus string) ([]byte, error)  {
	_ = c.stub.PutState("dealStatus", []byte(dealStatus))
	c.stub.SetEvent("Book Status Change", []byte("{\"status\":\"" + dealStatus + "\""))
	return nil, nil
}

func (c ChaincodeFunctions) AddOrder(investor string, ioi float64) ([]byte, error)  {
	dealStatus, _ := c.GetDealStatus()
	if(string(dealStatus) != "open") {
		c.stub.SetEvent("Problemo", []byte("Uh oh!"))
		return nil, errors.New("Orders cannot be placed unless deal status is 'Open'")
	}
	order := Order{Investor: investor, Ioi: ioi, Alloc: 0.0}
	c.saveOrderToBlockChain(order)
	return nil, nil
}

func (c ChaincodeFunctions) GetOrder(investor string) ([]byte, error) {
	orderJson := c.getOrderAsJsonFromBlockchain(investor)
	return []byte(orderJson), nil
}

func (c ChaincodeFunctions) GetOrderbook() ([]byte, error) {
	orderbookJson, _ := c.stub.GetState("orderbook")
	return []byte(orderbookJson), nil
}

func (c ChaincodeFunctions) AllocateOrder(investor string, alloc float64) ([]byte, error) {
	order := c.getOrderFromBlockChain(investor)
	order.Alloc = alloc
	c.saveOrderToBlockChain(order)
	return nil, nil
}

func (c ChaincodeFunctions) Echo(address string, f string, arg string) ([]byte, error) {
	invokeArgs := util.ToChaincodeArgs(f, arg)
	return c.stub.QueryChaincode(address, invokeArgs)
}

// Private Functions

func (c ChaincodeFunctions) getOrderAsJsonFromBlockchain(investor string) string {
	order := c.getOrderFromBlockChain(investor)
	orderJson, _ := json.Marshal(order)
	return string(orderJson)
}

func (c ChaincodeFunctions) getOrderFromBlockChain(investor string) Order {
	orderbook := c.getOrderbookFromBlockChain()
	return orderbook[investor]
}

func (c ChaincodeFunctions) saveOrderToBlockChain(order Order) {
	orderbook := c.getOrderbookFromBlockChain()
	orderbook[order.Investor] = order
	c.saveOrderbookToBlockChain(orderbook)
}

func (c ChaincodeFunctions) getOrderbookFromBlockChain() map[string]Order {
	orderbookJson, _ := c.stub.GetState("orderbook")
	var orderbook map[string]Order
	_ = json.Unmarshal(orderbookJson, &orderbook)
	return orderbook
}

func (c ChaincodeFunctions) saveOrderbookToBlockChain(orderbook map[string]Order) {
	orderbookJson, _ := json.Marshal(orderbook)
	_ = c.stub.PutState("orderbook", []byte(orderbookJson))
}<commit_msg>batch check-in<commit_after>package main

import (
	"errors"
	"fmt"
	"strconv"
	"encoding/json"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"github.com/hyperledger/fabric/core/util"
)

type Chaincode struct { }

type ChaincodeFunctions struct {
	stub shim.ChaincodeStubInterface
}

func main() {
	err := shim.Start(new(Chaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

// Init resets all the things
func (t Chaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	if len(args) > 0 {
		return nil, errors.New("Incorrect number of arguments. Expecting 0")
	}
	_ = stub.PutState("dealStatus", []byte("draft")) // Possible Values [draft, open, closed, allocated]
	_ = stub.PutState("orderbook", []byte("{}"))
	return nil, nil
}

func (t Chaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)
	fns := ChaincodeFunctions{stub}
	if function == "addOrder" {
		investor := args[0]
		ioi, err := strconv.ParseFloat(args[1], 64)
		if err != nil {
	        return nil, errors.New("Failed to parse " + args[1] + " as a float64")
    	}
		return fns.AddOrder(investor, ioi)
	} else if function == "allocateOrder" {
		investor := args[0]
		alloc, err := strconv.ParseFloat(args[1], 64)
		if err != nil {
	        return nil, errors.New("Failed to parse " + args[1] + " as a float64")
    	}
		return fns.AllocateOrder(investor, alloc)
	} else if function == "updateDealStatus" {
		status := args[0]
		return fns.UpdateDealStatus(status)
	}
	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation: " + function)
}

func (t Chaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)
	fns := ChaincodeFunctions{stub}
	if function == "getOrder" {
		investor := args[0]
		return fns.GetOrder(investor)
	} else if function == "getOrderbook" {
		return fns.GetOrderbook()
	} else if function == "echo" {
		address := args[0]
		f := "echo"
		arg := args[1]
		return fns.Echo(address, f, arg)
	} else if function == "getDealStatus" {
		return fns.GetDealStatus()
	}
	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query: " + function)
}

type Order struct {
	Investor	string 		`json:"investor"`
	Ioi 		float64 	`json:"ioi"`
	Alloc 		float64		`json:"alloc"`
}

// Public Functions

func (c ChaincodeFunctions) GetDealStatus() ([]byte, error)  {
	dealStatus, _ := c.stub.GetState("dealStatus")
	return dealStatus, nil
}

func (c ChaincodeFunctions) UpdateDealStatus(dealStatus string) ([]byte, error)  {
	_ = c.stub.PutState("dealStatus", []byte(dealStatus))
	c.stub.SetEvent("Book Status Change", []byte("{\"status\":\"" + dealStatus + "\"}"))
	return nil, nil
}

func (c ChaincodeFunctions) AddOrder(investor string, ioi float64) ([]byte, error)  {
	dealStatus, _ := c.GetDealStatus()
	if(string(dealStatus) != "open") {
		c.stub.SetEvent("Permission Denied", []byte("{\"reason\":\"book is not open\"}"))
		return nil, errors.New("Orders cannot be placed unless deal status is 'Open'")
	}
	order := Order{Investor: investor, Ioi: ioi, Alloc: 0.0}
	c.saveOrderToBlockChain(order)
	c.stub.SetEvent("Order Added", []byte("{\"investor\":\"" + investor + "\"}"))
	return nil, nil
}

func (c ChaincodeFunctions) GetOrder(investor string) ([]byte, error) {
	orderJson := c.getOrderAsJsonFromBlockchain(investor)
	return []byte(orderJson), nil
}

func (c ChaincodeFunctions) GetOrderbook() ([]byte, error) {
	orderbookJson, _ := c.stub.GetState("orderbook")
	return []byte(orderbookJson), nil
}

func (c ChaincodeFunctions) AllocateOrder(investor string, alloc float64) ([]byte, error) {
	order := c.getOrderFromBlockChain(investor)
	order.Alloc = alloc
	c.saveOrderToBlockChain(order)
	return nil, nil
}

func (c ChaincodeFunctions) Echo(address string, f string, arg string) ([]byte, error) {
	invokeArgs := util.ToChaincodeArgs(f, arg)
	return c.stub.QueryChaincode(address, invokeArgs)
}

// Private Functions

func (c ChaincodeFunctions) getOrderAsJsonFromBlockchain(investor string) string {
	order := c.getOrderFromBlockChain(investor)
	orderJson, _ := json.Marshal(order)
	return string(orderJson)
}

func (c ChaincodeFunctions) getOrderFromBlockChain(investor string) Order {
	orderbook := c.getOrderbookFromBlockChain()
	return orderbook[investor]
}

func (c ChaincodeFunctions) saveOrderToBlockChain(order Order) {
	orderbook := c.getOrderbookFromBlockChain()
	orderbook[order.Investor] = order
	c.saveOrderbookToBlockChain(orderbook)
}

func (c ChaincodeFunctions) getOrderbookFromBlockChain() map[string]Order {
	orderbookJson, _ := c.stub.GetState("orderbook")
	var orderbook map[string]Order
	_ = json.Unmarshal(orderbookJson, &orderbook)
	return orderbook
}

func (c ChaincodeFunctions) saveOrderbookToBlockChain(orderbook map[string]Order) {
	orderbookJson, _ := json.Marshal(orderbook)
	_ = c.stub.PutState("orderbook", []byte(orderbookJson))
}<|endoftext|>