<commit_before>// www.go

package www

import (
	"fmt"
	"net/http"

	"appengine"
	"appengine/user"
)

func init() {
	http.HandleFunc("/", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	u := user.Current(c)
	if u == nil {
		url, err := user.LoginURL(c, r.URL.String())
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Header().Set("Location", url)
		w.WriteHeader(http.StatusFound)
		return
	}
	fmt.Fprint(w, index_html, u, ih2)
}

const index_html = `
<!DOCTYPE html>

		<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
	    <title>Clio: Online Legal Practice Management Software | SaaS for Lawyers, Attorneys, Law Firms</title>
	    <meta name="description" content="Clio makes law practice management easy with legal case management software & online tools for small- to mid-sized law firms." />
	    <meta name="author" content="David Skinner" />
		<meta name="robots" content="INDEX, NOFOLLOW" />
		<link rel="icon" type="image/png" href="./images/favicon.png" />
		<link rel="shortcut icon" href="./images/favicon.ico" />
		<link type="text/css" rel="stylesheet" media="all" href="./stylesheets/davsk.css" />

GoClio.Davsk.com

Appropriate application of advanced technology.

Hello, `

const ih2 = `!

30 Day Free Trial

Clio leads the way in cloud-based practice management with a rich set of features that make managing everything from intake to invoicing a snap. Signup for a free trial at
				http://www.goclio.com/signup?referral_code=davsk
				and review the features available.

Local Support

You have local support at no additional charge to assist with commisioning, importing historical data and contacts, establishing procedures, and training staff.
				Online support and toll free support are also available as part of the package.

Local Community

Local firms using GoClio are available. You can see how others have integrated their firm management. You can talk to the people who use GoClio in their practice every workday.

Product Integration

Document Management: DropBox, Box, Google Drive

Calendars and Contacts:

Clio Sync for Outlook provides bidirectional sync between Clio and Microsoft Outlook for contacts, calendar entries and tasks.

Google Apps Integration. Single Sign-On, calendar sync and contact sync all help make sure switching between Google Apps and Clio is completely painless.

Email: Compatible with all e-mail clients, including Microsoft Outlook, Apple Mail, Thunderbird, and Gmail

Accounting: Quickbooks

Time Matters®

Conversions can sometimes be problematic. Data validity of prior database needs to be verified to avoid importing junk data.

				I have experience with the exporting of Time Matters®
				data from MsSql®
				database for bulk import and with the AutoHotKey®
				database driven automation of GoClio® data entry to preserve historical data and with custom AI programming for data validation.

Additional Services

Services not directly related to GoClio such as certification of network wiring, configuration of routers, compliance with Gramm-Leach-Bliley Act, may be contracted at standard rates
				http://forensic.davsk.com/index_files/page0007.html

Hot Links

GoClio Signup

Forensic Services

Contact Information

David Skinner

			670 S6th St Ste 16

			Arkadelphia  AR   71923-6242

text: 501-201-0414

email:

Disclaimer

Privacy Policy

Terms of Service

					© Copyright 2012 Davsk - All Rights Reserved

`
<commit_msg>Address change<commit_after>// www.go

package www

import (
	"fmt"
	"net/http"

	"appengine"
	"appengine/user"
)

func init() {
	http.HandleFunc("/", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	u := user.Current(c)
	if u == nil {
		url, err := user.LoginURL(c, r.URL.String())
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Header().Set("Location", url)
		w.WriteHeader(http.StatusFound)
		return
	}
	fmt.Fprint(w, index_html, u, ih2)
}

const index_html = `
<!DOCTYPE html>

		<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
	    <title>Clio: Online Legal Practice Management Software | SaaS for Lawyers, Attorneys, Law Firms</title>
	    <meta name="description" content="Clio makes law practice management easy with legal case management software & online tools for small- to mid-sized law firms." />
	    <meta name="author" content="David Skinner" />
		<meta name="robots" content="INDEX, NOFOLLOW" />
		<link rel="icon" type="image/png" href="./images/favicon.png" />
		<link rel="shortcut icon" href="./images/favicon.ico" />
		<link type="text/css" rel="stylesheet" media="all" href="./stylesheets/davsk.css" />

GoClio.Davsk.com

Appropriate application of advanced technology.

Hello, `

const ih2 = `!

30 Day Free Trial

Clio leads the way in cloud-based practice management with a rich set of features that make managing everything from intake to invoicing a snap. Signup for a free trial at
				http://www.goclio.com/signup?referral_code=davsk
				and review the features available.

Local Support

You have local support at no additional charge to assist with commisioning, importing historical data and contacts, establishing procedures, and training staff.
				Online support and toll free support are also available as part of the package.

Local Community

Local firms using GoClio are available. You can see how others have integrated their firm management. You can talk to the people who use GoClio in their practice every workday.

Product Integration

Document Management: DropBox, Box, Google Drive

Calendars and Contacts:

Clio Sync for Outlook provides bidirectional sync between Clio and Microsoft Outlook for contacts, calendar entries and tasks.

Google Apps Integration. Single Sign-On, calendar sync and contact sync all help make sure switching between Google Apps and Clio is completely painless.

Email: Compatible with all e-mail clients, including Microsoft Outlook, Apple Mail, Thunderbird, and Gmail

Accounting: Quickbooks

Time Matters®

Conversions can sometimes be problematic. Data validity of prior database needs to be verified to avoid importing junk data.

				I have experience with the exporting of Time Matters®
				data from MsSql®
				database for bulk import and with the AutoHotKey®
				database driven automation of GoClio® data entry to preserve historical data and with custom AI programming for data validation.

Additional Services

Services not directly related to GoClio such as certification of network wiring, configuration of routers, compliance with Gramm-Leach-Bliley Act, may be contracted at standard rates
				http://forensic.davsk.com/index_files/page0007.html

Hot Links

GoClio Signup

Forensic Services

Contact Information

David Skinner

			650 S5th St Apt 88

			Arkadelphia  AR   71923-6242

text: 501-201-0414

email:

Disclaimer

Privacy Policy

Terms of Service

					© Copyright 2012 Davsk - All Rights Reserved

`
<|endoftext|>


<commit_before>/*
Copyright 2021 Google LLC

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

    https://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 (
	"io/ioutil"
	"os"
	"path"
	"testing"

	"github.com/bazelbuild/buildtools/testutils"
	"github.com/bazelbuild/buildtools/warn"
)

func TestAllWarningsAreDocumented(t *testing.T) {
	testdata := path.Join(os.Getenv("TEST_SRCDIR"), os.Getenv("TEST_WORKSPACE"))

	textprotoPath := path.Join(testdata, "warn", "docs", "warnings.textproto")
	warnings, err := getWarnings(textprotoPath)
	if err != nil {
		t.Fatalf("getWarnings(%q) = %v", textprotoPath, err)
	}

	names := make(map[string]bool)
	for _, w := range warnings.Warnings {
		for _, n := range w.Name {
			names[n] = true
		}
	}

	for _, n := range warn.AllWarnings {
		if !names[n] {
			t.Errorf("warning %q is not documented in warn/docs/warnings.textproto", n)
		}
	}
}

func TestFilesMatch(t *testing.T) {
	testdata := path.Join(os.Getenv("TEST_SRCDIR"), os.Getenv("TEST_WORKSPACE"))

	generated, err := ioutil.ReadFile(path.Join(testdata, "warn", "docs", "WARNINGS.md"))
	if err != nil {
		t.Fatalf("ReadFile(%q) = %v", "warn/docs/WARNINGS.md", err)
	}

	checkedIn, err := ioutil.ReadFile(path.Join(testdata, "WARNINGS.md"))
	if err != nil {
		t.Fatalf("ReadFile(%q) = %v", "WARNINGS.md", err)
	}

	d, err := testutils.Diff(generated, checkedIn)
	if err != nil {
		t.Fatalf("diff(generated, checkedIn) = %v", err)
	}
	if len(d) != 0 {
		t.Errorf("diff(generated, checkedIn) = %v\n", string(d))
		t.Errorf("To update the documentation, run `bazel build //warn/docs:warnings_docs && cp bazel-bin/warn/docs/WARNINGS.md .`")
	}
}
<commit_msg>Address code review comments in a test (#951)<commit_after>/*
Copyright 2021 Google LLC

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

    https://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 (
	"io/ioutil"
	"os"
	"path"
	"testing"

	"github.com/bazelbuild/buildtools/testutils"
	"github.com/bazelbuild/buildtools/warn"
)

func TestAllWarningsAreDocumented(t *testing.T) {
	testdata := path.Join(os.Getenv("TEST_SRCDIR"), os.Getenv("TEST_WORKSPACE"))

	textprotoPath := path.Join(testdata, "warn", "docs", "warnings.textproto")
	warnings, err := getWarnings(textprotoPath)
	if err != nil {
		t.Fatalf("getWarnings(%q) = %v", textprotoPath, err)
	}

	names := make(map[string]bool)
	for _, w := range warnings.Warnings {
		for _, n := range w.Name {
			names[n] = true
		}
	}

	for _, n := range warn.AllWarnings {
		if !names[n] {
			t.Errorf("warning %q is not documented in warn/docs/warnings.textproto", n)
		}
	}
}

func TestFilesMatch(t *testing.T) {
	testdata := path.Join(os.Getenv("TEST_SRCDIR"), os.Getenv("TEST_WORKSPACE"))

	generatedPath := path.Join(testdata, "warn", "docs", "WARNINGS.md")
	generated, err := ioutil.ReadFile(generatedPath)
	if err != nil {
		t.Fatalf("ReadFile(%q) = %v", generatedPath, err)
	}

	checkedInPath := path.Join(testdata, "WARNINGS.md")
	checkedIn, err := ioutil.ReadFile(checkedInPath)
	if err != nil {
		t.Fatalf("ReadFile(%q) = %v", checkedInPath, err)
	}

	d, err := testutils.Diff(generated, checkedIn)
	if err != nil {
		t.Fatalf("diff(generated, checkedIn) returns error:", err)
	}
	if len(d) != 0 {
		t.Errorf("diff(generated, checkedIn) = %v\n", string(d))
		t.Errorf("To update the documentation, run `bazel build //warn/docs:warnings_docs && cp bazel-bin/warn/docs/WARNINGS.md .`")
	}
}
<|endoftext|>


<commit_before>package mux

import (
	"v2ray.com/core/common/buf"
	"v2ray.com/core/common/net"
	"v2ray.com/core/common/serial"
)

type SessionStatus byte

const (
	SessionStatusNew       SessionStatus = 0x01
	SessionStatusKeep      SessionStatus = 0x02
	SessionStatusEnd       SessionStatus = 0x03
	SessionStatusKeepAlive SessionStatus = 0x04
)

type Option byte

const (
	OptionData Option = 0x01
)

func (o Option) Has(x Option) bool {
	return (o & x) == x
}

func (o *Option) Add(x Option) {
	*o = (*o | x)
}

func (o *Option) Clear(x Option) {
	*o = (*o & (^x))
}

type TargetNetwork byte

const (
	TargetNetworkTCP TargetNetwork = 0x01
	TargetNetworkUDP TargetNetwork = 0x02
)

type AddressType byte

const (
	AddressTypeIPv4   AddressType = 0x01
	AddressTypeDomain AddressType = 0x02
	AddressTypeIPv6   AddressType = 0x03
)

/*
Frame format
2 bytes - length
2 bytes - session id
1 bytes - status
1 bytes - option

1 byte - network
2 bytes - port
n bytes - address

*/

type FrameMetadata struct {
	SessionID     uint16
	Target        net.Destination
	Option        Option
	SessionStatus SessionStatus
}

func (f FrameMetadata) AsSupplier() buf.Supplier {
	return func(b []byte) (int, error) {
		lengthBytes := b
		b = serial.Uint16ToBytes(uint16(0), b[:0]) // place holder for length

		b = serial.Uint16ToBytes(f.SessionID, b)
		b = append(b, byte(f.SessionStatus), byte(f.Option))
		length := 4

		if f.SessionStatus == SessionStatusNew {
			switch f.Target.Network {
			case net.Network_TCP:
				b = append(b, byte(TargetNetworkTCP))
			case net.Network_UDP:
				b = append(b, byte(TargetNetworkUDP))
			}
			length++

			b = serial.Uint16ToBytes(f.Target.Port.Value(), b)
			length += 2

			addr := f.Target.Address
			switch addr.Family() {
			case net.AddressFamilyIPv4:
				b = append(b, byte(AddressTypeIPv4))
				b = append(b, addr.IP()...)
				length += 5
			case net.AddressFamilyIPv6:
				b = append(b, byte(AddressTypeIPv6))
				b = append(b, addr.IP()...)
				length += 17
			case net.AddressFamilyDomain:
				nDomain := len(addr.Domain())
				b = append(b, byte(AddressTypeDomain), byte(nDomain))
				b = append(b, addr.Domain()...)
				length += nDomain + 2
			}
		}

		serial.Uint16ToBytes(uint16(length), lengthBytes[:0])
		return length + 2, nil
	}
}

func ReadFrameFrom(b []byte) (*FrameMetadata, error) {
	if len(b) < 4 {
		return nil, newError("insufficient buffer: ", len(b))
	}

	f := &FrameMetadata{
		SessionID:     serial.BytesToUint16(b[:2]),
		SessionStatus: SessionStatus(b[2]),
		Option:        Option(b[3]),
	}

	b = b[4:]

	if f.SessionStatus == SessionStatusNew {
		network := TargetNetwork(b[0])
		port := net.PortFromBytes(b[1:3])
		addrType := AddressType(b[3])
		b = b[4:]

		var addr net.Address
		switch addrType {
		case AddressTypeIPv4:
			addr = net.IPAddress(b[0:4])
			b = b[4:]
		case AddressTypeIPv6:
			addr = net.IPAddress(b[0:16])
			b = b[16:]
		case AddressTypeDomain:
			nDomain := int(b[0])
			addr = net.DomainAddress(string(b[1 : 1+nDomain]))
			b = b[nDomain+1:]
		default:
			return nil, newError("unknown address type: ", addrType)
		}
		switch network {
		case TargetNetworkTCP:
			f.Target = net.TCPDestination(addr, port)
		case TargetNetworkUDP:
			f.Target = net.UDPDestination(addr, port)
		default:
			return nil, newError("unknown network type: ", network)
		}
	}

	return f, nil
}
<commit_msg>fix frame meta<commit_after>package mux

import (
	"v2ray.com/core/common/buf"
	"v2ray.com/core/common/net"
	"v2ray.com/core/common/serial"
)

type SessionStatus byte

const (
	SessionStatusNew       SessionStatus = 0x01
	SessionStatusKeep      SessionStatus = 0x02
	SessionStatusEnd       SessionStatus = 0x03
	SessionStatusKeepAlive SessionStatus = 0x04
)

type Option byte

const (
	OptionData Option = 0x01
)

func (o Option) Has(x Option) bool {
	return (o & x) == x
}

func (o *Option) Add(x Option) {
	*o = (*o | x)
}

func (o *Option) Clear(x Option) {
	*o = (*o & (^x))
}

type TargetNetwork byte

const (
	TargetNetworkTCP TargetNetwork = 0x01
	TargetNetworkUDP TargetNetwork = 0x02
)

type AddressType byte

const (
	AddressTypeIPv4   AddressType = 0x01
	AddressTypeDomain AddressType = 0x02
	AddressTypeIPv6   AddressType = 0x03
)

/*
Frame format
2 bytes - length
2 bytes - session id
1 bytes - status
1 bytes - option

1 byte - network
2 bytes - port
n bytes - address

*/

type FrameMetadata struct {
	Target        net.Destination
	SessionID     uint16
	Option        Option
	SessionStatus SessionStatus
}

func (f FrameMetadata) AsSupplier() buf.Supplier {
	return func(b []byte) (int, error) {
		lengthBytes := b
		b = serial.Uint16ToBytes(uint16(0), b[:0]) // place holder for length

		b = serial.Uint16ToBytes(f.SessionID, b)
		b = append(b, byte(f.SessionStatus), byte(f.Option))
		length := 4

		if f.SessionStatus == SessionStatusNew {
			switch f.Target.Network {
			case net.Network_TCP:
				b = append(b, byte(TargetNetworkTCP))
			case net.Network_UDP:
				b = append(b, byte(TargetNetworkUDP))
			}
			length++

			b = serial.Uint16ToBytes(f.Target.Port.Value(), b)
			length += 2

			addr := f.Target.Address
			switch addr.Family() {
			case net.AddressFamilyIPv4:
				b = append(b, byte(AddressTypeIPv4))
				b = append(b, addr.IP()...)
				length += 5
			case net.AddressFamilyIPv6:
				b = append(b, byte(AddressTypeIPv6))
				b = append(b, addr.IP()...)
				length += 17
			case net.AddressFamilyDomain:
				nDomain := len(addr.Domain())
				b = append(b, byte(AddressTypeDomain), byte(nDomain))
				b = append(b, addr.Domain()...)
				length += nDomain + 2
			}
		}

		serial.Uint16ToBytes(uint16(length), lengthBytes[:0])
		return length + 2, nil
	}
}

func ReadFrameFrom(b []byte) (*FrameMetadata, error) {
	if len(b) < 4 {
		return nil, newError("insufficient buffer: ", len(b))
	}

	f := &FrameMetadata{
		SessionID:     serial.BytesToUint16(b[:2]),
		SessionStatus: SessionStatus(b[2]),
		Option:        Option(b[3]),
	}

	b = b[4:]

	if f.SessionStatus == SessionStatusNew {
		network := TargetNetwork(b[0])
		port := net.PortFromBytes(b[1:3])
		addrType := AddressType(b[3])
		b = b[4:]

		var addr net.Address
		switch addrType {
		case AddressTypeIPv4:
			addr = net.IPAddress(b[0:4])
			b = b[4:]
		case AddressTypeIPv6:
			addr = net.IPAddress(b[0:16])
			b = b[16:]
		case AddressTypeDomain:
			nDomain := int(b[0])
			addr = net.DomainAddress(string(b[1 : 1+nDomain]))
			b = b[nDomain+1:]
		default:
			return nil, newError("unknown address type: ", addrType)
		}
		switch network {
		case TargetNetworkTCP:
			f.Target = net.TCPDestination(addr, port)
		case TargetNetworkUDP:
			f.Target = net.UDPDestination(addr, port)
		default:
			return nil, newError("unknown network type: ", network)
		}
	}

	return f, nil
}
<|endoftext|>


<commit_before>package db

import (
	"database/sql"
	"fmt"

	sq "github.com/Masterminds/squirrel"
	"github.com/concourse/concourse/atc/db/lock"
)

//counterfeiter:generate . PipelineLifecycle
type PipelineLifecycle interface {
	ArchiveAbandonedPipelines() error
	RemoveBuildEventsForDeletedPipelines() error
}

func NewPipelineLifecycle(conn Conn, lockFactory lock.LockFactory) PipelineLifecycle {
	return &pipelineLifecycle{
		conn:        conn,
		lockFactory: lockFactory,
	}
}

type pipelineLifecycle struct {
	conn        Conn
	lockFactory lock.LockFactory
}

func (pl *pipelineLifecycle) ArchiveAbandonedPipelines() error {
	tx, err := pl.conn.Begin()
	if err != nil {
		return err
	}

	defer Rollback(tx)

	rows, err := pipelinesQuery.
		LeftJoin("jobs j ON j.id = p.parent_job_id").
		LeftJoin("pipelines p2 ON j.pipeline_id = p2.id").
		Where(sq.Or{
			// parent pipeline was destroyed
			sq.And{
				sq.NotEq{"p.parent_build_id": nil},
				sq.Eq{"j.id": nil},
			},
			// pipeline was set by a job. The job was removed from the parent pipeline
			sq.Eq{"j.active": false},
			// parent pipeline was archived
			sq.Eq{"p2.archived": true},
		}).
		RunWith(tx).
		Query()
	if err != nil {
		return err
	}
	defer rows.Close()

	err = archivePipelines(tx, pl.conn, pl.lockFactory, rows)
	if err != nil {
		return err
	}

	err = tx.Commit()
	if err != nil {
		return err
	}

	return nil
}

func archivePipelines(tx Tx, conn Conn, lockFactory lock.LockFactory, rows *sql.Rows) error {
	var toArchive []pipeline
	for rows.Next() {
		p := newPipeline(conn, lockFactory)
		if err := scanPipeline(p, rows); err != nil {
			return err
		}

		toArchive = append(toArchive, *p)
	}

	for _, pipeline := range toArchive {
		err := pipeline.archive(tx)
		if err != nil {
			return err
		}
	}

	return nil
}

func (p *pipelineLifecycle) RemoveBuildEventsForDeletedPipelines() error {
	rows, err := psql.Select("id").
		From("deleted_pipelines").
		RunWith(p.conn).
		Query()
	if err != nil {
		return err
	}

	var idsToDelete []int
	for rows.Next() {
		var id int
		if err := rows.Scan(&id); err != nil {
			return err
		}
		idsToDelete = append(idsToDelete, id)
	}

	rows.Close()

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

	for _, id := range idsToDelete {
		_, err = p.conn.Exec(fmt.Sprintf("DROP TABLE IF EXISTS pipeline_build_events_%d", id))
		if err != nil {
			return err
		}
	}

	_, err = psql.Delete("deleted_pipelines").
		Where(sq.Eq{"id": idsToDelete}).
		RunWith(p.conn).
		Exec()
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>remove redundant JOIN<commit_after>package db

import (
	"database/sql"
	"fmt"

	sq "github.com/Masterminds/squirrel"
	"github.com/concourse/concourse/atc/db/lock"
)

//counterfeiter:generate . PipelineLifecycle
type PipelineLifecycle interface {
	ArchiveAbandonedPipelines() error
	RemoveBuildEventsForDeletedPipelines() error
}

func NewPipelineLifecycle(conn Conn, lockFactory lock.LockFactory) PipelineLifecycle {
	return &pipelineLifecycle{
		conn:        conn,
		lockFactory: lockFactory,
	}
}

type pipelineLifecycle struct {
	conn        Conn
	lockFactory lock.LockFactory
}

func (pl *pipelineLifecycle) ArchiveAbandonedPipelines() error {
	tx, err := pl.conn.Begin()
	if err != nil {
		return err
	}

	defer Rollback(tx)

	rows, err := pipelinesQuery.
		LeftJoin("jobs j ON (j.id = p.parent_job_id AND j.pipeline_id = p.id)").
		Where(sq.Or{
			// parent pipeline was destroyed
			sq.And{
				sq.NotEq{"p.parent_build_id": nil},
				sq.Eq{"j.id": nil},
			},
			// pipeline was set by a job. The job was removed from the parent pipeline
			sq.Eq{"j.active": false},
			// parent pipeline was archived
			sq.Eq{"p.archived": true},
		}).
		RunWith(tx).
		Query()
	if err != nil {
		return err
	}
	defer rows.Close()

	err = archivePipelines(tx, pl.conn, pl.lockFactory, rows)
	if err != nil {
		return err
	}

	err = tx.Commit()
	if err != nil {
		return err
	}

	return nil
}

func archivePipelines(tx Tx, conn Conn, lockFactory lock.LockFactory, rows *sql.Rows) error {
	var toArchive []pipeline
	for rows.Next() {
		p := newPipeline(conn, lockFactory)
		if err := scanPipeline(p, rows); err != nil {
			return err
		}

		toArchive = append(toArchive, *p)
	}

	for _, pipeline := range toArchive {
		err := pipeline.archive(tx)
		if err != nil {
			return err
		}
	}

	return nil
}

func (p *pipelineLifecycle) RemoveBuildEventsForDeletedPipelines() error {
	rows, err := psql.Select("id").
		From("deleted_pipelines").
		RunWith(p.conn).
		Query()
	if err != nil {
		return err
	}

	var idsToDelete []int
	for rows.Next() {
		var id int
		if err := rows.Scan(&id); err != nil {
			return err
		}
		idsToDelete = append(idsToDelete, id)
	}

	rows.Close()

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

	for _, id := range idsToDelete {
		_, err = p.conn.Exec(fmt.Sprintf("DROP TABLE IF EXISTS pipeline_build_events_%d", id))
		if err != nil {
			return err
		}
	}

	_, err = psql.Delete("deleted_pipelines").
		Where(sq.Eq{"id": idsToDelete}).
		RunWith(p.conn).
		Exec()
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package git

/*
extern int _govcs_gcrypt_init();
#cgo LDFLAGS: -lgcrypt
*/
import "C"
import (
	"fmt"
	"log"
	"os"
	"strings"

	"crypto/md5"

	"code.google.com/p/go.crypto/ssh"

	git2go "github.com/libgit2/git2go"
	"github.com/sourcegraph/go-vcs/vcs"
	"github.com/sourcegraph/go-vcs/vcs/gitcmd"
	sshutil "github.com/sourcegraph/go-vcs/vcs/ssh"
	"github.com/sourcegraph/go-vcs/vcs/util"
)

func init() {
	// Overwrite the git cloner to use the faster libgit2
	// implementation.
	vcs.RegisterCloner("git", func(url, dir string, opt vcs.CloneOpt) (vcs.Repository, error) {
		return Clone(url, dir, opt)
	})
}

func init() {
	// Initialize gcrypt for multithreaded operation. See
	// gcrypt_init.c for more information.
	rv := C._govcs_gcrypt_init()
	if rv != 0 {
		log.Fatal("gcrypt multithreaded init failed (see gcrypt_init.c)")
	}
}

func Clone(url, dir string, opt vcs.CloneOpt) (vcs.Repository, error) {
	clopt := git2go.CloneOptions{Bare: opt.Bare}

	rc, cfs, err := makeRemoteCallbacks(url, opt.RemoteOpts)
	if err != nil {
		return nil, err
	}
	if cfs != nil {
		defer cfs.run()
	}
	clopt.RemoteCallbacks = rc

	u, err := git2go.Clone(url, dir, &clopt)
	if err != nil {
		return nil, err
	}
	cr, err := gitcmd.Open(dir)
	if err != nil {
		return nil, err
	}
	return &Repository{cr, u}, nil
}

func (r *Repository) UpdateEverything(opt vcs.RemoteOpts) error {
	// TODO(sqs): allow use of a remote other than "origin"
	rm, err := r.u.LoadRemote("origin")
	if err != nil {
		return err
	}

	rc, cfs, err := makeRemoteCallbacks(rm.Url(), opt)
	if err != nil {
		return err
	}
	if cfs != nil {
		defer cfs.run()
	}
	rm.SetCallbacks(rc)

	if err := rm.Fetch(nil, nil, ""); err != nil {
		return err
	}

	return nil
}

type cleanupFuncs []func() error

func (f cleanupFuncs) run() error {
	for _, cf := range f {
		if err := cf(); err != nil {
			return err
		}
	}
	return nil
}

// makeRemoteCallbacks constructs the remote callbacks for libgit2
// remote operations. Currently the remote callbacks are trivial
// (empty) except when using an SSH remote.
//
// cleanupFuncs's run method should be called when the RemoteCallbacks
// struct is done being used. It is OK to ignore the error return.
func makeRemoteCallbacks(url string, opt vcs.RemoteOpts) (rc *git2go.RemoteCallbacks, cfs cleanupFuncs, err error) {
	defer func() {
		// Clean up if error; don't expect the caller to clean up if
		// we have a non-nil error.
		if err != nil {
			cfs.run()
		}
	}()

	if opt.SSH != nil {
		privkeyFilename, privkeyFile, err := util.WriteKeyTempFile(url, opt.SSH.PrivateKey)
		if err != nil {
			return nil, nil, err
		}
		cfs = append(cfs, privkeyFile.Close)
		cfs = append(cfs, func() error { return os.Remove(privkeyFile.Name()) })

		// Derive public key from private key if empty.
		if opt.SSH.PublicKey == nil {
			privKey, err := ssh.ParsePrivateKey(opt.SSH.PrivateKey)
			if err != nil {
				return nil, cfs, err
			}
			opt.SSH.PublicKey = ssh.MarshalAuthorizedKey(privKey.PublicKey())
		}

		pubkeyFilename, pubkeyFile, err := util.WriteKeyTempFile(url, opt.SSH.PublicKey)
		if err != nil {
			return nil, cfs, err
		}
		cfs = append(cfs, pubkeyFile.Close)
		cfs = append(cfs, func() error { return os.Remove(pubkeyFile.Name()) })

		rc = &git2go.RemoteCallbacks{
			CredentialsCallback: func(url string, usernameFromURL string, allowedTypes git2go.CredType) (int, *git2go.Cred) {
				if allowedTypes&git2go.CredTypeSshKey != 0 {
					rv, cred := git2go.NewCredSshKey(usernameFromURL, pubkeyFilename, privkeyFilename, "")
					return rv, &cred
				}
				log.Printf("No authentication available for git URL %q.", url)
				return 1, nil
			},
			CertificateCheckCallback: func(cert *git2go.Certificate, valid bool, hostname string) int {
				// libgit2 currently always returns valid=false. It
				// may return valid=true in the future if it checks
				// host keys using known_hosts, but let's ignore valid
				// so we don't get that behavior unexpectedly.

				if InsecureSkipCheckVerifySSH {
					return 0
				}

				if cert == nil {
					return -1
				}

				if cert.Hostkey.Kind&git2go.HostkeyMD5 > 0 {
					keys, found := standardKnownHosts.Lookup(hostname)
					if found {
						hostFingerprint := md5String(cert.Hostkey.HashMD5)
						for _, key := range keys {
							knownFingerprint := md5String(md5.Sum(key.Marshal()))
							if hostFingerprint == knownFingerprint {
								return 0
							}
						}
					}
				}

				log.Printf("Invalid certificate for SSH host %s: %v.", hostname, cert)
				return -1
			},
		}
	}

	return rc, cfs, nil
}

// InsecureSkipCheckVerifySSH controls whether the client verifies the
// SSH server's certificate or host key. If InsecureSkipCheckVerifySSH
// is true, the program is susceptible to a man-in-the-middle
// attack. This should only be used for testing.
var InsecureSkipCheckVerifySSH bool

// standardKnownHosts contains known_hosts from the system known_hosts
// file and the user's known_hosts file.
var standardKnownHosts sshutil.KnownHosts

func init() {
	var err error
	standardKnownHosts, err = sshutil.ReadStandardKnownHostsFiles()
	if err != nil {
		log.Printf("Warning: failed to read standard SSH known_hosts files (%s). SSH host key checking will fail.")
	}
}

// md5String returns a formatted string representing the given md5Sum in hex
func md5String(md5Sum [16]byte) string {
	md5Str := fmt.Sprintf("% x", md5Sum)
	md5Str = strings.Replace(md5Str, " ", ":", -1)
	return md5Str
}
<commit_msg>use current user if no username is provided in URL<commit_after>package git

/*
extern int _govcs_gcrypt_init();
#cgo LDFLAGS: -lgcrypt
*/
import "C"
import (
	"fmt"
	"log"
	"os"
	"os/user"
	"strings"

	"crypto/md5"

	"code.google.com/p/go.crypto/ssh"

	git2go "github.com/libgit2/git2go"
	"github.com/sourcegraph/go-vcs/vcs"
	"github.com/sourcegraph/go-vcs/vcs/gitcmd"
	sshutil "github.com/sourcegraph/go-vcs/vcs/ssh"
	"github.com/sourcegraph/go-vcs/vcs/util"
)

func init() {
	// Overwrite the git cloner to use the faster libgit2
	// implementation.
	vcs.RegisterCloner("git", func(url, dir string, opt vcs.CloneOpt) (vcs.Repository, error) {
		return Clone(url, dir, opt)
	})
}

func init() {
	// Initialize gcrypt for multithreaded operation. See
	// gcrypt_init.c for more information.
	rv := C._govcs_gcrypt_init()
	if rv != 0 {
		log.Fatal("gcrypt multithreaded init failed (see gcrypt_init.c)")
	}
}

func Clone(url, dir string, opt vcs.CloneOpt) (vcs.Repository, error) {
	clopt := git2go.CloneOptions{Bare: opt.Bare}

	rc, cfs, err := makeRemoteCallbacks(url, opt.RemoteOpts)
	if err != nil {
		return nil, err
	}
	if cfs != nil {
		defer cfs.run()
	}
	clopt.RemoteCallbacks = rc

	u, err := git2go.Clone(url, dir, &clopt)
	if err != nil {
		return nil, err
	}
	cr, err := gitcmd.Open(dir)
	if err != nil {
		return nil, err
	}
	return &Repository{cr, u}, nil
}

func (r *Repository) UpdateEverything(opt vcs.RemoteOpts) error {
	// TODO(sqs): allow use of a remote other than "origin"
	rm, err := r.u.LoadRemote("origin")
	if err != nil {
		return err
	}

	rc, cfs, err := makeRemoteCallbacks(rm.Url(), opt)
	if err != nil {
		return err
	}
	if cfs != nil {
		defer cfs.run()
	}
	rm.SetCallbacks(rc)

	if err := rm.Fetch(nil, nil, ""); err != nil {
		return err
	}

	return nil
}

type cleanupFuncs []func() error

func (f cleanupFuncs) run() error {
	for _, cf := range f {
		if err := cf(); err != nil {
			return err
		}
	}
	return nil
}

// makeRemoteCallbacks constructs the remote callbacks for libgit2
// remote operations. Currently the remote callbacks are trivial
// (empty) except when using an SSH remote.
//
// cleanupFuncs's run method should be called when the RemoteCallbacks
// struct is done being used. It is OK to ignore the error return.
func makeRemoteCallbacks(url string, opt vcs.RemoteOpts) (rc *git2go.RemoteCallbacks, cfs cleanupFuncs, err error) {
	defer func() {
		// Clean up if error; don't expect the caller to clean up if
		// we have a non-nil error.
		if err != nil {
			cfs.run()
		}
	}()

	if opt.SSH != nil {
		privkeyFilename, privkeyFile, err := util.WriteKeyTempFile(url, opt.SSH.PrivateKey)
		if err != nil {
			return nil, nil, err
		}
		cfs = append(cfs, privkeyFile.Close)
		cfs = append(cfs, func() error { return os.Remove(privkeyFile.Name()) })

		// Derive public key from private key if empty.
		if opt.SSH.PublicKey == nil {
			privKey, err := ssh.ParsePrivateKey(opt.SSH.PrivateKey)
			if err != nil {
				return nil, cfs, err
			}
			opt.SSH.PublicKey = ssh.MarshalAuthorizedKey(privKey.PublicKey())
		}

		pubkeyFilename, pubkeyFile, err := util.WriteKeyTempFile(url, opt.SSH.PublicKey)
		if err != nil {
			return nil, cfs, err
		}
		cfs = append(cfs, pubkeyFile.Close)
		cfs = append(cfs, func() error { return os.Remove(pubkeyFile.Name()) })

		rc = &git2go.RemoteCallbacks{
			CredentialsCallback: func(url string, usernameFromURL string, allowedTypes git2go.CredType) (int, *git2go.Cred) {
				var username string
				if usernameFromURL != "" {
					username = usernameFromURL
				} else {
					u, err := user.Current()
					if err == nil {
						username = u.Username
					}
				}
				if allowedTypes&git2go.CredTypeSshKey != 0 {
					rv, cred := git2go.NewCredSshKey(username, pubkeyFilename, privkeyFilename, "")
					return rv, &cred
				}
				log.Printf("No authentication available for git URL %q.", url)
				return 1, nil
			},
			CertificateCheckCallback: func(cert *git2go.Certificate, valid bool, hostname string) int {
				// libgit2 currently always returns valid=false. It
				// may return valid=true in the future if it checks
				// host keys using known_hosts, but let's ignore valid
				// so we don't get that behavior unexpectedly.

				if InsecureSkipCheckVerifySSH {
					return 0
				}

				if cert == nil {
					return -1
				}

				if cert.Hostkey.Kind&git2go.HostkeyMD5 > 0 {
					keys, found := standardKnownHosts.Lookup(hostname)
					if found {
						hostFingerprint := md5String(cert.Hostkey.HashMD5)
						for _, key := range keys {
							knownFingerprint := md5String(md5.Sum(key.Marshal()))
							if hostFingerprint == knownFingerprint {
								return 0
							}
						}
					}
				}

				log.Printf("Invalid certificate for SSH host %s: %v.", hostname, cert)
				return -1
			},
		}
	}

	return rc, cfs, nil
}

// InsecureSkipCheckVerifySSH controls whether the client verifies the
// SSH server's certificate or host key. If InsecureSkipCheckVerifySSH
// is true, the program is susceptible to a man-in-the-middle
// attack. This should only be used for testing.
var InsecureSkipCheckVerifySSH bool

// standardKnownHosts contains known_hosts from the system known_hosts
// file and the user's known_hosts file.
var standardKnownHosts sshutil.KnownHosts

func init() {
	var err error
	standardKnownHosts, err = sshutil.ReadStandardKnownHostsFiles()
	if err != nil {
		log.Printf("Warning: failed to read standard SSH known_hosts files (%s). SSH host key checking will fail.")
	}
}

// md5String returns a formatted string representing the given md5Sum in hex
func md5String(md5Sum [16]byte) string {
	md5Str := fmt.Sprintf("% x", md5Sum)
	md5Str = strings.Replace(md5Str, " ", ":", -1)
	return md5Str
}
<|endoftext|>


<commit_before>package main

import (
    "database/sql"
    "encoding/json"
    "fmt"
    "log"
    "io"
    "io/ioutil"
    re "regexp"
    "strconv"
    "os"
    "os/exec"
    "sort"
    s "strings"
    "sync"
    "jfb/svgxml"
    _ "github.com/lib/pq"
)

type Config struct {
    Colours map[string]string                       `json:"colours"`
    Maps    map[string]map[string]map[string]string `json:"maps"`
}

type DbConfig struct {
    Server      map[string]string       `json:"db_server"`
    Creds       map[string]string       `json:"db_creds"`
    Schema      map[string]string       `json:"db_schema"`
}

// set up integer array sorting
type IntArray []int
func (list IntArray) Len() int          { return len(list) }
func (list IntArray) Swap(a, b int)     { list[a], list[b] = list[b], list[a] }
func (list IntArray) Less(a, b int) bool { return list[a] < list[b] }

// suck in count data
func db_data() (map[string]int, map[string]int) {
    var dbconfig        DbConfig

    jsoncfg, err := ioutil.ReadFile("dbconfig.json")
    if err != nil {
        panic(err)
    }

    err = json.Unmarshal(jsoncfg, &dbconfig)
    if err != nil {
        fmt.Fprintf(os.Stderr, "DB config unmarshal: ")
        panic(err)
    }

    state_counts :=     make(map[string]int)
    county_counts :=    make(map[string]int)

    dbh, err := sql.Open(dbconfig.Server["dbtype"],
        dbconfig.Server["dbtype"] + "://" + dbconfig.Creds["username"] + ":" +
        dbconfig.Creds["password"] + "@" + dbconfig.Server["dbhost"] + "/" +
        dbconfig.Server["dbname"] + dbconfig.Server["dbopts"])
    if err != nil {
        log.Fatal(err)
    }

    query :=
            "select " +
                dbconfig.Schema["state_column"] + ", " +
                dbconfig.Schema["county_column"] + ", " +
                dbconfig.Schema["tally_column"] +
            "from " +
                dbconfig.Schema["tables"] + " " +
            dbconfig.Schema["where"] + " " +
            dbconfig.Schema["group_by"]
    rows, err := dbh.Query(query)
    // fmt.Println(query)
    if err != nil {
        log.Fatal(err)
    }

    defer rows.Close()
    for rows.Next() {
        var state, county string
        var count int
        if err := rows.Scan(&state, &county, &count); err != nil {
            log.Fatal(err)
        }
        state_counts[state] += count
        state_county_key := s.Replace(state + " " + county, " ", "_", -1)
        county_counts[state_county_key] = count
    }
    if err := rows.Err(); err != nil {
        log.Fatal(err)
    }

    return state_counts, county_counts

}

func colour_svgdata(mapsvg_obj *svgxml.SVG, data map[string]int, re_fill *re.Regexp, colours map[string]string, mincount []int) (string, []string) {

    var errors []string

    for id, count := range data {
        for _, mc := range mincount {
            if count >= mc {
                element := svgxml.FindPathById(mapsvg_obj, id)
                if element != nil {
                    element.Style = string(re_fill.ReplaceAll([]byte(element.Style), []byte("${1}" + colours[strconv.Itoa(mc)])))
                } else {
                    errors = append(errors, "'" + id + "' not found")
                }
            }
        }
    }
    return string(svgxml.SVG2XML(mapsvg_obj, true)), errors
}

func main() {

    var config  Config
    var wg      sync.WaitGroup

    jsoncfg, err := ioutil.ReadFile("config.json")
    if err != nil {
        panic(err)
    }

    err = json.Unmarshal(jsoncfg, &config)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Config unmarshal: ")
        panic(err)
    }

    // make sorted list of keys (minimum counts) for later comparisons
    mincount := make([]int, len(config.Colours))
    i := 0
    for k, _ := range config.Colours {
        k_i, _ := strconv.ParseInt(k, 0, 64)
        mincount[i] = int(k_i)
        i++
    }

    sort.Sort(IntArray(mincount))

    re_fill, err := re.Compile(`(fill:#)......`)
    if err != nil {
        panic(err)
    }

    re_svgext, err := re.Compile(`\.svg$`)
    if err != nil {
        panic(err)
    }

    state_data, county_data := db_data()

    for maptype, mapset := range config.Maps {
        var data map[string]int

        if maptype == "states" {
            data = state_data
        } else {
            data = county_data
        }

        for infile, attrs := range mapset {
            wg.Add(1)
            go func(srcfile, dstfile, outsize, maptype string, mapdata map[string]int) {

                var county_data_new map[string]int

                defer wg.Done()
                defer os.Stderr.Close()

                mapsvg, err := ioutil.ReadFile(srcfile)
                if err != nil {
                    fmt.Fprintf(os.Stderr, "can't read '" + srcfile + "': " + err.Error())
                    return
                }

                mapsvg_obj := svgxml.XML2SVG(mapsvg)
                if mapsvg_obj == nil {
                    fmt.Fprintf(os.Stderr, "can't create SVG object from " + srcfile)
                    return
                }

                if maptype == "counties" {
                    // This block has the effect of pruning county data for
                    // *states* that don't appear in the given map. This is so
                    // that counties in states outside the map don't cause
                    // error messages and counties in the map that have a
                    // different (incorrect)( name in the data do generate
                    // errors.

                    var map_state_list []string

                    county_data_new = make(map[string]int)

                    // first, make a list of all states in the map using
                    // state_data as the source of state names
                    for _, g := range mapsvg_obj.G {
                        for state, _ := range state_data {
                            if s.Index(g.Id, state + "_") == 0 {
                                map_state_list = append(map_state_list, state + "_")
                            }
                        }
                    }

                    // next, search county names in data for states found in
                    // the map and copy only county data entries for those
                    // found states
                    for state_county, sc_count := range mapdata {
                        found_state := false
                        for _, state_ := range map_state_list {
                            if s.Index(state_county, state_) == 0 {
                                found_state = true
                                break
                            }
                        }
                        if found_state == true {
                            county_data_new[state_county] = sc_count
                        }
                    }

                    // replace the function-local dataset with the pruned data
                    mapdata = county_data_new
                }

                svg_coloured, errlist := colour_svgdata(mapsvg_obj, mapdata, re_fill, config.Colours, mincount)
                if len(errlist) > 0 {
                    for _, errmsg := range errlist {
                        fmt.Fprintf(os.Stderr, "%s: %s\n", srcfile, errmsg)
                    }
                }

                ret := re_svgext.Find([]byte(dstfile))
                if ret == nil {
                    // going to call ImageMagick's 'convert' because I can't find
                    // a damn SVG package that can write to a non-SVG image and I
                    // don't have the chops to write one.
                    cmd := exec.Command("convert", "svg:-", "-scale", outsize, dstfile)
                    convert_stdin, err := cmd.StdinPipe()
                    if err != nil {
                        log.Fatal(err)
                    }
                    go func() {
                        defer convert_stdin.Close()
                        io.WriteString(convert_stdin, svg_coloured)
                    }()
                    _, err = cmd.CombinedOutput()
                    if err != nil {
                        log.Fatal(err)
                    }
                } else {
                    // just going back to an SVG file
                    err := ioutil.WriteFile(dstfile, []byte(svg_coloured), 0666)
                    if err != nil {
                        fmt.Fprintf(os.Stderr, "can't write to '" + dstfile + "': " + err.Error())
                        return
                    }
                }

            }(infile, attrs["outfile"], attrs["outsize"], maptype, data)
        }
    }

    wg.Wait()

    // fmt.Println(string(svgxml.SVG2XML(mapsvg_obj, true)))

}

// vim:ts=4:et:
// ex:ai:sw=4:ts=1000:
<commit_msg>call `convert` with `-resize` instead of `-scale` for better-looking PNGs<commit_after>package main

import (
    "database/sql"
    "encoding/json"
    "fmt"
    "log"
    "io"
    "io/ioutil"
    re "regexp"
    "strconv"
    "os"
    "os/exec"
    "sort"
    s "strings"
    "sync"
    "jfb/svgxml"
    _ "github.com/lib/pq"
)

type Config struct {
    Colours map[string]string                       `json:"colours"`
    Maps    map[string]map[string]map[string]string `json:"maps"`
}

type DbConfig struct {
    Server      map[string]string       `json:"db_server"`
    Creds       map[string]string       `json:"db_creds"`
    Schema      map[string]string       `json:"db_schema"`
}

// set up integer array sorting
type IntArray []int
func (list IntArray) Len() int          { return len(list) }
func (list IntArray) Swap(a, b int)     { list[a], list[b] = list[b], list[a] }
func (list IntArray) Less(a, b int) bool { return list[a] < list[b] }

// suck in count data
func db_data() (map[string]int, map[string]int) {
    var dbconfig        DbConfig

    jsoncfg, err := ioutil.ReadFile("dbconfig.json")
    if err != nil {
        panic(err)
    }

    err = json.Unmarshal(jsoncfg, &dbconfig)
    if err != nil {
        fmt.Fprintf(os.Stderr, "DB config unmarshal: ")
        panic(err)
    }

    state_counts :=     make(map[string]int)
    county_counts :=    make(map[string]int)

    dbh, err := sql.Open(dbconfig.Server["dbtype"],
        dbconfig.Server["dbtype"] + "://" + dbconfig.Creds["username"] + ":" +
        dbconfig.Creds["password"] + "@" + dbconfig.Server["dbhost"] + "/" +
        dbconfig.Server["dbname"] + dbconfig.Server["dbopts"])
    if err != nil {
        log.Fatal(err)
    }

    query :=
            "select " +
                dbconfig.Schema["state_column"] + ", " +
                dbconfig.Schema["county_column"] + ", " +
                dbconfig.Schema["tally_column"] +
            "from " +
                dbconfig.Schema["tables"] + " " +
            dbconfig.Schema["where"] + " " +
            dbconfig.Schema["group_by"]
    rows, err := dbh.Query(query)
    // fmt.Println(query)
    if err != nil {
        log.Fatal(err)
    }

    defer rows.Close()
    for rows.Next() {
        var state, county string
        var count int
        if err := rows.Scan(&state, &county, &count); err != nil {
            log.Fatal(err)
        }
        state_counts[state] += count
        state_county_key := s.Replace(state + " " + county, " ", "_", -1)
        county_counts[state_county_key] = count
    }
    if err := rows.Err(); err != nil {
        log.Fatal(err)
    }

    return state_counts, county_counts

}

func colour_svgdata(mapsvg_obj *svgxml.SVG, data map[string]int, re_fill *re.Regexp, colours map[string]string, mincount []int) (string, []string) {

    var errors []string

    for id, count := range data {
        for _, mc := range mincount {
            if count >= mc {
                element := svgxml.FindPathById(mapsvg_obj, id)
                if element != nil {
                    element.Style = string(re_fill.ReplaceAll([]byte(element.Style), []byte("${1}" + colours[strconv.Itoa(mc)])))
                } else {
                    errors = append(errors, "'" + id + "' not found")
                }
            }
        }
    }
    return string(svgxml.SVG2XML(mapsvg_obj, true)), errors
}

func main() {

    var config  Config
    var wg      sync.WaitGroup

    jsoncfg, err := ioutil.ReadFile("config.json")
    if err != nil {
        panic(err)
    }

    err = json.Unmarshal(jsoncfg, &config)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Config unmarshal: ")
        panic(err)
    }

    // make sorted list of keys (minimum counts) for later comparisons
    mincount := make([]int, len(config.Colours))
    i := 0
    for k, _ := range config.Colours {
        k_i, _ := strconv.ParseInt(k, 0, 64)
        mincount[i] = int(k_i)
        i++
    }

    sort.Sort(IntArray(mincount))

    re_fill, err := re.Compile(`(fill:#)......`)
    if err != nil {
        panic(err)
    }

    re_svgext, err := re.Compile(`\.svg$`)
    if err != nil {
        panic(err)
    }

    state_data, county_data := db_data()

    for maptype, mapset := range config.Maps {
        var data map[string]int

        if maptype == "states" {
            data = state_data
        } else {
            data = county_data
        }

        for infile, attrs := range mapset {
            wg.Add(1)
            go func(srcfile, dstfile, outsize, maptype string, mapdata map[string]int) {

                var county_data_new map[string]int

                defer wg.Done()
                defer os.Stderr.Close()

                mapsvg, err := ioutil.ReadFile(srcfile)
                if err != nil {
                    fmt.Fprintf(os.Stderr, "can't read '" + srcfile + "': " + err.Error())
                    return
                }

                mapsvg_obj := svgxml.XML2SVG(mapsvg)
                if mapsvg_obj == nil {
                    fmt.Fprintf(os.Stderr, "can't create SVG object from " + srcfile)
                    return
                }

                if maptype == "counties" {
                    // This block has the effect of pruning county data for
                    // *states* that don't appear in the given map. This is so
                    // that counties in states outside the map don't cause
                    // error messages and counties in the map that have a
                    // different (incorrect)( name in the data do generate
                    // errors.

                    var map_state_list []string

                    county_data_new = make(map[string]int)

                    // first, make a list of all states in the map using
                    // state_data as the source of state names
                    for _, g := range mapsvg_obj.G {
                        for state, _ := range state_data {
                            if s.Index(g.Id, state + "_") == 0 {
                                map_state_list = append(map_state_list, state + "_")
                            }
                        }
                    }

                    // next, search county names in data for states found in
                    // the map and copy only county data entries for those
                    // found states
                    for state_county, sc_count := range mapdata {
                        found_state := false
                        for _, state_ := range map_state_list {
                            if s.Index(state_county, state_) == 0 {
                                found_state = true
                                break
                            }
                        }
                        if found_state == true {
                            county_data_new[state_county] = sc_count
                        }
                    }

                    // replace the function-local dataset with the pruned data
                    mapdata = county_data_new
                }

                svg_coloured, errlist := colour_svgdata(mapsvg_obj, mapdata, re_fill, config.Colours, mincount)
                if len(errlist) > 0 {
                    for _, errmsg := range errlist {
                        fmt.Fprintf(os.Stderr, "%s: %s\n", srcfile, errmsg)
                    }
                }

                ret := re_svgext.Find([]byte(dstfile))
                if ret == nil {
                    // going to call ImageMagick's 'convert' because I can't find
                    // a damn SVG package that can write to a non-SVG image and I
                    // don't have the chops to write one.
                    cmd := exec.Command("convert", "svg:-", "-resize", outsize, dstfile)
                    convert_stdin, err := cmd.StdinPipe()
                    if err != nil {
                        log.Fatal(err)
                    }
                    go func() {
                        defer convert_stdin.Close()
                        io.WriteString(convert_stdin, svg_coloured)
                    }()
                    _, err = cmd.CombinedOutput()
                    if err != nil {
                        log.Fatal(err)
                    }
                } else {
                    // just going back to an SVG file
                    err := ioutil.WriteFile(dstfile, []byte(svg_coloured), 0666)
                    if err != nil {
                        fmt.Fprintf(os.Stderr, "can't write to '" + dstfile + "': " + err.Error())
                        return
                    }
                }

            }(infile, attrs["outfile"], attrs["outsize"], maptype, data)
        }
    }

    wg.Wait()

}

// vim:ts=4:et:
// ex:ai:sw=4:ts=1000:
<|endoftext|>


<commit_before>package tinygraph

import "errors"

// MatrixType is log 2 of the datum size
type MatrixType uint8

const (
	Bit MatrixType = iota
	TwoBit
	FourBit
	Byte
	SixteenBit
	ThirtyTwoBit
	Long
)

const (
	WordSize    = uint8(64)
	WordSizeExp = uint8(6)
)

var (
	ErrOutOfBounds        = errors.New("Bit requested is outside the matrix bounds")
	_              Matrix = &ArrayMatrix{}
)

type Matrix interface {
	Set(i, j uint32) error
	Get(i, j uint32) uint8
	Transpose() Matrix
}

type ArrayMatrix struct {
	Words       []uint64
	Size        uint32
	LastIndex   uint32
	WordsPerRow uint32
	MType       MatrixType
}

func NewArrayMatrix(mtype MatrixType, size uint32) Matrix {
	matrix := &ArrayMatrix{
		Size:      size,
		LastIndex: size - 1,
		MType:     mtype,
	}
	// calculate the number of words required to store a square matrix of size
	// rows with size mtype cells per row.  Each row begins with a new uint64,
	// to avoid inefficient rebuilding of a row that starts in the middle of
	// a uint64.
	// Shift to get number of bits per row
	bitsPerRow := size << mtype
	// Ceiling division to get number of words per row
	matrix.WordsPerRow = ((bitsPerRow - 1) >> WordSizeExp) + 1
	// Now multiply by size to get total number of words required to store the
	// matrix
	matrix.Words = make([]uint64, size*matrix.WordsPerRow)
	return matrix
}

func (m *ArrayMatrix) GetWord(i uint32) uint32 {
	return uint32(i << m.MType >> WordSizeExp)
}

func (m *ArrayMatrix) Set(i, j uint32) error {
	if i > m.LastIndex || j > m.LastIndex {
		return ErrOutOfBounds
	}
	m.GetWord(i)
	return nil
}

func (m *ArrayMatrix) Get(i, j uint32) uint8 {
	var result uint8
	return result
}

func (m *ArrayMatrix) Transpose() Matrix {
	return &Transposed{m}
}
<commit_msg>Add some docs<commit_after>package tinygraph

import "errors"

// MatrixType is log 2 of the cell size
type MatrixType uint8

const (
	// Bit is a single-bit cell
	Bit MatrixType = iota
	// TwoBit is a two-bit cell
	TwoBit
	// FourBit is a four-bit cell
	FourBit
	// Byte is an eight-bit cell
	Byte
	// SixteenBit is a sixteen-bit cell
	SixteenBit
	// ThirtyTwoBit is a thirty-two-bit cell
	ThirtyTwoBit
	// Long is a sixty-four-bit cell
	Long
)

const (
	// WordSize is the size of the word we will be using to store the matrix
	WordSize = uint8(64)
	// WordSizeExp is log 2 of the word size
	WordSizeExp = uint8(6)
)

var (
	// ErrOutOfBounds is returned when a coordinate outside the bounds of the
	// matrix is requested or set
	ErrOutOfBounds        = errors.New("Bit requested is outside the matrix bounds")
	_              Matrix = &ArrayMatrix{}
)

// Matrix is a 2-dimensional square matrix.
type Matrix interface {
	Set(i, j uint32) error
	Get(i, j uint32) uint8
	Transpose() Matrix
}

// ArrayMatrix is an implementation of Matrix that stores cells as
// a 1-dimensional array of uint64s
type ArrayMatrix struct {
	Words       []uint64
	Size        uint32
	LastIndex   uint32
	WordsPerRow uint32
	MType       MatrixType
}

// NewArrayMatrix creates a new matrix with a given cell size and given dimensions
func NewArrayMatrix(mtype MatrixType, size uint32) Matrix {
	matrix := &ArrayMatrix{
		Size:      size,
		LastIndex: size - 1,
		MType:     mtype,
	}
	// calculate the number of words required to store a square matrix of size
	// rows with size mtype cells per row.  Each row begins with a new uint64,
	// to avoid inefficient rebuilding of a row that starts in the middle of
	// a uint64.
	// Shift to get number of bits per row
	bitsPerRow := size << mtype
	// Ceiling division to get number of words per row
	matrix.WordsPerRow = ((bitsPerRow - 1) >> WordSizeExp) + 1
	// Now multiply by size to get total number of words required to store the
	// matrix
	matrix.Words = make([]uint64, size*matrix.WordsPerRow)
	return matrix
}

// GetWord returns the index of the word that contains the coordinate specified
func (m *ArrayMatrix) GetWord(i uint32) uint32 {
	return uint32(i << m.MType >> WordSizeExp)
}

// Set sets the principal bit of the cell at the coordinates requested
func (m *ArrayMatrix) Set(i, j uint32) error {
	if i > m.LastIndex || j > m.LastIndex {
		return ErrOutOfBounds
	}
	m.GetWord(i)
	return nil
}

// Get gets the principal bit of the cell at the coordinates requested
func (m *ArrayMatrix) Get(i, j uint32) uint8 {
	var result uint8
	return result
}

// Transpose returns a view of the matrix with the axes transposed
func (m *ArrayMatrix) Transpose() Matrix {
	return &Transposed{m}
}
<|endoftext|>


<commit_before>package cryptfs

// CryptFS methods that translate offsets between ciphertext and plaintext

// get the block number at plain-text offset
func (be *CryptFS) PlainOffToBlockNo(plainOffset uint64) uint64 {
	return plainOffset / be.plainBS
}

// get the block number at ciphter-text offset
func (be *CryptFS) CipherOffToBlockNo(cipherOffset uint64) uint64 {
	return (cipherOffset - HEADER_LEN) / be.cipherBS
}

// get ciphertext offset of block "blockNo"
func (be *CryptFS) BlockNoToCipherOff(blockNo uint64) uint64 {
	return HEADER_LEN + blockNo*be.cipherBS
}

// get plaintext offset of block "blockNo"
func (be *CryptFS) BlockNoToPlainOff(blockNo uint64) uint64 {
	return blockNo * be.plainBS
}

// PlainSize - calculate plaintext size from ciphertext size
func (be *CryptFS) CipherSizeToPlainSize(cipherSize uint64) uint64 {

	// Zero sized files stay zero-sized
	if cipherSize == 0 {
		return 0
	}

	// Block number at last byte
	blockNo := be.CipherOffToBlockNo(cipherSize - 1)
	blockCount := blockNo + 1

	overhead := BLOCK_OVERHEAD*blockCount + HEADER_LEN

	return cipherSize - overhead
}

// CipherSize - calculate ciphertext size from plaintext size
func (be *CryptFS) PlainSizeToCipherSize(plainSize uint64) uint64 {

	// Block number at last byte
	blockNo := be.PlainOffToBlockNo(plainSize - 1)
	blockCount := blockNo + 1

	overhead := BLOCK_OVERHEAD*blockCount + HEADER_LEN

	return plainSize + overhead
}

// Split a plaintext byte range into (possibly partial) blocks
func (be *CryptFS) ExplodePlainRange(offset uint64, length uint64) []intraBlock {
	var blocks []intraBlock
	var nextBlock intraBlock
	nextBlock.fs = be

	for length > 0 {
		nextBlock.BlockNo = be.PlainOffToBlockNo(offset)
		nextBlock.Skip = offset - be.BlockNoToPlainOff(nextBlock.BlockNo)

		// Minimum of remaining data and remaining space in the block
		nextBlock.Length = MinUint64(length, be.plainBS-nextBlock.Skip)

		blocks = append(blocks, nextBlock)
		offset += nextBlock.Length
		length -= nextBlock.Length
	}
	return blocks
}

func MinUint64(x uint64, y uint64) uint64 {
	if x < y {
		return x
	}
	return y
}
<commit_msg>CipherSizeToPlainSize: Handle illegal states<commit_after>package cryptfs

// CryptFS methods that translate offsets between ciphertext and plaintext

// get the block number at plain-text offset
func (be *CryptFS) PlainOffToBlockNo(plainOffset uint64) uint64 {
	return plainOffset / be.plainBS
}

// get the block number at ciphter-text offset
func (be *CryptFS) CipherOffToBlockNo(cipherOffset uint64) uint64 {
	return (cipherOffset - HEADER_LEN) / be.cipherBS
}

// get ciphertext offset of block "blockNo"
func (be *CryptFS) BlockNoToCipherOff(blockNo uint64) uint64 {
	return HEADER_LEN + blockNo*be.cipherBS
}

// get plaintext offset of block "blockNo"
func (be *CryptFS) BlockNoToPlainOff(blockNo uint64) uint64 {
	return blockNo * be.plainBS
}

// PlainSize - calculate plaintext size from ciphertext size
func (be *CryptFS) CipherSizeToPlainSize(cipherSize uint64) uint64 {

	// Zero sized files stay zero-sized
	if cipherSize == 0 {
		return 0
	}

	if cipherSize == HEADER_LEN {
		Warn.Printf("cipherSize %d == header size: interrupted write?\n", cipherSize)
		return 0
	}

	if cipherSize < HEADER_LEN {
		Warn.Printf("cipherSize %d < header size: corrupt file\n", cipherSize)
		return 0
	}

	// Block number at last byte
	blockNo := be.CipherOffToBlockNo(cipherSize - 1)
	blockCount := blockNo + 1

	overhead := BLOCK_OVERHEAD*blockCount + HEADER_LEN

	return cipherSize - overhead
}

// CipherSize - calculate ciphertext size from plaintext size
func (be *CryptFS) PlainSizeToCipherSize(plainSize uint64) uint64 {

	// Block number at last byte
	blockNo := be.PlainOffToBlockNo(plainSize - 1)
	blockCount := blockNo + 1

	overhead := BLOCK_OVERHEAD*blockCount + HEADER_LEN

	return plainSize + overhead
}

// Split a plaintext byte range into (possibly partial) blocks
func (be *CryptFS) ExplodePlainRange(offset uint64, length uint64) []intraBlock {
	var blocks []intraBlock
	var nextBlock intraBlock
	nextBlock.fs = be

	for length > 0 {
		nextBlock.BlockNo = be.PlainOffToBlockNo(offset)
		nextBlock.Skip = offset - be.BlockNoToPlainOff(nextBlock.BlockNo)

		// Minimum of remaining data and remaining space in the block
		nextBlock.Length = MinUint64(length, be.plainBS-nextBlock.Skip)

		blocks = append(blocks, nextBlock)
		offset += nextBlock.Length
		length -= nextBlock.Length
	}
	return blocks
}

func MinUint64(x uint64, y uint64) uint64 {
	if x < y {
		return x
	}
	return y
}
<|endoftext|>


<commit_before>// Copyright (C) 2015 Nicolas Lamirault <nicolas.lamirault@gmail.com>

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package storage

import (
	//"fmt"
	"testing"
)

func Test_GetNotSupportedBackend(t *testing.T) {
	backend, err := InitStorage(
		"google", &Config{Data: "/tmp/google.db"})
	if backend != nil || err == nil {
		t.Fatalf("Error retrieve an invalid backend")
	}
}

func Test_GetMemDBBackend(t *testing.T) {
	backend, err := InitStorage("memdb", &Config{Data: "/tmp"})
	if err != nil || backend == nil {
		t.Fatalf("Error retrieve MemDB backend %v.", err)
	}
}

func Test_GetBoltDBBackend(t *testing.T) {
	backend, err := InitStorage(
		"boltdb", &Config{Data: "/tmp/foo.db"})
	if err != nil || backend == nil {
		t.Fatalf("Error retrieve BoltDB backend %v.", err)
	}
}

func Test_GetLevelDBBackend(t *testing.T) {
	backend, err := InitStorage(
		"leveldb", &Config{Data: "/tmp"})
	if err != nil || backend == nil {
		t.Fatalf("Error retrieve LevelDB backend %v.", err)
	}
}

func Test_GetRedisBackend(t *testing.T) {
	backend, err := InitStorage(
		"redis", &Config{Port: "6379"})
	if err != nil || backend == nil {
		t.Fatalf("Error retrieve Redis backend %v.", err)
	}
}
<commit_msg>Add MongoDB unit tests<commit_after>// Copyright (C) 2015 Nicolas Lamirault <nicolas.lamirault@gmail.com>

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package storage

import (
	//"fmt"
	"testing"
)

func Test_GetNotSupportedBackend(t *testing.T) {
	backend, err := InitStorage(
		"google", &Config{Data: "/tmp/google.db"})
	if backend != nil || err == nil {
		t.Fatalf("Error retrieve an invalid backend")
	}
}

func Test_GetMemDBBackend(t *testing.T) {
	backend, err := InitStorage("memdb", &Config{Data: "/tmp"})
	if err != nil || backend == nil {
		t.Fatalf("Error retrieve MemDB backend %v.", err)
	}
}

func Test_GetBoltDBBackend(t *testing.T) {
	backend, err := InitStorage(
		"boltdb", &Config{Data: "/tmp/foo.db"})
	if err != nil || backend == nil {
		t.Fatalf("Error retrieve BoltDB backend %v.", err)
	}
}

func Test_GetLevelDBBackend(t *testing.T) {
	backend, err := InitStorage(
		"leveldb", &Config{Data: "/tmp"})
	if err != nil || backend == nil {
		t.Fatalf("Error retrieve LevelDB backend %v.", err)
	}
}

func Test_GetRedisBackend(t *testing.T) {
	backend, err := InitStorage(
		"redis", &Config{BackendURL: "127.0.0.1:6379"})
	if err != nil || backend == nil {
		t.Fatalf("Error retrieve Redis backend %v.", err)
	}
}

func Test_GetMongoDBBackend(t *testing.T) {
	backend, err := InitStorage(
		"mongodb", &Config{BackendURL: "127.0.0.1:27017"})
	if err != nil || backend == nil {
		t.Fatalf("Error retrieve MongoDB backend %v.", err)
	}
}
<|endoftext|>


<commit_before>package umarell

import (
	"fmt"
	"log"
)

type buildver struct {
	// sha1 records the previous version compared to build.sha1.
	sha1  string
	build *build
}

type mergereq struct {
	notif *notif
	build *build
}

func newMergereq(notif *notif, build *build) *mergereq {
	return &mergereq{
		notif: notif,
		build: build,
	}
}

type checkout struct {
	stage string
	dir   string
	ver   buildver
}

func newCheckout(stage, dir string, ver buildver) *checkout {
	return &checkout{
		dir:   dir,
		stage: stage,
		ver:   ver,
	}
}

type mergebot struct {
	project   string
	checkouts map[string]*checkout // stage : checkout
	vers      map[string]*buildver // stage : version
	reqs      chan *mergereq
	srv       *server
}

func newMergebot(project string, s *server) *mergebot {
	b := &mergebot{
		project:   project,
		srv:       s,
		checkouts: make(map[string]*checkout),
		vers:      make(map[string]*buildver),
		reqs:      make(chan *mergereq),
	}
	return b
}

func (b *mergebot) addCheckout(dir string, notif *notif, build *build) {
	bv := buildver{
		sha1:  notif.sha1,
		build: build,
	}
	b.checkouts[build.stage] = newCheckout(build.stage, dir, bv)
	log.Printf("[mergebot] %s: init %s to %s using stage %s", b.project, notif.branch, notif.sha1, build.stage)
}

func (b *mergebot) registerBuild(req *mergereq) {
	bv := b.vers[req.build.stage]
	if bv == nil {
		bv = &buildver{
			build: req.build,
		}
	}
	bv.sha1 = req.notif.sha1
	b.vers[req.build.stage] = bv
	log.Printf("[mergebot] %s: set latest revision to %s stage %s", b.project, req.notif.sha1, req.build.stage)
}

func (b *mergebot) checkMerged(notif *notif, co *checkout, pjs *projects) error {
	ver := co.ver
	// Not a merge, just a commit to a mergeable branch.
	if ver.build.stage == co.stage {
		log.Printf("[mergebot] %s: direct commit to %s ignored", b.project, ver.build.stage)
		return nil
	}
	// Do not attempt to merge a checked out stage.
	if _, ok := b.checkouts[ver.build.stage]; ok {
		log.Printf("[mergebot] %s: merge to %s ignored", b.project, ver.build.stage)
		return nil
	}
	log.Printf("[mergebot] %s: checking that %s from %s has been merged to %s", b.project, ver.sha1, ver.build.stage, co.stage)
	commits := newGitcommits()
	if ver.sha1 == "" {
		return fmt.Errorf("cannot fetch commits since last build, last SHA1 is empty", b.project)
	}
	if err := commits.since(ver.sha1, co.dir); err != nil {
		return fmt.Errorf("%s: can't fetch commits since %s: %s", co.dir, ver.sha1, err)
	}
	merged := make([]string, 0) // merged stages to remove
	for k, bv := range b.vers {
		if commits.contains(githash(bv.sha1)) {
			log.Printf("[mergebot] %s: can remove env %s, it was merged", b.project, bv.build.stage)
			b.srv.urls.del(bv.build.stage)
			// As we have been called by pjs, to make a request we need to wait for the current one to finish.
			// To avoid a deadlock, we must notify of the merge in the background.
			go pjs.merge(bv.build, notif)
			merged = append(merged, k)
		}
	}
	for _, k := range merged {
		delete(b.vers, k)
	}
	return nil
}

func (b *mergebot) send(req *mergereq) {
	b.reqs <- req
}

func (b *mergebot) run(pjs *projects) {
	for req := range b.reqs {
		b.doReq(req, pjs)
	}
}

func (b *mergebot) doReq(req *mergereq, pjs *projects) {
	co, hasCheckout := b.checkouts[req.build.stage]
	if !hasCheckout {
		// normally update some tracked version
		b.registerBuild(req)
		return
	}
	// It's a push to a checked out stage, trigger the delete etc
	if err := b.checkMerged(req.notif, co, pjs); err != nil {
		log.Printf("[mergebot] %s: failed merge check: %s", b.project, err)
	}
	co.ver.sha1 = req.notif.sha1
	log.Printf("[mergebot] %s: merge check done, set latest revision to %s stage %s", b.project, req.notif.sha1, co.ver.build.stage)
}

type mergebots map[string]*mergebot // project : mergebots

func makeMergebots() mergebots {
	return mergebots(make(map[string]*mergebot))
}

func (m mergebots) get(project string) *mergebot {
	return m[project]
}

func (m mergebots) create(project string, s *server) *mergebot {
	b := newMergebot(project, s)
	m[project] = b
	return b
}
<commit_msg>Remove invalid check for same env in merge detector<commit_after>package umarell

import (
	"fmt"
	"log"
)

type buildver struct {
	// sha1 records the previous version compared to build.sha1.
	sha1  string
	build *build
}

type mergereq struct {
	notif *notif
	build *build
}

func newMergereq(notif *notif, build *build) *mergereq {
	return &mergereq{
		notif: notif,
		build: build,
	}
}

type checkout struct {
	stage string
	dir   string
	ver   buildver
}

func newCheckout(stage, dir string, ver buildver) *checkout {
	return &checkout{
		dir:   dir,
		stage: stage,
		ver:   ver,
	}
}

type mergebot struct {
	project   string
	checkouts map[string]*checkout // stage : checkout
	vers      map[string]*buildver // stage : version
	reqs      chan *mergereq
	srv       *server
}

func newMergebot(project string, s *server) *mergebot {
	b := &mergebot{
		project:   project,
		srv:       s,
		checkouts: make(map[string]*checkout),
		vers:      make(map[string]*buildver),
		reqs:      make(chan *mergereq),
	}
	return b
}

func (b *mergebot) addCheckout(dir string, notif *notif, build *build) {
	bv := buildver{
		sha1:  notif.sha1,
		build: build,
	}
	b.checkouts[build.stage] = newCheckout(build.stage, dir, bv)
	log.Printf("[mergebot] %s: init %s to %s using stage %s", b.project, notif.branch, notif.sha1, build.stage)
}

func (b *mergebot) registerBuild(req *mergereq) {
	bv := b.vers[req.build.stage]
	if bv == nil {
		bv = &buildver{
			build: req.build,
		}
	}
	bv.sha1 = req.notif.sha1
	b.vers[req.build.stage] = bv
	log.Printf("[mergebot] %s: set latest revision to %s stage %s", b.project, req.notif.sha1, req.build.stage)
}

func (b *mergebot) checkMerged(notif *notif, co *checkout, pjs *projects) error {
	ver := co.ver
	// Do not attempt to merge a checked out stage.
	if _, ok := b.checkouts[ver.build.stage]; ok {
		log.Printf("[mergebot] %s: merge to %s ignored", b.project, ver.build.stage)
		return nil
	}
	log.Printf("[mergebot] %s: checking that %s from %s has been merged to %s", b.project, ver.sha1, ver.build.stage, co.stage)
	commits := newGitcommits()
	if ver.sha1 == "" {
		return fmt.Errorf("cannot fetch commits since last build, last SHA1 is empty", b.project)
	}
	if err := commits.since(ver.sha1, co.dir); err != nil {
		return fmt.Errorf("%s: can't fetch commits since %s: %s", co.dir, ver.sha1, err)
	}
	merged := make([]string, 0) // merged stages to remove
	for k, bv := range b.vers {
		if commits.contains(githash(bv.sha1)) {
			log.Printf("[mergebot] %s: can remove env %s, it was merged", b.project, bv.build.stage)
			b.srv.urls.del(bv.build.stage)
			// As we have been called by pjs, to make a request we need to wait for the current one to finish.
			// To avoid a deadlock, we must notify of the merge in the background.
			go pjs.merge(bv.build, notif)
			merged = append(merged, k)
		}
	}
	for _, k := range merged {
		delete(b.vers, k)
	}
	return nil
}

func (b *mergebot) send(req *mergereq) {
	b.reqs <- req
}

func (b *mergebot) run(pjs *projects) {
	for req := range b.reqs {
		b.doReq(req, pjs)
	}
}

func (b *mergebot) doReq(req *mergereq, pjs *projects) {
	co, hasCheckout := b.checkouts[req.build.stage]
	if !hasCheckout {
		// normally update some tracked version
		b.registerBuild(req)
		return
	}
	// It's a push to a checked out stage, trigger the delete etc
	if err := b.checkMerged(req.notif, co, pjs); err != nil {
		log.Printf("[mergebot] %s: failed merge check: %s", b.project, err)
	}
	co.ver.sha1 = req.notif.sha1
	log.Printf("[mergebot] %s: merge check done, set latest revision to %s stage %s", b.project, req.notif.sha1, co.ver.build.stage)
}

type mergebots map[string]*mergebot // project : mergebots

func makeMergebots() mergebots {
	return mergebots(make(map[string]*mergebot))
}

func (m mergebots) get(project string) *mergebot {
	return m[project]
}

func (m mergebots) create(project string, s *server) *mergebot {
	b := newMergebot(project, s)
	m[project] = b
	return b
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"time"
)

const (
	TIME_OUT = 30

	ORIGIN   = "GAUGE"
	DELTA_PS = "COUNTER"
	DELTA    = ""
)

// COUNTER: Speed per second
// GAUGE: Original, DEFAULT
var DataType = map[string]string{
	"Innodb_buffer_pool_reads":         DELTA_PS,
	"Innodb_buffer_pool_read_requests": DELTA_PS,
	"Innodb_compress_time":             DELTA_PS,
	"Innodb_data_fsyncs":               DELTA_PS,
	"Innodb_data_read":                 DELTA_PS,
	"Innodb_data_reads":                DELTA_PS,
	"Innodb_data_writes":               DELTA_PS,
	"Innodb_data_written":              DELTA_PS,
	"Innodb_last_checkpoint_at":        DELTA_PS,
	"Innodb_log_flushed_up_to":         DELTA_PS,
	"Innodb_log_sequence_number":       DELTA_PS,
	"Innodb_mutex_os_waits":            DELTA_PS,
	"Innodb_mutex_spin_rounds":         DELTA_PS,
	"Innodb_mutex_spin_waits":          DELTA_PS,
	"Innodb_pages_flushed_up_to":       DELTA_PS,
	"Innodb_rows_deleted":              DELTA_PS,
	"Innodb_rows_inserted":             DELTA_PS,
	"Innodb_rows_locked":               DELTA_PS,
	"Innodb_rows_modified":             DELTA_PS,
	"Innodb_rows_read":                 DELTA_PS,
	"Innodb_rows_updated":              DELTA_PS,
	"Innodb_row_lock_time":             DELTA_PS,
	"Innodb_row_lock_waits":            DELTA_PS,
	"Innodb_uncompress_time":           DELTA_PS,

	"Binlog_event_count": DELTA_PS,
	"Binlog_number":      DELTA_PS,
	"Slave_count":        DELTA_PS,

	"Com_admin_commands":        DELTA_PS,
	"Com_assign_to_keycache":    DELTA_PS,
	"Com_alter_db":              DELTA_PS,
	"Com_alter_db_upgrade":      DELTA_PS,
	"Com_alter_event":           DELTA_PS,
	"Com_alter_function":        DELTA_PS,
	"Com_alter_procedure":       DELTA_PS,
	"Com_alter_server":          DELTA_PS,
	"Com_alter_table":           DELTA_PS,
	"Com_alter_tablespace":      DELTA_PS,
	"Com_analyze":               DELTA_PS,
	"Com_begin":                 DELTA_PS,
	"Com_binlog":                DELTA_PS,
	"Com_call_procedure":        DELTA_PS,
	"Com_change_db":             DELTA_PS,
	"Com_change_master":         DELTA_PS,
	"Com_check":                 DELTA_PS,
	"Com_checksum":              DELTA_PS,
	"Com_commit":                DELTA_PS,
	"Com_create_db":             DELTA_PS,
	"Com_create_event":          DELTA_PS,
	"Com_create_function":       DELTA_PS,
	"Com_create_index":          DELTA_PS,
	"Com_create_procedure":      DELTA_PS,
	"Com_create_server":         DELTA_PS,
	"Com_create_table":          DELTA_PS,
	"Com_create_trigger":        DELTA_PS,
	"Com_create_udf":            DELTA_PS,
	"Com_create_user":           DELTA_PS,
	"Com_create_view":           DELTA_PS,
	"Com_dealloc_sql":           DELTA_PS,
	"Com_delete":                DELTA_PS,
	"Com_delete_multi":          DELTA_PS,
	"Com_do":                    DELTA_PS,
	"Com_drop_db":               DELTA_PS,
	"Com_drop_event":            DELTA_PS,
	"Com_drop_function":         DELTA_PS,
	"Com_drop_index":            DELTA_PS,
	"Com_drop_procedure":        DELTA_PS,
	"Com_drop_server":           DELTA_PS,
	"Com_drop_table":            DELTA_PS,
	"Com_drop_trigger":          DELTA_PS,
	"Com_drop_user":             DELTA_PS,
	"Com_drop_view":             DELTA_PS,
	"Com_empty_query":           DELTA_PS,
	"Com_execute_sql":           DELTA_PS,
	"Com_flush":                 DELTA_PS,
	"Com_grant":                 DELTA_PS,
	"Com_ha_close":              DELTA_PS,
	"Com_ha_open":               DELTA_PS,
	"Com_ha_read":               DELTA_PS,
	"Com_help":                  DELTA_PS,
	"Com_insert":                DELTA_PS,
	"Com_insert_select":         DELTA_PS,
	"Com_install_plugin":        DELTA_PS,
	"Com_kill":                  DELTA_PS,
	"Com_load":                  DELTA_PS,
	"Com_lock_tables":           DELTA_PS,
	"Com_optimize":              DELTA_PS,
	"Com_preload_keys":          DELTA_PS,
	"Com_prepare_sql":           DELTA_PS,
	"Com_purge":                 DELTA_PS,
	"Com_purge_before_date":     DELTA_PS,
	"Com_release_savepoint":     DELTA_PS,
	"Com_rename_table":          DELTA_PS,
	"Com_rename_user":           DELTA_PS,
	"Com_repair":                DELTA_PS,
	"Com_replace":               DELTA_PS,
	"Com_replace_select":        DELTA_PS,
	"Com_reset":                 DELTA_PS,
	"Com_resignal":              DELTA_PS,
	"Com_revoke":                DELTA_PS,
	"Com_revoke_all":            DELTA_PS,
	"Com_rollback":              DELTA_PS,
	"Com_rollback_to_savepoint": DELTA_PS,
	"Com_savepoint":             DELTA_PS,
	"Com_select":                DELTA_PS,
	"Com_set_option":            DELTA_PS,
	"Com_signal":                DELTA_PS,
	"Com_show_authors":          DELTA_PS,
	"Com_show_binlog_events":    DELTA_PS,
	"Com_show_binlogs":          DELTA_PS,
	"Com_show_charsets":         DELTA_PS,
	"Com_show_collations":       DELTA_PS,
	"Com_show_contributors":     DELTA_PS,
	"Com_show_create_db":        DELTA_PS,
	"Com_show_create_event":     DELTA_PS,
	"Com_show_create_func":      DELTA_PS,
	"Com_show_create_proc":      DELTA_PS,
	"Com_show_create_table":     DELTA_PS,
	"Com_show_create_trigger":   DELTA_PS,
	"Com_show_databases":        DELTA_PS,
	"Com_show_engine_logs":      DELTA_PS,
	"Com_show_engine_mutex":     DELTA_PS,
	"Com_show_engine_status":    DELTA_PS,
	"Com_show_events":           DELTA_PS,
	"Com_show_errors":           DELTA_PS,
	"Com_show_fields":           DELTA_PS,
	"Com_show_function_status":  DELTA_PS,
	"Com_show_grants":           DELTA_PS,
	"Com_show_keys":             DELTA_PS,
	"Com_show_master_status":    DELTA_PS,
	"Com_show_open_tables":      DELTA_PS,
	"Com_show_plugins":          DELTA_PS,
	"Com_show_privileges":       DELTA_PS,
	"Com_show_procedure_status": DELTA_PS,
	"Com_show_processlist":      DELTA_PS,
	"Com_show_profile":          DELTA_PS,
	"Com_show_profiles":         DELTA_PS,
	"Com_show_relaylog_events":  DELTA_PS,
	"Com_show_slave_hosts":      DELTA_PS,
	"Com_show_slave_status":     DELTA_PS,
	"Com_show_status":           DELTA_PS,
	"Com_show_storage_engines":  DELTA_PS,
	"Com_show_table_status":     DELTA_PS,
	"Com_show_tables":           DELTA_PS,
	"Com_show_triggers":         DELTA_PS,
	"Com_show_variables":        DELTA_PS,
	"Com_show_warnings":         DELTA_PS,
	"Com_slave_start":           DELTA_PS,
	"Com_slave_stop":            DELTA_PS,
	"Com_stmt_close":            DELTA_PS,
	"Com_stmt_execute":          DELTA_PS,
	"Com_stmt_fetch":            DELTA_PS,
	"Com_stmt_prepare":          DELTA_PS,
	"Com_stmt_reprepare":        DELTA_PS,
	"Com_stmt_reset":            DELTA_PS,
	"Com_stmt_send_long_data":   DELTA_PS,
	"Com_truncate":              DELTA_PS,
	"Com_uninstall_plugin":      DELTA_PS,
	"Com_unlock_tables":         DELTA_PS,
	"Com_update":                DELTA_PS,
	"Com_update_multi":          DELTA_PS,
	"Com_xa_commit":             DELTA_PS,
	"Com_xa_end":                DELTA_PS,
	"Com_xa_prepare":            DELTA_PS,
	"Com_xa_recover":            DELTA_PS,
	"Com_xa_rollback":           DELTA_PS,
	"Com_xa_start":              DELTA_PS,

	"Aborted_clients":            DELTA_PS,
	"Aborted_connects":           DELTA_PS,
	"Access_denied_errors":       DELTA_PS,
	"Binlog_bytes_written":       DELTA_PS,
	"Binlog_cache_disk_use":      DELTA_PS,
	"Binlog_cache_use":           DELTA_PS,
	"Binlog_stmt_cache_disk_use": DELTA_PS,
	"Binlog_stmt_cache_use":      DELTA_PS,
	"Bytes_received":             DELTA_PS,
	"Bytes_sent":                 DELTA_PS,
	"Connections":                DELTA_PS,
	"Created_tmp_disk_tables":    DELTA_PS,
	"Created_tmp_files":          DELTA_PS,
	"Created_tmp_tables":         DELTA_PS,
	"Handler_delete":             DELTA_PS,
	"Handler_read_first":         DELTA_PS,
	"Handler_read_key":           DELTA_PS,
	"Handler_read_last":          DELTA_PS,
	"Handler_read_next":          DELTA_PS,
	"Handler_read_prev":          DELTA_PS,
	"Handler_read_rnd":           DELTA_PS,
	"Handler_read_rnd_next":      DELTA_PS,
	"Handler_update":             DELTA_PS,
	"Handler_write":              DELTA_PS,
	"Opened_files":               DELTA_PS,
	"Opened_tables":              DELTA_PS,
	"Opened_table_definitions":   DELTA_PS,
	"Qcache_hits":                DELTA_PS,
	"Qcache_inserts":             DELTA_PS,
	"Qcache_lowmem_prunes":       DELTA_PS,
	"Qcache_not_cached":          DELTA_PS,
	"Queries":                    DELTA_PS,
	"Questions":                  DELTA_PS,
	"Select_full_join":           DELTA_PS,
	"Select_full_range_join":     DELTA_PS,
	"Select_range_check":         DELTA_PS,
	"Select_scan":                DELTA_PS,
	"Slow_queries":               DELTA_PS,
	"Sort_merge_passes":          DELTA_PS,
	"Sort_range":                 DELTA_PS,
	"Sort_rows":                  DELTA_PS,
	"Sort_scan":                  DELTA_PS,
	"Table_locks_immediate":      DELTA_PS,
	"Table_locks_waited":         DELTA_PS,
	"Threads_created":            DELTA_PS,
}

type MysqlIns struct {
	Host string
	Port int
	Tag  string
}

func dataType(key_ string) string {
	if v, ok := DataType[key_]; ok {
		return v
	}
	return ORIGIN
}

type MetaData struct {
	Metric      string      `json:"metric"`      //key
	Endpoint    string      `json:"endpoint"`    //hostname
	Value       interface{} `json:"value"`       // number or string
	CounterType string      `json:"counterType"` // GAUGE  原值   COUNTER 差值(ps)
	Tags        string      `json:"tags"`        // port=3306,k=v
	Timestamp   int64       `json:"timestamp"`
	Step        int64       `json:"step"`
}

func (m *MetaData) String() string {
	s := fmt.Sprintf("MetaData Metric:%s Endpoint:%s Value:%v CounterType:%s Tags:%s Timestamp:%d Step:%d",
		m.Metric, m.Endpoint, m.Value, m.CounterType, m.Tags, m.Timestamp, m.Step)
	return s
}

func NewMetric(name string) *MetaData {
	return &MetaData{
		Metric:      name,
		Endpoint:    hostname(),
		CounterType: dataType(name),
		Tags:        fmt.Sprintf("port=%d", cfg.Port),
		Timestamp:   time.Now().Unix(),
		Step:        60,
	}
}

func hostname() string {
	host := Cfg.Hostname
    if host != "" {
        return host
    }
	host, err := os.Hostname()
	if err != nil {
		host = cfg.Host
	}
	return host
}

func (m *MetaData) SetValue(v interface{}) {
	m.Value = v
}
<commit_msg>代码格式化<commit_after>package main

import (
	"fmt"
	"os"
	"time"
)

const (
	TIME_OUT = 30

	ORIGIN   = "GAUGE"
	DELTA_PS = "COUNTER"
	DELTA    = ""
)

// COUNTER: Speed per second
// GAUGE: Original, DEFAULT
var DataType = map[string]string{
	"Innodb_buffer_pool_reads":         DELTA_PS,
	"Innodb_buffer_pool_read_requests": DELTA_PS,
	"Innodb_compress_time":             DELTA_PS,
	"Innodb_data_fsyncs":               DELTA_PS,
	"Innodb_data_read":                 DELTA_PS,
	"Innodb_data_reads":                DELTA_PS,
	"Innodb_data_writes":               DELTA_PS,
	"Innodb_data_written":              DELTA_PS,
	"Innodb_last_checkpoint_at":        DELTA_PS,
	"Innodb_log_flushed_up_to":         DELTA_PS,
	"Innodb_log_sequence_number":       DELTA_PS,
	"Innodb_mutex_os_waits":            DELTA_PS,
	"Innodb_mutex_spin_rounds":         DELTA_PS,
	"Innodb_mutex_spin_waits":          DELTA_PS,
	"Innodb_pages_flushed_up_to":       DELTA_PS,
	"Innodb_rows_deleted":              DELTA_PS,
	"Innodb_rows_inserted":             DELTA_PS,
	"Innodb_rows_locked":               DELTA_PS,
	"Innodb_rows_modified":             DELTA_PS,
	"Innodb_rows_read":                 DELTA_PS,
	"Innodb_rows_updated":              DELTA_PS,
	"Innodb_row_lock_time":             DELTA_PS,
	"Innodb_row_lock_waits":            DELTA_PS,
	"Innodb_uncompress_time":           DELTA_PS,

	"Binlog_event_count": DELTA_PS,
	"Binlog_number":      DELTA_PS,
	"Slave_count":        DELTA_PS,

	"Com_admin_commands":        DELTA_PS,
	"Com_assign_to_keycache":    DELTA_PS,
	"Com_alter_db":              DELTA_PS,
	"Com_alter_db_upgrade":      DELTA_PS,
	"Com_alter_event":           DELTA_PS,
	"Com_alter_function":        DELTA_PS,
	"Com_alter_procedure":       DELTA_PS,
	"Com_alter_server":          DELTA_PS,
	"Com_alter_table":           DELTA_PS,
	"Com_alter_tablespace":      DELTA_PS,
	"Com_analyze":               DELTA_PS,
	"Com_begin":                 DELTA_PS,
	"Com_binlog":                DELTA_PS,
	"Com_call_procedure":        DELTA_PS,
	"Com_change_db":             DELTA_PS,
	"Com_change_master":         DELTA_PS,
	"Com_check":                 DELTA_PS,
	"Com_checksum":              DELTA_PS,
	"Com_commit":                DELTA_PS,
	"Com_create_db":             DELTA_PS,
	"Com_create_event":          DELTA_PS,
	"Com_create_function":       DELTA_PS,
	"Com_create_index":          DELTA_PS,
	"Com_create_procedure":      DELTA_PS,
	"Com_create_server":         DELTA_PS,
	"Com_create_table":          DELTA_PS,
	"Com_create_trigger":        DELTA_PS,
	"Com_create_udf":            DELTA_PS,
	"Com_create_user":           DELTA_PS,
	"Com_create_view":           DELTA_PS,
	"Com_dealloc_sql":           DELTA_PS,
	"Com_delete":                DELTA_PS,
	"Com_delete_multi":          DELTA_PS,
	"Com_do":                    DELTA_PS,
	"Com_drop_db":               DELTA_PS,
	"Com_drop_event":            DELTA_PS,
	"Com_drop_function":         DELTA_PS,
	"Com_drop_index":            DELTA_PS,
	"Com_drop_procedure":        DELTA_PS,
	"Com_drop_server":           DELTA_PS,
	"Com_drop_table":            DELTA_PS,
	"Com_drop_trigger":          DELTA_PS,
	"Com_drop_user":             DELTA_PS,
	"Com_drop_view":             DELTA_PS,
	"Com_empty_query":           DELTA_PS,
	"Com_execute_sql":           DELTA_PS,
	"Com_flush":                 DELTA_PS,
	"Com_grant":                 DELTA_PS,
	"Com_ha_close":              DELTA_PS,
	"Com_ha_open":               DELTA_PS,
	"Com_ha_read":               DELTA_PS,
	"Com_help":                  DELTA_PS,
	"Com_insert":                DELTA_PS,
	"Com_insert_select":         DELTA_PS,
	"Com_install_plugin":        DELTA_PS,
	"Com_kill":                  DELTA_PS,
	"Com_load":                  DELTA_PS,
	"Com_lock_tables":           DELTA_PS,
	"Com_optimize":              DELTA_PS,
	"Com_preload_keys":          DELTA_PS,
	"Com_prepare_sql":           DELTA_PS,
	"Com_purge":                 DELTA_PS,
	"Com_purge_before_date":     DELTA_PS,
	"Com_release_savepoint":     DELTA_PS,
	"Com_rename_table":          DELTA_PS,
	"Com_rename_user":           DELTA_PS,
	"Com_repair":                DELTA_PS,
	"Com_replace":               DELTA_PS,
	"Com_replace_select":        DELTA_PS,
	"Com_reset":                 DELTA_PS,
	"Com_resignal":              DELTA_PS,
	"Com_revoke":                DELTA_PS,
	"Com_revoke_all":            DELTA_PS,
	"Com_rollback":              DELTA_PS,
	"Com_rollback_to_savepoint": DELTA_PS,
	"Com_savepoint":             DELTA_PS,
	"Com_select":                DELTA_PS,
	"Com_set_option":            DELTA_PS,
	"Com_signal":                DELTA_PS,
	"Com_show_authors":          DELTA_PS,
	"Com_show_binlog_events":    DELTA_PS,
	"Com_show_binlogs":          DELTA_PS,
	"Com_show_charsets":         DELTA_PS,
	"Com_show_collations":       DELTA_PS,
	"Com_show_contributors":     DELTA_PS,
	"Com_show_create_db":        DELTA_PS,
	"Com_show_create_event":     DELTA_PS,
	"Com_show_create_func":      DELTA_PS,
	"Com_show_create_proc":      DELTA_PS,
	"Com_show_create_table":     DELTA_PS,
	"Com_show_create_trigger":   DELTA_PS,
	"Com_show_databases":        DELTA_PS,
	"Com_show_engine_logs":      DELTA_PS,
	"Com_show_engine_mutex":     DELTA_PS,
	"Com_show_engine_status":    DELTA_PS,
	"Com_show_events":           DELTA_PS,
	"Com_show_errors":           DELTA_PS,
	"Com_show_fields":           DELTA_PS,
	"Com_show_function_status":  DELTA_PS,
	"Com_show_grants":           DELTA_PS,
	"Com_show_keys":             DELTA_PS,
	"Com_show_master_status":    DELTA_PS,
	"Com_show_open_tables":      DELTA_PS,
	"Com_show_plugins":          DELTA_PS,
	"Com_show_privileges":       DELTA_PS,
	"Com_show_procedure_status": DELTA_PS,
	"Com_show_processlist":      DELTA_PS,
	"Com_show_profile":          DELTA_PS,
	"Com_show_profiles":         DELTA_PS,
	"Com_show_relaylog_events":  DELTA_PS,
	"Com_show_slave_hosts":      DELTA_PS,
	"Com_show_slave_status":     DELTA_PS,
	"Com_show_status":           DELTA_PS,
	"Com_show_storage_engines":  DELTA_PS,
	"Com_show_table_status":     DELTA_PS,
	"Com_show_tables":           DELTA_PS,
	"Com_show_triggers":         DELTA_PS,
	"Com_show_variables":        DELTA_PS,
	"Com_show_warnings":         DELTA_PS,
	"Com_slave_start":           DELTA_PS,
	"Com_slave_stop":            DELTA_PS,
	"Com_stmt_close":            DELTA_PS,
	"Com_stmt_execute":          DELTA_PS,
	"Com_stmt_fetch":            DELTA_PS,
	"Com_stmt_prepare":          DELTA_PS,
	"Com_stmt_reprepare":        DELTA_PS,
	"Com_stmt_reset":            DELTA_PS,
	"Com_stmt_send_long_data":   DELTA_PS,
	"Com_truncate":              DELTA_PS,
	"Com_uninstall_plugin":      DELTA_PS,
	"Com_unlock_tables":         DELTA_PS,
	"Com_update":                DELTA_PS,
	"Com_update_multi":          DELTA_PS,
	"Com_xa_commit":             DELTA_PS,
	"Com_xa_end":                DELTA_PS,
	"Com_xa_prepare":            DELTA_PS,
	"Com_xa_recover":            DELTA_PS,
	"Com_xa_rollback":           DELTA_PS,
	"Com_xa_start":              DELTA_PS,

	"Aborted_clients":            DELTA_PS,
	"Aborted_connects":           DELTA_PS,
	"Access_denied_errors":       DELTA_PS,
	"Binlog_bytes_written":       DELTA_PS,
	"Binlog_cache_disk_use":      DELTA_PS,
	"Binlog_cache_use":           DELTA_PS,
	"Binlog_stmt_cache_disk_use": DELTA_PS,
	"Binlog_stmt_cache_use":      DELTA_PS,
	"Bytes_received":             DELTA_PS,
	"Bytes_sent":                 DELTA_PS,
	"Connections":                DELTA_PS,
	"Created_tmp_disk_tables":    DELTA_PS,
	"Created_tmp_files":          DELTA_PS,
	"Created_tmp_tables":         DELTA_PS,
	"Handler_delete":             DELTA_PS,
	"Handler_read_first":         DELTA_PS,
	"Handler_read_key":           DELTA_PS,
	"Handler_read_last":          DELTA_PS,
	"Handler_read_next":          DELTA_PS,
	"Handler_read_prev":          DELTA_PS,
	"Handler_read_rnd":           DELTA_PS,
	"Handler_read_rnd_next":      DELTA_PS,
	"Handler_update":             DELTA_PS,
	"Handler_write":              DELTA_PS,
	"Opened_files":               DELTA_PS,
	"Opened_tables":              DELTA_PS,
	"Opened_table_definitions":   DELTA_PS,
	"Qcache_hits":                DELTA_PS,
	"Qcache_inserts":             DELTA_PS,
	"Qcache_lowmem_prunes":       DELTA_PS,
	"Qcache_not_cached":          DELTA_PS,
	"Queries":                    DELTA_PS,
	"Questions":                  DELTA_PS,
	"Select_full_join":           DELTA_PS,
	"Select_full_range_join":     DELTA_PS,
	"Select_range_check":         DELTA_PS,
	"Select_scan":                DELTA_PS,
	"Slow_queries":               DELTA_PS,
	"Sort_merge_passes":          DELTA_PS,
	"Sort_range":                 DELTA_PS,
	"Sort_rows":                  DELTA_PS,
	"Sort_scan":                  DELTA_PS,
	"Table_locks_immediate":      DELTA_PS,
	"Table_locks_waited":         DELTA_PS,
	"Threads_created":            DELTA_PS,
}

type MysqlIns struct {
	Host string
	Port int
	Tag  string
}

func dataType(key_ string) string {
	if v, ok := DataType[key_]; ok {
		return v
	}
	return ORIGIN
}

type MetaData struct {
	Metric      string      `json:"metric"`      //key
	Endpoint    string      `json:"endpoint"`    //hostname
	Value       interface{} `json:"value"`       // number or string
	CounterType string      `json:"counterType"` // GAUGE  原值   COUNTER 差值(ps)
	Tags        string      `json:"tags"`        // port=3306,k=v
	Timestamp   int64       `json:"timestamp"`
	Step        int64       `json:"step"`
}

func (m *MetaData) String() string {
	s := fmt.Sprintf("MetaData Metric:%s Endpoint:%s Value:%v CounterType:%s Tags:%s Timestamp:%d Step:%d",
		m.Metric, m.Endpoint, m.Value, m.CounterType, m.Tags, m.Timestamp, m.Step)
	return s
}

func NewMetric(name string) *MetaData {
	return &MetaData{
		Metric:      name,
		Endpoint:    hostname(),
		CounterType: dataType(name),
		Tags:        fmt.Sprintf("port=%d", cfg.Port),
		Timestamp:   time.Now().Unix(),
		Step:        60,
	}
}

func hostname() string {
    host := Cfg.Hostname
    if host != "" {
       return host
    }

	host, err := os.Hostname()
	if err != nil {
		host = cfg.Host
	}
	return host
}

func (m *MetaData) SetValue(v interface{}) {
	m.Value = v
}
<|endoftext|>