<commit_before>package models

import (
	"errors"
	"fmt"
	"reflect"
	"strings"
	"time"

	"github.com/astaxie/beego/orm"
)

type Set struct {
	SetID            int       `orm:"column(id);auto"`
	ApplicationID int      `orm:"column(application_id)"`
	Capacity      int       `orm:"column(capacity)"`
	ChnName       string    `orm:"column(chn_name);size(255);null"`
	CreateTime    time.Time `orm:"column(create_time);type(timestamp);null"`
	Default       int      `orm:"column(default);null"`
	Description   string    `orm:"column(description);size(255);null"`
	EnviType      int      `orm:"column(envi_type)"`
	LastTime      time.Time `orm:"column(last_time);type(timestamp);null"`
	OpenStatus    string      `orm:"column(open_status);size(255)"`
	ParentID      int       `orm:"column(parent_id);null"`
	ServiceStatus int      `orm:"column(service_status)"`
	SetName       string    `orm:"column(set_name);size(255)"`
	Owner         int      `orm:"column(owner)"`
}

func (t *Set) TableName() string {
	return "set"
}

func init() {
	orm.RegisterModel(new(Set))
}

// AddSet insert a new Set into database and returns
// last inserted Id on success.
func AddSet(m *Set) (id int64, err error) {
	o := orm.NewOrm()
	id, err = o.Insert(m)
	return
}

// GetSetById retrieves Set by Id. Returns error if
// Id doesn't exist
func GetSetById(id int) (v *Set, err error) {
	o := orm.NewOrm()
	v = &Set{SetID: id}
	if err = o.Read(v); err == nil {
		return v, nil
	}
	return nil, err
}

// GetAllSet retrieves all Set matches certain condition. Returns empty list if
// no records exist
func GetAllSet(query map[string]string, fields []string, sortby []string, order []string,
	offset int64, limit int64) (ml []interface{}, err error) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(Set))
	// query k=v
	for k, v := range query {
		// rewrite dot-notation to Object__Attribute
		k = strings.Replace(k, ".", "__", -1)
		qs = qs.Filter(k, v)
	}
	// order by:
	var sortFields []string
	if len(sortby) != 0 {
		if len(sortby) == len(order) {
			// 1) for each sort field, there is an associated order
			for i, v := range sortby {
				orderby := ""
				if order[i] == "desc" {
					orderby = "-" + v
				} else if order[i] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
			qs = qs.OrderBy(sortFields...)
		} else if len(sortby) != len(order) && len(order) == 1 {
			// 2) there is exactly one order, all the sorted fields will be sorted by this order
			for _, v := range sortby {
				orderby := ""
				if order[0] == "desc" {
					orderby = "-" + v
				} else if order[0] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
		} else if len(sortby) != len(order) && len(order) != 1 {
			return nil, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1")
		}
	} else {
		if len(order) != 0 {
			return nil, errors.New("Error: unused 'order' fields")
		}
	}

	var l []Set
	qs = qs.OrderBy(sortFields...)
	if _, err := qs.Limit(limit, offset).All(&l, fields...); err == nil {
		if len(fields) == 0 {
			for _, v := range l {
				ml = append(ml, v)
			}
		} else {
			// trim unused fields
			for _, v := range l {
				m := make(map[string]interface{})
				val := reflect.ValueOf(v)
				for _, fname := range fields {
					m[fname] = val.FieldByName(fname).Interface()
				}
				ml = append(ml, m)
			}
		}
		return ml, nil
	}
	return nil, err
}

// UpdateSet updates Set by Id and returns error if
// the record to be updated doesn't exist
func UpdateSetById(m *Set) (err error) {
	o := orm.NewOrm()
	v := Set{SetID: m.SetID}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Update(m); err == nil {
			fmt.Println("Number of records updated in database:", num)
		}
	}
	return
}

// DeleteSet deletes Set by Id and returns error if
// the record to be deleted doesn't exist
func DeleteSet(id int) (err error) {
	o := orm.NewOrm()
	v := Set{SetID: id}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Delete(&Set{SetID: id}); err == nil {
			fmt.Println("Number of records deleted in database:", num)
		}
	}
	return
}
<commit_msg>增加业务删除、查询方法<commit_after>package models

import (
	"errors"
	"fmt"
	"reflect"
	"strings"
	"time"

	"github.com/astaxie/beego/orm"
)

type Set struct {
	SetID         int       `orm:"column(id);auto"`
	ApplicationID int       `orm:"column(application_id)"`
	Capacity      int       `orm:"column(capacity)"`
	ChnName       string    `orm:"column(chn_name);size(255);null"`
	CreateTime    time.Time `orm:"column(create_time);type(timestamp);null"`
	Default       bool      `orm:"column(default);null"`
	Description   string    `orm:"column(description);size(255);null"`
	EnviType      int       `orm:"column(envi_type)"`
	LastTime      time.Time `orm:"column(last_time);type(timestamp);null"`
	OpenStatus    string    `orm:"column(open_status);size(255)"`
	ParentID      int       `orm:"column(parent_id);null"`
	ServiceStatus int       `orm:"column(service_status)"`
	SetName       string    `orm:"column(set_name);size(255)"`
	Owner         int       `orm:"column(owner)"`
}

func (t *Set) TableName() string {
	return "set"
}

func init() {
	orm.RegisterModel(new(Set))
}

// AddSet insert a new Set into database and returns
// last inserted Id on success.
func AddSet(m *Set) (id int64, err error) {
	o := orm.NewOrm()
	id, err = o.Insert(m)
	return
}

// GetSetById retrieves Set by Id. Returns error if
// Id doesn't exist
func GetSetById(id int) (v *Set, err error) {
	o := orm.NewOrm()
	v = &Set{SetID: id}
	if err = o.Read(v); err == nil {
		return v, nil
	}
	return nil, err
}

// GetAllSet retrieves all Set matches certain condition. Returns empty list if
// no records exist
func GetAllSet(query map[string]string, fields []string, sortby []string, order []string,
	offset int64, limit int64) (ml []interface{}, err error) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(Set))
	// query k=v
	for k, v := range query {
		// rewrite dot-notation to Object__Attribute
		k = strings.Replace(k, ".", "__", -1)
		qs = qs.Filter(k, v)
	}
	// order by:
	var sortFields []string
	if len(sortby) != 0 {
		if len(sortby) == len(order) {
			// 1) for each sort field, there is an associated order
			for i, v := range sortby {
				orderby := ""
				if order[i] == "desc" {
					orderby = "-" + v
				} else if order[i] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
			qs = qs.OrderBy(sortFields...)
		} else if len(sortby) != len(order) && len(order) == 1 {
			// 2) there is exactly one order, all the sorted fields will be sorted by this order
			for _, v := range sortby {
				orderby := ""
				if order[0] == "desc" {
					orderby = "-" + v
				} else if order[0] == "asc" {
					orderby = v
				} else {
					return nil, errors.New("Error: Invalid order. Must be either [asc|desc]")
				}
				sortFields = append(sortFields, orderby)
			}
		} else if len(sortby) != len(order) && len(order) != 1 {
			return nil, errors.New("Error: 'sortby', 'order' sizes mismatch or 'order' size is not 1")
		}
	} else {
		if len(order) != 0 {
			return nil, errors.New("Error: unused 'order' fields")
		}
	}

	var l []Set
	qs = qs.OrderBy(sortFields...)
	if _, err := qs.Limit(limit, offset).All(&l, fields...); err == nil {
		if len(fields) == 0 {
			for _, v := range l {
				ml = append(ml, v)
			}
		} else {
			// trim unused fields
			for _, v := range l {
				m := make(map[string]interface{})
				val := reflect.ValueOf(v)
				for _, fname := range fields {
					m[fname] = val.FieldByName(fname).Interface()
				}
				ml = append(ml, m)
			}
		}
		return ml, nil
	}
	return nil, err
}

// UpdateSet updates Set by Id and returns error if
// the record to be updated doesn't exist
func UpdateSetById(m *Set) (err error) {
	o := orm.NewOrm()
	v := Set{SetID: m.SetID}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Update(m); err == nil {
			fmt.Println("Number of records updated in database:", num)
		}
	}
	return
}

// DeleteSet deletes Set by Id and returns error if
// the record to be deleted doesn't exist
func DeleteSet(id int) (err error) {
	o := orm.NewOrm()
	v := Set{SetID: id}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		var num int64
		if num, err = o.Delete(&Set{SetID: id}); err == nil {
			fmt.Println("Number of records deleted in database:", num)
		}
	}
	return
}

// 根据业务ID删除集群
func DeleteSetByAppId(id int) (num int64, err error) {
	o := orm.NewOrm()
	num, err = o.QueryTable("set").Filter("ApplicationID", id).Delete()
	return
}

// 根据业务ID查询默认setId
func GetDesetidByAppId(id int) (s Set) {
	o := orm.NewOrm()
	err := o.QueryTable("set").Filter("SetName", "空闲机池").Filter("ApplicationID", id).One(&s)
	if err != nil {
		return
	}
	return
}
<|endoftext|>


<commit_before>// Copyright 2015 Unknwon
//
// 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 models

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"
	"sync"

	"github.com/Unknwon/com"
	"github.com/Unknwon/log"
	"github.com/mschoch/blackfriday-text"
	"github.com/russross/blackfriday"
	"gopkg.in/ini.v1"

	"github.com/peachdocs/peach/modules/setting"
)

type Node struct {
	Name    string // Name in TOC
	Title   string // Name in given language
	content []byte
	Text    string // Clean text without formatting

	Plain    bool   // Root node without content
	FileName string // Full path with .md extension
	Nodes    []*Node
}

var textRender = blackfridaytext.TextRenderer()

func parseNodeName(name string, data []byte) (string, []byte) {
	data = bytes.TrimSpace(data)
	if len(data) < 3 || string(data[:3]) != "---" {
		return name, []byte("")
	}
	endIdx := bytes.Index(data[3:], []byte("---")) + 3
	if endIdx == -1 {
		return name, []byte("")
	}

	opts := strings.Split(strings.TrimSpace(string(string(data[3:endIdx]))), "\n")

	title := name
	for _, opt := range opts {
		infos := strings.SplitN(opt, ":", 2)
		if len(infos) != 2 {
			continue
		}

		switch strings.TrimSpace(infos[0]) {
		case "name":
			title = strings.TrimSpace(infos[1])
		}
	}

	return title, data[endIdx+3:]
}

func (n *Node) ReloadContent() error {
	data, err := ioutil.ReadFile(n.FileName)
	if err != nil {
		return err
	}

	n.Title, data = parseNodeName(n.Name, data)
	n.Plain = len(bytes.TrimSpace(data)) == 0

	if !n.Plain {
		n.content = markdown(data)
		n.Text = string(bytes.ToLower(blackfriday.Markdown(data, textRender, 0)))
	}

	htmlRoot := "data/html"
	return n.GenLocalHTML(htmlRoot)
}

// Generate local HTML
func (n *Node) GenLocalHTML(htmlRoot string) error {

	r := strings.NewReplacer("data/docs", htmlRoot, ".md", ".html")
	htmlFile := r.Replace(n.FileName)

	return com.WriteFile(htmlFile, n.content)
}

func (n *Node) Content() []byte {
	if !setting.ProdMode {
		if err := n.ReloadContent(); err != nil {
			log.Error("Fail to reload content: %v", err)
		}
	}

	return n.content
}

// Toc represents table of content in a specific language.
type Toc struct {
	RootPath string
	Lang     string
	Nodes    []*Node
	Pages    []*Node
}

// GetDoc should only be called by top level toc.
func (t *Toc) GetDoc(name string) (string, []byte, bool) {
	name = strings.TrimPrefix(name, "/")

	// Returns first node whatever avaiable as default.
	if len(name) == 0 {
		if len(t.Nodes) == 0 ||
			t.Nodes[0].Plain {
			return "", nil, false
		}
		return t.Nodes[0].Title, t.Nodes[0].Content(), false
	}

	infos := strings.Split(name, "/")

	// Dir node.
	if len(infos) == 1 {
		for i := range t.Nodes {
			if t.Nodes[i].Name == infos[0] {
				return t.Nodes[i].Title, t.Nodes[i].Content(), false
			}
		}
		return "", nil, false
	}

	// File node.
	for i := range t.Nodes {
		if t.Nodes[i].Name == infos[0] {
			for j := range t.Nodes[i].Nodes {
				if t.Nodes[i].Nodes[j].Name == infos[1] {
					if com.IsFile(t.Nodes[i].Nodes[j].FileName) {
						return t.Nodes[i].Nodes[j].Title, t.Nodes[i].Nodes[j].Content(), false
					}

					// If not default language, try again.
					title, content, _ := Tocs[setting.Docs.Langs[0]].GetDoc(name)
					return title, content, true
				}
			}
		}
	}

	return "", nil, false
}

type SearchResult struct {
	Title string
	Path  string
	Match string
}

func adjustRange(start, end, length int) (int, int) {
	start -= 20
	if start < 0 {
		start = 0
	}
	end += 230
	if end > length {
		end = length
	}
	return start, end
}

func (t *Toc) Search(q string) []*SearchResult {
	if len(q) == 0 {
		return nil
	}
	q = strings.ToLower(q)

	results := make([]*SearchResult, 0, 5)

	// Dir node.
	for i := range t.Nodes {
		if idx := strings.Index(t.Nodes[i].Text, q); idx > -1 {
			start, end := adjustRange(idx, idx+len(q), len(t.Nodes[i].Text))
			results = append(results, &SearchResult{
				Title: t.Nodes[i].Title,
				Path:  t.Nodes[i].Name,
				Match: t.Nodes[i].Text[start:end],
			})
		}
	}

	// File node.
	for i := range t.Nodes {
		for j := range t.Nodes[i].Nodes {
			if idx := strings.Index(t.Nodes[i].Nodes[j].Text, q); idx > -1 {
				start, end := adjustRange(idx, idx+len(q), len(t.Nodes[i].Nodes[j].Text))
				results = append(results, &SearchResult{
					Title: t.Nodes[i].Nodes[j].Title,
					Path:  path.Join(t.Nodes[i].Name, t.Nodes[i].Nodes[j].Name),
					Match: t.Nodes[i].Nodes[j].Text[start:end],
				})
			}
		}
	}

	return results
}

var (
	tocLocker = sync.RWMutex{}
	Tocs      map[string]*Toc
)

func initToc(localRoot string) (map[string]*Toc, error) {
	tocPath := path.Join(localRoot, "TOC.ini")
	if !com.IsFile(tocPath) {
		return nil, fmt.Errorf("TOC not found: %s", tocPath)
	}

	// Generate Toc.
	tocCfg, err := ini.Load(tocPath)
	if err != nil {
		return nil, fmt.Errorf("Fail to load TOC.ini: %v", err)
	}

	tocs := make(map[string]*Toc)
	for _, lang := range setting.Docs.Langs {
		toc := &Toc{
			RootPath: localRoot,
			Lang:     lang,
		}
		dirs := tocCfg.Section("").KeyStrings()
		toc.Nodes = make([]*Node, 0, len(dirs))
		for _, dir := range dirs {
			dirName := tocCfg.Section("").Key(dir).String()
			fmt.Println(dirName + "/")
			files := tocCfg.Section(dirName).KeyStrings()

			// Skip empty directory.
			if len(files) == 0 {
				continue
			}

			dirNode := &Node{
				Name:     dirName,
				FileName: path.Join(localRoot, lang, dirName, tocCfg.Section(dirName).Key(files[0]).String()) + ".md",
				Nodes:    make([]*Node, 0, len(files)-1),
			}
			toc.Nodes = append(toc.Nodes, dirNode)

			for _, file := range files[1:] {
				fileName := tocCfg.Section(dirName).Key(file).String()
				fmt.Println(strings.Repeat(" ", len(dirName))+"|__", fileName)

				node := &Node{
					Name:     fileName,
					FileName: path.Join(localRoot, lang, dirName, fileName) + ".md",
				}
				dirNode.Nodes = append(dirNode.Nodes, node)
			}
		}

		// Single pages.
		pages := tocCfg.Section("pages").KeyStrings()
		toc.Pages = make([]*Node, 0, len(pages))
		for _, page := range pages {
			pageName := tocCfg.Section("pages").Key(page).String()
			fmt.Println(pageName)

			toc.Pages = append(toc.Pages, &Node{
				Name:     pageName,
				FileName: path.Join(localRoot, lang, pageName) + ".md",
			})
		}

		tocs[lang] = toc
	}
	return tocs, nil
}

func ReloadDocs() error {
	tocLocker.Lock()
	defer tocLocker.Unlock()

	localRoot := setting.Docs.Target

	// Del htmlRoot path
	htmlRoot := "data/html"
	if com.IsExist(htmlRoot) {
		err := os.RemoveAll(htmlRoot)
		if err != nil {
			return fmt.Errorf("htmlRoot not found:: %v", err)
		}
	}

	// Fetch docs from remote.
	if setting.Docs.Type == "remote" {
		localRoot = "data/docs"

		absRoot, err := filepath.Abs(localRoot)
		if err != nil {
			return fmt.Errorf("filepath.Abs: %v", err)
		}

		// Clone new or pull to update.
		if com.IsDir(absRoot) {
			stdout, stderr, err := com.ExecCmdDir(absRoot, "git", "pull")
			if err != nil {
				return fmt.Errorf("Fail to update docs from remote source(%s): %v - %s", setting.Docs.Target, err, stderr)
			}
			fmt.Println(stdout)
		} else {
			stdout, stderr, err := com.ExecCmd("git", "clone", setting.Docs.Target, absRoot)
			if err != nil {
				return fmt.Errorf("Fail to clone docs from remote source(%s): %v - %s", setting.Docs.Target, err, stderr)
			}
			fmt.Println(stdout)
		}
	}

	if !com.IsDir(localRoot) {
		return fmt.Errorf("Documentation not found: %s - %s", setting.Docs.Type, localRoot)
	}

	tocs, err := initToc(localRoot)
	if err != nil {
		return fmt.Errorf("initToc: %v", err)
	}
	initDocs(tocs, localRoot)
	Tocs = tocs
	return nil
}

func NewContext() {
	if err := ReloadDocs(); err != nil {
		log.Fatal("Fail to init docs: %v", err)
	}
}
<commit_msg>修正批注的问题<commit_after>// Copyright 2015 Unknwon
//
// 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 models

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"
	"sync"

	"github.com/Unknwon/com"
	"github.com/Unknwon/log"
	"github.com/mschoch/blackfriday-text"
	"github.com/russross/blackfriday"
	"gopkg.in/ini.v1"

	"github.com/peachdocs/peach/modules/setting"
)

type Node struct {
	Name    string // Name in TOC
	Title   string // Name in given language
	content []byte
	Text    string // Clean text without formatting

	Plain    bool   // Root node without content
	FileName string // Full path with .md extension
	Nodes    []*Node
}

var textRender = blackfridaytext.TextRenderer()
var htmlRoot = "data/html"

func parseNodeName(name string, data []byte) (string, []byte) {
	data = bytes.TrimSpace(data)
	if len(data) < 3 || string(data[:3]) != "---" {
		return name, []byte("")
	}
	endIdx := bytes.Index(data[3:], []byte("---")) + 3
	if endIdx == -1 {
		return name, []byte("")
	}

	opts := strings.Split(strings.TrimSpace(string(string(data[3:endIdx]))), "\n")

	title := name
	for _, opt := range opts {
		infos := strings.SplitN(opt, ":", 2)
		if len(infos) != 2 {
			continue
		}

		switch strings.TrimSpace(infos[0]) {
		case "name":
			title = strings.TrimSpace(infos[1])
		}
	}

	return title, data[endIdx+3:]
}

func (n *Node) ReloadContent() error {
	data, err := ioutil.ReadFile(n.FileName)
	if err != nil {
		return err
	}

	n.Title, data = parseNodeName(n.Name, data)
	n.Plain = len(bytes.TrimSpace(data)) == 0

	if !n.Plain {
		n.content = markdown(data)
		n.Text = string(bytes.ToLower(blackfriday.Markdown(data, textRender, 0)))
	}

	htmlRoot := "data/html"
	return n.GenLocalHTML(htmlRoot)
}

// Generate local HTML
func (n *Node) GenLocalHTML(htmlRoot string) error {

	changePath := strings.Replace(n.FileName, "data/docs", htmlRoot, 1)
	htmlFile := strings.Replace(changePath, ".md", ".html", 1)

	return com.WriteFile(htmlFile, n.content)
}

func (n *Node) Content() []byte {
	if !setting.ProdMode {
		if err := n.ReloadContent(); err != nil {
			log.Error("Fail to reload content: %v", err)
		}
	}

	return n.content
}

// Toc represents table of content in a specific language.
type Toc struct {
	RootPath string
	Lang     string
	Nodes    []*Node
	Pages    []*Node
}

// GetDoc should only be called by top level toc.
func (t *Toc) GetDoc(name string) (string, []byte, bool) {
	name = strings.TrimPrefix(name, "/")

	// Returns first node whatever avaiable as default.
	if len(name) == 0 {
		if len(t.Nodes) == 0 ||
			t.Nodes[0].Plain {
			return "", nil, false
		}
		return t.Nodes[0].Title, t.Nodes[0].Content(), false
	}

	infos := strings.Split(name, "/")

	// Dir node.
	if len(infos) == 1 {
		for i := range t.Nodes {
			if t.Nodes[i].Name == infos[0] {
				return t.Nodes[i].Title, t.Nodes[i].Content(), false
			}
		}
		return "", nil, false
	}

	// File node.
	for i := range t.Nodes {
		if t.Nodes[i].Name == infos[0] {
			for j := range t.Nodes[i].Nodes {
				if t.Nodes[i].Nodes[j].Name == infos[1] {
					if com.IsFile(t.Nodes[i].Nodes[j].FileName) {
						return t.Nodes[i].Nodes[j].Title, t.Nodes[i].Nodes[j].Content(), false
					}

					// If not default language, try again.
					title, content, _ := Tocs[setting.Docs.Langs[0]].GetDoc(name)
					return title, content, true
				}
			}
		}
	}

	return "", nil, false
}

type SearchResult struct {
	Title string
	Path  string
	Match string
}

func adjustRange(start, end, length int) (int, int) {
	start -= 20
	if start < 0 {
		start = 0
	}
	end += 230
	if end > length {
		end = length
	}
	return start, end
}

func (t *Toc) Search(q string) []*SearchResult {
	if len(q) == 0 {
		return nil
	}
	q = strings.ToLower(q)

	results := make([]*SearchResult, 0, 5)

	// Dir node.
	for i := range t.Nodes {
		if idx := strings.Index(t.Nodes[i].Text, q); idx > -1 {
			start, end := adjustRange(idx, idx+len(q), len(t.Nodes[i].Text))
			results = append(results, &SearchResult{
				Title: t.Nodes[i].Title,
				Path:  t.Nodes[i].Name,
				Match: t.Nodes[i].Text[start:end],
			})
		}
	}

	// File node.
	for i := range t.Nodes {
		for j := range t.Nodes[i].Nodes {
			if idx := strings.Index(t.Nodes[i].Nodes[j].Text, q); idx > -1 {
				start, end := adjustRange(idx, idx+len(q), len(t.Nodes[i].Nodes[j].Text))
				results = append(results, &SearchResult{
					Title: t.Nodes[i].Nodes[j].Title,
					Path:  path.Join(t.Nodes[i].Name, t.Nodes[i].Nodes[j].Name),
					Match: t.Nodes[i].Nodes[j].Text[start:end],
				})
			}
		}
	}

	return results
}

var (
	tocLocker = sync.RWMutex{}
	Tocs      map[string]*Toc
)

func initToc(localRoot string) (map[string]*Toc, error) {
	tocPath := path.Join(localRoot, "TOC.ini")
	if !com.IsFile(tocPath) {
		return nil, fmt.Errorf("TOC not found: %s", tocPath)
	}

	// Generate Toc.
	tocCfg, err := ini.Load(tocPath)
	if err != nil {
		return nil, fmt.Errorf("Fail to load TOC.ini: %v", err)
	}

	tocs := make(map[string]*Toc)
	for _, lang := range setting.Docs.Langs {
		toc := &Toc{
			RootPath: localRoot,
			Lang:     lang,
		}
		dirs := tocCfg.Section("").KeyStrings()
		toc.Nodes = make([]*Node, 0, len(dirs))
		for _, dir := range dirs {
			dirName := tocCfg.Section("").Key(dir).String()
			fmt.Println(dirName + "/")
			files := tocCfg.Section(dirName).KeyStrings()

			// Skip empty directory.
			if len(files) == 0 {
				continue
			}

			dirNode := &Node{
				Name:     dirName,
				FileName: path.Join(localRoot, lang, dirName, tocCfg.Section(dirName).Key(files[0]).String()) + ".md",
				Nodes:    make([]*Node, 0, len(files)-1),
			}
			toc.Nodes = append(toc.Nodes, dirNode)

			for _, file := range files[1:] {
				fileName := tocCfg.Section(dirName).Key(file).String()
				fmt.Println(strings.Repeat(" ", len(dirName))+"|__", fileName)

				node := &Node{
					Name:     fileName,
					FileName: path.Join(localRoot, lang, dirName, fileName) + ".md",
				}
				dirNode.Nodes = append(dirNode.Nodes, node)
			}
		}

		// Single pages.
		pages := tocCfg.Section("pages").KeyStrings()
		toc.Pages = make([]*Node, 0, len(pages))
		for _, page := range pages {
			pageName := tocCfg.Section("pages").Key(page).String()
			fmt.Println(pageName)

			toc.Pages = append(toc.Pages, &Node{
				Name:     pageName,
				FileName: path.Join(localRoot, lang, pageName) + ".md",
			})
		}

		tocs[lang] = toc
	}
	return tocs, nil
}

func ReloadDocs() error {
	tocLocker.Lock()
	defer tocLocker.Unlock()

	localRoot := setting.Docs.Target

	// Del htmlRoot path
	if com.IsExist(htmlRoot) {
		err := os.RemoveAll(htmlRoot)
		if err != nil {
			return fmt.Errorf("htmlRoot not found: %v", err)
		}
	}

	// Fetch docs from remote.
	if setting.Docs.Type == "remote" {
		localRoot = "data/docs"

		absRoot, err := filepath.Abs(localRoot)
		if err != nil {
			return fmt.Errorf("filepath.Abs: %v", err)
		}

		// Clone new or pull to update.
		if com.IsDir(absRoot) {
			stdout, stderr, err := com.ExecCmdDir(absRoot, "git", "pull")
			if err != nil {
				return fmt.Errorf("Fail to update docs from remote source(%s): %v - %s", setting.Docs.Target, err, stderr)
			}
			fmt.Println(stdout)
		} else {
			stdout, stderr, err := com.ExecCmd("git", "clone", setting.Docs.Target, absRoot)
			if err != nil {
				return fmt.Errorf("Fail to clone docs from remote source(%s): %v - %s", setting.Docs.Target, err, stderr)
			}
			fmt.Println(stdout)
		}
	}

	if !com.IsDir(localRoot) {
		return fmt.Errorf("Documentation not found: %s - %s", setting.Docs.Type, localRoot)
	}

	tocs, err := initToc(localRoot)
	if err != nil {
		return fmt.Errorf("initToc: %v", err)
	}
	initDocs(tocs, localRoot)
	Tocs = tocs
	return nil
}

func NewContext() {
	if err := ReloadDocs(); err != nil {
		log.Fatal("Fail to init docs: %v", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"time"

	"gopkg.in/mgo.v2/bson"
)

type Health struct {
	RepositoryOwner    string    `json:"repository_owner"`
	RepositoryName     string    `json:"repository_name"`
	RepositoryURL      string    `json:"repository_url"`
	RepositoryFullName string    `json:"repository_full_name"`
	Timestamp          time.Time `json:"timestamp"`
	Indicators         struct {
		AverageResponseTimes []struct {
			UserName            string `json:"user_name"`
			AverageResponseTime string `json:"average_response_time"`
		} `json:"average_response_times"`
		Commits struct {
			TimeSinceFirstCommit string `json:"time_since_first_commit"`
			TimeSinceLastCommit  string `json:"time_since_last_commit"`
			CommitFrequency      struct {
				TotalCommits string `json:"total_commits"`
				PerWeek      string `json:"per_week"`
				PerMonth     string `json:"per_month"`
			} `json:"commit_frequency"`
		} `json:"commits"`
		Issues struct {
			TotalIssues        string `json:"total_issues"`
			AverageTimeToClose string `json:"average_time_to_close"`
			OpenVsClosed       struct {
				PerWeek  string `json:"per_week"`
				PerMonth string `json:"per_month"`
			} `json:"open_vs_closed"`
		} `json:"issues"`
		License      License `json:"license"`
		PullRequests struct {
			TotalPullRequests  string `json:"total_pull_requests"`
			MergedPullRequests string `json:"merged_pull_requests"`
			SentVsMerged       struct {
				PerWeek  string `json:"per_week"`
				PerMonth string `json:"per_month"`
			} `json:"sent_vs_merged"`
		} `json:"pull_requests"`
		Readme Readme `json:"readme"`
	} `json:"indicators"`
}

type Readme struct {
	Exists bool   `json:"exists"`
	URL    string `json:"url"`
}

type License struct {
	Exists bool   `json:"exists"`
	URL    string `json:"url"`
	Name   string `json:"name"`
}

type Indicator struct {
	ID   bson.ObjectId `bson:"_id" json:"id"`
	Name string        `bson:"name" json:"name"`
	Key  string        `bson:"key" json:"key"`
}
<commit_msg>Seperate indicators into their own structs<commit_after>package main

import "gopkg.in/mgo.v2/bson"

type Health struct {
	RepositoryOwner    string `json:"repository_owner"`
	RepositoryName     string `json:"repository_name"`
	RepositoryURL      string `json:"repository_url"`
	RepositoryFullName string `json:"repository_full_name"`
	Timestamp          string `json:"timestamp"`
	Indicators         struct {
		AverageResponseTimes []AverageResponseTime `json:"average_response_times"`
		Commits              Commits               `json:"commits"`
		Issues               Issues                `json:"issues"`
		License              License               `json:"license"`
		PullRequests         PullRequests          `json:"pull_requests"`
		Readme               Readme                `json:"readme"`
	} `json:"indicators"`
}

type Readme struct {
	Exists bool   `json:"exists"`
	URL    string `json:"url"`
}

type License struct {
	Exists bool   `json:"exists"`
	URL    string `json:"url"`
	Name   string `json:"name"`
}

type PullRequests struct {
	TotalPullRequests  string `json:"total_pull_requests"`
	MergedPullRequests string `json:"merged_pull_requests"`
	SentVsMerged       struct {
		PerWeek  string `json:"per_week"`
		PerMonth string `json:"per_month"`
	} `json:"sent_vs_merged"`
}

type Issues struct {
	TotalPullRequests  string `json:"total_pull_requests"`
	MergedPullRequests string `json:"merged_pull_requests"`
	SentVsMerged       struct {
		PerWeek  string `json:"per_week"`
		PerMonth string `json:"per_month"`
	} `json:"sent_vs_merged"`
}

type Commits struct {
	TotalPullRequests  string `json:"total_pull_requests"`
	MergedPullRequests string `json:"merged_pull_requests"`
	SentVsMerged       struct {
		PerWeek  string `json:"per_week"`
		PerMonth string `json:"per_month"`
	} `json:"sent_vs_merged"`
}

type AverageResponseTime struct {
	UserName            string `json:"user_name"`
	AverageResponseTime string `json:"average_response_time"`
}

type Indicator struct {
	ID   bson.ObjectId `bson:"_id" json:"id"`
	Name string        `bson:"name" json:"name"`
	Key  string        `bson:"key" json:"key"`
}
<|endoftext|>


<commit_before>package icmp

import (
	"fmt"
	"net"
	"os"
	"os/signal"
	"sort"
	"syscall"
	"time"

	"github.com/mehrdadrad/mylg/cli"
)

// Trace represents trace properties
type Trace struct {
	src     string
	host    string
	ips     []net.IP
	ttl     int
	timeout int64
}

type HopResp struct {
	hop     string
	ip      string
	elapsed float64
	last    bool
}

type MHopResp []HopResp

// NewTrace creates new trace object
func NewTrace(args string) (*Trace, error) {
	target, flag := cli.Flag(args)

	// show help
	if _, ok := flag["help"]; ok || len(target) < 3 {
		helpTrace()
		return nil, nil
	}
	ips, err := net.LookupIP(target)
	if err != nil {
		return nil, err
	}
	return &Trace{
		host:    target,
		ips:     ips,
		timeout: 5000,
	}, nil
}

func (h MHopResp) Len() int           { return len(h) }
func (h MHopResp) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
func (h MHopResp) Less(i, j int) bool { return len(h[i].ip) > len(h[j].ip) }

// SetTTL set the IP packat time to live
func (i *Trace) SetTTL(ttl int) {
	i.ttl = ttl
}

// Send tries to send an UDP packet
func (i *Trace) Send() error {
	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
	if err != nil {
		println(err.Error())
	}
	defer syscall.Close(fd)
	// Set options
	syscall.SetsockoptInt(fd, 0x0, syscall.IP_TTL, i.ttl)

	if IsIPv4(i.ips[0]) {
		var b [4]byte
		copy(b[:], i.ips[0].To4())
		addr := syscall.SockaddrInet4{
			Port: 33434,
			Addr: b,
		}
		if err := syscall.Sendto(fd, []byte{0x0}, 0, &addr); err != nil {
			return err
		}
	} else if IsIPv6(i.ips[0]) {
		var b [16]byte
		copy(b[:], i.ips[0].To16())
		addr := syscall.SockaddrInet6{
			Port: 33434,
			Addr: b,
		}
		if err := syscall.Sendto(fd, []byte{0x0}, 0, &addr); err != nil {
			return err
		}
	}
	return nil
}

// Bind starts to listen for ICMP reply
func (i *Trace) Bind() int {
	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_ICMP)
	if err != nil {
		println("e2", err.Error())
	}
	tv := syscall.NsecToTimeval(1e6 * i.timeout)
	err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
	if err != nil {
		println(err.Error())
	}
	b := net.ParseIP("0.0.0.0").To4()
	addr := syscall.SockaddrInet4{
		Port: 0,
		Addr: [4]byte{b[0], b[1], b[2], b[3]},
	}

	if err := syscall.Bind(fd, &addr); err != nil {
		println("e3", err.Error())
	}
	return fd
}

// Recv gets the replied icmp packet
func (i *Trace) Recv(fd int) (int, int, string) {
	var typ, code int
	buf := make([]byte, 512)
	n, from, err := syscall.Recvfrom(fd, buf, 0)
	if err == nil {
		buf = buf[:n]
		typ = int(buf[20])  // ICMP Type
		code = int(buf[21]) // ICMP Code
	}
	if typ != 0 {
		b := from.(*syscall.SockaddrInet4).Addr
		return typ, code, fmt.Sprintf("%v.%v.%v.%v", b[0], b[1], b[2], b[3])
	}
	return typ, code, ""
}

// Done close the socket
func (i *Trace) Done(fd int) {
	syscall.Close(fd)
}

// NextHop pings the specific hop by set TTL
func (i *Trace) NextHop(fd, hop int) HopResp {
	var (
		r HopResp
	)
	i.SetTTL(hop)
	ts := time.Now().UnixNano()
	err := i.Send()
	if err != nil {
		println("e5", err.Error())
	}
	t, c, ip := i.Recv(fd)
	elapsed := time.Now().UnixNano() - ts
	if t != 0 {
		name, _ := net.LookupAddr(ip)
		if len(name) > 0 {
			r = HopResp{name[0], ip, float64(elapsed) / 1e6, false}
		} else {
			r = HopResp{"", ip, float64(elapsed) / 1e6, false}
		}
	}
	if c == 3 {
		r.last = true
	}
	return r
}

// Run provides trace based on the other methods
func (i *Trace) Run(retry int) chan []HopResp {
	var (
		c = make(chan []HopResp, 1)
		r []HopResp
	)
	fd := i.Bind()
	go func() {
		for h := 1; h < 30; h++ {
			for n := 0; n < retry; n++ {
				r = append(r, i.NextHop(fd, h))
			}
			c <- r
			if r[0].last {
				close(c)
				break
			}
			r = r[:0]
		}
	}()
	return c
}

// PrintPretty prints out trace result
func (i *Trace) PrintPretty() {
	var (
		loop    = true
		counter int
		sigCh   = make(chan os.Signal, 1)
		resp    = i.Run(3)
	)

	signal.Notify(sigCh, os.Interrupt)
	defer signal.Stop(sigCh)

	for loop {
		select {
		case r, ok := <-resp:
			if !ok {
				loop = false
				break
			}
			counter++
			sort.Sort(MHopResp(r))
			// there is not any load balancing and there is at least a timeout
			if r[0].ip != r[1].ip && (r[1].elapsed == 0 || r[2].elapsed == 0) {
				fmt.Printf("%-2d %s", counter, fmtHops(r, 1))
				continue
			}
			// there is not any load balancing and there is at least a timeout
			if r[1].ip != r[2].ip && (r[0].elapsed == 0 || r[1].elapsed == 0) {
				fmt.Printf("%-2d %s", counter, fmtHops(r, 1))
				continue
			}
			// load balance between three routes
			if r[0].ip != r[1].ip && r[0].ip != r[2].ip && r[1].ip != r[2].ip {
				fmt.Printf("%-2d %s   %s   %s", counter, fmtHops(r[0:1], 0), fmtHops(r[1:2], 0), fmtHops(r[2:3], 1))
				continue
			}
			// load balance between two routes
			if r[0].ip == r[1].ip && r[1].ip != r[2].ip {
				fmt.Printf("%-2d %s   %s", counter, fmtHops(r[0:2], 0), fmtHops(r[2:3], 1))
				continue
			}
			// load balance between two routes
			if r[0].ip != r[1].ip && r[1].ip == r[2].ip {
				fmt.Printf("%-2d %s   %s", counter, fmtHops(r[0:1], 0), fmtHops(r[1:3], 1))
				continue
			}
			// there is not any load balancing
			if r[0].ip == r[1].ip && r[1].ip == r[2].ip {
				fmt.Printf("%-2d %s", counter, fmtHops(r, 1))
			}

		case <-sigCh:
			loop = false
		}
	}
}

func fmtHops(m []HopResp, last int) string {
	var (
		timeout = false
		msg     string
	)
	for _, r := range m {
		if (msg == "" || timeout) && r.hop != "" {
			msg += fmt.Sprintf("%s (%s) ", r.hop, r.ip)
		}
		if (msg == "" || timeout) && r.hop == "" {
			msg += fmt.Sprintf("%s ", r.ip)
		}
		if r.elapsed != 0 {
			msg += fmt.Sprintf("%.3f ms ", r.elapsed)
			timeout = false
		} else {
			msg += "*  "
			timeout = true
		}
	}
	if !timeout || last == 1 {
		msg += "\n"
	}
	return msg
}

func helpTrace() {
	fmt.Println(`
    usage:
          trace IP address / domain name
    options:

    Example:
          trace 8.8.8.8
	`)

}
<commit_msg>fixed formating<commit_after>package icmp

import (
	"fmt"
	"net"
	"os"
	"os/signal"
	"sort"
	"syscall"
	"time"

	"github.com/mehrdadrad/mylg/cli"
)

// Trace represents trace properties
type Trace struct {
	src     string
	host    string
	ips     []net.IP
	ttl     int
	timeout int64
}

type HopResp struct {
	hop     string
	ip      string
	elapsed float64
	last    bool
}

type MHopResp []HopResp

// NewTrace creates new trace object
func NewTrace(args string) (*Trace, error) {
	target, flag := cli.Flag(args)

	// show help
	if _, ok := flag["help"]; ok || len(target) < 3 {
		helpTrace()
		return nil, nil
	}
	ips, err := net.LookupIP(target)
	if err != nil {
		return nil, err
	}
	return &Trace{
		host:    target,
		ips:     ips,
		timeout: 5000,
	}, nil
}

func (h MHopResp) Len() int           { return len(h) }
func (h MHopResp) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
func (h MHopResp) Less(i, j int) bool { return len(h[i].ip) > len(h[j].ip) }

// SetTTL set the IP packat time to live
func (i *Trace) SetTTL(ttl int) {
	i.ttl = ttl
}

// Send tries to send an UDP packet
func (i *Trace) Send() error {
	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
	if err != nil {
		println(err.Error())
	}
	defer syscall.Close(fd)
	// Set options
	syscall.SetsockoptInt(fd, 0x0, syscall.IP_TTL, i.ttl)

	if IsIPv4(i.ips[0]) {
		var b [4]byte
		copy(b[:], i.ips[0].To4())
		addr := syscall.SockaddrInet4{
			Port: 33434,
			Addr: b,
		}
		if err := syscall.Sendto(fd, []byte{0x0}, 0, &addr); err != nil {
			return err
		}
	} else if IsIPv6(i.ips[0]) {
		var b [16]byte
		copy(b[:], i.ips[0].To16())
		addr := syscall.SockaddrInet6{
			Port: 33434,
			Addr: b,
		}
		if err := syscall.Sendto(fd, []byte{0x0}, 0, &addr); err != nil {
			return err
		}
	}
	return nil
}

// Bind starts to listen for ICMP reply
func (i *Trace) Bind() int {
	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_ICMP)
	if err != nil {
		println("e2", err.Error())
	}
	tv := syscall.NsecToTimeval(1e6 * i.timeout)
	err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
	if err != nil {
		println(err.Error())
	}
	b := net.ParseIP("0.0.0.0").To4()
	addr := syscall.SockaddrInet4{
		Port: 0,
		Addr: [4]byte{b[0], b[1], b[2], b[3]},
	}

	if err := syscall.Bind(fd, &addr); err != nil {
		println("e3", err.Error())
	}
	return fd
}

// Recv gets the replied icmp packet
func (i *Trace) Recv(fd int) (int, int, string) {
	var typ, code int
	buf := make([]byte, 512)
	n, from, err := syscall.Recvfrom(fd, buf, 0)
	if err == nil {
		buf = buf[:n]
		typ = int(buf[20])  // ICMP Type
		code = int(buf[21]) // ICMP Code
	}
	if typ != 0 {
		b := from.(*syscall.SockaddrInet4).Addr
		return typ, code, fmt.Sprintf("%v.%v.%v.%v", b[0], b[1], b[2], b[3])
	}
	return typ, code, ""
}

// Done close the socket
func (i *Trace) Done(fd int) {
	syscall.Close(fd)
}

// NextHop pings the specific hop by set TTL
func (i *Trace) NextHop(fd, hop int) HopResp {
	var (
		r HopResp
	)
	i.SetTTL(hop)
	ts := time.Now().UnixNano()
	err := i.Send()
	if err != nil {
		println("e5", err.Error())
	}
	t, c, ip := i.Recv(fd)
	elapsed := time.Now().UnixNano() - ts
	if t != 0 {
		name, _ := net.LookupAddr(ip)
		if len(name) > 0 {
			r = HopResp{name[0], ip, float64(elapsed) / 1e6, false}
		} else {
			r = HopResp{"", ip, float64(elapsed) / 1e6, false}
		}
	}
	if c == 3 {
		r.last = true
	}
	return r
}

// Run provides trace based on the other methods
func (i *Trace) Run(retry int) chan []HopResp {
	var (
		c = make(chan []HopResp, 1)
		r []HopResp
	)
	fd := i.Bind()
	go func() {
		for h := 1; h < 30; h++ {
			for n := 0; n < retry; n++ {
				r = append(r, i.NextHop(fd, h))
			}
			c <- r
			if r[0].last {
				close(c)
				i.Done(fd)
				break
			}
			r = r[:0]
		}
	}()
	return c
}

// PrintPretty prints out trace result
func (i *Trace) PrintPretty() {
	var (
		loop    = true
		counter int
		sigCh   = make(chan os.Signal, 1)
		resp    = i.Run(3)
	)

	signal.Notify(sigCh, os.Interrupt)
	defer signal.Stop(sigCh)

	// header
	fmt.Printf("trace route to %s (%s), 30 hops max\n", i.host, i.ips[0])

	for loop {
		select {
		case r, ok := <-resp:
			if !ok {
				loop = false
				break
			}
			counter++
			sort.Sort(MHopResp(r))
			// there is not any load balancing and there is at least a timeout
			if r[0].ip != r[1].ip && (r[1].elapsed == 0 || r[2].elapsed == 0) {
				fmt.Printf("%-2d %s", counter, fmtHops(r, 1))
				continue
			}
			// there is not any load balancing and there is at least a timeout
			if r[1].ip != r[2].ip && (r[0].elapsed == 0 || r[1].elapsed == 0) {
				fmt.Printf("%-2d %s", counter, fmtHops(r, 1))
				continue
			}
			// load balance between three routes
			if r[0].ip != r[1].ip && r[0].ip != r[2].ip && r[1].ip != r[2].ip {
				fmt.Printf("%-2d %s %s %s", counter, fmtHops(r[0:1], 0), fmtHops(r[1:2], 0), fmtHops(r[2:3], 1))
				continue
			}
			// load balance between two routes
			if r[0].ip == r[1].ip && r[1].ip != r[2].ip {
				fmt.Printf("%-2d %s %s", counter, fmtHops(r[0:2], 0), fmtHops(r[2:3], 1))
				continue
			}
			// load balance between two routes
			if r[0].ip != r[1].ip && r[1].ip == r[2].ip {
				fmt.Printf("%-2d %s %s", counter, fmtHops(r[0:1], 0), fmtHops(r[1:3], 1))
				continue
			}
			// there is not any load balancing
			if r[0].ip == r[1].ip && r[1].ip == r[2].ip {
				fmt.Printf("%-2d %s", counter, fmtHops(r, 1))
			}

		case <-sigCh:
			loop = false
		}
	}
}

func fmtHops(m []HopResp, newLine int) string {
	var (
		timeout = false
		msg     string
	)
	for _, r := range m {
		if (msg == "" || timeout) && r.hop != "" {
			msg += fmt.Sprintf("%s (%s) ", r.hop, r.ip)
		}
		if (msg == "" || timeout) && r.hop == "" {
			msg += fmt.Sprintf("%s ", r.ip)
		}
		if r.elapsed != 0 {
			msg += fmt.Sprintf("%.3f ms ", r.elapsed)
			timeout = false
		} else {
			msg += "* "
			timeout = true
		}
	}
	if newLine == 1 {
		msg += "\n"
	}
	return msg
}

func helpTrace() {
	fmt.Println(`
    usage:
          trace IP address / domain name
    options:

    Example:
          trace 8.8.8.8
	`)

}
<|endoftext|>


<commit_before>package fuse_test

import (
	"io/ioutil"
	"os"
	"path"
	"strings"
	"testing"

	"golang.org/x/net/context"

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/fuseops"
	"github.com/jacobsa/fuse/fuseutil"
)

////////////////////////////////////////////////////////////////////////
// minimalFS
////////////////////////////////////////////////////////////////////////

// A minimal fuseutil.FileSystem that can successfully mount but do nothing
// else.
type minimalFS struct {
	fuseutil.NotImplementedFileSystem
}

func (fs *minimalFS) StatFS(
	ctx context.Context,
	op *fuseops.StatFSOp) (err error) {
	return
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func TestSuccessfulMount(t *testing.T) {
	ctx := context.Background()

	// Set up a temporary directory.
	dir, err := ioutil.TempDir("", "mount_test")
	if err != nil {
		t.Fatal("ioutil.TempDir: %v", err)
	}

	defer os.RemoveAll(dir)

	// Mount.
	fs := &minimalFS{}
	mfs, err := fuse.Mount(
		dir,
		fuseutil.NewFileSystemServer(fs),
		&fuse.MountConfig{})

	if err != nil {
		t.Fatalf("fuse.Mount: %v", err)
	}

	defer func() {
		if err := mfs.Join(ctx); err != nil {
			t.Errorf("Joining: %v", err)
		}
	}()

	defer fuse.Unmount(mfs.Dir())
}

func TestNonEmptyMountPoint(t *testing.T) {
	// Set up a temporary directory.
	dir, err := ioutil.TempDir("", "mount_test")
	if err != nil {
		t.Fatal("ioutil.TempDir: %v", err)
	}

	defer os.RemoveAll(dir)

	// Add a file within it.
	err = ioutil.WriteFile(path.Join(dir, "foo"), []byte{}, 0600)
	if err != nil {
		t.Fatalf("ioutil.WriteFile: %v", err)
	}

	// Attempt to mount.
	fs := &minimalFS{}
	_, err = fuse.Mount(
		dir,
		fuseutil.NewFileSystemServer(fs),
		&fuse.MountConfig{})

	const want = "not empty"
	if err == nil || !strings.Contains(err.Error(), want) {
		t.Errorf("Unexpected error: %v", err)
	}
}
<commit_msg>TestNonEmptyMountPoint: clean up in the event of a successful mount.<commit_after>package fuse_test

import (
	"io/ioutil"
	"os"
	"path"
	"strings"
	"testing"

	"golang.org/x/net/context"

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/fuseops"
	"github.com/jacobsa/fuse/fuseutil"
)

////////////////////////////////////////////////////////////////////////
// minimalFS
////////////////////////////////////////////////////////////////////////

// A minimal fuseutil.FileSystem that can successfully mount but do nothing
// else.
type minimalFS struct {
	fuseutil.NotImplementedFileSystem
}

func (fs *minimalFS) StatFS(
	ctx context.Context,
	op *fuseops.StatFSOp) (err error) {
	return
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func TestSuccessfulMount(t *testing.T) {
	ctx := context.Background()

	// Set up a temporary directory.
	dir, err := ioutil.TempDir("", "mount_test")
	if err != nil {
		t.Fatal("ioutil.TempDir: %v", err)
	}

	defer os.RemoveAll(dir)

	// Mount.
	fs := &minimalFS{}
	mfs, err := fuse.Mount(
		dir,
		fuseutil.NewFileSystemServer(fs),
		&fuse.MountConfig{})

	if err != nil {
		t.Fatalf("fuse.Mount: %v", err)
	}

	defer func() {
		if err := mfs.Join(ctx); err != nil {
			t.Errorf("Joining: %v", err)
		}
	}()

	defer fuse.Unmount(mfs.Dir())
}

func TestNonEmptyMountPoint(t *testing.T) {
	ctx := context.Background()

	// Set up a temporary directory.
	dir, err := ioutil.TempDir("", "mount_test")
	if err != nil {
		t.Fatal("ioutil.TempDir: %v", err)
	}

	defer os.RemoveAll(dir)

	// Add a file within it.
	err = ioutil.WriteFile(path.Join(dir, "foo"), []byte{}, 0600)
	if err != nil {
		t.Fatalf("ioutil.WriteFile: %v", err)
	}

	// Attempt to mount.
	fs := &minimalFS{}
	mfs, err := fuse.Mount(
		dir,
		fuseutil.NewFileSystemServer(fs),
		&fuse.MountConfig{})

	if err == nil {
		fuse.Unmount(mfs.Dir())
		mfs.Join(ctx)
		t.Fatal("fuse.Mount returned nil")
	}

	const want = "not empty"
	if got := err.Error(); !strings.Contains(got, want) {
		t.Errorf("Unexpected error: %v", got)
	}
}
<|endoftext|>


<commit_before>package main

import (
    "github.com/nsf/termbox-go"
    "encoding/json"
    "net/http"
    "io/ioutil"
    "strconv"
    "strings"
    "log"
    "sort"
)

type Entries struct {
    Title string
    Year string
    ImdbID string
}

type Data struct {
    Search []Entries
}

type MoviesTab struct {
    a *Apollo
    name string
    status string

    movies []Movie
    view string
    sorter string
    offset int
    cursor int
    omdb Data
    ratings bool
}

func CreateMoviesTab(a *Apollo) *MoviesTab {
    t := &MoviesTab{
        a: a,
        name: "movies",
        status: "movies",
        view: "watched",
        sorter: "title",
    }

    t.refreshSlice()

    return t
}

func (t *MoviesTab) Name() string {
    return t.name
}

func (t *MoviesTab) Status() string {
    return t.status
}

func (t *MoviesTab) HandleKeyEvent(ev *termbox.Event) bool {
    if len(t.omdb.Search) > 0 {
        indexes := map[rune]int{'0': 0, '1': 1, '2': 2, '3': 3,
                                '4': 4, '5': 5, '6': 6, '7': 7,
                                '8': 8, '9': 9,}
        if index, exist := indexes[ev.Ch]; exist {
            if index < len(t.omdb.Search) {
                log.Print(t.omdb.Search[index])
                dbIndex := t.index()
                t.a.d.Movies[dbIndex].Year = t.omdb.Search[index].Year
                t.a.d.Movies[dbIndex].Title = t.omdb.Search[index].Title
                t.a.d.Movies[dbIndex].ImdbID = t.omdb.Search[index].ImdbID
            }
        }

        t.omdb.Search = t.omdb.Search[:0]
        t.a.d.save()
        t.refreshSlice()

        return true
    }

    switch ev.Ch {
    case '1':
        t.view = "watched"
        t.cursor = 0
        t.offset = 0
        t.refreshSlice()
    case '2':
        t.view = "unwatched"
        t.cursor = 0
        t.offset = 0
        t.refreshSlice()
    case '3':
        t.view = "all"
        t.cursor = 0
        t.offset = 0
        t.refreshSlice()
    case 's':
        t.cursor = 0
        t.offset = 0
        t.sort()
    case 'D':
        if len(t.movies) > 0 {
            t.a.d.Movies = append(t.a.d.Movies[:t.index()], t.a.d.Movies[t.index()+1:]...)
            t.a.d.save()
            t.refreshSlice()
        }
    case 't':
        t.autoTag()
    case 'r':
        if t.ratings {
            t.ratings = false
        } else {
            t.ratings = true
        }
    case 'q':
        if len(t.movies) > 0 {
            if t.a.d.Movies[t.index()].Rating > 0 {
                t.a.d.Movies[t.index()].Rating--
                t.a.d.save()
                t.refreshSlice()
            }
        }
    case 'e':
        if len(t.movies) > 0 {
            if t.a.d.Movies[t.index()].Rating < 6 {
                t.a.d.Movies[t.index()].Rating++
                t.a.d.save()
                t.refreshSlice()
            }
        }
    }

    switch ev.Key {
    case termbox.KeyArrowUp:
        t.cursor--
        if t.cursor < 0 {
            t.cursor = 0
        } else if t.cursor - t.offset < 0 {
            t.offset--
        }
    case termbox.KeyPgup:
        t.cursor -= 5
        if t.cursor < 0 {
            t.cursor = 0
            t.offset = 0
        } else if t.cursor - t.offset < 0 {
            t.offset -= 5
            if t.offset < 0 {
                t.offset = 0
            }
        }
    case termbox.KeyArrowDown:
        t.cursor++
        if t.cursor > len(t.movies) - 1 {
            t.cursor--
        } else if t.cursor - t.offset > t.a.height - 4 {
            t.offset++
        }
    case termbox.KeyPgdn:
        t.cursor += 5
        if t.cursor > len(t.movies) - 1 {
            t.cursor = len(t.movies) - 1
            if len(t.movies) > t.a.height - 3 {
                t.offset = len(t.movies) - (t.a.height - 3)
            }
        } else if t.cursor - t.offset > t.a.height - 4 {
            t.offset += 5
            if t.cursor - t.offset < t.a.height - 3 {
                t.offset = t.cursor - (t.a.height - 4)
            }
        }
    default:
        return false
    }

    log.Print("cursor: " + strconv.Itoa(t.cursor) + " offset: " + strconv.Itoa(t.offset) +
    " len:" + strconv.Itoa(len(t.movies)) + " height:" + strconv.Itoa(t.a.height))

    return true
}

func (t *MoviesTab) Draw() {
    if len(t.omdb.Search) == 0 {
        for j := 0; j < t.a.height - 3; j++ {
            if j < len(t.movies) {
                if t.ratings {
                    for i := 0; i < t.movies[j + t.offset].Rating; i++ {
                        termbox.SetCell(i + 3, j + 1, '*', color['d'], color['d'])
                    }
                }

                runes := []rune("[" + t.movies[j + t.offset].Year + "] " + t.movies[j + t.offset].Title)
                for i := 0; i < len(runes); i++ {
                    if t.ratings {
                        termbox.SetCell(i + 10, j + 1, runes[i], color['d'], color['d'])
                    } else {
                        termbox.SetCell(i + 3, j + 1, runes[i], color['d'], color['d'])
                    }
                }
            }
        }

        termbox.SetCell(1, t.cursor - t.offset + 1, '*', color['d'], color['d'])
    } else {
        for j := 0; j < len(t.omdb.Search); j++ {
            runes := []rune(strconv.Itoa(j) + ". [" + t.omdb.Search[j].Year + "] " + t.omdb.Search[j].Title)
            for i := 0; i < len(runes); i++ {
                termbox.SetCell(i, j + 1, runes[i], color['d'], color['d'])
            }
        }
    }
}

func (t *MoviesTab) Query(query string) {
    t.a.d.Movies = append(t.a.d.Movies, Movie{Title: query, State: "Watched"})
    t.a.d.save()
    t.refreshSlice()

    for i := 0; i < len(t.movies); i++ {
        if t.movies[i].Title == query {
            t.cursor = i
            if t.cursor > t.a.height - 4 {
                t.offset = t.cursor - (t.a.height - 4)
            }
            t.a.inputActive = false
            t.autoTag()
        }
    }
}

func (t *MoviesTab) index() int {
    for i := 0; i < len(t.a.d.Movies); i++ {
        if t.a.d.Movies[i].Title == t.movies[t.cursor].Title {
            return i
        }
    }

    return -1
}

func (t *MoviesTab) refreshSlice() {
    t.movies = t.movies[:0]
    for i := 0; i < len(t.a.d.Movies); i++ {
        if t.a.d.Movies[i].State == "Watched" {
            if t.view == "watched" || t.view == "all" {
                t.movies = append(t.movies, t.a.d.Movies[i])
            }
        } else if t.a.d.Movies[i].State == "Unwatched" {
            if t.view == "unwatched" || t.view == "all" {
                t.movies = append(t.movies, t.a.d.Movies[i])
            }
        }
    }
    t.sort()

    if t.cursor > len(t.movies) - 1 {
        t.cursor--
    }

    if t.offset > 0 {
        if len(t.movies) - t.offset < t.a.height - 3 {
            t.offset--
        }
    }

    t.status = "movies - " + t.view + " (" + strconv.Itoa(len(t.movies)) + " entries)"
}

func (t *MoviesTab) sort() {
    var titles []string
    for i := 0; i < len(t.movies); i++ {
        titles = append(titles, t.movies[i].Title)
    }
    sort.Strings(titles)

    var movies []Movie
    for j := 0; j < len(titles); j++ {
        for i := 0; i < len(t.movies); i++ {
            if titles[j] == t.movies[i].Title {
                movies = append(movies, t.movies[i])
            }
        }
    }
    t.movies = movies
}

func (t *MoviesTab) autoTag() {
    title := strings.Replace(t.movies[t.cursor].Title, " ", "+", -1)
    url := "http://www.omdbapi.com/?s=" + title + "&type=movie&y=&plot=full&r=json"
    log.Print(url)

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

    err = json.Unmarshal(body, &t.omdb)
    if err != nil {
        log.Fatal(err)
    } else {
        for i := 0; i < len(t.omdb.Search); i++ {
            log.Print(t.omdb.Search[i].Title + " - " + t.omdb.Search[i].Year)
        }
        log.Print(t.omdb)
    }
}
<commit_msg>Added some colors in the movies tab<commit_after>package main

import (
    "github.com/nsf/termbox-go"
    "encoding/json"
    "net/http"
    "io/ioutil"
    "strconv"
    "strings"
    "log"
    "sort"
)

type Entries struct {
    Title string
    Year string
    ImdbID string
}

type Data struct {
    Search []Entries
}

type MoviesTab struct {
    a *Apollo
    name string
    status string

    movies []Movie
    view string
    sorter string
    offset int
    cursor int
    omdb Data
    ratings bool
}

func CreateMoviesTab(a *Apollo) *MoviesTab {
    t := &MoviesTab{
        a: a,
        name: "movies",
        status: "movies",
        view: "watched",
        sorter: "title",
    }

    t.refreshSlice()

    return t
}

func (t *MoviesTab) Name() string {
    return t.name
}

func (t *MoviesTab) Status() string {
    return t.status
}

func (t *MoviesTab) HandleKeyEvent(ev *termbox.Event) bool {
    if len(t.omdb.Search) > 0 {
        indexes := map[rune]int{'0': 0, '1': 1, '2': 2, '3': 3,
                                '4': 4, '5': 5, '6': 6, '7': 7,
                                '8': 8, '9': 9,}
        if index, exist := indexes[ev.Ch]; exist {
            if index < len(t.omdb.Search) {
                log.Print(t.omdb.Search[index])
                dbIndex := t.index()
                t.a.d.Movies[dbIndex].Year = t.omdb.Search[index].Year
                t.a.d.Movies[dbIndex].Title = t.omdb.Search[index].Title
                t.a.d.Movies[dbIndex].ImdbID = t.omdb.Search[index].ImdbID
            }
        }

        t.omdb.Search = t.omdb.Search[:0]
        t.a.d.save()
        t.refreshSlice()

        return true
    }

    switch ev.Ch {
    case '1':
        t.view = "watched"
        t.cursor = 0
        t.offset = 0
        t.refreshSlice()
    case '2':
        t.view = "unwatched"
        t.cursor = 0
        t.offset = 0
        t.refreshSlice()
    case '3':
        t.view = "all"
        t.cursor = 0
        t.offset = 0
        t.refreshSlice()
    case 's':
        t.cursor = 0
        t.offset = 0
        t.sort()
    case 'D':
        if len(t.movies) > 0 {
            t.a.d.Movies = append(t.a.d.Movies[:t.index()], t.a.d.Movies[t.index()+1:]...)
            t.a.d.save()
            t.refreshSlice()
        }
    case 't':
        t.autoTag()
    case 'r':
        if t.ratings {
            t.ratings = false
        } else {
            t.ratings = true
        }
    case 'q':
        if len(t.movies) > 0 {
            if t.a.d.Movies[t.index()].Rating > 0 {
                t.a.d.Movies[t.index()].Rating--
                t.a.d.save()
                t.refreshSlice()
            }
        }
    case 'e':
        if len(t.movies) > 0 {
            if t.a.d.Movies[t.index()].Rating < 6 {
                t.a.d.Movies[t.index()].Rating++
                t.a.d.save()
                t.refreshSlice()
            }
        }
    }

    switch ev.Key {
    case termbox.KeyArrowUp:
        t.cursor--
        if t.cursor < 0 {
            t.cursor = 0
        } else if t.cursor - t.offset < 0 {
            t.offset--
        }
    case termbox.KeyPgup:
        t.cursor -= 5
        if t.cursor < 0 {
            t.cursor = 0
            t.offset = 0
        } else if t.cursor - t.offset < 0 {
            t.offset -= 5
            if t.offset < 0 {
                t.offset = 0
            }
        }
    case termbox.KeyArrowDown:
        t.cursor++
        if t.cursor > len(t.movies) - 1 {
            t.cursor--
        } else if t.cursor - t.offset > t.a.height - 4 {
            t.offset++
        }
    case termbox.KeyPgdn:
        t.cursor += 5
        if t.cursor > len(t.movies) - 1 {
            t.cursor = len(t.movies) - 1
            if len(t.movies) > t.a.height - 3 {
                t.offset = len(t.movies) - (t.a.height - 3)
            }
        } else if t.cursor - t.offset > t.a.height - 4 {
            t.offset += 5
            if t.cursor - t.offset < t.a.height - 3 {
                t.offset = t.cursor - (t.a.height - 4)
            }
        }
    default:
        return false
    }

    log.Print("cursor: " + strconv.Itoa(t.cursor) + " offset: " + strconv.Itoa(t.offset) +
    " len:" + strconv.Itoa(len(t.movies)) + " height:" + strconv.Itoa(t.a.height))

    return true
}

func (t *MoviesTab) Draw() {
    if len(t.omdb.Search) == 0 {
        for j := 0; j < t.a.height - 3; j++ {
            if j < len(t.movies) {
                if t.ratings {
                    for i := 0; i < t.movies[j + t.offset].Rating; i++ {
                        if t.movies[j + t.offset].State == "Watched" {
                            termbox.SetCell(i + 3, j + 1, '*', color['y'], color['d'])
                        } else {
                            termbox.SetCell(i + 3, j + 1, '*', color['b'], color['d'])
                        }
                    }
                }

                runes := []rune(t.movies[j + t.offset].Year + " " + t.movies[j + t.offset].Title)
                for i := 0; i < len(runes); i++ {
                    fg := color['d']
                    if i < 4 {
                        fg = color['c']
                    }

                    if t.ratings {
                        termbox.SetCell(i + 10, j + 1, runes[i], fg, color['d'])
                    } else {
                        termbox.SetCell(i + 3, j + 1, runes[i], fg, color['d'])
                    }
                }
            }
        }

        termbox.SetCell(1, t.cursor - t.offset + 1, '*', color['d'], color['d'])
    } else {
        for j := 0; j < len(t.omdb.Search); j++ {
            runes := []rune(strconv.Itoa(j) + ". [" + t.omdb.Search[j].Year + "] " + t.omdb.Search[j].Title)
            for i := 0; i < len(runes); i++ {
                termbox.SetCell(i, j + 1, runes[i], color['d'], color['d'])
            }
        }
    }
}

func (t *MoviesTab) Query(query string) {
    t.a.d.Movies = append(t.a.d.Movies, Movie{Title: query, State: "Watched"})
    t.a.d.save()
    t.refreshSlice()

    for i := 0; i < len(t.movies); i++ {
        if t.movies[i].Title == query {
            t.cursor = i
            if t.cursor > t.a.height - 4 {
                t.offset = t.cursor - (t.a.height - 4)
            }
            t.a.inputActive = false
            t.autoTag()
        }
    }
}

func (t *MoviesTab) index() int {
    for i := 0; i < len(t.a.d.Movies); i++ {
        if t.a.d.Movies[i].Title == t.movies[t.cursor].Title {
            return i
        }
    }

    return -1
}

func (t *MoviesTab) refreshSlice() {
    t.movies = t.movies[:0]
    for i := 0; i < len(t.a.d.Movies); i++ {
        if t.a.d.Movies[i].State == "Watched" {
            if t.view == "watched" || t.view == "all" {
                t.movies = append(t.movies, t.a.d.Movies[i])
            }
        } else if t.a.d.Movies[i].State == "Unwatched" {
            if t.view == "unwatched" || t.view == "all" {
                t.movies = append(t.movies, t.a.d.Movies[i])
            }
        }
    }
    t.sort()

    if t.cursor > len(t.movies) - 1 {
        t.cursor--
    }

    if t.offset > 0 {
        if len(t.movies) - t.offset < t.a.height - 3 {
            t.offset--
        }
    }

    t.status = "movies - " + t.view + " (" + strconv.Itoa(len(t.movies)) + " entries)"
}

func (t *MoviesTab) sort() {
    var titles []string
    for i := 0; i < len(t.movies); i++ {
        titles = append(titles, t.movies[i].Title)
    }
    sort.Strings(titles)

    var movies []Movie
    for j := 0; j < len(titles); j++ {
        for i := 0; i < len(t.movies); i++ {
            if titles[j] == t.movies[i].Title {
                movies = append(movies, t.movies[i])
            }
        }
    }
    t.movies = movies
}

func (t *MoviesTab) autoTag() {
    title := strings.Replace(t.movies[t.cursor].Title, " ", "+", -1)
    url := "http://www.omdbapi.com/?s=" + title + "&type=movie&y=&plot=full&r=json"
    log.Print(url)

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

    err = json.Unmarshal(body, &t.omdb)
    if err != nil {
        log.Fatal(err)
    } else {
        for i := 0; i < len(t.omdb.Search); i++ {
            log.Print(t.omdb.Search[i].Title + " - " + t.omdb.Search[i].Year)
        }
        log.Print(t.omdb)
    }
}
<|endoftext|>


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

package aggregate_test

import (
	"testing"

	"istio.io/istio/pilot/pkg/config/aggregate"
	"istio.io/istio/pilot/pkg/config/memory"
	"istio.io/istio/pilot/pkg/model"
	"istio.io/istio/pilot/test/mock"
)

const (
	// TestNamespace for testing
	TestNamespace = "test"
)

func TestStoreInvariant(t *testing.T) {
	store, _ := makeCache(t)
	mock.CheckMapInvariant(store, t, "", 10)
}

func TestStoreValidation(t *testing.T) {
	mockStore := memory.Make(mock.Types)
	if _, err := aggregate.Make([]model.ConfigStore{mockStore, mockStore}); err == nil {
		t.Error("expected error in duplicate types in the config store")
	}
}

func makeCache(t *testing.T) (model.ConfigStore, model.ConfigStoreCache) {
	mockStore := memory.Make(mock.Types)
	mockStoreCache := memory.NewController(mockStore)
	istioStore := memory.Make(model.IstioConfigTypes)
	istioStoreCache := memory.NewController(istioStore)

	store, err := aggregate.Make([]model.ConfigStore{mockStore, istioStore})
	if err != nil {
		t.Fatalf("unexpected error %v", err)
	}
	ctl, err := aggregate.MakeCache([]model.ConfigStoreCache{mockStoreCache, istioStoreCache})
	if err != nil {
		t.Fatalf("unexpected error %v", err)
	}
	return store, ctl
}

// TODO: fix race conditions and re-enable tests.
//func TestControllerEvents(t *testing.T) {
//	_, ctl := makeCache(t)
//	mock.CheckCacheEvents(ctl, ctl, TestNamespace, 5, t)
//}
//
//func TestControllerCacheFreshness(t *testing.T) {
//	_, ctl := makeCache(t)
//	mock.CheckCacheFreshness(ctl, TestNamespace, t)
//}
//
// func TestControllerClientSync(t *testing.T) {
// 	store, ctl := makeCache(t)
// 	mock.CheckCacheSync(store, ctl, TestNamespace, 5, t)
// }
<commit_msg>reenable aggregate TestControllerClientSync (#4151)<commit_after>// Copyright 2017 Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package aggregate_test

import (
	"testing"

	"istio.io/istio/pilot/pkg/config/aggregate"
	"istio.io/istio/pilot/pkg/config/memory"
	"istio.io/istio/pilot/pkg/model"
	"istio.io/istio/pilot/test/mock"
)

const (
	// TestNamespace for testing
	TestNamespace = "test"
)

func TestStoreInvariant(t *testing.T) {
	store, _ := makeCache(t)
	mock.CheckMapInvariant(store, t, "", 10)
}

func TestStoreValidation(t *testing.T) {
	mockStore := memory.Make(mock.Types)
	if _, err := aggregate.Make([]model.ConfigStore{mockStore, mockStore}); err == nil {
		t.Error("expected error in duplicate types in the config store")
	}
}

func makeCache(t *testing.T) (model.ConfigStore, model.ConfigStoreCache) {
	mockStore := memory.Make(mock.Types)
	mockStoreCache := memory.NewController(mockStore)
	istioStore := memory.Make(model.IstioConfigTypes)
	istioStoreCache := memory.NewController(istioStore)

	store, err := aggregate.Make([]model.ConfigStore{mockStore, istioStore})
	if err != nil {
		t.Fatalf("unexpected error %v", err)
	}
	ctl, err := aggregate.MakeCache([]model.ConfigStoreCache{mockStoreCache, istioStoreCache})
	if err != nil {
		t.Fatalf("unexpected error %v", err)
	}
	return store, ctl
}

// TODO: fix race conditions and re-enable tests.
//func TestControllerEvents(t *testing.T) {
//	_, ctl := makeCache(t)
//	mock.CheckCacheEvents(ctl, ctl, TestNamespace, 5, t)
//}
//
//func TestControllerCacheFreshness(t *testing.T) {
//	_, ctl := makeCache(t)
//	mock.CheckCacheFreshness(ctl, TestNamespace, t)
//}
//
func TestControllerClientSync(t *testing.T) {
	store, ctl := makeCache(t)
	mock.CheckCacheSync(store, ctl, TestNamespace, 5, t)
}
<|endoftext|>


<commit_before>/***
Copyright 2019 Cisco Systems 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 watchers

import (
	log "github.com/sirupsen/logrus"
	restclient "k8s.io/client-go/rest"

	"context"
	aciv1 "github.com/noironetworks/aci-containers/pkg/gbpcrd/apis/acipolicy/v1"
	aciclientset "github.com/noironetworks/aci-containers/pkg/gbpcrd/clientset/versioned"
	aciclientsetv1 "github.com/noironetworks/aci-containers/pkg/gbpcrd/clientset/versioned/typed/acipolicy/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
	stateObject  = "gbp-server"
	inboxSize    = 32
	FieldClassID = iota
	FieldTunnelID
)

// K8sStateDriver implements gbpserver.StateDriver
type K8sStateDriver struct {
	gsi    aciclientsetv1.GBPSStateInterface
	inbox  chan *aciv1.GBPSState
	curr   *aciv1.GBPSState
	copier func(s, d *aciv1.GBPSState)
}

func (ks *K8sStateDriver) Init(wrField int) error {
	cfg, err := restclient.InClusterConfig()
	if err != nil {
		return err
	}

	aciClient, err := aciclientset.NewForConfig(cfg)
	if err != nil {
		return err
	}
	ks.gsi = aciClient.AciV1().GBPSStates(sysNs)
	// if the state object doesn't exist, create it now
	s, err := ks.gsi.Get(context.TODO(), stateObject, metav1.GetOptions{})
	if err != nil || s == nil {
		log.Infof("%s object not found, creating", stateObject)
		s = &aciv1.GBPSState{}
		s.Kind = "GBPSState"
		s.APIVersion = "aci.aw/v1"
		s.ObjectMeta.Name = stateObject
		s, err = ks.gsi.Create(context.TODO(), s, metav1.CreateOptions{})
		if err != nil {
			log.Errorf("Failed to create %s CRD - %v", stateObject, err)
			return err
		}
	}

	ks.inbox = make(chan *aciv1.GBPSState, inboxSize)
	ks.curr = s
	switch wrField {
	case FieldClassID:
		ks.copier = copyClassID
	case FieldTunnelID:
		ks.copier = copyTunnelID
	}

	go ks.run()

	return nil
}

func copyClassID(src, dest *aciv1.GBPSState) {
	dest.Kind = "GBPSState"
	dest.APIVersion = "aci.aw/v1"
	dest.Status.ClassIDs = src.Status.ClassIDs
}

func copyTunnelID(src, dest *aciv1.GBPSState) {
	dest.Kind = "GBPSState"
	dest.APIVersion = "aci.aw/v1"
	dest.Status.TunnelIDs = src.Status.TunnelIDs
}

func (ks *K8sStateDriver) Get() (*aciv1.GBPSState, error) {
	s, err := ks.gsi.Get(context.TODO(), stateObject, metav1.GetOptions{})
	if err == nil {
		ks.curr = s
	} else {
		log.Errorf("Failed to get %s CRD - %v", stateObject, err)
	}

	return s, err
}

func (ks *K8sStateDriver) Update(s *aciv1.GBPSState) error {
	ks.inbox <- s
	return nil
}

func (ks *K8sStateDriver) run() {
	for {
		// wait for an incoming request
		s := <-ks.inbox

		// pick up latest update
	latest:
		for {
			select {
			case s = <-ks.inbox:
			default:
				break latest
			}
		}

		c := *ks.curr
		ks.copier(s, &c)

		newS, err := ks.gsi.UpdateStatus(context.TODO(), &c, metav1.UpdateOptions{})
		if err == nil {
			ks.curr = newS
		} else {
			log.Warnf("State driver Update failed(will retry): %v, %+v", err, c)
			ks.Get() // refresh current
			goto latest
		}
	}
}
<commit_msg>Commit missing change<commit_after>/***
Copyright 2019 Cisco Systems 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 watchers

import (
	log "github.com/sirupsen/logrus"
	restclient "k8s.io/client-go/rest"

	"context"
	aciv1 "github.com/noironetworks/aci-containers/pkg/gbpcrd/apis/acipolicy/v1"
	aciclientset "github.com/noironetworks/aci-containers/pkg/gbpcrd/clientset/versioned"
	aciclientsetv1 "github.com/noironetworks/aci-containers/pkg/gbpcrd/clientset/versioned/typed/acipolicy/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
	stateObject  = "gbp-server"
	inboxSize    = 32
	FieldClassID = iota
	FieldTunnelID
)

// K8sStateDriver implements gbpserver.StateDriver
type K8sStateDriver struct {
	gsi    aciclientsetv1.GBPSStateInterface
	inbox  chan *aciv1.GBPSState
	curr   *aciv1.GBPSState
	copier func(s, d *aciv1.GBPSState)
}

func (ks *K8sStateDriver) StateExists() (bool, error) {
	cfg, err := restclient.InClusterConfig()
	if err != nil {
		return false, err
	}
	aciClient, err := aciclientset.NewForConfig(cfg)
	if err != nil {
		return false, err
	}
	ks.gsi = aciClient.AciV1().GBPSStates(sysNs)
	s, err := ks.gsi.Get(context.TODO(), stateObject, metav1.GetOptions{})
	if err != nil || s == nil {
		// no state
		return false, nil
	}

	return true, nil
}

func (ks *K8sStateDriver) Init(wrField int) error {
	cfg, err := restclient.InClusterConfig()
	if err != nil {
		return err
	}

	aciClient, err := aciclientset.NewForConfig(cfg)
	if err != nil {
		return err
	}
	ks.gsi = aciClient.AciV1().GBPSStates(sysNs)
	// if the state object doesn't exist, create it now
	s, err := ks.gsi.Get(context.TODO(), stateObject, metav1.GetOptions{})
	if err != nil || s == nil {
		log.Infof("%s object not found, creating", stateObject)
		s = &aciv1.GBPSState{}
		s.Kind = "GBPSState"
		s.APIVersion = "aci.aw/v1"
		s.ObjectMeta.Name = stateObject
		s, err = ks.gsi.Create(context.TODO(), s, metav1.CreateOptions{})
		if err != nil {
			log.Errorf("Failed to create %s CRD - %v", stateObject, err)
			return err
		}
	}

	ks.inbox = make(chan *aciv1.GBPSState, inboxSize)
	ks.curr = s
	switch wrField {
	case FieldClassID:
		ks.copier = copyClassID
	case FieldTunnelID:
		ks.copier = copyTunnelID
	}

	go ks.run()

	return nil
}

func copyClassID(src, dest *aciv1.GBPSState) {
	dest.Kind = "GBPSState"
	dest.APIVersion = "aci.aw/v1"
	dest.Status.ClassIDs = src.Status.ClassIDs
}

func copyTunnelID(src, dest *aciv1.GBPSState) {
	dest.Kind = "GBPSState"
	dest.APIVersion = "aci.aw/v1"
	dest.Status.TunnelIDs = src.Status.TunnelIDs
}

func (ks *K8sStateDriver) Get() (*aciv1.GBPSState, error) {
	s, err := ks.gsi.Get(context.TODO(), stateObject, metav1.GetOptions{})
	if err == nil {
		ks.curr = s
	} else {
		log.Errorf("Failed to get %s CRD - %v", stateObject, err)
	}

	return s, err
}

func (ks *K8sStateDriver) Update(s *aciv1.GBPSState) error {
	ks.inbox <- s
	return nil
}

func (ks *K8sStateDriver) run() {
	for {
		// wait for an incoming request
		s := <-ks.inbox

		// pick up latest update
	latest:
		for {
			select {
			case s = <-ks.inbox:
			default:
				break latest
			}
		}

		c := *ks.curr
		ks.copier(s, &c)

		newS, err := ks.gsi.UpdateStatus(context.TODO(), &c, metav1.UpdateOptions{})
		if err == nil {
			ks.curr = newS
		} else {
			log.Warnf("State driver Update failed(will retry): %v, %+v", err, c)
			ks.Get() // refresh current
			goto latest
		}
	}
}
<|endoftext|>


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

package main

import (
	"bytes"
	"fmt"
	"net"
	"net/http"
	"os"
	"sync"
	"time"

	"golang.org/x/net/icmp"
	"golang.org/x/net/ipv4"
	"golang.org/x/net/ipv6"

	"github.com/prometheus/common/log"
)

var (
	icmpSequence      uint16
	icmpSequenceMutex sync.Mutex
)

func getICMPSequence() uint16 {
	icmpSequenceMutex.Lock()
	defer icmpSequenceMutex.Unlock()
	icmpSequence++
	return icmpSequence
}

func probeICMP(target string, w http.ResponseWriter, module Module) (success bool) {
	var (
		socket           *icmp.PacketConn
		requestType      icmp.Type
		replyType        icmp.Type
		fallbackProtocol string
	)

	deadline := time.Now().Add(module.Timeout)

	// Defaults to IPv4 to be compatible with older versions
	if module.ICMP.Protocol == "" {
		module.ICMP.Protocol = "icmp"
	}

	// In case of ICMP prefer IPv6 by default
	if module.ICMP.Protocol == "icmp" && module.ICMP.PreferredIpProtocol == "" {
		module.ICMP.PreferredIpProtocol = "ip6"
	}

	if module.ICMP.Protocol == "icmp4" {
		module.ICMP.PreferredIpProtocol = "ip4"
		fallbackProtocol = ""
	} else if module.ICMP.Protocol == "icmp6" {
		module.ICMP.PreferredIpProtocol = "ip6"
		fallbackProtocol = ""
	} else if module.ICMP.PreferredIpProtocol == "ip6" {
		fallbackProtocol = "ip4"
	} else {
		fallbackProtocol = "ip6"
	}

	ip, err := net.ResolveIPAddr(module.ICMP.PreferredIpProtocol, target)
	if err != nil && fallbackProtocol != "" {
		ip, err = net.ResolveIPAddr(fallbackProtocol, target)
	}
	if err != nil {
		log.Errorf("Error resolving address %s: %s", target, err)
	}

	if ip.IP.To4() == nil {
		requestType = ipv6.ICMPTypeEchoRequest
		replyType = ipv6.ICMPTypeEchoReply
		socket, err = icmp.ListenPacket("ip6:ipv6-icmp", "::")
		fmt.Fprintf(w, "probe_ip_protocol 6\n")
	} else {
		requestType = ipv4.ICMPTypeEcho
		replyType = ipv4.ICMPTypeEchoReply
		socket, err = icmp.ListenPacket("ip4:icmp", "0.0.0.0")
		fmt.Fprintf(w, "probe_ip_protocol 4\n")
	}

	if err != nil {
		log.Errorf("Error listening to socket: %s", err)
		return
	}
	defer socket.Close()

	if err != nil {
		log.Errorf("Error resolving address %s: %s", target, err)
		return
	}

	seq := getICMPSequence()
	pid := os.Getpid() & 0xffff

	wm := icmp.Message{
		Type: requestType,
		Code: 0,
		Body: &icmp.Echo{
			ID: pid, Seq: int(seq),
			Data: []byte("Prometheus Blackbox Exporter"),
		},
	}

	wb, err := wm.Marshal(nil)
	if err != nil {
		log.Errorf("Error marshalling packet for %s: %s", target, err)
		return
	}
	if _, err := socket.WriteTo(wb, ip); err != nil {
		log.Errorf("Error writing to socker for %s: %s", target, err)
		return
	}

	// Reply should be the same except for the message type.
	wm.Type = replyType
	wb, err = wm.Marshal(nil)
	if err != nil {
		log.Errorf("Error marshalling packet for %s: %s", target, err)
		return
	}

	rb := make([]byte, 1500)
	if err := socket.SetReadDeadline(deadline); err != nil {
		log.Errorf("Error setting socket deadline for %s: %s", target, err)
		return
	}
	for {
		n, peer, err := socket.ReadFrom(rb)
		if err != nil {
			if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
				log.Infof("Timeout reading from socket for %s: %s", target, err)
				return
			}
			log.Errorf("Error reading from socket for %s: %s", target, err)
			continue
		}
		if peer.String() != ip.String() {
			continue
		}
		if replyType == ipv6.ICMPTypeEchoReply {
			// Clear checksum to make comparison succeed.
			rb[2] = 0
			rb[3] = 0
		}
		if bytes.Compare(rb[:n], wb) == 0 {
			success = true
			return
		}
	}
}
<commit_msg>Fix 'socker' typo (#104)<commit_after>// Copyright 2016 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"bytes"
	"fmt"
	"net"
	"net/http"
	"os"
	"sync"
	"time"

	"golang.org/x/net/icmp"
	"golang.org/x/net/ipv4"
	"golang.org/x/net/ipv6"

	"github.com/prometheus/common/log"
)

var (
	icmpSequence      uint16
	icmpSequenceMutex sync.Mutex
)

func getICMPSequence() uint16 {
	icmpSequenceMutex.Lock()
	defer icmpSequenceMutex.Unlock()
	icmpSequence++
	return icmpSequence
}

func probeICMP(target string, w http.ResponseWriter, module Module) (success bool) {
	var (
		socket           *icmp.PacketConn
		requestType      icmp.Type
		replyType        icmp.Type
		fallbackProtocol string
	)

	deadline := time.Now().Add(module.Timeout)

	// Defaults to IPv4 to be compatible with older versions
	if module.ICMP.Protocol == "" {
		module.ICMP.Protocol = "icmp"
	}

	// In case of ICMP prefer IPv6 by default
	if module.ICMP.Protocol == "icmp" && module.ICMP.PreferredIpProtocol == "" {
		module.ICMP.PreferredIpProtocol = "ip6"
	}

	if module.ICMP.Protocol == "icmp4" {
		module.ICMP.PreferredIpProtocol = "ip4"
		fallbackProtocol = ""
	} else if module.ICMP.Protocol == "icmp6" {
		module.ICMP.PreferredIpProtocol = "ip6"
		fallbackProtocol = ""
	} else if module.ICMP.PreferredIpProtocol == "ip6" {
		fallbackProtocol = "ip4"
	} else {
		fallbackProtocol = "ip6"
	}

	ip, err := net.ResolveIPAddr(module.ICMP.PreferredIpProtocol, target)
	if err != nil && fallbackProtocol != "" {
		ip, err = net.ResolveIPAddr(fallbackProtocol, target)
	}
	if err != nil {
		log.Errorf("Error resolving address %s: %s", target, err)
	}

	if ip.IP.To4() == nil {
		requestType = ipv6.ICMPTypeEchoRequest
		replyType = ipv6.ICMPTypeEchoReply
		socket, err = icmp.ListenPacket("ip6:ipv6-icmp", "::")
		fmt.Fprintf(w, "probe_ip_protocol 6\n")
	} else {
		requestType = ipv4.ICMPTypeEcho
		replyType = ipv4.ICMPTypeEchoReply
		socket, err = icmp.ListenPacket("ip4:icmp", "0.0.0.0")
		fmt.Fprintf(w, "probe_ip_protocol 4\n")
	}

	if err != nil {
		log.Errorf("Error listening to socket: %s", err)
		return
	}
	defer socket.Close()

	if err != nil {
		log.Errorf("Error resolving address %s: %s", target, err)
		return
	}

	seq := getICMPSequence()
	pid := os.Getpid() & 0xffff

	wm := icmp.Message{
		Type: requestType,
		Code: 0,
		Body: &icmp.Echo{
			ID: pid, Seq: int(seq),
			Data: []byte("Prometheus Blackbox Exporter"),
		},
	}

	wb, err := wm.Marshal(nil)
	if err != nil {
		log.Errorf("Error marshalling packet for %s: %s", target, err)
		return
	}
	if _, err := socket.WriteTo(wb, ip); err != nil {
		log.Errorf("Error writing to socket for %s: %s", target, err)
		return
	}

	// Reply should be the same except for the message type.
	wm.Type = replyType
	wb, err = wm.Marshal(nil)
	if err != nil {
		log.Errorf("Error marshalling packet for %s: %s", target, err)
		return
	}

	rb := make([]byte, 1500)
	if err := socket.SetReadDeadline(deadline); err != nil {
		log.Errorf("Error setting socket deadline for %s: %s", target, err)
		return
	}
	for {
		n, peer, err := socket.ReadFrom(rb)
		if err != nil {
			if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
				log.Infof("Timeout reading from socket for %s: %s", target, err)
				return
			}
			log.Errorf("Error reading from socket for %s: %s", target, err)
			continue
		}
		if peer.String() != ip.String() {
			continue
		}
		if replyType == ipv6.ICMPTypeEchoReply {
			// Clear checksum to make comparison succeed.
			rb[2] = 0
			rb[3] = 0
		}
		if bytes.Compare(rb[:n], wb) == 0 {
			success = true
			return
		}
	}
}
<|endoftext|>


<commit_before>package nuance

/*
#cgo CPPFLAGS: -I /usr/local/include/nuance-omnipage-csdk-19.2
#cgo LDFLAGS: -L /usr/local/lib/nuance-omnipage-csdk-lib64-19.2 -lrecapiplus -lkernelapi -lrecpdf -Wl,-rpath-link,/usr/local/lib/nuance-omnipage-csdk-lib64-19.2,-rpath,/usr/local/lib/nuance-omnipage-csdk-lib64-19.2

#include <KernelApi.h>

#include "nuancec.h"
*/
import "C"

import (
	"errors"
	"fmt"
	"unsafe"
	"math/rand"
	"time"
	"path"
	"os"
	"io/ioutil"
)

type nuance struct {
	nuancePtr C.nuancePtr
}

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func init(){
	rand.Seed(time.Now().UnixNano())
}

func New() (n nuance) {
	n.nuancePtr = C.nuanceNew()
	return
}

func (n *nuance) Free() {
	C.nuanceFree(unsafe.Pointer(n.nuancePtr))
}

func (n *nuance) Init(company string, product string) (err error) {
	errBuff := make([]byte, 1024)
	if C.nuanceInit(
		unsafe.Pointer(n.nuancePtr),
		C.CString(company),
		C.CString(product),
		(*C.char)(unsafe.Pointer(&errBuff[0])),
		C.int(len(errBuff))) != 0 {

		err = errors.New(string(errBuff))
		return
	}

	err = nil
	return
}

func (n *nuance) SetLicense(licenseFile string, oemCode string) (err error) {
	errBuff := make([]byte, 1024)

	if C.nuanceSetLicense(
		unsafe.Pointer(n.nuancePtr),
		C.CString(licenseFile),
		C.CString(oemCode),
		(*C.char)(unsafe.Pointer(&errBuff[0])),
		C.int(len(errBuff))) != 0 {

		err = errors.New(string(errBuff))
		return
	}

	err = nil
	return
}

func (n *nuance) Quit() {
	C.nuanceQuit(unsafe.Pointer(n.nuancePtr))
}

func (n *nuance) LoadFormTemplateLibrary(templateFile string) (err error) {
	errBuff := make([]byte, 1024)
	if C.nuanceLoadFormTemplateLibrary(
		unsafe.Pointer(n.nuancePtr),
		C.CString(templateFile),
		(*C.char)(unsafe.Pointer(&errBuff[0])),
		C.int(len(errBuff))) != 0 {

		err = errors.New(string(errBuff))
		return
	}

	err = nil
	return
}

func (n *nuance) OCRImgWithTemplate(imgFile string) (ret map[string]string, err error) {
	errBuff := make([]byte, 1024)
	ret = make(map[string]string)

	if C.nuancePreprocessImgWithTemplate(
		unsafe.Pointer(n.nuancePtr),
		C.CString(imgFile),
		(*C.char)(unsafe.Pointer(&errBuff[0])),
		C.int(len(errBuff))) != 0 {

		err = errors.New(string(errBuff))
		return
	}

	zoneCount := int(C.nuanceGetZoneCount(unsafe.Pointer(n.nuancePtr)))

	fmt.Println("zoneCount:", zoneCount)

	for i := 0; i < zoneCount; i++ {
		zoneName := make([]byte, 256)
		zoneText := make([]byte, 256)

		C.nuanceGetZoneData(
			unsafe.Pointer(n.nuancePtr),
			C.int(i),
			(*C.char)(unsafe.Pointer(&zoneName[0])),
			C.int(256),
			(*C.char)(unsafe.Pointer(&zoneText[0])),
			C.int(256))

		ret[string(zoneName)] = string(zoneText)
		//fmt.Printf("%s: [%s]\n", string(zoneName), string(zoneText))
	}

	C.nuanceFreeImgWithTemplate(unsafe.Pointer(n.nuancePtr))
	err = nil
	return
}

func (n *nuance) OCRImgToFile(imgFile string,
	outputFile string,
	nPage int,
	auxDocumentFile string) (err error) {
	errBuff := make([]byte, 1024)

	if C.nuanceOCRImgToFile(
		unsafe.Pointer(n.nuancePtr),
		C.CString(imgFile),
		C.CString(outputFile),
		C.int(nPage),
		C.CString(auxDocumentFile),
		(*C.char)(unsafe.Pointer(&errBuff[0])),
		C.int(len(errBuff))) != 0 {

		err = errors.New(string(errBuff))
		return
	}

	err = nil
	return
}

func randString(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

func (n *nuance) OCRImgPageToText(imgFile string,
	nPage int,
	) (txt string,err error) {
	randomAux := randString(6)
	tempDir := path.Join(os.TempDir(),randomAux)
	tempFile := fmt.Sprintf("%s.txt", tempDir)
	defer func() {
		os.Remove(tempFile)
		os.RemoveAll(tempDir)
	}()
	err = n.OCRImgToFile(imgFile, tempFile, nPage, tempDir)
	if err != nil{
		fmt.Println(err)
		return "", err
	}
	rawTxt, err := ioutil.ReadFile(tempFile)
	if err != nil {
		fmt.Println(err)
		return "", err
	}
	txt = string(rawTxt)
	return
}

func (n *nuance) OCRImgToText(imgFile string) (txt string, err error){
	pages, err := n.CountPages(imgFile)
	if err != nil {
		return
	}
	for i:=0;i < pages;i++{
		aux, err := n.OCRImgPageToText(imgFile, i)
		if err != nil{
			return
		}
		if len(txt) > 0{
			txt += "\f"
		}
		txt += aux
	}
	return
}

func (n *nuance) SetLanguagePtBr() (err error) {
	errBuff := make([]byte, 1024)

	if C.nuanceSetLanguagePtBr(
		unsafe.Pointer(n.nuancePtr),
		(*C.char)(unsafe.Pointer(&errBuff[0])),
		C.int(len(errBuff))) != 0 {

		err = errors.New(string(errBuff))
		return
	}

	err = nil
	return
}

func (n *nuance) CountPages(imgFile string) (nPage int, err error) {
	errBuff := make([]byte, 1024)
	nPage = 0

	if C.nuanceCountPages(
		unsafe.Pointer(n.nuancePtr),
		C.CString(imgFile),
		(*C.int)(unsafe.Pointer(&nPage)),
		(*C.char)(unsafe.Pointer(&errBuff[0])),
		C.int(len(errBuff))) != 0 {

		err = errors.New(string(errBuff))
		return
	}

	err = nil
	return
}
<commit_msg>correcting shaded variables<commit_after>package nuance

/*
#cgo CPPFLAGS: -I /usr/local/include/nuance-omnipage-csdk-19.2
#cgo LDFLAGS: -L /usr/local/lib/nuance-omnipage-csdk-lib64-19.2 -lrecapiplus -lkernelapi -lrecpdf -Wl,-rpath-link,/usr/local/lib/nuance-omnipage-csdk-lib64-19.2,-rpath,/usr/local/lib/nuance-omnipage-csdk-lib64-19.2

#include <KernelApi.h>

#include "nuancec.h"
*/
import "C"

import (
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"os"
	"path"
	"time"
	"unsafe"
)

type nuance struct {
	nuancePtr C.nuancePtr
}

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func init() {
	rand.Seed(time.Now().UnixNano())
}

func New() (n nuance) {
	n.nuancePtr = C.nuanceNew()
	return
}

func (n *nuance) Free() {
	C.nuanceFree(unsafe.Pointer(n.nuancePtr))
}

func (n *nuance) Init(company string, product string) (err error) {
	errBuff := make([]byte, 1024)
	if C.nuanceInit(
		unsafe.Pointer(n.nuancePtr),
		C.CString(company),
		C.CString(product),
		(*C.char)(unsafe.Pointer(&errBuff[0])),
		C.int(len(errBuff))) != 0 {

		err = errors.New(string(errBuff))
		return
	}

	err = nil
	return
}

func (n *nuance) SetLicense(licenseFile string, oemCode string) (err error) {
	errBuff := make([]byte, 1024)

	if C.nuanceSetLicense(
		unsafe.Pointer(n.nuancePtr),
		C.CString(licenseFile),
		C.CString(oemCode),
		(*C.char)(unsafe.Pointer(&errBuff[0])),
		C.int(len(errBuff))) != 0 {

		err = errors.New(string(errBuff))
		return
	}

	err = nil
	return
}

func (n *nuance) Quit() {
	C.nuanceQuit(unsafe.Pointer(n.nuancePtr))
}

func (n *nuance) LoadFormTemplateLibrary(templateFile string) (err error) {
	errBuff := make([]byte, 1024)
	if C.nuanceLoadFormTemplateLibrary(
		unsafe.Pointer(n.nuancePtr),
		C.CString(templateFile),
		(*C.char)(unsafe.Pointer(&errBuff[0])),
		C.int(len(errBuff))) != 0 {

		err = errors.New(string(errBuff))
		return
	}

	err = nil
	return
}

func (n *nuance) OCRImgWithTemplate(imgFile string) (ret map[string]string, err error) {
	errBuff := make([]byte, 1024)
	ret = make(map[string]string)

	if C.nuancePreprocessImgWithTemplate(
		unsafe.Pointer(n.nuancePtr),
		C.CString(imgFile),
		(*C.char)(unsafe.Pointer(&errBuff[0])),
		C.int(len(errBuff))) != 0 {

		err = errors.New(string(errBuff))
		return
	}

	zoneCount := int(C.nuanceGetZoneCount(unsafe.Pointer(n.nuancePtr)))

	fmt.Println("zoneCount:", zoneCount)

	for i := 0; i < zoneCount; i++ {
		zoneName := make([]byte, 256)
		zoneText := make([]byte, 256)

		C.nuanceGetZoneData(
			unsafe.Pointer(n.nuancePtr),
			C.int(i),
			(*C.char)(unsafe.Pointer(&zoneName[0])),
			C.int(256),
			(*C.char)(unsafe.Pointer(&zoneText[0])),
			C.int(256))

		ret[string(zoneName)] = string(zoneText)
		//fmt.Printf("%s: [%s]\n", string(zoneName), string(zoneText))
	}

	C.nuanceFreeImgWithTemplate(unsafe.Pointer(n.nuancePtr))
	err = nil
	return
}

func (n *nuance) OCRImgToFile(imgFile string,
	outputFile string,
	nPage int,
	auxDocumentFile string) (err error) {
	errBuff := make([]byte, 1024)

	if C.nuanceOCRImgToFile(
		unsafe.Pointer(n.nuancePtr),
		C.CString(imgFile),
		C.CString(outputFile),
		C.int(nPage),
		C.CString(auxDocumentFile),
		(*C.char)(unsafe.Pointer(&errBuff[0])),
		C.int(len(errBuff))) != 0 {

		err = errors.New(string(errBuff))
		return
	}

	err = nil
	return
}

func randString(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

func (n *nuance) OCRImgPageToText(imgFile string,
	nPage int,
) (txt string, err error) {
	randomAux := randString(6)
	tempDir := path.Join(os.TempDir(), randomAux)
	tempFile := fmt.Sprintf("%s.txt", tempDir)
	defer func() {
		os.Remove(tempFile)
		os.RemoveAll(tempDir)
	}()
	err = n.OCRImgToFile(imgFile, tempFile, nPage, tempDir)
	if err != nil {
		fmt.Println(err)
		return "", err
	}
	rawTxt, err := ioutil.ReadFile(tempFile)
	if err != nil {
		fmt.Println(err)
		return "", err
	}
	txt = string(rawTxt)
	return
}

func (n *nuance) OCRImgToText(imgFile string) (txt string, err error) {
	var pages int
	pages, err = n.CountPages(imgFile)
	if err != nil {
		return
	}
	var aux string
	for i := 0; i < pages; i++ {
		aux, err = n.OCRImgPageToText(imgFile, i)
		if err != nil {
			return
		}
		if len(txt) > 0 {
			txt += "\f"
		}
		txt += aux
	}
	return
}

func (n *nuance) SetLanguagePtBr() (err error) {
	errBuff := make([]byte, 1024)

	if C.nuanceSetLanguagePtBr(
		unsafe.Pointer(n.nuancePtr),
		(*C.char)(unsafe.Pointer(&errBuff[0])),
		C.int(len(errBuff))) != 0 {

		err = errors.New(string(errBuff))
		return
	}

	err = nil
	return
}

func (n *nuance) CountPages(imgFile string) (nPage int, err error) {
	errBuff := make([]byte, 1024)
	nPage = 0

	if C.nuanceCountPages(
		unsafe.Pointer(n.nuancePtr),
		C.CString(imgFile),
		(*C.int)(unsafe.Pointer(&nPage)),
		(*C.char)(unsafe.Pointer(&errBuff[0])),
		C.int(len(errBuff))) != 0 {

		err = errors.New(string(errBuff))
		return
	}

	err = nil
	return
}
<|endoftext|>


<commit_before>/*
Copyright 2017 WALLIX

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 config

import (
	"fmt"
	"os"
	"path/filepath"

	"strconv"

	"github.com/wallix/awless/aws/services"
	"github.com/wallix/awless/database"
)

var (
	AwlessHome         = filepath.Join(os.Getenv("HOME"), ".awless")
	DBPath             = filepath.Join(AwlessHome, database.Filename)
	Dir                = filepath.Join(AwlessHome, "aws")
	KeysDir            = filepath.Join(AwlessHome, "keys")
	AwlessFirstInstall bool
)

func init() {
	os.Setenv("__AWLESS_HOME", AwlessHome)
	os.Setenv("__AWLESS_CACHE", filepath.Join(AwlessHome, "cache"))
	os.Setenv("__AWLESS_KEYS_DIR", KeysDir)
}

func InitAwlessEnv() error {
	_, err := os.Stat(DBPath)

	AwlessFirstInstall = os.IsNotExist(err)
	os.Setenv("__AWLESS_FIRST_INSTALL", strconv.FormatBool(AwlessFirstInstall))

	os.MkdirAll(KeysDir, 0700)

	if AwlessFirstInstall {
		fmt.Println("Welcome to awless! Resolving environment data...")
		fmt.Println()

		if err = InitConfig(resolveRequiredConfigFromEnv()); err != nil {
			return err
		}

		err = database.Execute(func(db *database.DB) error {
			return db.SetStringValue("current.version", Version)
		})
		if err != nil {
			fmt.Printf("cannot store current version in db: %s\n", err)
		}
	}

	if err = LoadConfig(); err != nil {
		return err
	}

	return nil
}

func resolveRequiredConfigFromEnv() map[string]string {
	region, ami := awsservices.ResolveRegionAndAmiFromEnv()

	resolved := make(map[string]string)
	if region != "" {
		resolved[RegionConfigKey] = region
	}

	if ami != "" {
		resolved[instanceImageDefaultsKey] = ami
	}

	return resolved
}
<commit_msg>First install: redirect to Stderr to avoid ... ... polluting grep output on first install<commit_after>/*
Copyright 2017 WALLIX

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 config

import (
	"fmt"
	"os"
	"path/filepath"

	"strconv"

	"github.com/wallix/awless/aws/services"
	"github.com/wallix/awless/database"
)

var (
	AwlessHome         = filepath.Join(os.Getenv("HOME"), ".awless")
	DBPath             = filepath.Join(AwlessHome, database.Filename)
	Dir                = filepath.Join(AwlessHome, "aws")
	KeysDir            = filepath.Join(AwlessHome, "keys")
	AwlessFirstInstall bool
)

func init() {
	os.Setenv("__AWLESS_HOME", AwlessHome)
	os.Setenv("__AWLESS_CACHE", filepath.Join(AwlessHome, "cache"))
	os.Setenv("__AWLESS_KEYS_DIR", KeysDir)
}

func InitAwlessEnv() error {
	_, err := os.Stat(DBPath)

	AwlessFirstInstall = os.IsNotExist(err)
	os.Setenv("__AWLESS_FIRST_INSTALL", strconv.FormatBool(AwlessFirstInstall))

	os.MkdirAll(KeysDir, 0700)

	if AwlessFirstInstall {
		fmt.Fprintln(os.Stderr, "Welcome to awless! Resolving environment data...")
		fmt.Fprintln(os.Stderr)

		if err = InitConfig(resolveRequiredConfigFromEnv()); err != nil {
			return err
		}

		err = database.Execute(func(db *database.DB) error {
			return db.SetStringValue("current.version", Version)
		})
		if err != nil {
			fmt.Fprintf(os.Stderr, "cannot store current version in db: %s\n", err)
		}
	}

	if err = LoadConfig(); err != nil {
		return err
	}

	return nil
}

func resolveRequiredConfigFromEnv() map[string]string {
	region, ami := awsservices.ResolveRegionAndAmiFromEnv()

	resolved := make(map[string]string)
	if region != "" {
		resolved[RegionConfigKey] = region
	}

	if ami != "" {
		resolved[instanceImageDefaultsKey] = ami
	}

	return resolved
}
<|endoftext|>