<commit_before>// go-rst - A reStructuredText parser for Go
// 2014 (c) The go-rst Authors
// MIT Licensed. See LICENSE for details.

package parse

import (
	"fmt"
	"github.com/demizer/go-elog"
	"github.com/demizer/go-spew/spew"
	"reflect"
)

var spd = spew.ConfigState{Indent: "\t", DisableMethods: true}

type systemMessageLevel int

const (
	levelInfo systemMessageLevel = iota
	levelWarning
	levelError
	levelSevere
)

var systemMessageLevels = [...]string{
	"INFO",
	"WARNING",
	"ERROR",
	"SEVERE",
}

func (s systemMessageLevel) String() string {
	return systemMessageLevels[s]
}

type parserError int

const (
	errorUnexpectedSectionTitle parserError = iota
	errorUnexpectedSectionTitleOrTransition
)

var parserErrors = [...]string{
	"errorUnexpectedSectionTitle",
	"errorUnexpectedSectionTitleOrTransition",
}

func (p parserError) String() string {
	return parserErrors[p]
}

func (p parserError) Message() (s string) {
	switch p {
	case errorUnexpectedSectionTitle:
		s = "Unexpected section title."
	case errorUnexpectedSectionTitleOrTransition:
		s = "Unexpected section title or transition."
	}
	return
}

func (p parserError) Level() (s systemMessageLevel) {
	switch p {
	case errorUnexpectedSectionTitle:
		s = levelSevere
	case errorUnexpectedSectionTitleOrTransition:
		s = levelSevere
	}
	return
}

type sectionLevels []*SectionNode

func (s *sectionLevels) String() string {
	var out string
	for _, sec := range *s {
		out += fmt.Sprintf("level: %d, rune: %q, overline: %t, length: %d\n",
			sec.Level, sec.UnderLine.Rune, sec.OverLine != nil, sec.Length)
	}
	return out
}

// Returns nil if not found
func (s *sectionLevels) FindByRune(adornChar rune) *SectionNode {
	for _, sec := range *s {
		if sec.UnderLine.Rune == adornChar {
			return sec
		}
	}
	return nil
}

// If exists == true, a section node with the same text and underline has been found in
// sectionLevels, sec is the matching SectionNode. If exists == false, then the sec return value is
// the similarly leveled SectionNode. If exists == false and sec == nil, then the SectionNode added
// to sectionLevels is a new Node.
func (s *sectionLevels) Add(section *SectionNode) (exists bool, sec *SectionNode) {
	sec = s.FindByRune(section.UnderLine.Rune)
	if sec != nil {
		if sec.Text == section.Text {
			return true, sec
		} else if sec.Text != section.Text {
			section.Level = sec.Level
		}
	} else {
		section.Level = len(*s) + 1
	}
	exists = false
	*s = append(*s, section)
	return
}

func (s *sectionLevels) Level() int {
	return len(*s)
}

// Parse is the entry point for the reStructuredText parser.
func Parse(name, text string) (t *Tree, errors []error) {
	t = New(name)
	t.text = text
	_, errors = t.Parse(text, t)
	return
}

func New(name string) *Tree {
	return &Tree{
		Name:          name,
		Nodes:         newList(),
		nodeTarget:    newList(),
		sectionLevels: new(sectionLevels),
		indentWidth:   indentWidth,
	}
}

const (
	tokenPos    = 3
	indentWidth = 4 // Default indent width
)

type Tree struct {
	Name             string
	Nodes            *NodeList // The root node list
	nodeTarget       *NodeList // Used by the parser to add nodes to a target NodeList
	Errors           []error
	text             string
	lex              *lexer
	tokenBackupCount int
	tokenPeekCount   int
	token            [7]*item
	sectionLevels    *sectionLevels // Encountered section levels
	id               int            // The unique id of the node in the tree
	indentWidth      int
	indentLevel      int
}

func (t *Tree) errorf(format string, args ...interface{}) {
	format = fmt.Sprintf("go-rst: %s:%d: %s\n", t.Name, t.lex.lineNumber(), format)
	t.Errors = append(t.Errors, fmt.Errorf(format, args...))
}

func (t *Tree) error(err error) {
	t.errorf("%s\n", err)
}

// startParse initializes the parser, using the lexer.
func (t *Tree) startParse(lex *lexer) {
	t.lex = lex
}

// stopParse terminates parsing.
func (t *Tree) stopParse() {
	t.Nodes = nil
	t.nodeTarget = nil
	t.lex = nil
}

func (t *Tree) Parse(text string, treeSet *Tree) (tree *Tree, errors []error) {
	log.Debugln("Start")
	t.startParse(lex(t.Name, text))
	t.text = text
	t.parse(treeSet)
	log.Debugln("End")
	return t, t.Errors
}

func (t *Tree) parse(tree *Tree) {
	log.Debugln("Start")

	t.nodeTarget = t.Nodes

	for t.peek(1).Type != itemEOF {
		var n Node
		token := t.next()
		t.id++
		token.Id = t.id
		log.Infof("Got token: %#+v\n", token)

		switch token.Type {
		case itemSectionAdornment:
			n = t.section(token)
			t.id++
		case itemParagraph:
			n = newParagraph(token)
		case itemSpace:
			n = t.indent(token)
			if n == nil {
				continue
			}
		case itemTitle, itemBlankLine:
			// itemTitle is consumed when evaluating itemSectionAdornment
			t.id--
			continue
		default:
			t.errorf("%q Not implemented!", token.Type)
			continue
		}

		t.nodeTarget.append(n)

		switch n.NodeType() {
		case NodeSection, NodeBlockQuote:
			// Set the loop to append items to the NodeList of the new section
			t.nodeTarget = reflect.ValueOf(n).Elem().FieldByName("NodeList").Addr().Interface().(*NodeList)
		case NodeSystemMessage:
			t.id--
		}
	}

	log.Debugln("End")
}

func (t *Tree) backup() *item {
	t.tokenBackupCount++
	// log.Debugln("t.tokenBackupCount:", t.tokenPeekCount)
	for i := len(t.token) - 1; i > 0; i-- {
		t.token[i] = t.token[i-1]
		t.token[i-1] = nil
	}
	// log.Debugf("\n##### backup() aftermath #####\n\n")
	// spd.Dump(t.token)
	return t.token[tokenPos-t.tokenBackupCount]
}

func (t *Tree) peekBack(pos int) *item {
	return t.token[tokenPos-pos]
}

func (t *Tree) peek(pos int) *item {
	// log.Debugln("t.tokenPeekCount:", t.tokenPeekCount, "Pos:", pos)
	for i := 0; i < pos; i++ {
		t.tokenPeekCount++
		if t.token[tokenPos+t.tokenPeekCount] == nil {
			t.token[tokenPos+t.tokenPeekCount] = t.lex.nextItem()
		}
	}
	// log.Debugf("\n##### peek() aftermath #####\n\n")
	// spd.Dump(t.token)
	return t.token[tokenPos+t.tokenPeekCount]
}

func (t *Tree) next() *item {
	// log.Debugln("t.tokenPeekCount:", t.tokenPeekCount)
	// shifts the pointers left in t.token, pos is the amount to shift
	shift := func(pos int) {
		for i := pos; i > 0; i-- {
			for x := 0; x < 4; x++ {
				t.token[x] = t.token[x+1]
				t.token[x+1] = nil
			}
		}
	}
	if t.tokenPeekCount > 0 {
		shift(t.tokenPeekCount)
	} else {
		shift(1)
		t.token[tokenPos] = t.lex.nextItem()
	}
	t.tokenBackupCount, t.tokenPeekCount = 0, 0
	// log.Debugf("\n##### next() aftermath #####\n\n")
	// spd.Dump(t.token)
	return t.token[tokenPos]
}

func (t *Tree) section(i *item) Node {
	log.Debugln("Start")
	var overAdorn, title, underAdorn *item
	var overline bool

	peekBack := t.peekBack(1)
	if peekBack != nil {
		if peekBack.Type == itemSpace {
			// Looking back past the white space
			if t.peekBack(2).Type == itemTitle {
				return t.errorReporter(errorUnexpectedSectionTitle)
			}
			return t.errorReporter(errorUnexpectedSectionTitleOrTransition)
		} else if peekBack.Type == itemTitle {
			if t.peekBack(2) != nil && t.peekBack(2).Type == itemSectionAdornment {
				// The overline of the section
				overline = true
				overAdorn = peekBack
			}
		}
	}

	title = t.peekBack(1)
	underAdorn = i

	// TODO: Change these into proper error messages!
	// Check adornment for proper syntax
	if underAdorn.Type == itemSpace {
		t.backup() // Put the parser back on the title
		return t.errorReporter(errorUnexpectedSectionTitle)
	} else if title.Length != underAdorn.Length {
		t.errorf("Section under line not equal to title length!")
	} else if overline && title.Length != overAdorn.Length {
		t.errorf("Section over line not equal to title length!")
	} else if overline && overAdorn.Text != underAdorn.Text {
		t.errorf("Section title over line does not match section title under line.")
	}

	sec := newSection(title, overAdorn, underAdorn)
	exists, eSec := t.sectionLevels.Add(sec)
	if exists && eSec != nil {
		t.errorf("SectionNode using Text \"%s\" and Rune '%s' was previously parsed!",
			sec.Text, string(sec.UnderLine.Rune))
	} else if !exists && eSec != nil {
		// There is a matching level in sectionLevels
		t.nodeTarget = &(*t.sectionLevels)[sec.Level-2].NodeList
	}

	log.Debugln("End")
	return sec
}

func (t *Tree) errorReporter(err parserError) Node {
	var lbText string
	var lbTextLen int

	s := newSystemMessage(&item{
		Id:   t.id - 1,
		Type: itemSystemMessage,
		Line: t.token[tokenPos].Line,
	},
		err.Level())

	msg := newParagraph(&item{
		Id:     t.id,
		Text:   err.Message(),
		Length: len(err.Message()),
	})

	switch err {
	case errorUnexpectedSectionTitle:
		log.Debugln("FOUND errorUnexpectedSectionTitle")
		lbText = t.token[1].Text.(string) + "\n" + t.token[3].Text.(string)
		lbTextLen = len(lbText) + 1
	case errorUnexpectedSectionTitleOrTransition:
		log.Debugln("FOUND errorUnexpectedSectionTitleOrTransition")
		lbText = t.token[tokenPos].Text.(string)
		lbTextLen = len(lbText)
	}

	lb := newLiteralBlock(&item{
		Id:     t.id + 1,
		Type:   itemLiteralBlock,
		Text:   lbText,
		Length: lbTextLen, // Add one to account for the backslash
	})

	s.NodeList = append(s.NodeList, msg, lb)

	// log.Debugf("\n##### TOKENS #####\n\n")
	// spd.Dump(t.token)
	// log.Debugf("\n##### NODE #####\n\n")
	// spd.Dump(nb)

	return s
}

func (t *Tree) indent(i *item) Node {
	level := i.Length / t.indentWidth
	if t.peekBack(1).Type == itemBlankLine {
		if t.indentLevel == level {
			// Append to the current blockquote NodeList
			return nil
		}
		t.indentLevel = level
		return newBlockQuote(&item{Id: i.Id, Type: itemBlockquote, Line: i.Line}, level)
	}
	return nil
}
<commit_msg>parse.go: Add Tree.skip()<commit_after>// go-rst - A reStructuredText parser for Go
// 2014 (c) The go-rst Authors
// MIT Licensed. See LICENSE for details.

package parse

import (
	"fmt"
	"github.com/demizer/go-elog"
	"github.com/demizer/go-spew/spew"
	"reflect"
)

var spd = spew.ConfigState{Indent: "\t", DisableMethods: true}

type systemMessageLevel int

const (
	levelInfo systemMessageLevel = iota
	levelWarning
	levelError
	levelSevere
)

var systemMessageLevels = [...]string{
	"INFO",
	"WARNING",
	"ERROR",
	"SEVERE",
}

func (s systemMessageLevel) String() string {
	return systemMessageLevels[s]
}

type parserError int

const (
	errorUnexpectedSectionTitle parserError = iota
	errorUnexpectedSectionTitleOrTransition
)

var parserErrors = [...]string{
	"errorUnexpectedSectionTitle",
	"errorUnexpectedSectionTitleOrTransition",
}

func (p parserError) String() string {
	return parserErrors[p]
}

func (p parserError) Message() (s string) {
	switch p {
	case errorUnexpectedSectionTitle:
		s = "Unexpected section title."
	case errorUnexpectedSectionTitleOrTransition:
		s = "Unexpected section title or transition."
	}
	return
}

func (p parserError) Level() (s systemMessageLevel) {
	switch p {
	case errorUnexpectedSectionTitle:
		s = levelSevere
	case errorUnexpectedSectionTitleOrTransition:
		s = levelSevere
	}
	return
}

type sectionLevels []*SectionNode

func (s *sectionLevels) String() string {
	var out string
	for _, sec := range *s {
		out += fmt.Sprintf("level: %d, rune: %q, overline: %t, length: %d\n",
			sec.Level, sec.UnderLine.Rune, sec.OverLine != nil, sec.Length)
	}
	return out
}

// Returns nil if not found
func (s *sectionLevels) FindByRune(adornChar rune) *SectionNode {
	for _, sec := range *s {
		if sec.UnderLine.Rune == adornChar {
			return sec
		}
	}
	return nil
}

// If exists == true, a section node with the same text and underline has been found in
// sectionLevels, sec is the matching SectionNode. If exists == false, then the sec return value is
// the similarly leveled SectionNode. If exists == false and sec == nil, then the SectionNode added
// to sectionLevels is a new Node.
func (s *sectionLevels) Add(section *SectionNode) (exists bool, sec *SectionNode) {
	sec = s.FindByRune(section.UnderLine.Rune)
	if sec != nil {
		if sec.Text == section.Text {
			return true, sec
		} else if sec.Text != section.Text {
			section.Level = sec.Level
		}
	} else {
		section.Level = len(*s) + 1
	}
	exists = false
	*s = append(*s, section)
	return
}

func (s *sectionLevels) Level() int {
	return len(*s)
}

// Parse is the entry point for the reStructuredText parser.
func Parse(name, text string) (t *Tree, errors []error) {
	t = New(name)
	t.text = text
	_, errors = t.Parse(text, t)
	return
}

func New(name string) *Tree {
	return &Tree{
		Name:          name,
		Nodes:         newList(),
		nodeTarget:    newList(),
		sectionLevels: new(sectionLevels),
		indentWidth:   indentWidth,
	}
}

const (
	tokenPos    = 3
	indentWidth = 4 // Default indent width
)

type Tree struct {
	Name             string
	Nodes            *NodeList // The root node list
	nodeTarget       *NodeList // Used by the parser to add nodes to a target NodeList
	Errors           []error
	text             string
	lex              *lexer
	tokenBackupCount int
	tokenPeekCount   int
	token            [7]*item
	sectionLevels    *sectionLevels // Encountered section levels
	id               int            // The unique id of the node in the tree
	indentWidth      int
	indentLevel      int
}

func (t *Tree) errorf(format string, args ...interface{}) {
	format = fmt.Sprintf("go-rst: %s:%d: %s\n", t.Name, t.lex.lineNumber(), format)
	t.Errors = append(t.Errors, fmt.Errorf(format, args...))
}

func (t *Tree) error(err error) {
	t.errorf("%s\n", err)
}

// startParse initializes the parser, using the lexer.
func (t *Tree) startParse(lex *lexer) {
	t.lex = lex
}

// stopParse terminates parsing.
func (t *Tree) stopParse() {
	t.Nodes = nil
	t.nodeTarget = nil
	t.lex = nil
}

func (t *Tree) Parse(text string, treeSet *Tree) (tree *Tree, errors []error) {
	log.Debugln("Start")
	t.startParse(lex(t.Name, text))
	t.text = text
	t.parse(treeSet)
	log.Debugln("End")
	return t, t.Errors
}

func (t *Tree) parse(tree *Tree) {
	log.Debugln("Start")

	t.nodeTarget = t.Nodes

	for t.peek(1).Type != itemEOF {
		var n Node
		token := t.next()
		t.id++
		token.Id = t.id
		log.Infof("Got token: %#+v\n", token)

		switch token.Type {
		case itemSectionAdornment:
			n = t.section(token)
			t.id++
		case itemParagraph:
			n = newParagraph(token)
		case itemSpace:
			n = t.indent(token)
			if n == nil {
				continue
			}
		case itemTitle, itemBlankLine:
			// itemTitle is consumed when evaluating itemSectionAdornment
			t.id--
			continue
		default:
			t.errorf("%q Not implemented!", token.Type)
			continue
		}

		t.nodeTarget.append(n)

		switch n.NodeType() {
		case NodeSection, NodeBlockQuote:
			// Set the loop to append items to the NodeList of the new section
			t.nodeTarget = reflect.ValueOf(n).Elem().FieldByName("NodeList").Addr().Interface().(*NodeList)
		case NodeSystemMessage:
			t.id--
		}
	}

	log.Debugln("End")
}

func (t *Tree) backup() *item {
	t.tokenBackupCount++
	// log.Debugln("t.tokenBackupCount:", t.tokenPeekCount)
	for i := len(t.token) - 1; i > 0; i-- {
		t.token[i] = t.token[i-1]
		t.token[i-1] = nil
	}
	// log.Debugf("\n##### backup() aftermath #####\n\n")
	// spd.Dump(t.token)
	return t.token[tokenPos-t.tokenBackupCount]
}

func (t *Tree) peekBack(pos int) *item {
	return t.token[tokenPos-pos]
}

func (t *Tree) peek(pos int) *item {
	// log.Debugln("t.tokenPeekCount:", t.tokenPeekCount, "Pos:", pos)
	for i := 0; i < pos; i++ {
		t.tokenPeekCount++
		if t.token[tokenPos+t.tokenPeekCount] == nil {
			t.token[tokenPos+t.tokenPeekCount] = t.lex.nextItem()
		}
	}
	// log.Debugf("\n##### peek() aftermath #####\n\n")
	// spd.Dump(t.token)
	return t.token[tokenPos+t.tokenPeekCount]
}

// skip shifts the pointers left in t.token, pos is the amount to shift
func (t *Tree) skip(num int) {
	for i := num; i > 0; i-- {
		for x := 0; x < len(t.token)-1; x++ {
			t.token[x] = t.token[x+1]
			t.token[x+1] = nil
		}
	}
}

func (t *Tree) next() *item {
	// log.Debugln("t.tokenPeekCount:", t.tokenPeekCount)
	if t.tokenPeekCount > 0 {
		t.skip(t.tokenPeekCount)
	} else {
		t.skip(1)
		t.token[tokenPos] = t.lex.nextItem()
	}
	t.tokenBackupCount, t.tokenPeekCount = 0, 0
	// log.Debugf("\n##### next() aftermath #####\n\n")
	// spd.Dump(t.token)
	return t.token[tokenPos]
}

func (t *Tree) section(i *item) Node {
	log.Debugln("Start")
	var overAdorn, title, underAdorn *item
	var overline bool

	peekBack := t.peekBack(1)
	if peekBack != nil {
		if peekBack.Type == itemSpace {
			// Looking back past the white space
			if t.peekBack(2).Type == itemTitle {
				return t.errorReporter(errorUnexpectedSectionTitle)
			}
			return t.errorReporter(errorUnexpectedSectionTitleOrTransition)
		} else if peekBack.Type == itemTitle {
			if t.peekBack(2) != nil && t.peekBack(2).Type == itemSectionAdornment {
				// The overline of the section
				overline = true
				overAdorn = peekBack
			}
		}
	}

	title = t.peekBack(1)
	underAdorn = i

	// TODO: Change these into proper error messages!
	// Check adornment for proper syntax
	if underAdorn.Type == itemSpace {
		t.backup() // Put the parser back on the title
		return t.errorReporter(errorUnexpectedSectionTitle)
	} else if title.Length != underAdorn.Length {
		t.errorf("Section under line not equal to title length!")
	} else if overline && title.Length != overAdorn.Length {
		t.errorf("Section over line not equal to title length!")
	} else if overline && overAdorn.Text != underAdorn.Text {
		t.errorf("Section title over line does not match section title under line.")
	}

	sec := newSection(title, overAdorn, underAdorn)
	exists, eSec := t.sectionLevels.Add(sec)
	if exists && eSec != nil {
		t.errorf("SectionNode using Text \"%s\" and Rune '%s' was previously parsed!",
			sec.Text, string(sec.UnderLine.Rune))
	} else if !exists && eSec != nil {
		// There is a matching level in sectionLevels
		t.nodeTarget = &(*t.sectionLevels)[sec.Level-2].NodeList
	}

	log.Debugln("End")
	return sec
}

func (t *Tree) errorReporter(err parserError) Node {
	var lbText string
	var lbTextLen int

	s := newSystemMessage(&item{
		Id:   t.id - 1,
		Type: itemSystemMessage,
		Line: t.token[tokenPos].Line,
	},
		err.Level())

	msg := newParagraph(&item{
		Id:     t.id,
		Text:   err.Message(),
		Length: len(err.Message()),
	})

	switch err {
	case errorUnexpectedSectionTitle:
		log.Debugln("FOUND errorUnexpectedSectionTitle")
		lbText = t.token[1].Text.(string) + "\n" + t.token[3].Text.(string)
		lbTextLen = len(lbText) + 1
	case errorUnexpectedSectionTitleOrTransition:
		log.Debugln("FOUND errorUnexpectedSectionTitleOrTransition")
		lbText = t.token[tokenPos].Text.(string)
		lbTextLen = len(lbText)
	}

	lb := newLiteralBlock(&item{
		Id:     t.id + 1,
		Type:   itemLiteralBlock,
		Text:   lbText,
		Length: lbTextLen, // Add one to account for the backslash
	})

	s.NodeList = append(s.NodeList, msg, lb)

	// log.Debugf("\n##### TOKENS #####\n\n")
	// spd.Dump(t.token)
	// log.Debugf("\n##### NODE #####\n\n")
	// spd.Dump(nb)

	return s
}

func (t *Tree) indent(i *item) Node {
	level := i.Length / t.indentWidth
	if t.peekBack(1).Type == itemBlankLine {
		if t.indentLevel == level {
			// Append to the current blockquote NodeList
			return nil
		}
		t.indentLevel = level
		return newBlockQuote(&item{Id: i.Id, Type: itemBlockquote, Line: i.Line}, level)
	}
	return nil
}
<|endoftext|>


<commit_before>package oss

import "os"

// ACLType bucket/object ACL
type ACLType string

const (
	// ACLPrivate definition : private read and write
	ACLPrivate ACLType = "private"

	// ACLPublicRead definition : public read and private write
	ACLPublicRead ACLType = "public-read"

	// ACLPublicReadWrite definition : public read and public write
	ACLPublicReadWrite ACLType = "public-read-write"

	// ACLDefault Object. It's only applicable for object.
	ACLDefault ACLType = "default"
)

// bucket versioning status
type VersioningStatus string

const (
	// Versioning Status definition: Enabled
	VersionEnabled VersioningStatus = "Enabled"

	// Versioning Status definition: Suspended
	VersionSuspended VersioningStatus = "Suspended"
)

// MetadataDirectiveType specifying whether use the metadata of source object when copying object.
type MetadataDirectiveType string

const (
	// MetaCopy the target object's metadata is copied from the source one
	MetaCopy MetadataDirectiveType = "COPY"

	// MetaReplace the target object's metadata is created as part of the copy request (not same as the source one)
	MetaReplace MetadataDirectiveType = "REPLACE"
)

// TaggingDirectiveType specifying whether use the tagging of source object when copying object.
type TaggingDirectiveType string

const (
	// TaggingCopy the target object's tagging is copied from the source one
	TaggingCopy TaggingDirectiveType = "COPY"

	// TaggingReplace the target object's tagging is created as part of the copy request (not same as the source one)
	TaggingReplace TaggingDirectiveType = "REPLACE"
)

// AlgorithmType specifying the server side encryption algorithm name
type AlgorithmType string

const (
	KMSAlgorithm AlgorithmType = "KMS"
	AESAlgorithm AlgorithmType = "AES256"
)

// StorageClassType bucket storage type
type StorageClassType string

const (
	// StorageStandard standard
	StorageStandard StorageClassType = "Standard"

	// StorageIA infrequent access
	StorageIA StorageClassType = "IA"

	// StorageArchive archive
	StorageArchive StorageClassType = "Archive"
)

// PayerType the type of request payer
type PayerType string

const (
	// Requester the requester who send the request
	Requester PayerType = "requester"
)

// HTTPMethod HTTP request method
type HTTPMethod string

const (
	// HTTPGet HTTP GET
	HTTPGet HTTPMethod = "GET"

	// HTTPPut HTTP PUT
	HTTPPut HTTPMethod = "PUT"

	// HTTPHead HTTP HEAD
	HTTPHead HTTPMethod = "HEAD"

	// HTTPPost HTTP POST
	HTTPPost HTTPMethod = "POST"

	// HTTPDelete HTTP DELETE
	HTTPDelete HTTPMethod = "DELETE"
)

// HTTP headers
const (
	HTTPHeaderAcceptEncoding     string = "Accept-Encoding"
	HTTPHeaderAuthorization             = "Authorization"
	HTTPHeaderCacheControl              = "Cache-Control"
	HTTPHeaderContentDisposition        = "Content-Disposition"
	HTTPHeaderContentEncoding           = "Content-Encoding"
	HTTPHeaderContentLength             = "Content-Length"
	HTTPHeaderContentMD5                = "Content-MD5"
	HTTPHeaderContentType               = "Content-Type"
	HTTPHeaderContentLanguage           = "Content-Language"
	HTTPHeaderDate                      = "Date"
	HTTPHeaderEtag                      = "ETag"
	HTTPHeaderExpires                   = "Expires"
	HTTPHeaderHost                      = "Host"
	HTTPHeaderLastModified              = "Last-Modified"
	HTTPHeaderRange                     = "Range"
	HTTPHeaderLocation                  = "Location"
	HTTPHeaderOrigin                    = "Origin"
	HTTPHeaderServer                    = "Server"
	HTTPHeaderUserAgent                 = "User-Agent"
	HTTPHeaderIfModifiedSince           = "If-Modified-Since"
	HTTPHeaderIfUnmodifiedSince         = "If-Unmodified-Since"
	HTTPHeaderIfMatch                   = "If-Match"
	HTTPHeaderIfNoneMatch               = "If-None-Match"

	HTTPHeaderOssACL                         = "X-Oss-Acl"
	HTTPHeaderOssMetaPrefix                  = "X-Oss-Meta-"
	HTTPHeaderOssObjectACL                   = "X-Oss-Object-Acl"
	HTTPHeaderOssSecurityToken               = "X-Oss-Security-Token"
	HTTPHeaderOssServerSideEncryption        = "X-Oss-Server-Side-Encryption"
	HTTPHeaderOssServerSideEncryptionKeyID   = "X-Oss-Server-Side-Encryption-Key-Id"
	HTTPHeaderOssCopySource                  = "X-Oss-Copy-Source"
	HTTPHeaderOssCopySourceRange             = "X-Oss-Copy-Source-Range"
	HTTPHeaderOssCopySourceIfMatch           = "X-Oss-Copy-Source-If-Match"
	HTTPHeaderOssCopySourceIfNoneMatch       = "X-Oss-Copy-Source-If-None-Match"
	HTTPHeaderOssCopySourceIfModifiedSince   = "X-Oss-Copy-Source-If-Modified-Since"
	HTTPHeaderOssCopySourceIfUnmodifiedSince = "X-Oss-Copy-Source-If-Unmodified-Since"
	HTTPHeaderOssMetadataDirective           = "X-Oss-Metadata-Directive"
	HTTPHeaderOssNextAppendPosition          = "X-Oss-Next-Append-Position"
	HTTPHeaderOssRequestID                   = "X-Oss-Request-Id"
	HTTPHeaderOssCRC64                       = "X-Oss-Hash-Crc64ecma"
	HTTPHeaderOssSymlinkTarget               = "X-Oss-Symlink-Target"
	HTTPHeaderOssStorageClass                = "X-Oss-Storage-Class"
	HTTPHeaderOssCallback                    = "X-Oss-Callback"
	HTTPHeaderOssCallbackVar                 = "X-Oss-Callback-Var"
	HTTPHeaderOssRequester                   = "X-Oss-Request-Payer"
	HTTPHeaderOssTagging                     = "X-Oss-Tagging"
	HTTPHeaderOssTaggingDirective            = "X-Oss-Tagging-Directive"
)

// HTTP Param
const (
	HTTPParamExpires       = "Expires"
	HTTPParamAccessKeyID   = "OSSAccessKeyId"
	HTTPParamSignature     = "Signature"
	HTTPParamSecurityToken = "security-token"
	HTTPParamPlaylistName  = "playlistName"
)

// Other constants
const (
	MaxPartSize = 5 * 1024 * 1024 * 1024 // Max part size, 5GB
	MinPartSize = 100 * 1024             // Min part size, 100KB

	FilePermMode = os.FileMode(0664) // Default file permission

	TempFilePrefix = "oss-go-temp-" // Temp file prefix
	TempFileSuffix = ".temp"        // Temp file suffix

	CheckpointFileSuffix = ".cp" // Checkpoint file suffix

	NullVersion = "null"

	Version = "v1.9.9" // Go SDK version
)
<commit_msg>change version to v2.0.0 alpha<commit_after>package oss

import "os"

// ACLType bucket/object ACL
type ACLType string

const (
	// ACLPrivate definition : private read and write
	ACLPrivate ACLType = "private"

	// ACLPublicRead definition : public read and private write
	ACLPublicRead ACLType = "public-read"

	// ACLPublicReadWrite definition : public read and public write
	ACLPublicReadWrite ACLType = "public-read-write"

	// ACLDefault Object. It's only applicable for object.
	ACLDefault ACLType = "default"
)

// bucket versioning status
type VersioningStatus string

const (
	// Versioning Status definition: Enabled
	VersionEnabled VersioningStatus = "Enabled"

	// Versioning Status definition: Suspended
	VersionSuspended VersioningStatus = "Suspended"
)

// MetadataDirectiveType specifying whether use the metadata of source object when copying object.
type MetadataDirectiveType string

const (
	// MetaCopy the target object's metadata is copied from the source one
	MetaCopy MetadataDirectiveType = "COPY"

	// MetaReplace the target object's metadata is created as part of the copy request (not same as the source one)
	MetaReplace MetadataDirectiveType = "REPLACE"
)

// TaggingDirectiveType specifying whether use the tagging of source object when copying object.
type TaggingDirectiveType string

const (
	// TaggingCopy the target object's tagging is copied from the source one
	TaggingCopy TaggingDirectiveType = "COPY"

	// TaggingReplace the target object's tagging is created as part of the copy request (not same as the source one)
	TaggingReplace TaggingDirectiveType = "REPLACE"
)

// AlgorithmType specifying the server side encryption algorithm name
type AlgorithmType string

const (
	KMSAlgorithm AlgorithmType = "KMS"
	AESAlgorithm AlgorithmType = "AES256"
)

// StorageClassType bucket storage type
type StorageClassType string

const (
	// StorageStandard standard
	StorageStandard StorageClassType = "Standard"

	// StorageIA infrequent access
	StorageIA StorageClassType = "IA"

	// StorageArchive archive
	StorageArchive StorageClassType = "Archive"
)

// PayerType the type of request payer
type PayerType string

const (
	// Requester the requester who send the request
	Requester PayerType = "requester"
)

// HTTPMethod HTTP request method
type HTTPMethod string

const (
	// HTTPGet HTTP GET
	HTTPGet HTTPMethod = "GET"

	// HTTPPut HTTP PUT
	HTTPPut HTTPMethod = "PUT"

	// HTTPHead HTTP HEAD
	HTTPHead HTTPMethod = "HEAD"

	// HTTPPost HTTP POST
	HTTPPost HTTPMethod = "POST"

	// HTTPDelete HTTP DELETE
	HTTPDelete HTTPMethod = "DELETE"
)

// HTTP headers
const (
	HTTPHeaderAcceptEncoding     string = "Accept-Encoding"
	HTTPHeaderAuthorization             = "Authorization"
	HTTPHeaderCacheControl              = "Cache-Control"
	HTTPHeaderContentDisposition        = "Content-Disposition"
	HTTPHeaderContentEncoding           = "Content-Encoding"
	HTTPHeaderContentLength             = "Content-Length"
	HTTPHeaderContentMD5                = "Content-MD5"
	HTTPHeaderContentType               = "Content-Type"
	HTTPHeaderContentLanguage           = "Content-Language"
	HTTPHeaderDate                      = "Date"
	HTTPHeaderEtag                      = "ETag"
	HTTPHeaderExpires                   = "Expires"
	HTTPHeaderHost                      = "Host"
	HTTPHeaderLastModified              = "Last-Modified"
	HTTPHeaderRange                     = "Range"
	HTTPHeaderLocation                  = "Location"
	HTTPHeaderOrigin                    = "Origin"
	HTTPHeaderServer                    = "Server"
	HTTPHeaderUserAgent                 = "User-Agent"
	HTTPHeaderIfModifiedSince           = "If-Modified-Since"
	HTTPHeaderIfUnmodifiedSince         = "If-Unmodified-Since"
	HTTPHeaderIfMatch                   = "If-Match"
	HTTPHeaderIfNoneMatch               = "If-None-Match"

	HTTPHeaderOssACL                         = "X-Oss-Acl"
	HTTPHeaderOssMetaPrefix                  = "X-Oss-Meta-"
	HTTPHeaderOssObjectACL                   = "X-Oss-Object-Acl"
	HTTPHeaderOssSecurityToken               = "X-Oss-Security-Token"
	HTTPHeaderOssServerSideEncryption        = "X-Oss-Server-Side-Encryption"
	HTTPHeaderOssServerSideEncryptionKeyID   = "X-Oss-Server-Side-Encryption-Key-Id"
	HTTPHeaderOssCopySource                  = "X-Oss-Copy-Source"
	HTTPHeaderOssCopySourceRange             = "X-Oss-Copy-Source-Range"
	HTTPHeaderOssCopySourceIfMatch           = "X-Oss-Copy-Source-If-Match"
	HTTPHeaderOssCopySourceIfNoneMatch       = "X-Oss-Copy-Source-If-None-Match"
	HTTPHeaderOssCopySourceIfModifiedSince   = "X-Oss-Copy-Source-If-Modified-Since"
	HTTPHeaderOssCopySourceIfUnmodifiedSince = "X-Oss-Copy-Source-If-Unmodified-Since"
	HTTPHeaderOssMetadataDirective           = "X-Oss-Metadata-Directive"
	HTTPHeaderOssNextAppendPosition          = "X-Oss-Next-Append-Position"
	HTTPHeaderOssRequestID                   = "X-Oss-Request-Id"
	HTTPHeaderOssCRC64                       = "X-Oss-Hash-Crc64ecma"
	HTTPHeaderOssSymlinkTarget               = "X-Oss-Symlink-Target"
	HTTPHeaderOssStorageClass                = "X-Oss-Storage-Class"
	HTTPHeaderOssCallback                    = "X-Oss-Callback"
	HTTPHeaderOssCallbackVar                 = "X-Oss-Callback-Var"
	HTTPHeaderOssRequester                   = "X-Oss-Request-Payer"
	HTTPHeaderOssTagging                     = "X-Oss-Tagging"
	HTTPHeaderOssTaggingDirective            = "X-Oss-Tagging-Directive"
)

// HTTP Param
const (
	HTTPParamExpires       = "Expires"
	HTTPParamAccessKeyID   = "OSSAccessKeyId"
	HTTPParamSignature     = "Signature"
	HTTPParamSecurityToken = "security-token"
	HTTPParamPlaylistName  = "playlistName"
)

// Other constants
const (
	MaxPartSize = 5 * 1024 * 1024 * 1024 // Max part size, 5GB
	MinPartSize = 100 * 1024             // Min part size, 100KB

	FilePermMode = os.FileMode(0664) // Default file permission

	TempFilePrefix = "oss-go-temp-" // Temp file prefix
	TempFileSuffix = ".temp"        // Temp file suffix

	CheckpointFileSuffix = ".cp" // Checkpoint file suffix

	NullVersion = "null"

	Version = "v2.0.0 alpha" // Go SDK version
)
<|endoftext|>


<commit_before>package wiki
<commit_msg>Delete markdown.go<commit_after><|endoftext|>


<commit_before>// (c) Copyright 2015-2017 JONNALAGADDA Srinivas
//
// 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 flow

import (
	"database/sql"
	"testing"

	_ "github.com/go-sql-driver/mysql"
)

const (
	wflowName = "DATA_PLAT:STOR_REQ"
)

// Driver test function.
func TestWorkflows01(t *testing.T) {
	// Connect to the database.
	driver, connStr := "mysql", "travis@/flow"
	db, err := sql.Open(driver, connStr)
	if err != nil {
		t.Fatalf("could not connect to database : %v\n", err)
	}
	defer db.Close()
	err = db.Ping()
	if err != nil {
		t.Fatalf("could not ping the database : %v\n", err)
	}
	RegisterDB(db)

	// Tear down.
	defer func() {
		tx, err := db.Begin()
		if err != nil {
			t.Fatalf("error starting transaction : %v\n", err)
		}
		defer tx.Rollback()

		_, err = tx.Exec(`DELETE FROM wf_workflows`)
		if err != nil {
			t.Fatalf("error running transaction : %v\n", err)
		}

		_, err = tx.Exec(`DELETE FROM wf_docstates_master`)
		if err != nil {
			t.Fatalf("error running transaction : %v\n", err)
		}

		_, err = tx.Exec(`DELETE FROM wf_doctypes_master`)
		if err != nil {
			t.Fatalf("error running transaction : %v\n", err)
		}

		err = tx.Commit()
		if err != nil {
			t.Fatalf("error committing transaction : %v\n", err)
		}
	}()

	// Test-local state.
	var dtypeStorReqID DocTypeID
	var dstateID DocStateID
	var wid WorkflowID

	// Register a few new workflows.
	t.Run("Create", func(t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatalf("error starting transaction : %v\n", err)
		}
		defer tx.Rollback()

		dtypeStorReqID, err = DocTypes().New(tx, dtypeStorReq)
		if err != nil {
			t.Fatalf("error creating document type '%s' : %v\n", dtypeStorReq, err)
		}
		for _, name := range storReqStates {
			dstateID, err = DocStates().New(tx, dtypeStorReqID, name)
			if err != nil {
				t.Fatalf("error creating document type:state '%d:%s' : %v\n", dtypeStorReqID, name, err)
			}
		}

		wid, err = Workflows().New(tx, wflowName, dtypeStorReqID, dstateID)
		if err != nil {
			t.Fatalf("error creating workflow : %v\n", err)
		}

		err = tx.Commit()
		if err != nil {
			t.Fatalf("error committing transaction : %v\n", err)
		}
	})

	// Test reading.
	t.Run("Read", func(t *testing.T) {
		_, err = Workflows().Get(wid)
		if err != nil {
			t.Fatalf("error getting workflow : %v\n", err)
		}

		_, err = Workflows().GetByName(wflowName)
		if err != nil {
			t.Fatalf("error getting workflow : %v\n", err)
		}

		_, err = Workflows().List(0, 0)
		if err != nil {
			t.Fatalf("error : %v", err)
		}
	})

	// Test renaming.
	t.Run("Rename", func(t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatalf("error starting transaction : %v\n", err)
		}
		defer tx.Rollback()

		err = Workflows().Rename(tx, wid, "TEST_WFLOW")
		if err != nil {
			t.Fatalf("error renaming workflow : %v\n", err)
		}
		err = Workflows().Rename(tx, wid, wflowName)
		if err != nil {
			t.Fatalf("error renaming workflow : %v\n", err)
		}

		err = tx.Commit()
		if err != nil {
			t.Fatalf("error committing transaction : %v\n", err)
		}
	})

	// Test activation and inactivation.
	t.Run("Active", func(t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatalf("error starting transaction : %v\n", err)
		}
		defer tx.Rollback()

		err = Workflows().SetActive(tx, wid, false)
		if err != nil {
			t.Fatalf("error inactivating workflow : %v\n", err)
		}
		err = Workflows().SetActive(tx, wid, true)
		if err != nil {
			t.Fatalf("error activating workflow : %v\n", err)
		}

		err = tx.Commit()
		if err != nil {
			t.Fatalf("error committing transaction : %v\n", err)
		}
	})
}
<commit_msg>Update workflow tests to refer to `Workflows` instead of `Workflows()`<commit_after>// (c) Copyright 2015-2017 JONNALAGADDA Srinivas
//
// 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 flow

import (
	"database/sql"
	"testing"

	_ "github.com/go-sql-driver/mysql"
)

const (
	wflowName = "DATA_PLAT:STOR_REQ"
)

// Driver test function.
func TestWorkflows01(t *testing.T) {
	// Connect to the database.
	driver, connStr := "mysql", "travis@/flow"
	db, err := sql.Open(driver, connStr)
	if err != nil {
		t.Fatalf("could not connect to database : %v\n", err)
	}
	defer db.Close()
	err = db.Ping()
	if err != nil {
		t.Fatalf("could not ping the database : %v\n", err)
	}
	RegisterDB(db)

	// Tear down.
	defer func() {
		tx, err := db.Begin()
		if err != nil {
			t.Fatalf("error starting transaction : %v\n", err)
		}
		defer tx.Rollback()

		_, err = tx.Exec(`DELETE FROM wf_workflows`)
		if err != nil {
			t.Fatalf("error running transaction : %v\n", err)
		}

		_, err = tx.Exec(`DELETE FROM wf_docstates_master`)
		if err != nil {
			t.Fatalf("error running transaction : %v\n", err)
		}

		_, err = tx.Exec(`DELETE FROM wf_doctypes_master`)
		if err != nil {
			t.Fatalf("error running transaction : %v\n", err)
		}

		err = tx.Commit()
		if err != nil {
			t.Fatalf("error committing transaction : %v\n", err)
		}
	}()

	// Test-local state.
	var dtypeStorReqID DocTypeID
	var dstateID DocStateID
	var wid WorkflowID

	// Register a few new workflows.
	t.Run("Create", func(t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatalf("error starting transaction : %v\n", err)
		}
		defer tx.Rollback()

		dtypeStorReqID, err = DocTypes().New(tx, dtypeStorReq)
		if err != nil {
			t.Fatalf("error creating document type '%s' : %v\n", dtypeStorReq, err)
		}
		for _, name := range storReqStates {
			dstateID, err = DocStates().New(tx, dtypeStorReqID, name)
			if err != nil {
				t.Fatalf("error creating document type:state '%d:%s' : %v\n", dtypeStorReqID, name, err)
			}
		}

		wid, err = Workflows.New(tx, wflowName, dtypeStorReqID, dstateID)
		if err != nil {
			t.Fatalf("error creating workflow : %v\n", err)
		}

		err = tx.Commit()
		if err != nil {
			t.Fatalf("error committing transaction : %v\n", err)
		}
	})

	// Test reading.
	t.Run("Read", func(t *testing.T) {
		_, err = Workflows.Get(wid)
		if err != nil {
			t.Fatalf("error getting workflow : %v\n", err)
		}

		_, err = Workflows.GetByName(wflowName)
		if err != nil {
			t.Fatalf("error getting workflow : %v\n", err)
		}

		_, err = Workflows.List(0, 0)
		if err != nil {
			t.Fatalf("error : %v", err)
		}
	})

	// Test renaming.
	t.Run("Rename", func(t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatalf("error starting transaction : %v\n", err)
		}
		defer tx.Rollback()

		err = Workflows.Rename(tx, wid, "TEST_WFLOW")
		if err != nil {
			t.Fatalf("error renaming workflow : %v\n", err)
		}
		err = Workflows.Rename(tx, wid, wflowName)
		if err != nil {
			t.Fatalf("error renaming workflow : %v\n", err)
		}

		err = tx.Commit()
		if err != nil {
			t.Fatalf("error committing transaction : %v\n", err)
		}
	})

	// Test activation and inactivation.
	t.Run("Active", func(t *testing.T) {
		tx, err := db.Begin()
		if err != nil {
			t.Fatalf("error starting transaction : %v\n", err)
		}
		defer tx.Rollback()

		err = Workflows.SetActive(tx, wid, false)
		if err != nil {
			t.Fatalf("error inactivating workflow : %v\n", err)
		}
		err = Workflows.SetActive(tx, wid, true)
		if err != nil {
			t.Fatalf("error activating workflow : %v\n", err)
		}

		err = tx.Commit()
		if err != nil {
			t.Fatalf("error committing transaction : %v\n", err)
		}
	})
}
<|endoftext|>


<commit_before>package neutrino

import (
	"github.com/btcsuite/btcd/addrmgr"
	"github.com/btcsuite/btcd/blockchain"
	"github.com/btcsuite/btcd/peer"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btclog"
)

// log is a logger that is initialized with no output filters.  This
// means the package will not perform any logging by default until the caller
// requests it.
var log btclog.Logger

// The default amount of logging is none.
func init() {
	DisableLog()
}

// DisableLog disables all library log output.  Logging output is disabled
// by default until either UseLogger or SetLogWriter are called.
func DisableLog() {
	log = btclog.Disabled
}

// UseLogger uses a specified Logger to output package logging info.
// This should be used in preference to SetLogWriter if the caller is also
// using btclog.
func UseLogger(logger btclog.Logger) {
	log = logger
	blockchain.UseLogger(logger)
	txscript.UseLogger(logger)
	peer.UseLogger(logger)
	addrmgr.UseLogger(logger)
}
<commit_msg>log: add newLogClosure function<commit_after>package neutrino

import (
	"github.com/btcsuite/btcd/addrmgr"
	"github.com/btcsuite/btcd/blockchain"
	"github.com/btcsuite/btcd/peer"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btclog"
)

// log is a logger that is initialized with no output filters.  This
// means the package will not perform any logging by default until the caller
// requests it.
var log btclog.Logger

// The default amount of logging is none.
func init() {
	DisableLog()
}

// DisableLog disables all library log output.  Logging output is disabled
// by default until either UseLogger or SetLogWriter are called.
func DisableLog() {
	log = btclog.Disabled
}

// UseLogger uses a specified Logger to output package logging info.
// This should be used in preference to SetLogWriter if the caller is also
// using btclog.
func UseLogger(logger btclog.Logger) {
	log = logger
	blockchain.UseLogger(logger)
	txscript.UseLogger(logger)
	peer.UseLogger(logger)
	addrmgr.UseLogger(logger)
}

// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string

// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
	return c()
}

// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
	return logClosure(c)
}
<|endoftext|>


<commit_before>package log

import (
	"reflect"
)

const TIME_FORMAT = "2006-01-02T15:04:05.000000"
const LEVEL_DEBUG = "DEBUG"
const LEVEL_INFO  = "INFO"

type Config struct {
	Level string
	Formatter func(level string, message string, tags map[string]string) string
	Output func(formattedMessage string)
	Program string
	DateFormat string
	Tags map[string]string
}

type Log struct {
	config *Config
}
type LogFormattingFailed string
func (err LogFormattingFailed) String() string {
	return "LogFormattingFailed"
}

func (log Log) Info(message string, tags interface{}) {
	log.config.Output(log.config.Formatter(LEVEL_INFO, message, mergeTags(log.config.Tags, tags)))
}

func (log Log) Debug(message string, tags interface{}) {
	if log.config.Level == LEVEL_DEBUG {
		log.config.Output(log.config.Formatter(LEVEL_DEBUG, message, mergeTags(log.config.Tags, tags)))
	}
}

func (log Log) ChildLogger(function string, additionalTags map[string]string) *Log {
	childConfig := new(Config)
	childConfig.Level = log.config.Level
	childConfig.Formatter = log.config.Formatter
	childConfig.Output = log.config.Output
	childConfig.DateFormat = log.config.DateFormat
	childConfig.Program = log.config.Program
	childConfig.Tags = log.config.Tags
	childConfig.Tags["function"] = function
	for name, value := range additionalTags {
		childConfig.Tags[name] = value
	}
	return NewLogger(childConfig)

}

func NewLogger(config *Config) *Log {
	config.Tags["program"] = config.Program
	config.Tags["function"] = "main"
	logger := new(Log)
	logger.config = config
	return logger
}

func mergeTags(tags map[string]string, additionalTags interface{}) map[string]string {
	outputTags := map[string]string{}
	for name, value := range tags {
		outputTags[name] = value
	}

	reflectedContext := reflect.TypeOf(&additionalTags).Elem()
	reflectedValue := reflect.ValueOf(&additionalTags).Elem()
	if reflectedValue.Kind() == reflect.Map {
		for _, name := range reflectedValue.MapKeys() {
			outputTags[name] = reflectedValue.MapIndex(name).String()
		}
	} else if reflectedValue.Kind() == reflect.Struct {
		for i := 0; i < reflectedContext.NumField(); i++ {
			currentField := reflectedContext.Field(i)
			outputTags[currentField.Name] = reflectedValue.FieldByName(currentField.Name).String()
		}
	}

	return outputTags
}
<commit_msg>bugfixes<commit_after>package log

import (
	"reflect"
)

const TIME_FORMAT = "2006-01-02T15:04:05.000000"
const LEVEL_DEBUG = "DEBUG"
const LEVEL_INFO  = "INFO"

type Config struct {
	Level string
	Formatter func(level string, message string, tags map[string]string, dateFormat string) string
	Output func(formattedMessage string)
	Program string
	DateFormat string
	Tags map[string]string
}

type Log struct {
	config *Config
}
type LogFormattingFailed string
func (err LogFormattingFailed) String() string {
	return "LogFormattingFailed"
}

func (log Log) Info(message string, tags interface{}) {
	log.config.Output(log.config.Formatter(LEVEL_INFO, message, mergeTags(log.config.Tags, tags), log.config.DateFormat))
}

func (log Log) Debug(message string, tags interface{}) {
	if log.config.Level == LEVEL_DEBUG {
		log.config.Output(log.config.Formatter(LEVEL_DEBUG, message, mergeTags(log.config.Tags, tags), log.config.DateFormat))
	}
}

func (log Log) ChildLogger(function string, additionalTags map[string]string) *Log {
	childConfig := new(Config)
	childConfig.Level = log.config.Level
	childConfig.Formatter = log.config.Formatter
	childConfig.Output = log.config.Output
	childConfig.DateFormat = log.config.DateFormat
	childConfig.Program = log.config.Program
	childConfig.Tags = log.config.Tags
	childConfig.Tags["function"] = function
	for name, value := range additionalTags {
		childConfig.Tags[name] = value
	}
	return NewLogger(childConfig)

}

func NewLogger(config *Config) *Log {
	config.Tags["program"] = config.Program
	config.Tags["function"] = "main"
	logger := new(Log)
	logger.config = config
	return logger
}

func mergeTags(tags map[string]string, additionalTags interface{}) map[string]string {
	outputTags := map[string]string{}
	for name, value := range tags {
		outputTags[name] = value
	}

	reflectedContext := reflect.TypeOf(&additionalTags).Elem()
	reflectedValue := reflect.ValueOf(&additionalTags).Elem()
	if reflectedValue.Kind() == reflect.Map {
		for _, name := range reflectedValue.MapKeys() {
			outputTags[name.String()] = reflectedValue.MapIndex(name).String()
		}
	} else if reflectedValue.Kind() == reflect.Struct {
		for i := 0; i < reflectedContext.NumField(); i++ {
			currentField := reflectedContext.Field(i)
			outputTags[currentField.Name] = reflectedValue.FieldByName(currentField.Name).String()
		}
	}

	return outputTags
}
<|endoftext|>


<commit_before>package wechat

import "go.uber.org/zap"

var Logger *zap.Logger
var Sugar *zap.SugaredLogger

func InitLogger(config ...zap.Config) {
	var conf zap.Config
	if len(config) > 1 {
		conf = config[0]
	} else {
		conf := zap.NewDevelopmentConfig()
		conf.DisableStacktrace = true
	}
	var err error
	Logger, err = conf.Build()
	if err != nil {
		panic(err)
	}
	Sugar = Logger.Sugar()
}
<commit_msg>Update source files<commit_after>package wechat

import "go.uber.org/zap"

var Logger *zap.Logger
var Sugar *zap.SugaredLogger

func InitLogger(config ...zap.Config) {
	var conf zap.Config
	if len(config) > 1 {
		conf = config[0]
	} else {
		conf = zap.NewDevelopmentConfig()
		conf.DisableStacktrace = true
	}
	var err error
	Logger, err = conf.Build()
	if err != nil {
		panic(err)
	}
	Sugar = Logger.Sugar()
}
<|endoftext|>


<commit_before>package reign

import (
	"fmt"
	"log"
)

// A ClusterLogger is the logging interface used by the Cluster system.
//
// The clustering system uses Info for situations that are not problems.
// This includes:
//  * Address resolution progress of remote cluster nodes. (Common DNS
//    problems or misconfigurations can cause excessive times for
//    resolution. This should give enough visibility into the resolution
//    process to rapidly identify the problem.)
//
// The clustering system uses Warn for situations that are problematic
// and you need to know about them, but are generally "expected" and may
// resolve themselves without any direction action. (That is, in general,
// losing network connections is "bad", but also perfectly normal and
// expected.) The clustering system uses Warn for:
//  * Connections established and lost to the other nodes
//  * Attempts to update the cluster configuration that fail due to
//    invalid configuration
//
// The clustering system uses Error for situations that prevent connection
// to some target node, and will most likely not resolve themselves without
// active human intervention. The clustering system will user Error for:
//  * Handshake with foreign node failed due to:
//    * Remote said they had a different NodeID than I expected.
//    * Incompatible clustering version.
//    * Failed SSL handshake.
// The goal is that all Errors are things that should fire alarming
// systems, and all things that should fire alarming systems are Errors.
//
// You can wrap a standard *log.Logger with the provided WrapLogger.
type ClusterLogger interface {
	Error(string)
	Errorf(format string, args ...interface{})
	Warn(string)
	Warnf(format string, args ...interface{})
	Info(string)
	Infof(format string, args ...interface{})
	Trace(string)
	Tracef(format string, args ...interface{})
}

// WrapLogger takes as standard *log.Logger and returns a ClusterLogger
// that uses that logger.
func WrapLogger(l *log.Logger) ClusterLogger {
	return wrapLogger{l}
}

type wrapLogger struct {
	logger *log.Logger
}

func (sl wrapLogger) Error(s string) {
	sl.Errorf("%s", s)
}

func (sl wrapLogger) Errorf(format string, args ...interface{}) {
	sl.logger.Output(2, fmt.Sprintf("[ERROR] reign: "+format+"\n", args...))
}

func (sl wrapLogger) Warn(s string) {
	sl.Warnf("%s", s)
}

func (sl wrapLogger) Warnf(format string, args ...interface{}) {
	sl.logger.Output(2, fmt.Sprintf("[WARN] reign: "+format+"\n", args...))
}

func (sl wrapLogger) Info(s string) {
	sl.Infof("%s", s)
}

func (sl wrapLogger) Infof(format string, args ...interface{}) {
	sl.logger.Output(2, fmt.Sprintf("[INFO] reign: "+format+"\n", args...))
}

func (sl wrapLogger) Trace(s string) {
	sl.Tracef("%s", s)
}

func (sl wrapLogger) Tracef(format string, args ...interface{}) {
	sl.logger.Output(2, fmt.Sprintf("[TRACE] reign: "+format+"\n", args...))
}

// StdLogger is a ClusterLogger that will use the log.Output function
// from the standard logging package.
var StdLogger = stdLogger{}

type stdLogger struct{}

func (sl stdLogger) Error(s string) {
	sl.Errorf("%s", s)
}

func (sl stdLogger) Errorf(format string, args ...interface{}) {
	fmt.Printf("[ERROR] reign: "+format+"\n", args...)
}

func (sl stdLogger) Warn(s string) {
	sl.Warnf("%s", s)
}

func (sl stdLogger) Warnf(format string, args ...interface{}) {
	fmt.Printf("[WARN] reign: "+format+"\n", args...)
}

func (sl stdLogger) Info(s string) {
	sl.Infof("%s", s)
}

func (sl stdLogger) Infof(format string, args ...interface{}) {
	fmt.Printf("[INFO] reign: "+format+"\n", args...)
}

func (sl stdLogger) Trace(s string) {
	sl.Tracef("%s", s)
}

func (sl stdLogger) Tracef(format string, args ...interface{}) {
	fmt.Printf("[TRACE] reign: "+format+"\n", args...)
}

// NullLogger implements ClusterLogger, and throws all logging messages away.
var NullLogger = nullLogger{}

type nullLogger struct{}

func (nl nullLogger) Error(s string)                            {}
func (nl nullLogger) Errorf(format string, args ...interface{}) {}
func (nl nullLogger) Warn(s string)                             {}
func (nl nullLogger) Warnf(format string, args ...interface{})  {}
func (nl nullLogger) Info(s string)                             {}
func (nl nullLogger) Infof(format string, args ...interface{})  {}
func (nl nullLogger) Trace(s string)                            {}
func (nl nullLogger) Tracef(format string, args ...interface{}) {}

var (
	_ ClusterLogger = (*wrapLogger)(nil)
	_ ClusterLogger = (*stdLogger)(nil)
	_ ClusterLogger = (*nullLogger)(nil)
)
<commit_msg>Tweaked non-formatted log methods to use variadic input.<commit_after>package reign

import (
	"fmt"
	"log"
)

// A ClusterLogger is the logging interface used by the Cluster system.
//
// The clustering system uses Info for situations that are not problems.
// This includes:
//  * Address resolution progress of remote cluster nodes. (Common DNS
//    problems or misconfigurations can cause excessive times for
//    resolution. This should give enough visibility into the resolution
//    process to rapidly identify the problem.)
//
// The clustering system uses Warn for situations that are problematic
// and you need to know about them, but are generally "expected" and may
// resolve themselves without any direction action. (That is, in general,
// losing network connections is "bad", but also perfectly normal and
// expected.) The clustering system uses Warn for:
//  * Connections established and lost to the other nodes
//  * Attempts to update the cluster configuration that fail due to
//    invalid configuration
//
// The clustering system uses Error for situations that prevent connection
// to some target node, and will most likely not resolve themselves without
// active human intervention. The clustering system will user Error for:
//  * Handshake with foreign node failed due to:
//    * Remote said they had a different NodeID than I expected.
//    * Incompatible clustering version.
//    * Failed SSL handshake.
// The goal is that all Errors are things that should fire alarming
// systems, and all things that should fire alarming systems are Errors.
//
// You can wrap a standard *log.Logger with the provided WrapLogger.
type ClusterLogger interface {
	Error(...interface{})
	Errorf(format string, args ...interface{})
	Warn(...interface{})
	Warnf(format string, args ...interface{})
	Info(...interface{})
	Infof(format string, args ...interface{})
	Trace(...interface{})
	Tracef(format string, args ...interface{})
}

// WrapLogger takes as standard *log.Logger and returns a ClusterLogger
// that uses that logger.
func WrapLogger(l *log.Logger) ClusterLogger {
	return wrapLogger{l}
}

type wrapLogger struct {
	logger *log.Logger
}

func (sl wrapLogger) Error(args ...interface{}) {
	sl.logger.Output(2, "[ERROR] reign: "+fmt.Sprint(args...)+"\n")
}

func (sl wrapLogger) Errorf(format string, args ...interface{}) {
	sl.logger.Output(2, fmt.Sprintf("[ERROR] reign: "+format+"\n", args...))
}

func (sl wrapLogger) Warn(args ...interface{}) {
	sl.logger.Output(2, "[WARN] reign: "+fmt.Sprint(args...)+"\n")
}

func (sl wrapLogger) Warnf(format string, args ...interface{}) {
	sl.logger.Output(2, fmt.Sprintf("[WARN] reign: "+format+"\n", args...))
}

func (sl wrapLogger) Info(args ...interface{}) {
	sl.logger.Output(2, "[INFO] reign: "+fmt.Sprint(args...)+"\n")
}

func (sl wrapLogger) Infof(format string, args ...interface{}) {
	sl.logger.Output(2, fmt.Sprintf("[INFO] reign: "+format+"\n", args...))
}

func (sl wrapLogger) Trace(args ...interface{}) {
	sl.logger.Output(2, "[TRACE] reign: "+fmt.Sprint(args...)+"\n")
}

func (sl wrapLogger) Tracef(format string, args ...interface{}) {
	sl.logger.Output(2, fmt.Sprintf("[TRACE] reign: "+format+"\n", args...))
}

// StdLogger is a ClusterLogger that will use the log.Output function
// from the standard logging package.
var StdLogger = stdLogger{}

type stdLogger struct{}

func (sl stdLogger) Error(args ...interface{}) {
	fmt.Println("[ERROR] reign: " + fmt.Sprint(args...))
}

func (sl stdLogger) Errorf(format string, args ...interface{}) {
	fmt.Printf("[ERROR] reign: "+format+"\n", args...)
}

func (sl stdLogger) Warn(args ...interface{}) {
	fmt.Println("[WARN] reign: " + fmt.Sprint(args...))
}

func (sl stdLogger) Warnf(format string, args ...interface{}) {
	fmt.Printf("[WARN] reign: "+format+"\n", args...)
}

func (sl stdLogger) Info(args ...interface{}) {
	fmt.Println("[INFO] reign: " + fmt.Sprint(args...))
}

func (sl stdLogger) Infof(format string, args ...interface{}) {
	fmt.Printf("[INFO] reign: "+format+"\n", args...)
}

func (sl stdLogger) Trace(args ...interface{}) {
	fmt.Println("[TRACE] reign: " + fmt.Sprint(args...))
}

func (sl stdLogger) Tracef(format string, args ...interface{}) {
	fmt.Printf("[TRACE] reign: "+format+"\n", args...)
}

// NullLogger implements ClusterLogger, and throws all logging messages away.
var NullLogger = nullLogger{}

type nullLogger struct{}

func (nl nullLogger) Error(args ...interface{})                 {}
func (nl nullLogger) Errorf(format string, args ...interface{}) {}
func (nl nullLogger) Warn(args ...interface{})                  {}
func (nl nullLogger) Warnf(format string, args ...interface{})  {}
func (nl nullLogger) Info(args ...interface{})                  {}
func (nl nullLogger) Infof(format string, args ...interface{})  {}
func (nl nullLogger) Trace(args ...interface{})                 {}
func (nl nullLogger) Tracef(format string, args ...interface{}) {}

var (
	_ ClusterLogger = (*wrapLogger)(nil)
	_ ClusterLogger = (*stdLogger)(nil)
	_ ClusterLogger = (*nullLogger)(nil)
)
<|endoftext|>


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

package martian

import (
	"fmt"

	stdlog "log"
)

// Infof logs an info message with caller information.
func Infof(format string, args ...interface{}) {
	msg := format
	if len(args) > 0 {
		msg = fmt.Sprintf(format, args...)
	}

	//log.InfoDepth(1, msg)
	stdlog.Println(msg)
}

// Debugf logs a debug message with caller information.
func Debugf(format string, args ...interface{}) {
	msg := format
	if len(args) > 0 {
		msg = fmt.Sprintf(format, args...)
	}

	//if log.V(2) {
	//log.InfoDepth(1, msg)
	stdlog.Println(msg)
	//}
}

// Errorf logs an error message with caller information.
func Errorf(format string, args ...interface{}) {
	msg := format
	if len(args) > 0 {
		msg = fmt.Sprintf(format, args...)
	}

	//log.ErrorDepth(1, msg)
	stdlog.Println(msg)
}
<commit_msg>log.go: remove artifacts of glog and cleanup.<commit_after>// Copyright 2015 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package martian

import (
	"fmt"
	"log"
)

// Infof logs an info message with caller information.
func Infof(format string, args ...interface{}) {
	msg := fmt.Sprintf("INFO: %s", format)
	if len(args) > 0 {
		msg = fmt.Sprintf(format, args...)
	}

	log.Println(msg)
}

// Debugf logs a debug message with caller information.
func Debugf(format string, args ...interface{}) {
	msg := fmt.Sprintf("DEBUG: %s", format)
	if len(args) > 0 {
		msg = fmt.Sprintf(format, args...)
	}

	log.Println(msg)
}

// Errorf logs an error message with caller information.
func Errorf(format string, args ...interface{}) {
	msg := fmt.Sprintf("ERROR: %s", format)
	if len(args) > 0 {
		msg = fmt.Sprintf(format, args...)
	}

	log.Println(msg)
}
<|endoftext|>


<commit_before>package gontpd

import (
	"container/list"
	"net"
)

type lru struct {
	cache    map[string]*list.Element
	ll       *list.List
	maxEntry int
}

func newLRU(s int) *lru {
	return &lru{
		map[string]*list.Element{},
		list.New(),
		s}
}

type entry struct {
	key      net.IP
	lastUnix int64
}

func (u *lru) Add(ip net.IP, val int64) {

	if ee, ok := u.cache[string(ip)]; ok {
		u.ll.MoveToFront(ee)
		ee.Value.(*entry).lastUnix = val
		return
	}

	ele := u.ll.PushFront(&entry{ip, val})
	u.cache[string(ip)] = ele
	if u.maxEntry < u.ll.Len() {
		u.RemoveOldest()
	}
}

func (u *lru) RemoveOldest() {
	ele := u.ll.Back()
	ee := ele.Value.(*entry)
	delete(u.cache, string(ee.key))
	u.ll.Remove(ele)
}

func (u *lru) Get(ip net.IP) (val int64, ok bool) {

	var ele *list.Element
	if ele, ok = u.cache[string(ip)]; ok {
		val = ele.Value.(*entry).lastUnix
	}
	return
}
<commit_msg>fix alloc new obj<commit_after>package gontpd

import (
	"container/list"
	"net"
	"sync"
)

type lru struct {
	cache    map[string]*list.Element
	ll       *list.List
	maxEntry int
	pool     sync.Pool
}

func newLRU(s int) *lru {
	pool := sync.Pool{
		New: func() interface{} {
			return &entry{}
		}}
	return &lru{
		map[string]*list.Element{},
		list.New(),
		s, pool,
	}
}

type entry struct {
	key      net.IP
	lastUnix int64
}

func (u *lru) Add(ip net.IP, val int64) {

	if ee, ok := u.cache[string(ip)]; ok {
		u.ll.MoveToFront(ee)
		ee.Value.(*entry).lastUnix = val
		return
	}

	e := u.pool.Get().(*entry)
	e.key = ip
	e.lastUnix = val
	ele := u.ll.PushFront(e)
	u.cache[string(ip)] = ele
	if u.maxEntry < u.ll.Len() {
		u.RemoveOldest()
	}
}

func (u *lru) RemoveOldest() {
	ele := u.ll.Back()
	ee := ele.Value.(*entry)
	delete(u.cache, string(ee.key))
	u.ll.Remove(ele)
	u.pool.Put(ee)
}

func (u *lru) Get(ip net.IP) (val int64, ok bool) {

	var ele *list.Element
	if ele, ok = u.cache[string(ip)]; ok {
		val = ele.Value.(*entry).lastUnix
	}
	return
}
<|endoftext|>


<commit_before>package last

import (
	"container/list"
	"runtime/debug"
	"sync"
)

type Cache interface {
	// SetMinFreeMemory sets the minimum amount of free ram
	// before the cache starts evicting objects.
	SetMinFreeMemory(v uint64)

	// Put pushes the item to the front of the cache.
	Put(k string, v interface{})

	// Get get the item from the cache and pushes it to the front.
	Get(k string) (interface{}, bool)

	// Del removes the item from the cache
	Del(k string)

	// Len returns the number of items stored in the cache.
	Len() int

	// Evict evicts the last n items from the cache.
	Evict(n int)
}

type lru struct {
	mtx        sync.Mutex
	scheduled  int32
	minFreeMem uint64
	lookup     map[string]*list.Element
	list       *list.List
}

type lruItem struct {
	key   string
	value interface{}
}

func New() Cache {
	return &lru{
		minFreeMem: 1024 * 1024 * 10, // 10MB
		lookup:     make(map[string]*list.Element),
		list:       list.New(),
	}
}

func (c *lru) SetMinFreeMemory(v uint64) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	c.minFreeMem = v
}

func (c *lru) Put(k string, v interface{}) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	if v == nil {
		return
	}
	c.evictIfNecessary()
	c.lookup[k] = c.list.PushFront(&lruItem{
		key:   k,
		value: v,
	})
}

func (c *lru) Get(k string) (interface{}, bool) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	if e, ok := c.lookup[k]; ok {
		c.list.MoveToFront(e)
		return e.Value.(*lruItem).value, true
	}
	return nil, false
}

func (c *lru) Del(k string) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	if e, ok := c.lookup[k]; ok {
		c.list.Remove(e)
		delete(c.lookup, k)
	}
}

func (c *lru) Len() int {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	return c.list.Len()
}

func (c *lru) Evict(n int) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	c.evict(n)
}

func (c *lru) evictIfNecessary() {
	err := refreshMemStats()
	if err != nil {
		panic(err)
	}
	if memStats.Free < c.minFreeMem {
		c.evict(c.list.Len() / 4)
		debug.FreeOSMemory()
	}
}

func (c *lru) evict(n int) {
	for {
		if n < 1 {
			break
		}
		e := c.list.Back()
		delete(c.lookup, e.Value.(*lruItem).key)
		c.list.Remove(e)
		n--
	}
}
<commit_msg>Evict a constant number of items<commit_after>package last

import (
	"container/list"
	"runtime/debug"
	"sync"
)

type Cache interface {
	// SetMinFreeMemory sets the minimum amount of free ram
	// before the cache starts evicting objects.
	SetMinFreeMemory(v uint64)

	// Put pushes the item to the front of the cache.
	Put(k string, v interface{})

	// Get get the item from the cache and pushes it to the front.
	Get(k string) (interface{}, bool)

	// Del removes the item from the cache
	Del(k string)

	// Len returns the number of items stored in the cache.
	Len() int

	// Evict evicts the last n items from the cache.
	Evict(n int)
}

type lru struct {
	mtx        sync.Mutex
	scheduled  int32
	minFreeMem uint64
	lookup     map[string]*list.Element
	list       *list.List
}

type lruItem struct {
	key   string
	value interface{}
}

func New() Cache {
	return &lru{
		minFreeMem: 1024 * 1024 * 10, // 10MB
		lookup:     make(map[string]*list.Element),
		list:       list.New(),
	}
}

func (c *lru) SetMinFreeMemory(v uint64) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	c.minFreeMem = v
}

func (c *lru) Put(k string, v interface{}) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	if v == nil {
		return
	}
	c.evictIfNecessary()
	c.lookup[k] = c.list.PushFront(&lruItem{
		key:   k,
		value: v,
	})
}

func (c *lru) Get(k string) (interface{}, bool) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	if e, ok := c.lookup[k]; ok {
		c.list.MoveToFront(e)
		return e.Value.(*lruItem).value, true
	}
	return nil, false
}

func (c *lru) Del(k string) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	if e, ok := c.lookup[k]; ok {
		c.list.Remove(e)
		delete(c.lookup, k)
	}
}

func (c *lru) Len() int {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	return c.list.Len()
}

func (c *lru) Evict(n int) {
	c.mtx.Lock()
	defer c.mtx.Unlock()
	c.evict(n)
}

func (c *lru) evictIfNecessary() {
	err := refreshMemStats()
	if err != nil {
		panic(err)
	}
	if memStats.Free < c.minFreeMem {
		c.evict(1000)
		debug.FreeOSMemory()
	}
}

func (c *lru) evict(n int) {
	for {
		if n < 1 {
			break
		}
		e := c.list.Back()
		delete(c.lookup, e.Value.(*lruItem).key)
		c.list.Remove(e)
		n--
	}
}
<|endoftext|>


<commit_before>// +build windows

package runcmd

import (
	"os/exec"
	"syscall"
)

// To keep alive the child process you have to put it in a different process
// group.
// You do that by setting CREATE_NEW_PROCESS_GROUP to true.
func start(cmd *exec.Cmd) (int, error) {
	keepAliveChild := true
	if keepAliveChild {
		if cmd.SysProcAttr == nil {
			cmd.SysProcAttr = &syscall.SysProcAttr{
				CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP,
			}
		} else {
			cmd.SysProcAttr.CreationFlags = syscall.CREATE_NEW_PROCESS_GROUP
		}
	}
	err := cmd.Start()
	if err != nil {
		return 0, err
	}
	process := cmd.Process
	return process.Pid, nil
}
<commit_msg>windows process<commit_after>// +build windows

package runcmd

import (
	"os"
	"os/exec"
	"syscall"
)

// To keep alive the child process you have to put it in a different process
// group.
// You do that by setting CREATE_NEW_PROCESS_GROUP to true.
func start(cmd *exec.Cmd) (*os.Process, error) {
	keepAliveChild := true
	if keepAliveChild {
		if cmd.SysProcAttr == nil {
			cmd.SysProcAttr = &syscall.SysProcAttr{
				CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP,
			}
		} else {
			cmd.SysProcAttr.CreationFlags = syscall.CREATE_NEW_PROCESS_GROUP
		}
	}
	err := cmd.Start()
	if err != nil {
		return nil, err
	}
	process := cmd.Process
	return process, nil
}
<|endoftext|>


<commit_before>package simplifier

import "github.com/twtiger/gosecco/tree"

func reduceTransformers(inp tree.Expression, ss ...tree.Transformer) tree.Expression {
	result := inp

	for _, s := range ss {
		result = s.Transform(result)
	}

	return result
}

// Simplify will take an expression and reduce it as much as possible using state operations
func Simplify(inp tree.Expression) tree.Expression {
	return reduceTransformers(inp,
		// X in [P]  ==>  P == Q
		// X in [P, Q, R]  where X and R can be determined to not be equal  ==>  X in [P, Q]
		// X in [P, Q, R]  where X and one of the values can be determined to be equal  ==>  true
		// X notIn [P]  ==>  X != P
		// X notIn [P, Q, R]  where X and R can be determined to not be equal  ==>  X notIn [P, Q]
		// X notIn [P, Q, R]  where X and one of the values can be determined to be equal  ==>  false
		createInclusionSimplifier(),

		// X in [P, Q, R]     ==>  X == P || X == Q || X == R
		// X notIn [P, Q, R]  ==>  X != P && X != Q && X != R
		createInclusionRemoverSimplifier(),

		// X < Y    ==>  Y >= X
		// X <= Y   ==>  Y > X
		createLtExpressionsSimplifier(),

		// Where X and Y can be determined statically:
		// X + Y   ==>  [X+Y]
		// X - Y   ==>  [X-Y]
		// X * Y   ==>  [X*Y]
		// X / Y   ==>  [X/Y]
		// X % Y   ==>  [X%Y]
		// X & Y   ==>  [X&Y]
		// X | Y   ==>  [X|Y]
		// X ^ Y   ==>  [X^Y]
		// X << Y  ==>  [X<<Y]
		// X >> Y  ==>  [X<<Y]
		// ~X      ==>  [~X]
		// - this could lead to different result than if they were evaluated by the BPF engine.
		createArithmeticSimplifier(),

		// Where X and Y can be determined statically:
		// X == Y  where X == Y  ==>  true
		// X == Y  where X != Y  ==>  false
		// X != Y  where X == Y  ==>  false
		// X != Y  where X != Y  ==>  true
		// X > Y   where X > Y   ==>  true
		// X > Y   where X <= Y  ==>  false
		// X >= Y  where X >= Y  ==>  true
		// X >= Y  where X < Y   ==>  false
		// X < Y   where X < Y   ==>  true
		// X < Y   where X >= Y  ==>  false
		// X <= Y  where X <= Y  ==>  true
		// X <= Y  where X > Y   ==>  false
		createComparisonSimplifier(),

		// !true           ==>  false
		// !false          ==>  true
		// false || Y      ==>  Y
		// false || true   ==>  true
		// false || false  ==>  false
		// true  || Y      ==>  true
		// true  && true   ==>  true
		// true  && false  ==>  false
		// true  && Y      ==>  Y
		// false && [any]  ==>  false
		createBooleanSimplifier(),

		// ~X  ==> X ^ 0xFFFFFFFFFFFFFFFF
		createBinaryNegationSimplifier(),

		// Where X can be determined statically (the opposite order is also valid)
		// arg0 == X     ==>  argL0 == X.low && argH0 == X.high
		// arg0 != X     ==>  argL0 != X.low || argH0 != X.high
		// arg0 > X      ==>  argH0 > X.high || (argH0 == X.high && argL0 > X.low)
		// arg0 >= X     ==>  argH0 > X.high || (argH0 == X.high && argL0 >= X.low)
		// arg0 == arg1  ==>  argL0 == argL1 && argH0 == argH1
		// arg0 != arg1  ==>  argL0 != argL1 || argH0 != argH1
		// arg0 > arg1   ==>  argH0 > argH1  || (argH0 == argH1 && argL0 > argL1)
		// arg0 >= arg1  ==>  argH0 > argH1  || (argH0 == argH1 && argL0 >= argL1)
		createFullArgumentSplitterSimplifier(),

		// We repeat some of the simplifiers in the hope that the above operations have opened up new avenues of simplification
		createArithmeticSimplifier(),
		createComparisonSimplifier(),
		createBooleanSimplifier(),
		createBinaryNegationSimplifier(),
	)
}

func potentialExtractFullArgument(a tree.Expression) (int, bool) {
	v, ok := a.(tree.Argument)
	if ok && v.Type == tree.Full {
		return v.Index, ok
	}
	return 0, false
}

func potentialExtractValue(a tree.Numeric) (uint64, bool) {
	v, ok := a.(tree.NumericLiteral)
	if ok {
		return v.Value, ok
	}
	return 0, false
}

func potentialExtractValueParts(a tree.Numeric) (uint64, uint64, bool) {
	v, ok := a.(tree.NumericLiteral)
	if ok {
		low := v.Value & 0xFFFFFFFF
		high := (v.Value >> 32) & 0xFFFFFFFF
		return low, high, ok
	}
	return 0, 0, false
}

func potentialExtractBooleanValue(a tree.Boolean) (bool, bool) {
	v, ok := a.(tree.BooleanLiteral)
	if ok {
		return v.Value, ok
	}
	return false, false
}
<commit_msg>Readding comment about 64 bit simplification<commit_after>package simplifier

import "github.com/twtiger/gosecco/tree"

func reduceTransformers(inp tree.Expression, ss ...tree.Transformer) tree.Expression {
	result := inp

	for _, s := range ss {
		result = s.Transform(result)
	}

	return result
}

// Simplify will take an expression and reduce it as much as possible using state operations
func Simplify(inp tree.Expression) tree.Expression {
	return reduceTransformers(inp,
		// X in [P]  ==>  P == Q
		// X in [P, Q, R]  where X and R can be determined to not be equal  ==>  X in [P, Q]
		// X in [P, Q, R]  where X and one of the values can be determined to be equal  ==>  true
		// X notIn [P]  ==>  X != P
		// X notIn [P, Q, R]  where X and R can be determined to not be equal  ==>  X notIn [P, Q]
		// X notIn [P, Q, R]  where X and one of the values can be determined to be equal  ==>  false
		createInclusionSimplifier(),

		// X in [P, Q, R]     ==>  X == P || X == Q || X == R
		// X notIn [P, Q, R]  ==>  X != P && X != Q && X != R
		createInclusionRemoverSimplifier(),

		// X < Y    ==>  Y >= X
		// X <= Y   ==>  Y > X
		createLtExpressionsSimplifier(),

		// Where X and Y can be determined statically:
		// X + Y   ==>  [X+Y]
		// X - Y   ==>  [X-Y]
		// X * Y   ==>  [X*Y]
		// X / Y   ==>  [X/Y]
		// X % Y   ==>  [X%Y]
		// X & Y   ==>  [X&Y]
		// X | Y   ==>  [X|Y]
		// X ^ Y   ==>  [X^Y]
		// X << Y  ==>  [X<<Y]
		// X >> Y  ==>  [X<<Y]
		// ~X      ==>  [~X]
		// Note that these calculations will all be done on 64bit unsigned values
		// - this could lead to different result than if they were evaluated by the BPF engine.
		createArithmeticSimplifier(),

		// Where X and Y can be determined statically:
		// X == Y  where X == Y  ==>  true
		// X == Y  where X != Y  ==>  false
		// X != Y  where X == Y  ==>  false
		// X != Y  where X != Y  ==>  true
		// X > Y   where X > Y   ==>  true
		// X > Y   where X <= Y  ==>  false
		// X >= Y  where X >= Y  ==>  true
		// X >= Y  where X < Y   ==>  false
		// X < Y   where X < Y   ==>  true
		// X < Y   where X >= Y  ==>  false
		// X <= Y  where X <= Y  ==>  true
		// X <= Y  where X > Y   ==>  false
		createComparisonSimplifier(),

		// !true           ==>  false
		// !false          ==>  true
		// false || Y      ==>  Y
		// false || true   ==>  true
		// false || false  ==>  false
		// true  || Y      ==>  true
		// true  && true   ==>  true
		// true  && false  ==>  false
		// true  && Y      ==>  Y
		// false && [any]  ==>  false
		createBooleanSimplifier(),

		// ~X  ==> X ^ 0xFFFFFFFFFFFFFFFF
		createBinaryNegationSimplifier(),

		// Where X can be determined statically (the opposite order is also valid)
		// arg0 == X     ==>  argL0 == X.low && argH0 == X.high
		// arg0 != X     ==>  argL0 != X.low || argH0 != X.high
		// arg0 > X      ==>  argH0 > X.high || (argH0 == X.high && argL0 > X.low)
		// arg0 >= X     ==>  argH0 > X.high || (argH0 == X.high && argL0 >= X.low)
		// arg0 == arg1  ==>  argL0 == argL1 && argH0 == argH1
		// arg0 != arg1  ==>  argL0 != argL1 || argH0 != argH1
		// arg0 > arg1   ==>  argH0 > argH1  || (argH0 == argH1 && argL0 > argL1)
		// arg0 >= arg1  ==>  argH0 > argH1  || (argH0 == argH1 && argL0 >= argL1)
		createFullArgumentSplitterSimplifier(),

		// We repeat some of the simplifiers in the hope that the above operations have opened up new avenues of simplification
		createArithmeticSimplifier(),
		createComparisonSimplifier(),
		createBooleanSimplifier(),
		createBinaryNegationSimplifier(),
	)
}

func potentialExtractFullArgument(a tree.Expression) (int, bool) {
	v, ok := a.(tree.Argument)
	if ok && v.Type == tree.Full {
		return v.Index, ok
	}
	return 0, false
}

func potentialExtractValue(a tree.Numeric) (uint64, bool) {
	v, ok := a.(tree.NumericLiteral)
	if ok {
		return v.Value, ok
	}
	return 0, false
}

func potentialExtractValueParts(a tree.Numeric) (uint64, uint64, bool) {
	v, ok := a.(tree.NumericLiteral)
	if ok {
		low := v.Value & 0xFFFFFFFF
		high := (v.Value >> 32) & 0xFFFFFFFF
		return low, high, ok
	}
	return 0, 0, false
}

func potentialExtractBooleanValue(a tree.Boolean) (bool, bool) {
	v, ok := a.(tree.BooleanLiteral)
	if ok {
		return v.Value, ok
	}
	return false, false
}
<|endoftext|>


<commit_before>package poller

import (
	"encoding/json"
	"github.com/zetafunction/steam-monster-game/messages"
	"github.com/zetafunction/steam-monster-game/steam"
	"log"
	"sort"
	"time"
)

type finderFunc func(*steam.GameDataResult) bool

func invalidGameFinder(r *steam.GameDataResult) bool {
	return r.Response.GetGameData().GetStatus() == messages.EMiniGameStatus_k_EMiniGameStatus_Invalid
}

func findGame(service *steam.APIService, start int, finder finderFunc) (int, error) {
	log.Print("new game scanner: searching for games starting at ", start)
	end := start
	errors := 0
	// Exponentially probe upwards to start.
	for i, inc := start, 1; ; i, inc = i+inc, inc*2 {
		log.Print("new game scanner: probing game ", i)
		result := <-service.GetGameData(i)
		if result.Err != nil {
			log.Print("GetGameData failed: ", result.Err)
			if errors > 8 {
				log.Print("new game scanner: too many errors while finding next invalid game, giving up!")
				return 0, result.Err
			}
			errors++
			continue
		}
		if finder(result) {
			end = i
			break
		}
		start = i
	}
	log.Print("new game scanner: binary searching between ", start, " and ", end)
	// Strictly speaking, a binary search is a bit dangerous because things might change.
	// Hopefully it returns close enough to the right result.
	offset := sort.Search(end-start, func(i int) bool {
		// TODO: Should this do the same error limiting that the previous loop does?
		result := <-service.GetGameData(start + i)
		if result.Err != nil {
			return false
		}
		return finder(result)
	})
	return start + offset, nil
}

type NewGameScanner struct {
	service *steam.APIService
	// The first invalid game ID. This may occasionally point to a valid game, since
	// the scanner scans 5 games ahead at a time.
	invalid int
	// If there are a lot of games in the waiting state, the new game scanner
	// sometimes has to temporarily increase the number of games to poll. The flex count
	// indicates the number of extra games that need to be polled at a given point.
	flex int

	DataUpdate        chan []byte
	InvalidGameUpdate chan int
}

func (s *NewGameScanner) Start() {
	go func() {
		for {
			if json, err := s.updateData(); err == nil {
				s.DataUpdate <- json
			} else {
				log.Print("updateData failed: ", err)
			}
			time.Sleep(time.Second)
		}
	}()
}

func (s *NewGameScanner) updateData() ([]byte, error) {
	log.Printf("new game scanner: updating (invalid: %d, flex: %d)\n", s.invalid, s.flex)
	start := s.invalid - 25 - s.flex
	end := s.invalid + 5

	type update struct {
		id     int
		result *steam.GameDataResult
	}
	c := make(chan update)
	requests := 0
	failed := 0
	for i := start; i < end; i++ {
		go func(i int) {
			result := <-s.service.GetGameData(i)
			if result.Err != nil {
				failed++
			}
			c <- update{i, result}
		}(i)
		requests++
	}
	m := make(map[int]*steam.GameDataResult)
	for requests > 0 {
		update := <-c
		m[update.id] = update.result
		requests--
	}

	type statusEntry struct {
		ID      int
		Status  string
		Players uint32
	}
	var results []statusEntry
	firstWaiting := end
	firstInvalid := end
	errors := 0
	for i := start; i < end; i++ {
		// Sometimes, the server likes to give out 500 errors, just because...
		if m[i].Err != nil {
			results = append(results, statusEntry{i, "???????", 0})
			errors++
			continue
		}
		var status string
		switch m[i].Response.GetGameData().GetStatus() {
		case messages.EMiniGameStatus_k_EMiniGameStatus_Invalid:
			if i < firstInvalid {
				firstInvalid = i
			}
			status = "invalid"
		case messages.EMiniGameStatus_k_EMiniGameStatus_Running:
			status = "running"
		case messages.EMiniGameStatus_k_EMiniGameStatus_WaitingForPlayers:
			if i < firstWaiting {
				firstWaiting = i
			}
			status = "waiting"
		case messages.EMiniGameStatus_k_EMiniGameStatus_Ended:
			status = "ended"
		}
		results = append(results, statusEntry{
			i,
			status,
			m[i].Response.GetStats().GetNumPlayers(),
		})
	}

	// Always try to have at least one actively updated non-waiting entry.
	reclaimableFlex := firstWaiting - (start + 1)
	if reclaimableFlex > 0 && s.flex > 0 {
		s.flex -= reclaimableFlex
		if s.flex < 0 {
			s.flex = 0
		}
	}

	// The index of the first invalid game changed: try to find the next one.
	if s.invalid != firstInvalid {
		// Only update the index of the first invalid game if the Steam API is mostly working.
		if errors < 8 {
			log.Print("new game scanner: finding next invalid game...")
			nextInvalid, err := findGame(s.service, firstInvalid, invalidGameFinder)
			if err != nil {
				log.Print("findGamefailed: ", err)
			} else {
				log.Print("new game scanner: next invalid game at ", nextInvalid)
				firstInvalid = nextInvalid
			}
			s.flex += firstInvalid - s.invalid
			s.invalid = firstInvalid
		} else {
			log.Print("new game scanner: skipping invalid game search due to Steam errors")
		}
	}

	return json.Marshal(results)
}

func NewNewGameScanner(service *steam.APIService) (*NewGameScanner, error) {
	// TODO: This should probably be a receiver method of NewGameScanner.
	invalid, err := findGame(service, 1, invalidGameFinder)
	if err != nil {
		log.Print("findGamefailed: ", err)
		return nil, err
	}
	log.Print("First invalid game around ", invalid)
	p := &NewGameScanner{service, invalid, 25, make(chan []byte), make(chan int)}
	return p, nil
}
<commit_msg>Remove unused channel from NewGameScanner.<commit_after>package poller

import (
	"encoding/json"
	"github.com/zetafunction/steam-monster-game/messages"
	"github.com/zetafunction/steam-monster-game/steam"
	"log"
	"sort"
	"time"
)

type finderFunc func(*steam.GameDataResult) bool

func invalidGameFinder(r *steam.GameDataResult) bool {
	return r.Response.GetGameData().GetStatus() == messages.EMiniGameStatus_k_EMiniGameStatus_Invalid
}

func findGame(service *steam.APIService, start int, finder finderFunc) (int, error) {
	log.Print("new game scanner: searching for games starting at ", start)
	end := start
	errors := 0
	// Exponentially probe upwards to start.
	for i, inc := start, 1; ; i, inc = i+inc, inc*2 {
		log.Print("new game scanner: probing game ", i)
		result := <-service.GetGameData(i)
		if result.Err != nil {
			log.Print("GetGameData failed: ", result.Err)
			if errors > 8 {
				log.Print("new game scanner: too many errors while finding next invalid game, giving up!")
				return 0, result.Err
			}
			errors++
			continue
		}
		if finder(result) {
			end = i
			break
		}
		start = i
	}
	log.Print("new game scanner: binary searching between ", start, " and ", end)
	// Strictly speaking, a binary search is a bit dangerous because things might change.
	// Hopefully it returns close enough to the right result.
	offset := sort.Search(end-start, func(i int) bool {
		// TODO: Should this do the same error limiting that the previous loop does?
		result := <-service.GetGameData(start + i)
		if result.Err != nil {
			return false
		}
		return finder(result)
	})
	return start + offset, nil
}

type NewGameScanner struct {
	service *steam.APIService
	// The first invalid game ID. This may occasionally point to a valid game, since
	// the scanner scans 5 games ahead at a time.
	invalid int
	// If there are a lot of games in the waiting state, the new game scanner
	// sometimes has to temporarily increase the number of games to poll. The flex count
	// indicates the number of extra games that need to be polled at a given point.
	flex int

	DataUpdate        chan []byte
}

func (s *NewGameScanner) Start() {
	go func() {
		for {
			if json, err := s.updateData(); err == nil {
				s.DataUpdate <- json
			} else {
				log.Print("updateData failed: ", err)
			}
			time.Sleep(time.Second)
		}
	}()
}

func (s *NewGameScanner) updateData() ([]byte, error) {
	log.Printf("new game scanner: updating (invalid: %d, flex: %d)\n", s.invalid, s.flex)
	start := s.invalid - 25 - s.flex
	end := s.invalid + 5

	type update struct {
		id     int
		result *steam.GameDataResult
	}
	c := make(chan update)
	requests := 0
	failed := 0
	for i := start; i < end; i++ {
		go func(i int) {
			result := <-s.service.GetGameData(i)
			if result.Err != nil {
				failed++
			}
			c <- update{i, result}
		}(i)
		requests++
	}
	m := make(map[int]*steam.GameDataResult)
	for requests > 0 {
		update := <-c
		m[update.id] = update.result
		requests--
	}

	type statusEntry struct {
		ID      int
		Status  string
		Players uint32
	}
	var results []statusEntry
	firstWaiting := end
	firstInvalid := end
	errors := 0
	for i := start; i < end; i++ {
		// Sometimes, the server likes to give out 500 errors, just because...
		if m[i].Err != nil {
			results = append(results, statusEntry{i, "???????", 0})
			errors++
			continue
		}
		var status string
		switch m[i].Response.GetGameData().GetStatus() {
		case messages.EMiniGameStatus_k_EMiniGameStatus_Invalid:
			if i < firstInvalid {
				firstInvalid = i
			}
			status = "invalid"
		case messages.EMiniGameStatus_k_EMiniGameStatus_Running:
			status = "running"
		case messages.EMiniGameStatus_k_EMiniGameStatus_WaitingForPlayers:
			if i < firstWaiting {
				firstWaiting = i
			}
			status = "waiting"
		case messages.EMiniGameStatus_k_EMiniGameStatus_Ended:
			status = "ended"
		}
		results = append(results, statusEntry{
			i,
			status,
			m[i].Response.GetStats().GetNumPlayers(),
		})
	}

	// Always try to have at least one actively updated non-waiting entry.
	reclaimableFlex := firstWaiting - (start + 1)
	if reclaimableFlex > 0 && s.flex > 0 {
		s.flex -= reclaimableFlex
		if s.flex < 0 {
			s.flex = 0
		}
	}

	// The index of the first invalid game changed: try to find the next one.
	if s.invalid != firstInvalid {
		// Only update the index of the first invalid game if the Steam API is mostly working.
		if errors < 8 {
			log.Print("new game scanner: finding next invalid game...")
			nextInvalid, err := findGame(s.service, firstInvalid, invalidGameFinder)
			if err != nil {
				log.Print("findGamefailed: ", err)
			} else {
				log.Print("new game scanner: next invalid game at ", nextInvalid)
				firstInvalid = nextInvalid
			}
			s.flex += firstInvalid - s.invalid
			s.invalid = firstInvalid
		} else {
			log.Print("new game scanner: skipping invalid game search due to Steam errors")
		}
	}

	return json.Marshal(results)
}

func NewNewGameScanner(service *steam.APIService) (*NewGameScanner, error) {
	// TODO: This should probably be a receiver method of NewGameScanner.
	invalid, err := findGame(service, 1, invalidGameFinder)
	if err != nil {
		log.Print("findGamefailed: ", err)
		return nil, err
	}
	log.Print("First invalid game around ", invalid)
	p := &NewGameScanner{service, invalid, 25, make(chan []byte), make(chan int)}
	return p, nil
}
<|endoftext|>