<commit_before>package models

import (
	"time"
	"reflect"
	"fmt"
	"strings"
)

type Book struct {
	Id				int64		`json: "id"`
	Name 			string		`json: "name"`
	Low_name 		string		`json: "low_name"`
	Author_id		int64		`json: "author_id"`
	Station_id		int64		`json: "station_id"`
	Date			time.Time	`json: "date"`
	Url				string		`json: "url"`
	Author_name 	string		`json: "author_name"`
	Station_name 	string		`json: "station_name"`
}

func (b *Book) Save() (int64, error) {

	stmt, err := db.Prepare("INSERT INTO book(author_id, name, low_name, date, station_id, url) values(?,?,?,?,?,?)")
	if err != nil {
		checkErr(err)
		return 0, err
	}
	defer stmt.Close()

	res, err := stmt.Exec(b.Author_id, strConv(b.Name), strConv(b.Low_name), b.Date, b.Station_id, b.Url)
	if err != nil {
		checkErr(err)
		return 0, err
	}

	b.Id, err = res.LastInsertId()

	return b.Id, err
}

func (b *Book) Update() (err error) {

	_, err = db.Exec(fmt.Sprintf(`UPDATE book SET author_id=%d, date=%s, name="%s", low_name="%s", station_id=%d, url="%s" WHERE id=%d`, b.Author_id, b.Date, strConv(b.Name), strConv(b.Low_name), b.Station_id, b.Url,  b.Id))
	if err != nil {
		checkErr(err)
		return
	}

	return
}

func (b *Book) AddFile(file *File) (err error) {

	file.Book_id = b.Id
	return file.Update()
}

func (b *Book) Remove() (err error) {
	return BookRemove(b.Id)
}

func (b *Book) FileExist(file *File) bool {

	if file != nil {
		return b.Id == file.Book_id
	}

	return false
}

func (b *Book) Files() ([]*File, error) {

	return FileGetAllByBook(b)
}

func BookRemove(id int64) (err error) {

	stmt, err := db.Prepare(`DELETE FROM book WHERE id=?`)
	if err != nil {
		checkErr(err)
		return
	}
	defer stmt.Close()

	res, err := stmt.Exec(id)
	if err != nil {
		checkErr(err)
		return
	}

	_, err = res.RowsAffected()

	return
}

func BookGet(val interface{}) (book *Book, err error) {

	book = new(Book)

	switch reflect.TypeOf(val).Name() {
	case "int":
		id := val.(int)
		rows, err := db.Query(fmt.Sprintf(`SELECT * FROM book WHERE id=%d LIMIT 1`, id))
		if err != nil {
			checkErr(err)
			return nil, err
		}
		defer rows.Close()

		for rows.Next() {
			if rows != nil {
				rows.Scan(&book.Author_id, &book.Date, &book.Id, &book.Name, &book.Low_name, &book.Station_id, &book.Url)
				book.Id = int64(id)
				return book, nil
			}
		}

	case "string":
		var name string = strConv(val.(string))
		rows, err := db.Query(fmt.Sprintf(`SELECT * FROM book WHERE name="%s" LIMIT 1`, name))
		if err != nil {
			checkErr(err)
			return nil, err
		}
		defer rows.Close()

		for rows.Next() {
			if rows != nil {
				rows.Scan(&book.Author_id, &book.Date, &book.Id, &book.Name, &book.Low_name, &book.Station_id, &book.Url)
				book.Name = name
				return book, nil
			}
		}
	}

	return nil, fmt.Errorf("book not found")
}

func BookGetAll(arg interface{}) (books []*Book, err error) {

	switch reflect.TypeOf(arg).String() {
	case "*models.Author":
		return  getAllByAuthor(arg.(*Author))
	case "*models.Station":
		return  getAllByStation(arg.(*Station))
	default:
		break
	}

	return
}

func getAllByAuthor(author *Author) (books []*Book, err error) {

	books = make([]*Book, 0)	//[]

	rows, err := db.Query(fmt.Sprintf(`SELECT * FROM book WHERE author_id=%d`, author.Id))
	if err != nil {
		checkErr(err)
		return
	}
	defer rows.Close()

	for rows.Next() {

		if rows != nil {
			book := new(Book)
			rows.Scan(&book.Id, &book.Author_id, &book.Name, &book.Low_name, &book.Date, &book.Station_id, &book.Url)
			books = append(books, book)
		}
	}

	return
}

func getAllByStation(station *Station) (books []*Book, err error) {

	books = make([]*Book, 0)	//[]

	rows, err := db.Query(fmt.Sprintf(`SELECT * FROM book WHERE station_id=%d`, station.Id))
	if err != nil {
		checkErr(err)
		return
	}
	defer rows.Close()

	for rows.Next() {

		if rows != nil {
			book := new(Book)
			rows.Scan(&book.Id, &book.Author_id, &book.Name, &book.Low_name, &book.Date, &book.Station_id, &book.Url)
			books = append(books, book)
		}
	}

	return
}

func strConv(str string) string {
	return strings.Replace(str, "\"", "", -1)
}

func (b *Book) Play() (err error) {

	return nil
}

func BookFind(book, author string, page, limit int) (books []*Book, total_items int32, err error) {

	if page > 0 {
		page -= 1
	} else {
		page = 0
	}

	books = make([]*Book, 0)	//[]

	query := fmt.Sprintf(`
		select result.*
		from
		(
			SELECT book.*
			from book, author
			WHERE book.low_name LIKE "%s" and author.low_name like "%s" AND book.author_id=author.id
		   order by book.id
		) result
	`, "%"+book+"%", "%"+author+"%")

	// rows count
	total_rows, err := db.Query(query)
	if err != nil {
		return
	}
	defer total_rows.Close()

	for total_rows.Next() {
		total_items++
	}

	// bookd page
	query = fmt.Sprintf(`
		select result.*, author.name as author_name , station.name as station_name

		from
		(
			SELECT book.*
			from book, author
			WHERE  book.low_name LIKE "%s" and author.low_name like "%s" AND book.author_id=author.id
		   order by book.id LIMIT "%d" OFFSET "%d"
		) result

		INNer JOIN author author on author.id = result.author_id
		INNer JOIN station station on station.id = result.station_id
	`, "%"+book+"%", "%"+author+"%", limit, page)
	rows, err := db.Query(query)
	if err != nil {
		return
	}
	defer rows.Close()

	for rows.Next() {
		book := new(Book)
		err = rows.Scan(&book.Author_id, &book.Date, &book.Id, &book.Name, &book.Station_id, &book.Url, &book.Low_name, &book.Author_name, &book.Station_name)
		if err != nil {
			return
		}

		books = append(books, book)
	}

	return
}<commit_msg>history<commit_after>package models

import (
	"time"
	"reflect"
	"fmt"
	"strings"
)

type Book struct {
	Id				int64		`json: "id"`
	Name 			string		`json: "name"`
	Low_name 		string		`json: "low_name"`
	Author_id		int64		`json: "author_id"`
	Station_id		int64		`json: "station_id"`
	Date			time.Time	`json: "date"`
	Url				string		`json: "url"`
	Author_name 	string		`json: "author_name"`
	Station_name 	string		`json: "station_name"`
	Last_play	 	interface{}	`json: "last_play"`
	Play_count 		int64		`json: "play_count"`
}

func (b *Book) Save() (int64, error) {

	stmt, err := db.Prepare("INSERT INTO book(author_id, name, low_name, date, station_id, url) values(?,?,?,?,?,?)")
	if err != nil {
		checkErr(err)
		return 0, err
	}
	defer stmt.Close()

	res, err := stmt.Exec(b.Author_id, strConv(b.Name), strConv(b.Low_name), b.Date, b.Station_id, b.Url)
	if err != nil {
		checkErr(err)
		return 0, err
	}

	b.Id, err = res.LastInsertId()

	return b.Id, err
}

func (b *Book) Update() (err error) {

	_, err = db.Exec(fmt.Sprintf(`UPDATE book SET author_id=%d, date=%s, name="%s", low_name="%s", station_id=%d, url="%s" WHERE id=%d`, b.Author_id, b.Date, strConv(b.Name), strConv(b.Low_name), b.Station_id, b.Url,  b.Id))
	if err != nil {
		checkErr(err)
		return
	}

	return
}

func (b *Book) AddFile(file *File) (err error) {

	file.Book_id = b.Id
	return file.Update()
}

func (b *Book) Remove() (err error) {
	return BookRemove(b.Id)
}

func (b *Book) FileExist(file *File) bool {

	if file != nil {
		return b.Id == file.Book_id
	}

	return false
}

func (b *Book) Files() ([]*File, error) {

	return FileGetAllByBook(b)
}

func BookRemove(id int64) (err error) {

	stmt, err := db.Prepare(`DELETE FROM book WHERE id=?`)
	if err != nil {
		checkErr(err)
		return
	}
	defer stmt.Close()

	res, err := stmt.Exec(id)
	if err != nil {
		checkErr(err)
		return
	}

	_, err = res.RowsAffected()

	return
}

func BookGet(val interface{}) (book *Book, err error) {

	book = new(Book)

	switch reflect.TypeOf(val).Name() {
	case "int":
		id := val.(int)
		rows, err := db.Query(fmt.Sprintf(`SELECT * FROM book WHERE id=%d LIMIT 1`, id))
		if err != nil {
			checkErr(err)
			return nil, err
		}
		defer rows.Close()

		for rows.Next() {
			if rows != nil {
				rows.Scan(&book.Author_id, &book.Date, &book.Id, &book.Name, &book.Low_name, &book.Station_id, &book.Url)
				book.Id = int64(id)
				return book, nil
			}
		}

	case "string":
		var name string = strConv(val.(string))
		rows, err := db.Query(fmt.Sprintf(`SELECT * FROM book WHERE name="%s" LIMIT 1`, name))
		if err != nil {
			checkErr(err)
			return nil, err
		}
		defer rows.Close()

		for rows.Next() {
			if rows != nil {
				rows.Scan(&book.Author_id, &book.Date, &book.Id, &book.Name, &book.Low_name, &book.Station_id, &book.Url)
				book.Name = name
				return book, nil
			}
		}
	}

	return nil, fmt.Errorf("book not found")
}

func BookGetAll(arg interface{}) (books []*Book, err error) {

	switch reflect.TypeOf(arg).String() {
	case "*models.Author":
		return  getAllByAuthor(arg.(*Author))
	case "*models.Station":
		return  getAllByStation(arg.(*Station))
	default:
		break
	}

	return
}

func getAllByAuthor(author *Author) (books []*Book, err error) {

	books = make([]*Book, 0)	//[]

	rows, err := db.Query(fmt.Sprintf(`SELECT * FROM book WHERE author_id=%d`, author.Id))
	if err != nil {
		checkErr(err)
		return
	}
	defer rows.Close()

	for rows.Next() {

		if rows != nil {
			book := new(Book)
			rows.Scan(&book.Id, &book.Author_id, &book.Name, &book.Low_name, &book.Date, &book.Station_id, &book.Url)
			books = append(books, book)
		}
	}

	return
}

func getAllByStation(station *Station) (books []*Book, err error) {

	books = make([]*Book, 0)	//[]

	rows, err := db.Query(fmt.Sprintf(`SELECT * FROM book WHERE station_id=%d`, station.Id))
	if err != nil {
		checkErr(err)
		return
	}
	defer rows.Close()

	for rows.Next() {

		if rows != nil {
			book := new(Book)
			rows.Scan(&book.Id, &book.Author_id, &book.Name, &book.Low_name, &book.Date, &book.Station_id, &book.Url)
			books = append(books, book)
		}
	}

	return
}

func strConv(str string) string {
	return strings.Replace(str, "\"", "", -1)
}

func (b *Book) Play() (err error) {

	return nil
}

func BookFind(book, author string, page, limit int) (books []*Book, total_items int32, err error) {

	if page > 0 {
		page -= 1
	} else {
		page = 0
	}

	books = make([]*Book, 0)	//[]

	query := fmt.Sprintf(`
		select result.*
		from
		(
			SELECT book.*
			from book, author
			WHERE book.low_name LIKE "%s" and author.low_name like "%s" AND book.author_id=author.id
		   order by book.id
		) result
	`, "%"+book+"%", "%"+author+"%")

	// rows count
	total_rows, err := db.Query(query)
	if err != nil {
		return
	}
	defer total_rows.Close()

	for total_rows.Next() {
		total_items++
	}

	// bookd page
	query = fmt.Sprintf(`
		select book.*, a.name as author_name, s.name as station_name, history.date as last_play, count(history.date) as play_count

		from book
		JOIN station as s on s.id = book.station_id
		JOIN author as a on a.id = book.author_id
		left JOIN history  history on history.book_id = book.id

		WHERE  book.low_name LIKE "%s"
		and a.low_name like "%s"
		AND book.author_id=a.id

		GROUP BY book.id
		order by book.id
		LIMIT "%d" OFFSET "%d"

	`, "%"+book+"%", "%"+author+"%", limit, page)
	rows, err := db.Query(query)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer rows.Close()

	if err = rows.Err(); err != nil {
		fmt.Println(err.Error())
		return
	}

	for rows.Next() {
		if rows.Err() != nil {
			fmt.Println(rows.Err())
		}

		book := new(Book)
		err = rows.Scan(&book.Author_id, &book.Date, &book.Id, &book.Name, &book.Station_id, &book.Url, &book.Low_name, &book.Author_name, &book.Station_name, &book.Last_play, &book.Play_count)
		if err != nil {
			fmt.Println(err.Error())
			return
		}

		books = append(books, book)
	}

	return
}<|endoftext|>


<commit_before>package thirdpartysw

import (
	"encoding/json"
	"fmt"
	"github.com/golang/glog"
	"github.com/jmuldoon/flac2mp3util/util"
	"io"
	"net/http"
	"os"
	"path/filepath"
)

const (
	thirdpartyswdir  = "./thirdpartysw"
	sourceconfigname = "sources.json"
	dependencyswpath = "./deps"
)

type ThirdPartyer interface {
	ReadURLs() (err error)
	Download() (err error)
}

type ThirdPartyType struct {
	Client       *http.Client
	Dependencies []*Url
}

type Url struct {
	URL string `json:"url"`
}

var thirdParty *ThirdPartyType

func init() {
	thirdParty = &ThirdPartyType{
		Client: &http.Client{},
	}
}

// InitDepsFolder creates the deps (dependencies) folder if it doesn't already
// exist
func initDepsFolder() (err error) {
	abs, err := filepath.Abs(dependencyswpath)
	if err != nil {
		return err
	}
	// if it exists we ignore the error, by not creating the dir
	if _, err := os.Stat(abs); os.IsNotExist(err) {
		os.Mkdir(abs, 0777)
	}
	return nil
}

// Download retrieves the tarballs from the url list given as a parameter.
func (tp *ThirdPartyType) Download() (err error) {
	if err := initDepsFolder(); err != nil {
		return err
	}
	for _, el := range tp.Dependencies {
		resp, err := tp.Client.Get(el.URL)
		if err != nil {
			return err
		}
		defer resp.Body.Close()
		fmt.Printf("%+v\n", resp.Body)
	}
	return nil
}

// decode takes the ThirdPartyType as a receiver to decode the io.Reader json
// structure and store it in the ThirdPartyType's Dependencies field.
func (tp *ThirdPartyType) decode(file io.Reader) (err error) {
	if err = json.NewDecoder(file).Decode(&tp.Dependencies); err != nil {
		return err
	}
	return nil
}

// read takes the ThirdPartyType as a receiver to readin the json information
// from the file specified by the path
func (tp *ThirdPartyType) read(path string) (err error) {
	file, err := os.OpenFile(path, os.O_RDONLY, 0777)
	if err != nil {
		return err
	}
	if err := tp.decode(file); err != nil {
		return err
	}

	return nil
}

// ReadURLs reads in the URLs from the sources.json file and stores them in the
// receiver ThirdPartyType's field Dependencies.
func (tp *ThirdPartyType) ReadURLs() (err error) {
	absPath, err := util.AbsolutePathHelper(thirdpartyswdir, sourceconfigname)
	glog.V(2).Infoln(absPath)
	if err != nil {
		return err
	}
	if err := tp.read(absPath); err != nil {
		return err
	}
	for i, el := range tp.Dependencies {
		glog.V(2).Infof("%d: %s\n", i, el.URL)
	}
	return nil
}
<commit_msg>broken at the http.Client{} use. need to figure out how to get the headers to work for the tarball retrieval<commit_after>package thirdpartysw

import (
	"encoding/json"
	"fmt"
	"github.com/golang/glog"
	"github.com/jmuldoon/flac2mp3util/util"
	"io"
	"net/http"
	"os"
	"path/filepath"
)

const (
	thirdpartyswdir  string = "./thirdpartysw"
	sourceconfigname string = "sources.json"
	dependencyswpath string = "./deps"
	clienttimeout    int    = 300
)

type ThirdPartyer interface {
	ReadURLs() (err error)
	Download() (err error)
}

type ThirdPartyType struct {
	Client       *http.Client
	Dependencies []*Url
}

type Url struct {
	URL string `json:"url"`
}

var thirdParty *ThirdPartyType

func init() {
	thirdParty = &ThirdPartyType{
		Client: &http.Client{
			Timeout: time.Second * 300,
		},
	}
}

// InitDepsFolder creates the deps (dependencies) folder if it doesn't already
// exist
func initDepsFolder() (err error) {
	abs, err := filepath.Abs(dependencyswpath)
	if err != nil {
		return err
	}
	// if it exists we ignore the error, by not creating the dir
	if _, err := os.Stat(abs); os.IsNotExist(err) {
		os.Mkdir(abs, 0777)
	}
	return nil
}

// Download retrieves the tarballs from the url list given as a parameter.
func (tp *ThirdPartyType) Download() (err error) {
	if err := initDepsFolder(); err != nil {
		return err
	}
	for _, el := range tp.Dependencies {
		resp, err := tp.Client.Get(el.URL)
		if err != nil {
			return err
		}
		defer resp.Body.Close()
		fmt.Printf("%+v\n", resp.Body)
	}
	return nil
}

// decode takes the ThirdPartyType as a receiver to decode the io.Reader json
// structure and store it in the ThirdPartyType's Dependencies field.
func (tp *ThirdPartyType) decode(file io.Reader) (err error) {
	if err = json.NewDecoder(file).Decode(&tp.Dependencies); err != nil {
		return err
	}
	return nil
}

// read takes the ThirdPartyType as a receiver to readin the json information
// from the file specified by the path
func (tp *ThirdPartyType) read(path string) (err error) {
	file, err := os.OpenFile(path, os.O_RDONLY, 0777)
	if err != nil {
		return err
	}
	if err := tp.decode(file); err != nil {
		return err
	}

	return nil
}

// ReadURLs reads in the URLs from the sources.json file and stores them in the
// receiver ThirdPartyType's field Dependencies.
func (tp *ThirdPartyType) ReadURLs() (err error) {
	absPath, err := util.AbsolutePathHelper(thirdpartyswdir, sourceconfigname)
	glog.V(2).Infoln(absPath)
	if err != nil {
		return err
	}
	if err := tp.read(absPath); err != nil {
		return err
	}
	for i, el := range tp.Dependencies {
		glog.V(2).Infof("%d: %s\n", i, el.URL)
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import "fmt"
import "database/sql"
import "github.com/joncrlsn/pgutil"

// ForeignKeySchema holds a channel streaming foreign key data from one of the databases as well as
// a reference to the current row of data we're viewing.
//
// ForeignKeySchema implements the Schema interface defined in pgdiff.go
type ForeignKeySchema struct {
	channel chan map[string]string
	row     map[string]string
	done    bool
}

// NextRow reads from the channel and tells you if there are (probably) more or not
func (c *ForeignKeySchema) NextRow() bool {
	c.row = <-c.channel
	if len(c.row) == 0 {
		c.done = true
	}
	return !c.done
}

// Compare tells you, in one pass, whether or not the first row matches, is less than, or greater than the second row
func (c *ForeignKeySchema) Compare(obj interface{}) int {
	c2, ok := obj.(*ForeignKeySchema)
	if !ok {
		fmt.Println("Error!!!, Change(...) needs a ForeignKeySchema instance", c2)
		return +999
	}

	//fmt.Printf("Comparing %s with %s", c.row["table_name"], c2.row["table_name"])
	val := _compareString(c.row["table_name"], c2.row["table_name"])
	if val != 0 {
		return val
	}

	val = _compareString(c.row["constraint_name"], c2.row["constraint_name"])
	return val
}

// Add returns SQL to add the foreign key
func (c ForeignKeySchema) Add() {
	fmt.Printf("ALTER TABLE %s ADD CONSTRAINT %s FOREIGN KEY(%s) REFERENCES %s(%s);\n", c.row["table_name"], c.row["constraint_name"], c.row["column_name"], c.row["foreign_table_name"], c.row["foreign_column_name"])
}

// Drop returns SQL to drop the foreign key
func (c ForeignKeySchema) Drop() {
	fmt.Printf("ALTER TABLE %s DROP CONSTRAINT IF EXISTS %s;\n", c.row["table_name"], c.row["constraint_name"])
}

// Change handles the case where the table and foreign key name, but the details do not
func (c ForeignKeySchema) Change(obj interface{}) {
	c2, ok := obj.(*ForeignKeySchema)
	if !ok {
		fmt.Println("Error!!!, change needs a ForeignKeySchema instance", c2)
	}
	//fmt.Printf("Change Table? %s - %s\n", c.row["table_name"], c2.row["table_name"])
}

/*
 * Compare the columns in the two databases
 */
func compareForeignKeys(conn1 *sql.DB, conn2 *sql.DB) {
	sql := `
SELECT tc.constraint_name
    , tc.table_name
    , kcu.column_name
    , ccu.table_name AS foreign_table_name
    , ccu.column_name AS foreign_column_name
	, rc.delete_rule AS on_delete
	, rc.update_rule AS on_update
FROM information_schema.table_constraints AS tc
     JOIN information_schema.key_column_usage AS kcu
       ON (tc.constraint_name = kcu.constraint_name)
     JOIN information_schema.constraint_column_usage AS ccu
       ON (ccu.constraint_name = tc.constraint_name)
     JOIN information_schema.referential_constraints rc
       ON (tc.constraint_catalog = rc.constraint_catalog
      AND tc.constraint_schema = rc.constraint_schema
      AND tc.constraint_name = rc.constraint_name)
WHERE tc.constraint_type = 'FOREIGN KEY'
ORDER BY tc.table_name, tc.constraint_name COLLATE "C" ASC; `

	rowChan1, _ := pgutil.QueryStrings(conn1, sql)
	rowChan2, _ := pgutil.QueryStrings(conn2, sql)

	// We have to explicitly type this as Schema for some reason
	var schema1 Schema = &ForeignKeySchema{channel: rowChan1}
	var schema2 Schema = &ForeignKeySchema{channel: rowChan2}

	// Compare the columns
	doDiff(schema1, schema2)
}
<commit_msg>Commented out superflous (for now) SQL<commit_after>package main

import "fmt"
import "database/sql"
import "github.com/joncrlsn/pgutil"

// ForeignKeySchema holds a channel streaming foreign key data from one of the databases as well as
// a reference to the current row of data we're viewing.
//
// ForeignKeySchema implements the Schema interface defined in pgdiff.go
type ForeignKeySchema struct {
	channel chan map[string]string
	row     map[string]string
	done    bool
}

// NextRow reads from the channel and tells you if there are (probably) more or not
func (c *ForeignKeySchema) NextRow() bool {
	c.row = <-c.channel
	if len(c.row) == 0 {
		c.done = true
	}
	return !c.done
}

// Compare tells you, in one pass, whether or not the first row matches, is less than, or greater than the second row
func (c *ForeignKeySchema) Compare(obj interface{}) int {
	c2, ok := obj.(*ForeignKeySchema)
	if !ok {
		fmt.Println("Error!!!, Change(...) needs a ForeignKeySchema instance", c2)
		return +999
	}

	//fmt.Printf("Comparing %s with %s", c.row["table_name"], c2.row["table_name"])
	val := _compareString(c.row["table_name"], c2.row["table_name"])
	if val != 0 {
		return val
	}

	val = _compareString(c.row["constraint_name"], c2.row["constraint_name"])
	return val
}

// Add returns SQL to add the foreign key
func (c ForeignKeySchema) Add() {
	fmt.Printf("ALTER TABLE %s ADD CONSTRAINT %s FOREIGN KEY(%s) REFERENCES %s(%s);\n", c.row["table_name"], c.row["constraint_name"], c.row["column_name"], c.row["foreign_table_name"], c.row["foreign_column_name"])
}

// Drop returns SQL to drop the foreign key
func (c ForeignKeySchema) Drop() {
	fmt.Printf("ALTER TABLE %s DROP CONSTRAINT IF EXISTS %s;\n", c.row["table_name"], c.row["constraint_name"])
}

// Change handles the case where the table and foreign key name, but the details do not
func (c ForeignKeySchema) Change(obj interface{}) {
	c2, ok := obj.(*ForeignKeySchema)
	if !ok {
		fmt.Println("Error!!!, change needs a ForeignKeySchema instance", c2)
	}
	//fmt.Printf("Change Table? %s - %s\n", c.row["table_name"], c2.row["table_name"])
}

/*
 * Compare the columns in the two databases
 */
func compareForeignKeys(conn1 *sql.DB, conn2 *sql.DB) {
	sql := `
SELECT tc.constraint_name
    , tc.table_name
    , kcu.column_name
    , ccu.table_name AS foreign_table_name
    , ccu.column_name AS foreign_column_name
	, rc.delete_rule AS on_delete
	, rc.update_rule AS on_update
FROM information_schema.table_constraints AS tc
     JOIN information_schema.key_column_usage AS kcu
       ON (tc.constraint_name = kcu.constraint_name)
     JOIN information_schema.constraint_column_usage AS ccu
       ON (ccu.constraint_name = tc.constraint_name)
     JOIN information_schema.referential_constraints rc
       ON (tc.constraint_catalog = rc.constraint_catalog
      AND tc.constraint_schema = rc.constraint_schema
      AND tc.constraint_name = rc.constraint_name)
WHERE tc.constraint_type = 'FOREIGN KEY'
ORDER BY tc.table_name, tc.constraint_name COLLATE "C" ASC;

-- Foreign Keys
--SELECT
--    con.relname AS child_table,
--    att2.attname AS child_column,
--    cl.relname AS parent_table,
--    att.attname AS parent_column
--FROM
--   (SELECT
--        unnest(con1.conkey) AS parent,
--        unnest(con1.confkey) AS child,
--        cl.relname,
--        con1.confrelid,
--        con1.conrelid
--    FROM pg_class AS cl
--    JOIN pg_namespace AS ns ON (cl.relnamespace = ns.oid)
--    JOIN pg_constraint AS con1 ON (con1.conrelid = cl.oid)
--    WHERE con1.contype = 'f'
--    --AND cl.relname = 't_org'
--    --AND ns.nspname = 'child_schema'
--   ) con
--JOIN pg_attribute AS att ON (att.attrelid = con.confrelid AND att.attnum = con.child)
--JOIN pg_class AS cl ON (cl.oid = con.confrelid)
--JOIN pg_attribute AS att2 ON (att2.attrelid = con.conrelid AND att2.attnum = con.parent)
--ORDER BY con.relname, att2.attname;

`

	rowChan1, _ := pgutil.QueryStrings(conn1, sql)
	rowChan2, _ := pgutil.QueryStrings(conn2, sql)

	// We have to explicitly type this as Schema for some reason
	var schema1 Schema = &ForeignKeySchema{channel: rowChan1}
	var schema2 Schema = &ForeignKeySchema{channel: rowChan2}

	// Compare the columns
	doDiff(schema1, schema2)
}
<|endoftext|>


<commit_before>// Copyright 2015-2018 Auburn University and others. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file defines a refactoring to rename variables, functions, methods,
// types, interfaces, and packages.

package refactoring

import (
	"go/ast"
	"go/token"
	"go/types"
	"os"
	"path/filepath"
	"reflect"
	"regexp"
	"runtime"
	"strings"

	"golang.org/x/tools/go/loader"

	"github.com/godoctor/godoctor/analysis/names"
	"github.com/godoctor/godoctor/text"
)

// Rename is a refactoring that changes the names of variables, functions,
// methods, types, interfaces, and packages in Go programs.  It attempts to
// prevent name changes that will introduce syntactic or semantic errors into
// the Program.
type Rename struct {
	RefactoringBase
	newName string // New name to be given to the selected identifier
}

func (r *Rename) Description() *Description {
	return &Description{
		Name:      "Rename",
		Synopsis:  "Changes the name of an identifier",
		Usage:     "<new_name>",
		HTMLDoc:   renameDoc,
		Multifile: true,
		Params: []Parameter{{
			Label:        "New Name:",
			Prompt:       "What to rename this identifier to.",
			DefaultValue: "",
		}},
		OptionalParams: nil,
		Hidden:         false,
	}
}

func (r *Rename) Run(config *Config) *Result {
	r.Init(config, r.Description())
	r.Log.ChangeInitialErrorsToWarnings()
	if r.Log.ContainsErrors() {
		return &r.Result
	}

	if r.SelectedNode == nil {
		r.Log.Error("Please select an identifier to rename.")
		r.Log.AssociatePos(r.SelectionStart, r.SelectionEnd)
		return &r.Result
	}

	r.newName = config.Args[0].(string)
	if r.newName == "" {
		r.Log.Error("newName cannot be empty")
		return &r.Result
	}
	if !isIdentifierValid(r.newName) {
		r.Log.Errorf("The new name \"%s\" is not a valid Go identifier", r.newName)
		return &r.Result
	}
	if isReservedWord(r.newName) {
		r.Log.Errorf("The new name \"%s\" is a reserved word", r.newName)
		return &r.Result
	}

	switch ident := r.SelectedNode.(type) {
	case *ast.Ident:

		// FIXME: Check if main function (not type/var/etc.) -JO
		if ident.Name == "main" && r.SelectedNodePkg.Pkg.Name() == "main" {
			r.Log.Error("The \"main\" function in the \"main\" package cannot be renamed: it will eliminate the program entrypoint")
			r.Log.AssociateNode(ident)
			return &r.Result
		}

		if isPredeclaredIdentifier(ident.Name) {
			r.Log.Errorf("selected predeclared  identifier \"%s\" , it cannot be renamed", ident.Name)
			r.Log.AssociateNode(ident)
			return &r.Result
		}

		if ast.IsExported(ident.Name) && !ast.IsExported(r.newName) {
			r.Log.Warn("Renaming an exported name to an unexported name will introduce errors outside the package in which it is declared.")
		}

		r.rename(ident, r.SelectedNodePkg)
		r.UpdateLog(config, false)
		return &r.Result

	default:
		r.Log.Errorf("Please select an identifier to rename. "+
			"(Selected node: %s)", reflect.TypeOf(ident))
		r.Log.AssociatePos(r.SelectionStart, r.SelectionEnd)
		return &r.Result
	}
}

func isIdentifierValid(newName string) bool {
	b, _ := regexp.MatchString("^[\\p{L}|_][\\p{L}|_|\\p{N}]*$", newName)
	return b
}

func isPredeclaredIdentifier(selectedIdentifier string) bool {
	b, _ := regexp.MatchString("^(bool|byte|complex64|complex128|error|float32|float64|int|int8|int16|int32|int64|rune|string|uint|uint8|uint16|uint32|uint64|uintptr|true|false|iota|nil|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print|println|real|recover)$", selectedIdentifier)
	return b
}

func isReservedWord(newName string) bool {
	b, _ := regexp.MatchString("^(break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go|goto|if|import|interface|map|package|range|return|select|struct|switch|type|var)$", newName)
	return b
}

func (r *Rename) rename(ident *ast.Ident, pkgInfo *loader.PackageInfo) {
	obj := pkgInfo.ObjectOf(ident)

	if obj == nil && r.selectedTypeSwitchVar() == nil {
		r.Log.Errorf("The selected identifier cannot be " +
			"renamed.  (Package and cgo renaming are not " +
			"currently supported.)")
		r.Log.AssociateNode(ident)
		return
	}

	if obj != nil && isInGoRoot(r.Program.Fset.Position(obj.Pos()).Filename) {
		r.Log.Errorf("%s is defined in $GOROOT and cannot be renamed",
			ident.Name)
		r.Log.AssociateNode(ident)
		return
	}
	if conflict := names.FindConflict(obj, r.newName); conflict != nil {
		r.Log.Errorf("Renaming %s to %s may cause conflicts with an existing declaration", ident.Name, r.newName)
		r.Log.AssociatePos(conflict.Pos(), conflict.Pos())
	}
	var scope *types.Scope
	var idents map[*ast.Ident]bool
	if ts := r.selectedTypeSwitchVar(); ts != nil {
		scope = types.NewScope(nil, ts.Pos(), ts.End(), "artificial scope for typeswitch")
		idents = names.FindTypeSwitchVarOccurrences(ts, r.SelectedNodePkg, r.Program)
	} else {
		if obj != nil {
			scope = obj.Parent()
		}
		idents = names.FindOccurrences(obj, r.Program)
	}

	r.addOccurrences(ident.Name, scope, r.extents(idents, r.Program.Fset))
}

func (r *Rename) selectedTypeSwitchVar() *ast.TypeSwitchStmt {
	obj := r.SelectedNodePkg.ObjectOf(r.SelectedNode.(*ast.Ident))

	for _, n := range r.PathEnclosingSelection {
		if typeSwitch, ok := n.(*ast.TypeSwitchStmt); ok {
			if asgt, ok := typeSwitch.Assign.(*ast.AssignStmt); ok {
				if len(asgt.Lhs) == 1 &&
					asgt.Tok == token.DEFINE &&
					asgt.Lhs[0] == r.SelectedNode {
					return typeSwitch
				}
			}
			for _, stmt := range typeSwitch.Body.List {
				cc := stmt.(*ast.CaseClause)
				if r.SelectedNodePkg.Implicits[cc] == obj {
					return typeSwitch
				}
			}
		}
	}
	return nil
}

func (r *Rename) extents(ids map[*ast.Ident]bool, fset *token.FileSet) map[string][]*text.Extent {
	result := map[string][]*text.Extent{}
	for id := range ids {
		pos := fset.Position(id.Pos())
		if _, ok := result[pos.Filename]; !ok {
			result[pos.Filename] = []*text.Extent{}
		}
		result[pos.Filename] = append(result[pos.Filename],
			&text.Extent{Offset: pos.Offset, Length: len(id.Name)})
	}

	sorted := map[string][]*text.Extent{}
	for fname, extents := range result {
		sorted[fname] = text.Sort(extents)
	}
	return sorted
}

func (r *Rename) addOccurrences(name string, scope *types.Scope, allOccurrences map[string][]*text.Extent) {
	hasOccsInGoRoot := false
	for filename, occurrences := range allOccurrences {
		if isInGoRoot(filename) {
			hasOccsInGoRoot = true
		} else {
			if r.Edits[filename] == nil {
				r.Edits[filename] = text.NewEditSet()
			}
			for _, occurrence := range occurrences {
				r.Edits[filename].Add(occurrence, r.newName)
			}
			_, file := r.fileNamed(filename)
			commentOccurrences := names.FindInComments(
				name, file, scope, r.Program.Fset)
			for _, occurrence := range commentOccurrences {
				r.Edits[filename].Add(occurrence, r.newName)
			}
		}
	}
	if hasOccsInGoRoot {
		r.Log.Warnf("Occurrences were found in files under $GOROOT, but these will not be renamed")
	}
}

func isInGoRoot(absPath string) bool {
	goRoot := os.Getenv("GOROOT")
	if goRoot == "" {
		goRoot = runtime.GOROOT()
	}

	if !strings.HasSuffix(goRoot, string(filepath.Separator)) {
		goRoot += string(filepath.Separator)
	}
	return strings.HasPrefix(absPath, goRoot)
}

func (r *Rename) fileNamed(filename string) (*loader.PackageInfo, *ast.File) {
	absFilename, _ := filepath.Abs(filename)
	for _, pkgInfo := range r.Program.AllPackages {
		for _, f := range pkgInfo.Files {
			thisFile := r.Program.Fset.Position(f.Pos()).Filename
			if thisFile == filename || thisFile == absFilename {
				return pkgInfo, f
			}
		}
	}
	return nil, nil
}

const renameDoc = `

Purpose

The Rename refactoring is used to change the names of variables,
  functions, methods, and types.  Package renaming is not currently
  supported.

Usage

Select an identifier to be renamed.

Activate the Rename refactoring.

Enter a new name for the identifier.

An error or warning will be reported if:

The renaming could introduce errors (e.g., two functions would have the
    same name).

The necessary changes cannot be made (e.g., the renaming would change
    the name of a function in the Go standard library).

Example

The example below demonstrates the effect of renaming the highlighted
  occurrence of <tt>hello</tt> to <tt>goodnight</tt>.  Note that there are two
  different variables named <tt>hello</tt>; since the local identifier was
  selected, only references to that variable are renamed, as shown.

      Before	 	After

package main
import "fmt"

var hello = ":-("

func main() {
    hello = ":-)"
    var hello string = "hello"
    var world string = "world"
    hello = hello + ", " + world
    hello += "!"
    fmt.Println(hello)
}

          ⇒&nbsp

package main
import "fmt"

var hello = ":-("

func main() {
    hello = ":-)"
    var goodnight string = "hello"
    var world string = "world"
    goodnight = goodnight + ", " + world
    goodnight += "!"
    fmt.Println(goodnight)
}

Limitations

Package renaming is not currently supported.  Package renaming
    requires renaming directories, which causes files to move on the file
    system.  When the refactoring is activated from a text editor (e.g., Vim),
    the editor needs to be notified of such changes and respond appropriately.
    Additional work is needed to support this behavior.

Name collision detection is overly conservative.  If renaming
    will introduce shadowing, this is reported as an error, even if it will not
    change the program's semantics.

`
<commit_msg>try to infer ident if something else was detected<commit_after>// Copyright 2015-2018 Auburn University and others. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file defines a refactoring to rename variables, functions, methods,
// types, interfaces, and packages.

package refactoring

import (
	"go/ast"
	"go/token"
	"go/types"
	"os"
	"path/filepath"
	"reflect"
	"regexp"
	"runtime"
	"strings"

	"golang.org/x/tools/go/loader"

	"github.com/godoctor/godoctor/analysis/names"
	"github.com/godoctor/godoctor/text"
)

// Rename is a refactoring that changes the names of variables, functions,
// methods, types, interfaces, and packages in Go programs.  It attempts to
// prevent name changes that will introduce syntactic or semantic errors into
// the Program.
type Rename struct {
	RefactoringBase
	newName string // New name to be given to the selected identifier
}

func (r *Rename) Description() *Description {
	return &Description{
		Name:      "Rename",
		Synopsis:  "Changes the name of an identifier",
		Usage:     "<new_name>",
		HTMLDoc:   renameDoc,
		Multifile: true,
		Params: []Parameter{{
			Label:        "New Name:",
			Prompt:       "What to rename this identifier to.",
			DefaultValue: "",
		}},
		OptionalParams: nil,
		Hidden:         false,
	}
}

func (r *Rename) Run(config *Config) *Result {
	r.Init(config, r.Description())
	r.Log.ChangeInitialErrorsToWarnings()
	if r.Log.ContainsErrors() {
		return &r.Result
	}

	if r.SelectedNode == nil {
		r.Log.Error("Please select an identifier to rename.")
		r.Log.AssociatePos(r.SelectionStart, r.SelectionEnd)
		return &r.Result
	}

	r.newName = config.Args[0].(string)
	if r.newName == "" {
		r.Log.Error("newName cannot be empty")
		return &r.Result
	}
	if !isIdentifierValid(r.newName) {
		r.Log.Errorf("The new name \"%s\" is not a valid Go identifier", r.newName)
		return &r.Result
	}
	if isReservedWord(r.newName) {
		r.Log.Errorf("The new name \"%s\" is a reserved word", r.newName)
		return &r.Result
	}

	// If no ident was found, try to get hold of the concrete node type and get it's name
	var ident *ast.Ident
	switch node := r.SelectedNode.(type) {
	case *ast.FuncDecl:
		ident = node.Name
	case *ast.Ident:
		ident = node
	default:
		r.Log.Errorf("Please select an identifier to rename. "+
			"(Selected node: %s)", reflect.TypeOf(r.SelectedNode))
		r.Log.AssociatePos(r.SelectionStart, r.SelectionEnd)
		return &r.Result
	}

	// FIXME: Check if main function (not type/var/etc.) -JO
	if ident.Name == "main" && r.SelectedNodePkg.Pkg.Name() == "main" {
		r.Log.Error("The \"main\" function in the \"main\" package cannot be renamed: it will eliminate the program entrypoint")
		r.Log.AssociateNode(ident)
		return &r.Result
	}

	if isPredeclaredIdentifier(ident.Name) {
		r.Log.Errorf("selected predeclared  identifier \"%s\" , it cannot be renamed", ident.Name)
		r.Log.AssociateNode(ident)
		return &r.Result
	}

	if ast.IsExported(ident.Name) && !ast.IsExported(r.newName) {
		r.Log.Warn("Renaming an exported name to an unexported name will introduce errors outside the package in which it is declared.")
	}

	r.rename(ident, r.SelectedNodePkg)
	r.UpdateLog(config, false)
	return &r.Result

}

func isIdentifierValid(newName string) bool {
	b, _ := regexp.MatchString("^[\\p{L}|_][\\p{L}|_|\\p{N}]*$", newName)
	return b
}

func isPredeclaredIdentifier(selectedIdentifier string) bool {
	b, _ := regexp.MatchString("^(bool|byte|complex64|complex128|error|float32|float64|int|int8|int16|int32|int64|rune|string|uint|uint8|uint16|uint32|uint64|uintptr|true|false|iota|nil|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print|println|real|recover)$", selectedIdentifier)
	return b
}

func isReservedWord(newName string) bool {
	b, _ := regexp.MatchString("^(break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go|goto|if|import|interface|map|package|range|return|select|struct|switch|type|var)$", newName)
	return b
}

func (r *Rename) rename(ident *ast.Ident, pkgInfo *loader.PackageInfo) {
	obj := pkgInfo.ObjectOf(ident)

	if obj == nil && r.selectedTypeSwitchVar(ident) == nil {
		r.Log.Errorf("The selected identifier cannot be " +
			"renamed.  (Package and cgo renaming are not " +
			"currently supported.)")
		r.Log.AssociateNode(ident)
		return
	}

	if obj != nil && isInGoRoot(r.Program.Fset.Position(obj.Pos()).Filename) {
		r.Log.Errorf("%s is defined in $GOROOT and cannot be renamed",
			ident.Name)
		r.Log.AssociateNode(ident)
		return
	}
	if conflict := names.FindConflict(obj, r.newName); conflict != nil {
		r.Log.Errorf("Renaming %s to %s may cause conflicts with an existing declaration", ident.Name, r.newName)
		r.Log.AssociatePos(conflict.Pos(), conflict.Pos())
	}
	var scope *types.Scope
	var idents map[*ast.Ident]bool
	if ts := r.selectedTypeSwitchVar(ident); ts != nil {
		scope = types.NewScope(nil, ts.Pos(), ts.End(), "artificial scope for typeswitch")
		idents = names.FindTypeSwitchVarOccurrences(ts, r.SelectedNodePkg, r.Program)
	} else {
		if obj != nil {
			scope = obj.Parent()
		}
		idents = names.FindOccurrences(obj, r.Program)
	}

	r.addOccurrences(ident.Name, scope, r.extents(idents, r.Program.Fset))
}

func (r *Rename) selectedTypeSwitchVar(ident *ast.Ident) *ast.TypeSwitchStmt {
	obj := r.SelectedNodePkg.ObjectOf(ident)

	for _, n := range r.PathEnclosingSelection {
		if typeSwitch, ok := n.(*ast.TypeSwitchStmt); ok {
			if asgt, ok := typeSwitch.Assign.(*ast.AssignStmt); ok {
				if len(asgt.Lhs) == 1 &&
					asgt.Tok == token.DEFINE &&
					asgt.Lhs[0] == r.SelectedNode {
					return typeSwitch
				}
			}
			for _, stmt := range typeSwitch.Body.List {
				cc := stmt.(*ast.CaseClause)
				if r.SelectedNodePkg.Implicits[cc] == obj {
					return typeSwitch
				}
			}
		}
	}
	return nil
}

func (r *Rename) extents(ids map[*ast.Ident]bool, fset *token.FileSet) map[string][]*text.Extent {
	result := map[string][]*text.Extent{}
	for id := range ids {
		pos := fset.Position(id.Pos())
		if _, ok := result[pos.Filename]; !ok {
			result[pos.Filename] = []*text.Extent{}
		}
		result[pos.Filename] = append(result[pos.Filename],
			&text.Extent{Offset: pos.Offset, Length: len(id.Name)})
	}

	sorted := map[string][]*text.Extent{}
	for fname, extents := range result {
		sorted[fname] = text.Sort(extents)
	}
	return sorted
}

func (r *Rename) addOccurrences(name string, scope *types.Scope, allOccurrences map[string][]*text.Extent) {
	hasOccsInGoRoot := false
	for filename, occurrences := range allOccurrences {
		if isInGoRoot(filename) {
			hasOccsInGoRoot = true
		} else {
			if r.Edits[filename] == nil {
				r.Edits[filename] = text.NewEditSet()
			}
			for _, occurrence := range occurrences {
				r.Edits[filename].Add(occurrence, r.newName)
			}
			_, file := r.fileNamed(filename)
			commentOccurrences := names.FindInComments(
				name, file, scope, r.Program.Fset)
			for _, occurrence := range commentOccurrences {
				r.Edits[filename].Add(occurrence, r.newName)
			}
		}
	}
	if hasOccsInGoRoot {
		r.Log.Warnf("Occurrences were found in files under $GOROOT, but these will not be renamed")
	}
}

func isInGoRoot(absPath string) bool {
	goRoot := os.Getenv("GOROOT")
	if goRoot == "" {
		goRoot = runtime.GOROOT()
	}

	if !strings.HasSuffix(goRoot, string(filepath.Separator)) {
		goRoot += string(filepath.Separator)
	}
	return strings.HasPrefix(absPath, goRoot)
}

func (r *Rename) fileNamed(filename string) (*loader.PackageInfo, *ast.File) {
	absFilename, _ := filepath.Abs(filename)
	for _, pkgInfo := range r.Program.AllPackages {
		for _, f := range pkgInfo.Files {
			thisFile := r.Program.Fset.Position(f.Pos()).Filename
			if thisFile == filename || thisFile == absFilename {
				return pkgInfo, f
			}
		}
	}
	return nil, nil
}

const renameDoc = `

Purpose

The Rename refactoring is used to change the names of variables,
  functions, methods, and types.  Package renaming is not currently
  supported.

Usage

Select an identifier to be renamed.

Activate the Rename refactoring.

Enter a new name for the identifier.

An error or warning will be reported if:

The renaming could introduce errors (e.g., two functions would have the
    same name).

The necessary changes cannot be made (e.g., the renaming would change
    the name of a function in the Go standard library).

Example

The example below demonstrates the effect of renaming the highlighted
  occurrence of <tt>hello</tt> to <tt>goodnight</tt>.  Note that there are two
  different variables named <tt>hello</tt>; since the local identifier was
  selected, only references to that variable are renamed, as shown.

      Before	 	After

package main
import "fmt"

var hello = ":-("

func main() {
    hello = ":-)"
    var hello string = "hello"
    var world string = "world"
    hello = hello + ", " + world
    hello += "!"
    fmt.Println(hello)
}

          ⇒&nbsp

package main
import "fmt"

var hello = ":-("

func main() {
    hello = ":-)"
    var goodnight string = "hello"
    var world string = "world"
    goodnight = goodnight + ", " + world
    goodnight += "!"
    fmt.Println(goodnight)
}

Limitations

Package renaming is not currently supported.  Package renaming
    requires renaming directories, which causes files to move on the file
    system.  When the refactoring is activated from a text editor (e.g., Vim),
    the editor needs to be notified of such changes and respond appropriately.
    Additional work is needed to support this behavior.

Name collision detection is overly conservative.  If renaming
    will introduce shadowing, this is reported as an error, even if it will not
    change the program's semantics.

`
<|endoftext|>


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

package main

import (
	"errors"
	"fmt"
	"reflect"
	"unsafe"
	"strings"
    "encoding/json"
	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// ReferralChaincode implementation stores and updates referral information on the blockchain
type ReferralChaincode struct {
}

type CustomerReferral struct {
	referralId string
    customerName string
	contactNumber string
	customerId string
	employeeId string
	departments []string
    createDate int64
	status string
}

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

func BytesToString(b []byte) string {
    bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
    sh := reflect.StringHeader{bh.Data, bh.Len}
    return *(*string)(unsafe.Pointer(&sh))
}

// Init resets all the things
func (t *ReferralChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	// There is no initialization to do
	return nil, nil
}

// Invoke is our entry point to invoke a chaincode function
func (t *ReferralChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "createReferral" {
		return []byte("Executing create referral"), nil
		return t.createReferral(stub, args)
	} else if function == "updateReferralStatus" {
		return t.updateReferralStatus(stub, args)
	}
	fmt.Println("invoke did not find func: " + function)

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

// Query is our entry point for queries
func (t *ReferralChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)

	// Handle different functions
	if function == "read" { //read a variable
		return t.read(stub, args)
	} else if function == "searchByStatus" {
		return searchByStatus(args[0], stub)
	} else if function == "searchByDepartment" {
		return searchByDepartment(args[0], stub)
	}
	fmt.Println("query did not find func: " + function)

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

// Adds the referral id to a ledger list item for the given department allowing for quick search of referrals in a given department
func indexByDepartment(referralId string, department string, stub *shim.ChaincodeStub) (error) {
	valAsbytes, err := stub.GetState(department)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + department + "\"}"
		return errors.New(jsonResp)
	}

	if valAsbytes == nil {
		err = stub.PutState(department, []byte(referralId))
	} else {
	    commaDelimitedStatuses := BytesToString(valAsbytes)
		err = stub.PutState(department, []byte(commaDelimitedStatuses + "," + referralId))
	}

	return err
}

func removeStatusReferralIndex(referralId string, status string, stub *shim.ChaincodeStub) (error) {
	valAsbytes, err := stub.GetState(status)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + status + "\"}"
		return errors.New(jsonResp)
	}

	if valAsbytes == nil {
		return nil;
	} else {
		// Remove the referral from this status type, if it exists
		commaDelimitedStatuses := BytesToString(valAsbytes)
		referralIdsInCurrentStatus := strings.Split(commaDelimitedStatuses, ",")
		updatedReferralIdList := ""

		appendComma := false
		for i := range referralIdsInCurrentStatus {
			if referralIdsInCurrentStatus[i] != referralId {
			    if appendComma == false {
					updatedReferralIdList += referralIdsInCurrentStatus[i]
					appendComma = true
				} else {
					updatedReferralIdList = updatedReferralIdList + "," + referralIdsInCurrentStatus[i]
				}
			}
		}

		err = stub.PutState(status, []byte(updatedReferralIdList))
	}

	if err != nil {
		jsonResp := "{\"Error\":\"Failed to update state for " + status + "\"}"
		return errors.New(jsonResp)
	}

	return nil
}

// Adds the referral id to a ledger list item for the given department allowing for quick search of referrals in a given department
func indexByStatus(referralId string, status string, stub *shim.ChaincodeStub) (error) {
	valAsbytes, err := stub.GetState(status)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + status + "\"}"
		return errors.New(jsonResp)
	}

	if valAsbytes == nil {
		err = stub.PutState(status, []byte(referralId))
	} else {
	    commaDelimitedStatuses := BytesToString(valAsbytes)
		err = stub.PutState(status, []byte(commaDelimitedStatuses + "," + referralId))
	}

	if err != nil {
		jsonResp := "{\"Error\":\"Failed to update state for " + status + "\"}"
		return errors.New(jsonResp)
	}

	return nil
}

func unmarshallBytes(valAsBytes []byte) (error, CustomerReferral) {
	var err error
	var referral CustomerReferral
	fmt.Println("Unmarshalling JSON")
	err = json.Unmarshal(valAsBytes, &referral)

	if err != nil {
		fmt.Println("Unmarshalling JSON failed")
	}

	return err, referral
}

func marshallReferral(referral CustomerReferral) (error, []byte) {
	fmt.Println("Marshalling JSON to bytes")
	valAsbytes, err := json.Marshal(referral)

	if err != nil {
		fmt.Println("Marshalling JSON to bytes failed")
		return err, nil
	}

	return nil, valAsbytes
}

func updateStatus(referral CustomerReferral, status string, stub *shim.ChaincodeStub) (error) {
	fmt.Println("Setting status")

	err := removeStatusReferralIndex(referral.referralId, referral.status, stub)
	if err != nil {
		return err
	}
	referral.status = status
	err = indexByStatus(referral.referralId, status, stub)

	return err
}

// updateReferral - invoke function to updateReferral key/value pair
func (t *ReferralChaincode) updateReferralStatus(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var key, status string
	var err error
	var referral CustomerReferral
	fmt.Println("running updateReferral()")

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2. name of the key and value to set")
	}

	key = args[0] //rename for funsies
	status = args[1]

	valAsbytes, err := stub.GetState(key)
	if err != nil {
		return nil, err
	}
	err, referral = unmarshallBytes(valAsbytes)

	if err != nil {
		return nil, err
	}

	updateStatus(referral, status, stub)

	fmt.Println("Marshalling JSON to bytes")
	err, valAsbytes = marshallReferral(referral)

	if err != nil {
		return nil, err
	}

	err = stub.PutState(key, valAsbytes) //write the variable into the chaincode state
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// createReferral - invoke function to write key/value pair
func (t *ReferralChaincode) createReferral(stub *shim.ChaincodeStub, args []string) ([]byte, error) {

	var key, value string
	var err error
	var referral CustomerReferral
	fmt.Println("running createReferral()")

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2. name of the key and value to set")
	}

	key = args[0] //rename for funsies
	value = args[1]

	err = stub.PutState(key, []byte(value)) //write the variable into the chaincode state
	if err != nil {
		return []byte("Could not put the key: " + key + " and value: " + value + " on the ledger"), err
	}

	// Deserialize the input string into a GO data structure to hold the referral
	err, referral = unmarshallBytes([]byte(value))
	if err != nil {
		return []byte("Count not unmarshall the bytes from the value: " + value + " on the ledger"), err
	}

	// Create a ledger record that indexes the referral id by the created status
	err = indexByStatus(referral.referralId, referral.status, stub)
	if err != nil {
		return []byte("Count not index the bytes by status from the value: " + value + " on the ledger"), err
	}

	// Create a ledger record that indexes the referral id by the created department
	for i := range referral.departments {
		err = indexByDepartment(referral.referralId, referral.departments[i], stub)
		if err != nil {
			return []byte("Count not index the bytes by department from the value: " + value + " on the ledger"), err
		}
	}

	return nil, err
}

func processCommaDelimitedReferrals(delimitedReferrals string, stub *shim.ChaincodeStub) ([]byte, error) {
	commaDelimitedReferrals := strings.Split(delimitedReferrals, ",")

	referralResultSet := ""
	appendComma := false

	for i := range commaDelimitedReferrals {
		valAsbytes, err := stub.GetState(commaDelimitedReferrals[i])

		if err != nil {
			return nil, err
		}

		if appendComma == false {
			referralResultSet += BytesToString(valAsbytes)
		} else {
			referralResultSet = referralResultSet + "," + BytesToString(valAsbytes)
		}
	}

	return []byte(referralResultSet), nil
}

func searchByDepartment(department string, stub *shim.ChaincodeStub) ([]byte, error) {
	valAsbytes, err := stub.GetState(department)

	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + department + "\"}"
		return nil, errors.New(jsonResp)
	}

	valAsbytes, err = processCommaDelimitedReferrals(BytesToString(valAsbytes), stub)

	if(err != nil) {
		return nil, err
	}

	return valAsbytes, nil
}

func searchByStatus(status string, stub *shim.ChaincodeStub) ([]byte, error) {
	valAsbytes, err := stub.GetState(status)

	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + status + "\"}"
		return nil, errors.New(jsonResp)
	}

	valAsbytes, err = processCommaDelimitedReferrals(BytesToString(valAsbytes), stub)

	if(err != nil) {
		return nil, err
	}

	return valAsbytes, nil
}

// read - query function to read key/value pair
func (t *ReferralChaincode) read(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var key, jsonResp string
	var err error

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting name of the key to query")
	}

	key = args[0]
	valAsbytes, err := stub.GetState(key)

	if err != nil {
		jsonResp = "{\"Error\":\"Failed to get state for " + key + "\"}"
		return []byte(jsonResp), err
	}

	if valAsbytes == nil {
		return []byte("Did not find entry for key: " + key), nil
	}
	return valAsbytes, nil
}<commit_msg>Add files via upload<commit_after>/*
Copyright IBM Corp 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
		 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"errors"
	"fmt"
	"reflect"
	"unsafe"
	"strings"
    "encoding/json"
	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// ReferralChaincode implementation stores and updates referral information on the blockchain
type ReferralChaincode struct {
}

type CustomerReferral struct {
	referralId string
    customerName string
	contactNumber string
	customerId string
	employeeId string
	departments []string
    createDate int64
	status string
}

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

func BytesToString(b []byte) string {
    bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
    sh := reflect.StringHeader{bh.Data, bh.Len}
    return *(*string)(unsafe.Pointer(&sh))
}

// Init resets all the things
func (t *ReferralChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	// There is no initialization to do
	return nil, nil
}

// Invoke is our entry point to invoke a chaincode function
func (t *ReferralChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	return []byte("Function: " + function + "being invoked"), nil
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "createReferral" {

		return t.createReferral(stub, args)
	} else if function == "updateReferralStatus" {
		return t.updateReferralStatus(stub, args)
	}

	return []byte("Function: " + function + "not found"), nil
	fmt.Println("invoke did not find func: " + function)

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

// Query is our entry point for queries
func (t *ReferralChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)

	// Handle different functions
	if function == "read" { //read a variable
		return t.read(stub, args)
	} else if function == "searchByStatus" {
		return searchByStatus(args[0], stub)
	} else if function == "searchByDepartment" {
		return searchByDepartment(args[0], stub)
	}
	fmt.Println("query did not find func: " + function)

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

// Adds the referral id to a ledger list item for the given department allowing for quick search of referrals in a given department
func indexByDepartment(referralId string, department string, stub *shim.ChaincodeStub) (error) {
	valAsbytes, err := stub.GetState(department)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + department + "\"}"
		return errors.New(jsonResp)
	}

	if valAsbytes == nil {
		err = stub.PutState(department, []byte(referralId))
	} else {
	    commaDelimitedStatuses := BytesToString(valAsbytes)
		err = stub.PutState(department, []byte(commaDelimitedStatuses + "," + referralId))
	}

	return err
}

func removeStatusReferralIndex(referralId string, status string, stub *shim.ChaincodeStub) (error) {
	valAsbytes, err := stub.GetState(status)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + status + "\"}"
		return errors.New(jsonResp)
	}

	if valAsbytes == nil {
		return nil;
	} else {
		// Remove the referral from this status type, if it exists
		commaDelimitedStatuses := BytesToString(valAsbytes)
		referralIdsInCurrentStatus := strings.Split(commaDelimitedStatuses, ",")
		updatedReferralIdList := ""

		appendComma := false
		for i := range referralIdsInCurrentStatus {
			if referralIdsInCurrentStatus[i] != referralId {
			    if appendComma == false {
					updatedReferralIdList += referralIdsInCurrentStatus[i]
					appendComma = true
				} else {
					updatedReferralIdList = updatedReferralIdList + "," + referralIdsInCurrentStatus[i]
				}
			}
		}

		err = stub.PutState(status, []byte(updatedReferralIdList))
	}

	if err != nil {
		jsonResp := "{\"Error\":\"Failed to update state for " + status + "\"}"
		return errors.New(jsonResp)
	}

	return nil
}

// Adds the referral id to a ledger list item for the given department allowing for quick search of referrals in a given department
func indexByStatus(referralId string, status string, stub *shim.ChaincodeStub) (error) {
	valAsbytes, err := stub.GetState(status)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + status + "\"}"
		return errors.New(jsonResp)
	}

	if valAsbytes == nil {
		err = stub.PutState(status, []byte(referralId))
	} else {
	    commaDelimitedStatuses := BytesToString(valAsbytes)
		err = stub.PutState(status, []byte(commaDelimitedStatuses + "," + referralId))
	}

	if err != nil {
		jsonResp := "{\"Error\":\"Failed to update state for " + status + "\"}"
		return errors.New(jsonResp)
	}

	return nil
}

func unmarshallBytes(valAsBytes []byte) (error, CustomerReferral) {
	var err error
	var referral CustomerReferral
	fmt.Println("Unmarshalling JSON")
	err = json.Unmarshal(valAsBytes, &referral)

	if err != nil {
		fmt.Println("Unmarshalling JSON failed")
	}

	return err, referral
}

func marshallReferral(referral CustomerReferral) (error, []byte) {
	fmt.Println("Marshalling JSON to bytes")
	valAsbytes, err := json.Marshal(referral)

	if err != nil {
		fmt.Println("Marshalling JSON to bytes failed")
		return err, nil
	}

	return nil, valAsbytes
}

func updateStatus(referral CustomerReferral, status string, stub *shim.ChaincodeStub) (error) {
	fmt.Println("Setting status")

	err := removeStatusReferralIndex(referral.referralId, referral.status, stub)
	if err != nil {
		return err
	}
	referral.status = status
	err = indexByStatus(referral.referralId, status, stub)

	return err
}

// updateReferral - invoke function to updateReferral key/value pair
func (t *ReferralChaincode) updateReferralStatus(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var key, status string
	var err error
	var referral CustomerReferral
	fmt.Println("running updateReferral()")

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2. name of the key and value to set")
	}

	key = args[0] //rename for funsies
	status = args[1]

	valAsbytes, err := stub.GetState(key)
	if err != nil {
		return nil, err
	}
	err, referral = unmarshallBytes(valAsbytes)

	if err != nil {
		return nil, err
	}

	updateStatus(referral, status, stub)

	fmt.Println("Marshalling JSON to bytes")
	err, valAsbytes = marshallReferral(referral)

	if err != nil {
		return nil, err
	}

	err = stub.PutState(key, valAsbytes) //write the variable into the chaincode state
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// createReferral - invoke function to write key/value pair
func (t *ReferralChaincode) createReferral(stub *shim.ChaincodeStub, args []string) ([]byte, error) {

	var key, value string
	var err error
	var referral CustomerReferral
	fmt.Println("running createReferral()")

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2. name of the key and value to set")
	}

	key = args[0] //rename for funsies
	value = args[1]

	err = stub.PutState(key, []byte(value)) //write the variable into the chaincode state
	if err != nil {
		return []byte("Could not put the key: " + key + " and value: " + value + " on the ledger"), err
	}

	// Deserialize the input string into a GO data structure to hold the referral
	err, referral = unmarshallBytes([]byte(value))
	if err != nil {
		return []byte("Count not unmarshall the bytes from the value: " + value + " on the ledger"), err
	}

	// Create a ledger record that indexes the referral id by the created status
	err = indexByStatus(referral.referralId, referral.status, stub)
	if err != nil {
		return []byte("Count not index the bytes by status from the value: " + value + " on the ledger"), err
	}

	// Create a ledger record that indexes the referral id by the created department
	for i := range referral.departments {
		err = indexByDepartment(referral.referralId, referral.departments[i], stub)
		if err != nil {
			return []byte("Count not index the bytes by department from the value: " + value + " on the ledger"), err
		}
	}

	return nil, err
}

func processCommaDelimitedReferrals(delimitedReferrals string, stub *shim.ChaincodeStub) ([]byte, error) {
	commaDelimitedReferrals := strings.Split(delimitedReferrals, ",")

	referralResultSet := ""
	appendComma := false

	for i := range commaDelimitedReferrals {
		valAsbytes, err := stub.GetState(commaDelimitedReferrals[i])

		if err != nil {
			return nil, err
		}

		if appendComma == false {
			referralResultSet += BytesToString(valAsbytes)
		} else {
			referralResultSet = referralResultSet + "," + BytesToString(valAsbytes)
		}
	}

	return []byte(referralResultSet), nil
}

func searchByDepartment(department string, stub *shim.ChaincodeStub) ([]byte, error) {
	valAsbytes, err := stub.GetState(department)

	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + department + "\"}"
		return nil, errors.New(jsonResp)
	}

	valAsbytes, err = processCommaDelimitedReferrals(BytesToString(valAsbytes), stub)

	if(err != nil) {
		return nil, err
	}

	return valAsbytes, nil
}

func searchByStatus(status string, stub *shim.ChaincodeStub) ([]byte, error) {
	valAsbytes, err := stub.GetState(status)

	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + status + "\"}"
		return nil, errors.New(jsonResp)
	}

	valAsbytes, err = processCommaDelimitedReferrals(BytesToString(valAsbytes), stub)

	if(err != nil) {
		return nil, err
	}

	return valAsbytes, nil
}

// read - query function to read key/value pair
func (t *ReferralChaincode) read(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	var key, jsonResp string
	var err error

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting name of the key to query")
	}

	key = args[0]
	valAsbytes, err := stub.GetState(key)

	if err != nil {
		jsonResp = "{\"Error\":\"Failed to get state for " + key + "\"}"
		return []byte(jsonResp), err
	}

	if valAsbytes == nil {
		return []byte("Did not find entry for key: " + key), nil
	}
	return valAsbytes, nil
}<|endoftext|>


<commit_before>package tools

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

func HelloServer(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(http.StatusNoContent)
	log.Printf("Health check request: %s %s", req.RemoteAddr, req.RequestURI)
}

func StartHealthCheck(port int) {
	http.HandleFunc("/", HelloServer)
	log.Printf("Starting health check handler on %v port", port)
	err := http.ListenAndServe(fmt.Sprintf(":%v", port), nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>Return 200 instead of 204<commit_after>package tools

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

func HelloServer(w http.ResponseWriter, req *http.Request) {
	w.WriteHeader(http.StatusOK)
	log.Printf("Health check request: %s %s", req.RemoteAddr, req.RequestURI)
}

func StartHealthCheck(port int) {
	http.HandleFunc("/", HelloServer)
	log.Printf("Starting health check handler on %v port", port)
	err := http.ListenAndServe(fmt.Sprintf(":%v", port), nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>// +build !windows

/*
   Copyright The containerd Authors.

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

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

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

package fs

import (
	"context"
	"os"
	"path/filepath"
	"syscall"
)

type inode struct {
	// TODO(stevvooe): Can probably reduce memory usage by not tracking
	// device, but we can leave this right for now.
	dev, ino uint64
}

func newInode(stat *syscall.Stat_t) inode {
	return inode{
		// Dev is uint32 on darwin/bsd, uint64 on linux/solaris
		dev: uint64(stat.Dev), // nolint: unconvert
		// Ino is uint32 on bsd, uint64 on darwin/linux/solaris
		ino: uint64(stat.Ino), // nolint: unconvert
	}
}

func diskUsage(ctx context.Context, roots ...string) (Usage, error) {

	var (
		size   int64
		inodes = map[inode]struct{}{} // expensive!
	)

	for _, root := range roots {
		if err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
			if err != nil {
				return err
			}

			select {
			case <-ctx.Done():
				return ctx.Err()
			default:
			}

			inoKey := newInode(fi.Sys().(*syscall.Stat_t))
			if _, ok := inodes[inoKey]; !ok {
				inodes[inoKey] = struct{}{}
				size += fi.Size()
			}

			return nil
		}); err != nil {
			return Usage{}, err
		}
	}

	return Usage{
		Inodes: int64(len(inodes)),
		Size:   size,
	}, nil
}

func diffUsage(ctx context.Context, a, b string) (Usage, error) {
	var (
		size   int64
		inodes = map[inode]struct{}{} // expensive!
	)

	if err := Changes(ctx, a, b, func(kind ChangeKind, _ string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if kind == ChangeKindAdd || kind == ChangeKindModify {
			inoKey := newInode(fi.Sys().(*syscall.Stat_t))
			if _, ok := inodes[inoKey]; !ok {
				inodes[inoKey] = struct{}{}
				size += fi.Size()
			}

			return nil

		}
		return nil
	}); err != nil {
		return Usage{}, err
	}

	return Usage{
		Inodes: int64(len(inodes)),
		Size:   size,
	}, nil
}
<commit_msg>Fix usage calculation to account for sparse files<commit_after>// +build !windows

/*
   Copyright The containerd Authors.

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

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

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

package fs

import (
	"context"
	"os"
	"path/filepath"
	"syscall"
)

type inode struct {
	// TODO(stevvooe): Can probably reduce memory usage by not tracking
	// device, but we can leave this right for now.
	dev, ino uint64
}

func newInode(stat *syscall.Stat_t) inode {
	return inode{
		// Dev is uint32 on darwin/bsd, uint64 on linux/solaris
		dev: uint64(stat.Dev), // nolint: unconvert
		// Ino is uint32 on bsd, uint64 on darwin/linux/solaris
		ino: uint64(stat.Ino), // nolint: unconvert
	}
}

func diskUsage(ctx context.Context, roots ...string) (Usage, error) {

	var (
		size   int64
		inodes = map[inode]struct{}{} // expensive!
	)

	for _, root := range roots {
		if err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
			if err != nil {
				return err
			}

			select {
			case <-ctx.Done():
				return ctx.Err()
			default:
			}

			stat := fi.Sys().(*syscall.Stat_t)
			inoKey := newInode(stat)
			if _, ok := inodes[inoKey]; !ok {
				inodes[inoKey] = struct{}{}
				size += stat.Blocks * stat.Blksize
			}

			return nil
		}); err != nil {
			return Usage{}, err
		}
	}

	return Usage{
		Inodes: int64(len(inodes)),
		Size:   size,
	}, nil
}

func diffUsage(ctx context.Context, a, b string) (Usage, error) {
	var (
		size   int64
		inodes = map[inode]struct{}{} // expensive!
	)

	if err := Changes(ctx, a, b, func(kind ChangeKind, _ string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if kind == ChangeKindAdd || kind == ChangeKindModify {
			stat := fi.Sys().(*syscall.Stat_t)
			inoKey := newInode(stat)
			if _, ok := inodes[inoKey]; !ok {
				inodes[inoKey] = struct{}{}
				size += stat.Blocks * stat.Blksize
			}

			return nil

		}
		return nil
	}); err != nil {
		return Usage{}, err
	}

	return Usage{
		Inodes: int64(len(inodes)),
		Size:   size,
	}, nil
}
<|endoftext|>


<commit_before>// +build !windows

/*
   Copyright The containerd Authors.

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

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

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

package fs

import (
	"context"
	"os"
	"path/filepath"
	"syscall"
)

type inode struct {
	// TODO(stevvooe): Can probably reduce memory usage by not tracking
	// device, but we can leave this right for now.
	dev, ino uint64
}

func newInode(stat *syscall.Stat_t) inode {
	return inode{
		// Dev is uint32 on darwin/bsd, uint64 on linux/solaris
		dev: uint64(stat.Dev), // nolint: unconvert
		// Ino is uint32 on bsd, uint64 on darwin/linux/solaris
		ino: uint64(stat.Ino), // nolint: unconvert
	}
}

func diskUsage(ctx context.Context, roots ...string) (Usage, error) {

	var (
		size   int64
		inodes = map[inode]struct{}{} // expensive!
	)

	for _, root := range roots {
		if err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
			if err != nil {
				return err
			}

			select {
			case <-ctx.Done():
				return ctx.Err()
			default:
			}

			stat := fi.Sys().(*syscall.Stat_t)
			inoKey := newInode(stat)
			if _, ok := inodes[inoKey]; !ok {
				inodes[inoKey] = struct{}{}
				size += stat.Blocks * stat.Blksize
			}

			return nil
		}); err != nil {
			return Usage{}, err
		}
	}

	return Usage{
		Inodes: int64(len(inodes)),
		Size:   size,
	}, nil
}

func diffUsage(ctx context.Context, a, b string) (Usage, error) {
	var (
		size   int64
		inodes = map[inode]struct{}{} // expensive!
	)

	if err := Changes(ctx, a, b, func(kind ChangeKind, _ string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if kind == ChangeKindAdd || kind == ChangeKindModify {
			stat := fi.Sys().(*syscall.Stat_t)
			inoKey := newInode(stat)
			if _, ok := inodes[inoKey]; !ok {
				inodes[inoKey] = struct{}{}
				size += stat.Blocks * stat.Blksize
			}

			return nil

		}
		return nil
	}); err != nil {
		return Usage{}, err
	}

	return Usage{
		Inodes: int64(len(inodes)),
		Size:   size,
	}, nil
}
<commit_msg>Fix building on arm64<commit_after>// +build !windows

/*
   Copyright The containerd Authors.

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

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

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

package fs

import (
	"context"
	"os"
	"path/filepath"
	"syscall"
)

type inode struct {
	// TODO(stevvooe): Can probably reduce memory usage by not tracking
	// device, but we can leave this right for now.
	dev, ino uint64
}

func newInode(stat *syscall.Stat_t) inode {
	return inode{
		// Dev is uint32 on darwin/bsd, uint64 on linux/solaris
		dev: uint64(stat.Dev), // nolint: unconvert
		// Ino is uint32 on bsd, uint64 on darwin/linux/solaris
		ino: uint64(stat.Ino), // nolint: unconvert
	}
}

func diskUsage(ctx context.Context, roots ...string) (Usage, error) {

	var (
		size   int64
		inodes = map[inode]struct{}{} // expensive!
	)

	for _, root := range roots {
		if err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
			if err != nil {
				return err
			}

			select {
			case <-ctx.Done():
				return ctx.Err()
			default:
			}

			stat := fi.Sys().(*syscall.Stat_t)
			inoKey := newInode(stat)
			if _, ok := inodes[inoKey]; !ok {
				inodes[inoKey] = struct{}{}
				// on arm64 stat.Blksize is int32
				size += stat.Blocks * int64(stat.Blksize) // nolint: unconvert
			}

			return nil
		}); err != nil {
			return Usage{}, err
		}
	}

	return Usage{
		Inodes: int64(len(inodes)),
		Size:   size,
	}, nil
}

func diffUsage(ctx context.Context, a, b string) (Usage, error) {
	var (
		size   int64
		inodes = map[inode]struct{}{} // expensive!
	)

	if err := Changes(ctx, a, b, func(kind ChangeKind, _ string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if kind == ChangeKindAdd || kind == ChangeKindModify {
			stat := fi.Sys().(*syscall.Stat_t)
			inoKey := newInode(stat)
			if _, ok := inodes[inoKey]; !ok {
				inodes[inoKey] = struct{}{}
				// on arm64 stat.Blksize is int32
				size += stat.Blocks * int64(stat.Blksize) // nolint: unconvert
			}

			return nil

		}
		return nil
	}); err != nil {
		return Usage{}, err
	}

	return Usage{
		Inodes: int64(len(inodes)),
		Size:   size,
	}, nil
}
<|endoftext|>


<commit_before>package api

import (
	"encoding/json"
	"errors"
	"fmt"
	"sync"

	"github.com/boltdb/bolt"
	"github.com/geodan/gost/src/sensorthings/entities"
	"github.com/geodan/gost/src/sensorthings/models"
	"log"
)

const (
	foiStateBucketName      = "foistate"
	foiDatastreamToThingKey = "datastreamToThing"
	foiThingToFoiKey        = "thingToFoi"
	foiUpdatedThingsKey     = "updatedThings"
)

var foiRepoLocker = &sync.Mutex{}

// FoiRepository is used to get a FeatureOfInterest (FOI) id by given datastream id. When an observation
// is added without any FOI id or FOI deep insert the linked things (last) Location should be used as FOI.
// FoiRepository loads the current state in memory and keeps track of FOI ID's created for a things location
// to do fast look ups of a FOI by observation.
type FoiRepository struct {
	db                *InternalDatabase
	updatedThings     []string
	thingToFoi        map[string]string
	datastreamToThing map[string]string
}

// LoadInMemory loads the previous FOI states into memory
func (f *FoiRepository) LoadInMemory() {
	f.updatedThings = make([]string, 0)
	f.thingToFoi = make(map[string]string, 0)
	f.datastreamToThing = make(map[string]string, 0)

	if !f.db.open {
		panic("BoltDB not opened yet")
	}

	f.db.bolt.Update(func(tx *bolt.Tx) error {
		tx.CreateBucketIfNotExists([]byte(foiStateBucketName))
		return nil
	})

	f.db.bolt.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(foiStateBucketName))
		if b == nil {
			return nil
		}

		json.Unmarshal(b.Get([]byte(foiUpdatedThingsKey)), &f.updatedThings)
		json.Unmarshal(b.Get([]byte(foiDatastreamToThingKey)), &f.datastreamToThing)
		json.Unmarshal(b.Get([]byte(foiThingToFoiKey)), &f.thingToFoi)

		return nil
	})
}

// ThingLocationUpdated should be called when a location by thing is updated, if needed a new
// FOI will be created and inserted into the database
func (f *FoiRepository) ThingLocationUpdated(thingID string) {
	// Do not add if already exist
	for _, t := range f.updatedThings {
		if t == thingID {
			return
		}
	}

	foiRepoLocker.Lock()
	log.Printf("Location updated")
	f.updatedThings = append(f.updatedThings, thingID)
	f.SaveState(foiUpdatedThingsKey)
	foiRepoLocker.Unlock()
}

// GetFoiIDByDatastreamID retrieves a FOI ID from memory by given datastream ID
func (f *FoiRepository) GetFoiIDByDatastreamID(gdb *models.Database, datastreamID interface{}) (string, error) {
	db := *gdb

	dId := toStringID(datastreamID)

	var ok bool
	var err error
	var foiID, tID string

	// check if datastream is in list, if not load from database including thing add to list, error if not found
	if tID, ok = f.datastreamToThing[dId]; !ok {
		// Datastream not found in list, look in database
		if _, err := db.GetDatastream(dId, nil); err != nil {
			// Datastream not found in database
			return "", errors.New("Datastream not found")
		} else {
			// Datastream found search for thing by datastream
			if thing, err := db.GetThingByDatastream(dId, nil); err != nil {
				return "", errors.New("Thing by datastream not found")
			} else {
				// Thing found, setup in datastreamToThing
				tStringId := toStringID(thing.ID)
				foiRepoLocker.Lock()
				log.Printf("Datastream to thing added: datastream: %v thing: %v", dId, tStringId)
				f.datastreamToThing[dId] = tStringId
				f.SaveState(foiDatastreamToThingKey)
				foiRepoLocker.Unlock()
				tID = tStringId
			}
		}
	}

	// Check if thing to foi is added
	if foiID, ok = f.thingToFoi[tID]; !ok {
		t, err := db.GetThing(tID, nil)

		// Thing not found in database
		if err != nil {
			return "", errors.New("Thing not found")
		}

		// Create a new foi
		if foiID, err = f.insertFoi(gdb, tID); err != nil {
			return "", errors.New("Error adding FeatureOfInterest")
		}

		// Update ThingToFoi list
		foiRepoLocker.Lock()
		f.thingToFoi[tID] = foiID
		log.Printf("ThingToFoi added: thing: %v foi: %v", toStringID(t.ID), foiID)
		f.SaveState(foiThingToFoiKey)
		foiRepoLocker.Unlock()
	}

	//check if foi needs to be updated (new location added for thing but no FOI created for it yet)
	for idx, t := range f.updatedThings {
		if t == tID {
			if foiID, err = f.insertFoi(gdb, tID); err != nil {
				return "", errors.New("Error adding FeatureOfInterest")
			}

			foiRepoLocker.Lock()
			f.thingToFoi[tID] = foiID
			f.updatedThings = append(f.updatedThings[:idx], f.updatedThings[idx+1:]...)
			f.SaveState(foiUpdatedThingsKey)
			foiRepoLocker.Unlock()
			break
		}
	}

	return foiID, nil
}

// insertFoi inserts a new FOI into the database and returns it's new ID
func (f *FoiRepository) insertFoi(gdb *models.Database, thingID string) (string, error) {
	db := *gdb

	l, err := db.GetLocationsByThing(thingID, nil)
	if err != nil || len(l) == 0 {
		return "", err
	}

	foi := &entities.FeatureOfInterest{}
	foi.Description = l[0].Description
	foi.EncodingType = l[0].EncodingType
	foi.Feature = l[0].Location

	nFoi, err := db.PostFeatureOfInterest(foi)
	if err != nil {
		return "", err
	}

	log.Printf("Inserted %v \n", nFoi.Description)

	return toStringID(nFoi.ID), nil
}

func (f *FoiRepository) SaveState(key string) error {
	if !f.db.open {
		return fmt.Errorf("db must be opened before saving!")
	}

	return f.db.bolt.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(foiStateBucketName))

		var value interface{}
		switch key {
		case foiUpdatedThingsKey:
			value = f.updatedThings
		case foiDatastreamToThingKey:
			value = f.datastreamToThing
		case foiThingToFoiKey:
			value = f.thingToFoi
		}

		enc, err := json.Marshal(value)
		if err != nil {
			return err
		}

		return b.Put([]byte(key), enc)
	})
}

func toStringID(id interface{}) string {
	return fmt.Sprintf("%v", id)
}
<commit_msg>build fixed<commit_after><|endoftext|>