<commit_before>package rbtree

import "errors"

// Interface need to implement Compare method
type Interface interface {
	// Compare data of reciever with argument
	// Return 0 if equal
	// Return 1/-1 if greater/less
	Compare(Interface) int
}

// BLACK and RED is color for edges
const (
	BLACK = false
	RED   = true
)

type node struct {
	left, right, p *node
	data           Interface
	color          bool
}

// RbTree is Red Black Tree
type RbTree struct {
	size       int
	null, root *node
}

// New return an initialized tree
func New() *RbTree {
	null := new(node)
	null.p = null
	null.right = null
	null.left = null
	null.data = nil
	null.color = BLACK
	return &RbTree{
		size: 0,
		null: null,
		root: null,
	}
}

// IsEmpty return true if the tree is empty
func (t *RbTree) IsEmpty() bool {
	return t.size == 0
}

// Clean reset a tree structure to it's initial stat
func (t *RbTree) Clean() *RbTree {
	t.size = 0
	t.root = t.null
	t.null = &node{
		p:     t.null,
		left:  t.null,
		right: t.null,
		color: BLACK,
	}
	return t
}

// Search return the element if found, or return non-nil error on not found
func (t *RbTree) Search(data Interface) (Interface, error) {
	x := t.search(t.root, data)
	if x == nil {
		return nil, errors.New("not found")
	}
	return x.data, nil
}

func (t *RbTree) search(r *node, data Interface) *node {
	x := r
	for x != t.null {
		var cmp int
		if cmp = data.Compare(x.data); cmp == 0 {
			return x
		}
		if cmp < 0 {
			x = x.left
		} else {
			x = x.right
		}
	}
	return nil
}

// Insert insert data into correct place
func (t *RbTree) Insert(data Interface) {
	x := t.root
	n := t.newNode(data)
	// n.color = RED
	p := t.null
	var cmp int
	for x != t.null {
		p = x
		if cmp = data.Compare(x.data); cmp < 0 {
			x = x.left
		} else {
			x = x.right
		}
	}
	n.p = p
	if p == t.null {
		t.root = n
	} else if cmp = data.Compare(p.data); cmp < 0 {
		p.left = n
	} else {
		p.right = n
	}
	t.insertFix(n)
	t.size++
}

/*
 * 1.                B
 *                  / \
 *                 R   R  <- y
 *                /
 *         x ->  R
 * 2.
 *                   B
 *                 /   \
 *                R     B  <- y
 *                 \
 *            x ->  R
 * 3.
 *                   B
 *                 /   \
 *                R     B  <- y
 *               /
 *        x ->  R
 */
func (t *RbTree) insertFix(x *node) {
	var y *node

	for x.p.color == RED {
		if x.p == x.p.p.left {
			y = x.p.p.right
			if y.color == RED {
				x.p.color = BLACK
				y.color = BLACK
				x.p.p.color = RED
				x = x.p.p
			} else {
				if x == x.p.right {
					x = x.p
					t.leftRotate(x)
				}
				x.p.color = BLACK
				x.p.p.color = RED
				t.rightRotate(x.p.p)
			}
		} else {
			y = x.p.p.left
			if y.color == RED {
				x.p.color = BLACK
				y.color = BLACK
				x.p.p.color = RED
				x = x.p.p
			} else {
				if x == x.p.left {
					x = x.p
					t.rightRotate(x)
				}
				x.p.color = BLACK
				x.p.p.color = RED
				t.leftRotate(x.p.p)
			}
		}
	}
	t.root.color = BLACK
}

// Delete remove data from tree
func (t *RbTree) Delete(data Interface) (Interface, error) {
	x := t.search(t.root, data)
	if x == nil {
		return nil, errors.New("not found")
	}

	var z *node
	y := x
	color := x.color
	if x.left == t.null {
		z = x.right
		t.transplant(x, x.right)
	} else if x.right == t.null {
		z = x.left
		t.transplant(x, x.left)
	} else {
		// y is the maxium node on x's right subtree
		// it will replace x
		y = func(n *node) *node {
			for n.left != t.null {
				n = n.left
			}
			return n
		}(x.right)

		color = y.color
		// z will replace y
		z = y.right
		if x.right == y {
			// Avoid y.p to point to y itself
			// Following statment may seem unneccesary,
			// but when z is t.null, value of it's p is uncertain
			z.p = y
		} else {
			t.transplant(y, y.right)
			y.right = x.right
			x.right.p = y
		}
		y.left = x.left
		x.left.p = y
		t.transplant(x, y)
		y.color = x.color
	}
	if color == BLACK {
		t.deleteFix(z)
	}
	t.size--
	return x.data, nil
}

/*
 * when this function is called, x seems to have an additional
 * black color, so this function aims to shift the extra color.
 * 1.
 *                    B
 *                 /     \
 *          x ->  B       R  <- y
 *                       / \
 *                      B   B
 * 2.
 *                   R|B
 *                 /     \
 *          x ->  B       B  <- y
 *                      /   \
 *                     B     B
 * 3.
 *                   R|B
 *                 /     \
 *          x ->  B       B  <- y
 *                      /   \
 *                     R     B
 * 4.
 *                   R|B
 *                 /     \
 *          x ->  B       B  <- y
 *                          \
 *                           R
 */
func (t *RbTree) deleteFix(x *node) {
	var y *node

	for x != t.root && x.color == BLACK {
		if x == x.p.left {
			y = x.p.right
			if y.color == RED {
				y.color = BLACK
				x.p.color = RED
				t.leftRotate(x.p)
				y = x.p.right
			}
			if y.right.color == BLACK && y.left.color == BLACK {
				y.color = RED
				x = x.p
			} else {
				if y.right.color == BLACK {
					y.left.color = BLACK
					y.color = RED
					t.rightRotate(y)
					y = x.p.right
				}
				y.color = x.p.color
				x.p.color = BLACK
				y.right.color = BLACK
				t.leftRotate(x.p)
				x = t.root
			}
		} else {
			y = x.p.left
			if y.color == RED {
				y.color = BLACK
				x.p.color = RED
				t.rightRotate(x.p)
				y = x.p.left
			}
			if y.left.color == BLACK && y.right.color == BLACK {
				y.color = RED
				x = x.p
			} else {
				if y.left.color == BLACK {
					y.right.color = BLACK
					y.color = RED
					t.leftRotate(y)
					y = x.p.left
				}
				y.color = x.p.color
				x.p.color = BLACK
				y.left.color = BLACK
				t.rightRotate(x.p)
				x = t.root
			}
		}
	}
	x.color = BLACK
}

// transplant s to the position of t
func (t *RbTree) transplant(pos, n *node) {
	if pos.p == t.null {
		t.root = n
	} else if pos == pos.p.left {
		pos.p.left = n
	} else {
		pos.p.right = n
	}
	n.p = pos.p
}

func (t *RbTree) newNode(data Interface) *node {
	return &node{
		left:  t.null,
		right: t.null,
		p:     t.null,
		data:  data,
		color: RED,
	}
}

/*
 *           x
 *          / \
 *         a   y
 *            / \
 *           b   c
 * ->
 *           y
 *          / \
 *         x   c
 *        / \
 *       a   b
 */
func (t *RbTree) leftRotate(x *node) {
	y := x.right
	x.right = y.left
	if y.left != t.null {
		y.left.p = x
	}
	t.transplant(x, y)
	y.left = x
	x.p = y
}

/*
 *           x
 *          / \
 *         y   c
 *        / \
 *       a   b
 * ->
 *           y
 *          / \
 *         a   x
 *            / \
 *           b   c
 */
func (t *RbTree) rightRotate(x *node) {
	y := x.left
	x.left = y.right
	if y.right != t.null {
		y.right.p = x
	}
	t.transplant(x, y)
	y.right = x
	x.p = y
}
<commit_msg>add package description<commit_after>/*
Package rbtree implements Red-Black Tree data structure on "Introduction to Algorithms".
*/
package rbtree

import "errors"

// Interface need to implement Compare method
type Interface interface {
	// Compare data of reciever with argument
	// Return 0 if equal
	// Return 1/-1 if greater/less
	Compare(Interface) int
}

// BLACK and RED is color for edges
const (
	BLACK = false
	RED   = true
)

type node struct {
	left, right, p *node
	data           Interface
	color          bool
}

// RbTree is Red Black Tree
type RbTree struct {
	size       int
	null, root *node
}

// New return an initialized tree
func New() *RbTree {
	null := new(node)
	null.p = null
	null.right = null
	null.left = null
	null.data = nil
	null.color = BLACK
	return &RbTree{
		size: 0,
		null: null,
		root: null,
	}
}

// IsEmpty return true if the tree is empty
func (t *RbTree) IsEmpty() bool {
	return t.size == 0
}

// Clean reset a tree structure to it's initial stat
func (t *RbTree) Clean() *RbTree {
	t.size = 0
	t.root = t.null
	t.null = &node{
		p:     t.null,
		left:  t.null,
		right: t.null,
		color: BLACK,
	}
	return t
}

// Search return the element if found, or return non-nil error on not found
func (t *RbTree) Search(data Interface) (Interface, error) {
	x := t.search(t.root, data)
	if x == nil {
		return nil, errors.New("not found")
	}
	return x.data, nil
}

func (t *RbTree) search(r *node, data Interface) *node {
	x := r
	for x != t.null {
		var cmp int
		if cmp = data.Compare(x.data); cmp == 0 {
			return x
		}
		if cmp < 0 {
			x = x.left
		} else {
			x = x.right
		}
	}
	return nil
}

// Insert insert data into correct place
func (t *RbTree) Insert(data Interface) {
	x := t.root
	n := t.newNode(data)
	// n.color = RED
	p := t.null
	var cmp int
	for x != t.null {
		p = x
		if cmp = data.Compare(x.data); cmp < 0 {
			x = x.left
		} else {
			x = x.right
		}
	}
	n.p = p
	if p == t.null {
		t.root = n
	} else if cmp = data.Compare(p.data); cmp < 0 {
		p.left = n
	} else {
		p.right = n
	}
	t.insertFix(n)
	t.size++
}

/*
 * 1.                B
 *                  / \
 *                 R   R  <- y
 *                /
 *         x ->  R
 * 2.
 *                   B
 *                 /   \
 *                R     B  <- y
 *                 \
 *            x ->  R
 * 3.
 *                   B
 *                 /   \
 *                R     B  <- y
 *               /
 *        x ->  R
 */
func (t *RbTree) insertFix(x *node) {
	var y *node

	for x.p.color == RED {
		if x.p == x.p.p.left {
			y = x.p.p.right
			if y.color == RED {
				x.p.color = BLACK
				y.color = BLACK
				x.p.p.color = RED
				x = x.p.p
			} else {
				if x == x.p.right {
					x = x.p
					t.leftRotate(x)
				}
				x.p.color = BLACK
				x.p.p.color = RED
				t.rightRotate(x.p.p)
			}
		} else {
			y = x.p.p.left
			if y.color == RED {
				x.p.color = BLACK
				y.color = BLACK
				x.p.p.color = RED
				x = x.p.p
			} else {
				if x == x.p.left {
					x = x.p
					t.rightRotate(x)
				}
				x.p.color = BLACK
				x.p.p.color = RED
				t.leftRotate(x.p.p)
			}
		}
	}
	t.root.color = BLACK
}

// Delete remove data from tree
func (t *RbTree) Delete(data Interface) (Interface, error) {
	x := t.search(t.root, data)
	if x == nil {
		return nil, errors.New("not found")
	}

	var z *node
	y := x
	color := x.color
	if x.left == t.null {
		z = x.right
		t.transplant(x, x.right)
	} else if x.right == t.null {
		z = x.left
		t.transplant(x, x.left)
	} else {
		// y is the maxium node on x's right subtree
		// it will replace x
		y = func(n *node) *node {
			for n.left != t.null {
				n = n.left
			}
			return n
		}(x.right)

		color = y.color
		// z will replace y
		z = y.right
		if x.right == y {
			// Avoid y.p to point to y itself
			// Following statment may seem unneccesary,
			// but when z is t.null, value of it's p is uncertain
			z.p = y
		} else {
			t.transplant(y, y.right)
			y.right = x.right
			x.right.p = y
		}
		y.left = x.left
		x.left.p = y
		t.transplant(x, y)
		y.color = x.color
	}
	if color == BLACK {
		t.deleteFix(z)
	}
	t.size--
	return x.data, nil
}

/*
 * when this function is called, x seems to have an additional
 * black color, so this function aims to shift the extra color.
 * 1.
 *                    B
 *                 /     \
 *          x ->  B       R  <- y
 *                       / \
 *                      B   B
 * 2.
 *                   R|B
 *                 /     \
 *          x ->  B       B  <- y
 *                      /   \
 *                     B     B
 * 3.
 *                   R|B
 *                 /     \
 *          x ->  B       B  <- y
 *                      /   \
 *                     R     B
 * 4.
 *                   R|B
 *                 /     \
 *          x ->  B       B  <- y
 *                          \
 *                           R
 */
func (t *RbTree) deleteFix(x *node) {
	var y *node

	for x != t.root && x.color == BLACK {
		if x == x.p.left {
			y = x.p.right
			if y.color == RED {
				y.color = BLACK
				x.p.color = RED
				t.leftRotate(x.p)
				y = x.p.right
			}
			if y.right.color == BLACK && y.left.color == BLACK {
				y.color = RED
				x = x.p
			} else {
				if y.right.color == BLACK {
					y.left.color = BLACK
					y.color = RED
					t.rightRotate(y)
					y = x.p.right
				}
				y.color = x.p.color
				x.p.color = BLACK
				y.right.color = BLACK
				t.leftRotate(x.p)
				x = t.root
			}
		} else {
			y = x.p.left
			if y.color == RED {
				y.color = BLACK
				x.p.color = RED
				t.rightRotate(x.p)
				y = x.p.left
			}
			if y.left.color == BLACK && y.right.color == BLACK {
				y.color = RED
				x = x.p
			} else {
				if y.left.color == BLACK {
					y.right.color = BLACK
					y.color = RED
					t.leftRotate(y)
					y = x.p.left
				}
				y.color = x.p.color
				x.p.color = BLACK
				y.left.color = BLACK
				t.rightRotate(x.p)
				x = t.root
			}
		}
	}
	x.color = BLACK
}

// transplant s to the position of t
func (t *RbTree) transplant(pos, n *node) {
	if pos.p == t.null {
		t.root = n
	} else if pos == pos.p.left {
		pos.p.left = n
	} else {
		pos.p.right = n
	}
	n.p = pos.p
}

func (t *RbTree) newNode(data Interface) *node {
	return &node{
		left:  t.null,
		right: t.null,
		p:     t.null,
		data:  data,
		color: RED,
	}
}

/*
 *           x
 *          / \
 *         a   y
 *            / \
 *           b   c
 * ->
 *           y
 *          / \
 *         x   c
 *        / \
 *       a   b
 */
func (t *RbTree) leftRotate(x *node) {
	y := x.right
	x.right = y.left
	if y.left != t.null {
		y.left.p = x
	}
	t.transplant(x, y)
	y.left = x
	x.p = y
}

/*
 *           x
 *          / \
 *         y   c
 *        / \
 *       a   b
 * ->
 *           y
 *          / \
 *         a   x
 *            / \
 *           b   c
 */
func (t *RbTree) rightRotate(x *node) {
	y := x.left
	x.left = y.right
	if y.right != t.null {
		y.right.p = x
	}
	t.transplant(x, y)
	y.right = x
	x.p = y
}
<|endoftext|>


<commit_before>package controllers

import (
	"net/http"

	"github.com/nicomo/EResourcesMetadataHub/logger"
	"github.com/nicomo/EResourcesMetadataHub/models"
	"github.com/nicomo/EResourcesMetadataHub/sudoc"
)

// SudocIsbn2PpnHandler manages the consuming of a web service to retrieve a Sudoc ID
//  There's a "priority" isbn, we try to get a marc record number for this one first
// using the other isbns only if we can't
func SudocIsbn2PpnHandler(w http.ResponseWriter, r *http.Request) {

	// data to be display in UI will be stored in this map
	d := make(map[string]interface{})

	// record ID is last part of the URL
	ebookId := r.URL.Path[len("/sudocisbn2ppn/"):]

	myEbook, err := models.EbookGetById(ebookId)
	if err != nil {
		logger.Error.Println(err)
	}

	// 2 URLs, 1 for the preferred isbn, 1 for the other isbns
	var priorityURL string
	var allIsbns []string
	allIsbnsURL := "http://www.sudoc.fr/services/isbn2ppn/"

	logger.Debug.Println(myEbook.Isbns)

	for _, v := range myEbook.Isbns {
		if v.Electronic {
			priorityURL = "http://www.sudoc.fr/services/isbn2ppn/" + v.Isbn
		} else {
			allIsbns = append(allIsbns, v.Isbn)
		}
	}

	for i, v := range allIsbns {
		if i < len(allIsbns)-1 {
			allIsbnsURL = allIsbnsURL + v + ","
		}
		allIsbnsURL = allIsbnsURL + v
	}

	logger.Debug.Println("priorityURL..." + priorityURL)
	logger.Debug.Println("allIsbnsURL..." + allIsbnsURL)

	// retrieve PPN from sudoc web service :
	// preferred isbns 1st if there's one
	// other isbns if preferred gets no result (error received)
	// FIXME: logic is wrong, too much repetitions between priority isbn and other isbns
	if priorityURL != "" {
		priorityPPN, sudocErr := sudoc.FetchPPN(priorityURL)
		if sudocErr != nil {
			logger.Error.Println(sudocErr)
			d["sudocErr"] = sudocErr
		}
		myPPN := models.PPNCreate(priorityPPN, true)
		myEbook.Ppns = myPPN
		logger.Debug.Printf("%v", myEbook)

		// actually save updated ebook struct to DB
		var ebkUpdateErr error
		myEbook, ebkUpdateErr = models.EbookUpdate(myEbook)
		if ebkUpdateErr != nil {
			logger.Error.Println(ebkUpdateErr)
		}
	}

	if len(myEbook.Ppns) == 0 {
		allPPN, allSudocErr := sudoc.FetchPPN(allIsbnsURL)
		if allSudocErr != nil {
			logger.Error.Println(allSudocErr)
			d["allSudocErr"] = allSudocErr
		}
		myPPNs := models.PPNCreate(allPPN, false)
		myEbook.Ppns = myPPNs
		logger.Debug.Printf("%v", myEbook)

		// actually save updated ebook struct to DB
		var ebkUpdateErr error
		myEbook, ebkUpdateErr = models.EbookUpdate(myEbook)
		if ebkUpdateErr != nil {
			logger.Error.Println(ebkUpdateErr)
		}
	}

	// redirect to book detail page
	// TODO: transmit either error or success message to user
	urlStr := "/ebook/" + ebookId
	http.Redirect(w, r, urlStr, 303)

}

func SudocGetRecordHandler(w http.ResponseWriter, r *http.Request) {

	// record ID is last part of the URL
	ebookId := r.URL.Path[len("/sudocgetrecord/"):]

	myEbook, err := models.EbookGetById(ebookId)
	if err != nil {
		logger.Error.Println(err)
	}

	// we put the "electronic" ppns 1st in the map, then the others
	// we sort the map
	// we fetch the record, and stop as soon as we get one
	var sortedPPNs []string
	for _, v := range myEbook.Ppns {
		if v.Electronic {
			sortedPPNs = append(sortedPPNs, "http://www.sudoc.fr/"+v.Ppn+".abes")
		}
	}
	for _, v := range myEbook.Ppns {
		if v.Electronic == false {
			sortedPPNs = append(sortedPPNs, "http://www.sudoc.fr/"+v.Ppn+".abes")
		}
	}

	logger.Debug.Println(sortedPPNs)

	for _, v := range sortedPPNs {
		record, err := sudoc.SudocGetRecord(v)
		if err != nil {
			logger.Error.Println(err)
			continue
		}
		logger.Debug.Println(record)

		// TODO: if the local record already has a mark record, update using delete / insert

		if record != "" {
			myEbook.MarcRecords = append(myEbook.MarcRecords, record)

			// actually save updated ebook struct to DB
			var ebkUpdateErr error
			myEbook, ebkUpdateErr = models.EbookUpdate(myEbook)
			if ebkUpdateErr != nil {
				logger.Error.Println(ebkUpdateErr)
			}
			logger.Debug.Println(myEbook)

			if len(myEbook.MarcRecords) > 0 {
				break
			}
		}
	}
}
<commit_msg>Sudoc record replace, stop at 1st record<commit_after>package controllers

import (
	"net/http"

	"github.com/nicomo/EResourcesMetadataHub/logger"
	"github.com/nicomo/EResourcesMetadataHub/models"
	"github.com/nicomo/EResourcesMetadataHub/sudoc"
)

// SudocIsbn2PpnHandler manages the consuming of a web service to retrieve a Sudoc ID
//  There's a "priority" isbn, we try to get a marc record number for this one first
// using the other isbns only if we can't
func SudocIsbn2PpnHandler(w http.ResponseWriter, r *http.Request) {

	// data to be display in UI will be stored in this map
	d := make(map[string]interface{})

	// record ID is last part of the URL
	ebookId := r.URL.Path[len("/sudocisbn2ppn/"):]

	myEbook, err := models.EbookGetById(ebookId)
	if err != nil {
		logger.Error.Println(err)
	}

	// 2 URLs, 1 for the preferred isbn, 1 for the other isbns
	var priorityURL string
	var allIsbns []string
	allIsbnsURL := "http://www.sudoc.fr/services/isbn2ppn/"

	logger.Debug.Println(myEbook.Isbns)

	for _, v := range myEbook.Isbns {
		if v.Electronic {
			priorityURL = "http://www.sudoc.fr/services/isbn2ppn/" + v.Isbn
		} else {
			allIsbns = append(allIsbns, v.Isbn)
		}
	}

	for i, v := range allIsbns {
		if i < len(allIsbns)-1 {
			allIsbnsURL = allIsbnsURL + v + ","
		}
		allIsbnsURL = allIsbnsURL + v
	}

	logger.Debug.Println("priorityURL..." + priorityURL)
	logger.Debug.Println("allIsbnsURL..." + allIsbnsURL)

	// retrieve PPN from sudoc web service :
	// preferred isbns 1st if there's one
	// other isbns if preferred gets no result (error received)
	// FIXME: logic is wrong, too much repetitions between priority isbn and other isbns
	if priorityURL != "" {
		priorityPPN, sudocErr := sudoc.FetchPPN(priorityURL)
		if sudocErr != nil {
			logger.Error.Println(sudocErr)
			d["sudocErr"] = sudocErr
		}
		myPPN := models.PPNCreate(priorityPPN, true)
		myEbook.Ppns = myPPN
		logger.Debug.Printf("%v", myEbook)

		// actually save updated ebook struct to DB
		var ebkUpdateErr error
		myEbook, ebkUpdateErr = models.EbookUpdate(myEbook)
		if ebkUpdateErr != nil {
			logger.Error.Println(ebkUpdateErr)
		}
	}

	if len(myEbook.Ppns) == 0 {
		allPPN, allSudocErr := sudoc.FetchPPN(allIsbnsURL)
		if allSudocErr != nil {
			logger.Error.Println(allSudocErr)
			d["allSudocErr"] = allSudocErr
		}
		myPPNs := models.PPNCreate(allPPN, false)
		myEbook.Ppns = myPPNs
		logger.Debug.Printf("%v", myEbook)

		// actually save updated ebook struct to DB
		var ebkUpdateErr error
		myEbook, ebkUpdateErr = models.EbookUpdate(myEbook)
		if ebkUpdateErr != nil {
			logger.Error.Println(ebkUpdateErr)
		}
	}

	// redirect to book detail page
	// TODO: transmit either error or success message to user
	urlStr := "/ebook/" + ebookId
	http.Redirect(w, r, urlStr, 303)

}

func SudocGetRecordHandler(w http.ResponseWriter, r *http.Request) {

	// record ID is last part of the URL
	ebookId := r.URL.Path[len("/sudocgetrecord/"):]

	myEbook, err := models.EbookGetById(ebookId)
	if err != nil {
		logger.Error.Println(err)
	}

	// we put the "electronic" ppns 1st in the map, then the others
	// we sort the map
	// we fetch the record, and stop as soon as we get one
	var sortedPPNs []string
	for _, v := range myEbook.Ppns {
		if v.Electronic {
			sortedPPNs = append(sortedPPNs, "http://www.sudoc.fr/"+v.Ppn+".abes")
		}
	}
	for _, v := range myEbook.Ppns {
		if v.Electronic == false {
			sortedPPNs = append(sortedPPNs, "http://www.sudoc.fr/"+v.Ppn+".abes")
		}
	}

	logger.Debug.Println(sortedPPNs)

	for _, v := range sortedPPNs {
		record, err := sudoc.SudocGetRecord(v)
		if err != nil {
			logger.Error.Println(err)
			continue
		}

		if record != "" {

			// if the local record already has a mark record, update using delete / insert
			myEbook.MarcRecords = nil
			myEbook.MarcRecords = append(myEbook.MarcRecords, record)

			// actually save updated ebook struct to DB
			var ebkUpdateErr error
			myEbook, ebkUpdateErr = models.EbookUpdate(myEbook)
			if ebkUpdateErr != nil {
				logger.Error.Println(ebkUpdateErr)
			}
			logger.Debug.Println(myEbook)

			if len(myEbook.MarcRecords) > 0 {
				break
			}
		}
	}

	// redirect to book detail page
	// TODO: transmit either error or success message to user
	urlStr := "/ebook/" + ebookId
	http.Redirect(w, r, urlStr, 303)
}
<|endoftext|>


<commit_before>package exec_test

import (
	"context"
	"errors"

	. "github.com/concourse/concourse/atc/exec"
	"github.com/concourse/concourse/atc/exec/build"
	"github.com/concourse/concourse/atc/exec/execfakes"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Retry Step", func() {
	var (
		ctx    context.Context
		cancel func()

		attempt1 *execfakes.FakeStep
		attempt2 *execfakes.FakeStep
		attempt3 *execfakes.FakeStep

		repo  *build.Repository
		state *execfakes.FakeRunState

		step Step
	)

	BeforeEach(func() {
		ctx, cancel = context.WithCancel(context.Background())

		attempt1 = new(execfakes.FakeStep)
		attempt2 = new(execfakes.FakeStep)
		attempt3 = new(execfakes.FakeStep)

		repo = build.NewRepository()
		state = new(execfakes.FakeRunState)
		state.ArtifactRepositoryReturns(repo)

		step = Retry(attempt1, attempt2, attempt3)
	})

	Context("when attempt 1 succeeds", func() {
		BeforeEach(func() {
			attempt1.SucceededReturns(true)
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns nil having only run the first attempt", func() {
				Expect(stepErr).ToNot(HaveOccurred())

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(0))
				Expect(attempt3.RunCallCount()).To(Equal(0))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 1", func() {
					// internal check for success within retry loop
					Expect(attempt1.SucceededCallCount()).To(Equal(1))

					attempt1.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt1.SucceededCallCount()).To(Equal(2))
				})
			})
		})
	})

	Context("when attempt 1 fails, and attempt 2 succeeds", func() {
		BeforeEach(func() {
			attempt1.SucceededReturns(false)
			attempt2.SucceededReturns(true)
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns nil having only run the first and second attempts", func() {
				Expect(stepErr).ToNot(HaveOccurred())

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(1))
				Expect(attempt3.RunCallCount()).To(Equal(0))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 2", func() {
					// internal check for success within retry loop
					Expect(attempt2.SucceededCallCount()).To(Equal(1))

					attempt2.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt2.SucceededCallCount()).To(Equal(2))
				})
			})
		})
	})

	Context("when attempt 1 errors, and attempt 2 succeeds", func() {
		BeforeEach(func() {
			attempt1.RunReturns(errors.New("nope"))
			attempt2.SucceededReturns(true)
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns nil having only run the first and second attempts", func() {
				Expect(stepErr).ToNot(HaveOccurred())

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(1))
				Expect(attempt3.RunCallCount()).To(Equal(0))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 2", func() {
					// internal check for success within retry loop
					Expect(attempt2.SucceededCallCount()).To(Equal(1))

					attempt2.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt2.SucceededCallCount()).To(Equal(2))
				})
			})
		})
	})

	Context("when attempt 1 errors, and attempt 2 is interrupted", func() {
		BeforeEach(func() {
			attempt1.RunReturns(errors.New("nope"))
			attempt2.RunStub = func(c context.Context, r RunState) error {
				cancel()
				return c.Err()
			}
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns the context error having only run the first and second attempts", func() {
				Expect(stepErr).To(Equal(context.Canceled))

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(1))
				Expect(attempt3.RunCallCount()).To(Equal(0))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 2", func() {
					// internal check for success within retry loop
					Expect(attempt2.SucceededCallCount()).To(Equal(0))

					attempt2.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt2.SucceededCallCount()).To(Equal(1))
				})
			})
		})
	})

	Context("when attempt 1 errors, attempt 2 times out, and attempt 3 succeeds", func() {
		BeforeEach(func() {
			attempt1.RunReturns(errors.New("nope"))
			attempt2.RunStub = func(c context.Context, r RunState) error {
				timeout, subCancel := context.WithTimeout(c, 0)
				defer subCancel()
				<-timeout.Done()
				return timeout.Err()
			}
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns nil after running all 3 steps", func() {
				Expect(stepErr).ToNot(HaveOccurred())

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(1))
				Expect(attempt3.RunCallCount()).To(Equal(1))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 3", func() {
					// internal check for success within retry loop
					Expect(attempt3.SucceededCallCount()).To(Equal(1))

					attempt3.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt3.SucceededCallCount()).To(Equal(2))
				})
			})
		})
	})

	Context("when attempt 1 fails, attempt 2 fails, and attempt 3 succeeds", func() {
		BeforeEach(func() {
			attempt1.SucceededReturns(false)
			attempt2.SucceededReturns(false)
			attempt3.SucceededReturns(true)
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns nil after running all 3 steps", func() {
				Expect(stepErr).ToNot(HaveOccurred())

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(1))
				Expect(attempt3.RunCallCount()).To(Equal(1))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 3", func() {
					// internal check for success within retry loop
					Expect(attempt3.SucceededCallCount()).To(Equal(1))

					attempt3.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt3.SucceededCallCount()).To(Equal(2))
				})
			})
		})
	})

	Context("when attempt 1 fails, attempt 2 fails, and attempt 3 errors", func() {
		disaster := errors.New("nope")

		BeforeEach(func() {
			attempt1.SucceededReturns(false)
			attempt2.SucceededReturns(false)
			attempt3.RunReturns(disaster)
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns the error", func() {
				Expect(stepErr).To(Equal(disaster))

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(1))
				Expect(attempt3.RunCallCount()).To(Equal(1))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 3", func() {
					// no internal check for success within retry loop, since it errored
					Expect(attempt3.SucceededCallCount()).To(Equal(0))

					attempt3.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt3.SucceededCallCount()).To(Equal(1))
				})
			})
		})
	})

	Context("when attempt 1 fails, attempt 2 fails, and attempt 3 fails", func() {
		BeforeEach(func() {
			attempt1.SucceededReturns(false)
			attempt2.SucceededReturns(false)
			attempt3.SucceededReturns(true)
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns nil having only run the first and second attempts", func() {
				Expect(stepErr).ToNot(HaveOccurred())

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(1))
				Expect(attempt3.RunCallCount()).To(Equal(1))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 3", func() {
					// internal check for success within retry loop
					Expect(attempt3.SucceededCallCount()).To(Equal(1))

					attempt3.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt3.SucceededCallCount()).To(Equal(2))
				})
			})
		})
	})

	Context("when the RetryStep is given no attempts", func() {
		BeforeEach(func() {
			step = Retry()
		})

		Describe("Succeeded", func() {
			It("should return false", func() {
				Expect(step.Succeeded()).To(BeFalse())
			})
		})
	})
})
<commit_msg>Add extra test<commit_after>package exec_test

import (
	"context"
	"errors"

	. "github.com/concourse/concourse/atc/exec"
	"github.com/concourse/concourse/atc/exec/build"
	"github.com/concourse/concourse/atc/exec/execfakes"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Retry Step", func() {
	var (
		ctx    context.Context
		cancel func()

		attempt1 *execfakes.FakeStep
		attempt2 *execfakes.FakeStep
		attempt3 *execfakes.FakeStep

		repo  *build.Repository
		state *execfakes.FakeRunState

		step Step
	)

	BeforeEach(func() {
		ctx, cancel = context.WithCancel(context.Background())

		attempt1 = new(execfakes.FakeStep)
		attempt2 = new(execfakes.FakeStep)
		attempt3 = new(execfakes.FakeStep)

		repo = build.NewRepository()
		state = new(execfakes.FakeRunState)
		state.ArtifactRepositoryReturns(repo)

		step = Retry(attempt1, attempt2, attempt3)
	})

	Context("when calling succeeded before running", func() {
		Context("when the RetryStep is given no attempts", func() {
			BeforeEach(func() {
				step = Retry()
			})

			Describe("Succeeded", func() {
				It("should return false", func() {
					Expect(step.Succeeded()).To(BeFalse())
				})
			})
		})

		Context("when the RetryStep is given attempts", func() {
			Describe("Succeeded", func() {
				It("should return false", func() {
					Expect(step.Succeeded()).To(BeFalse())
				})
			})
		})
	})
	Context("when attempt 1 succeeds", func() {
		BeforeEach(func() {
			attempt1.SucceededReturns(true)
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns nil having only run the first attempt", func() {
				Expect(stepErr).ToNot(HaveOccurred())

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(0))
				Expect(attempt3.RunCallCount()).To(Equal(0))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 1", func() {
					// internal check for success within retry loop
					Expect(attempt1.SucceededCallCount()).To(Equal(1))

					attempt1.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt1.SucceededCallCount()).To(Equal(2))
				})
			})
		})
	})

	Context("when attempt 1 fails, and attempt 2 succeeds", func() {
		BeforeEach(func() {
			attempt1.SucceededReturns(false)
			attempt2.SucceededReturns(true)
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns nil having only run the first and second attempts", func() {
				Expect(stepErr).ToNot(HaveOccurred())

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(1))
				Expect(attempt3.RunCallCount()).To(Equal(0))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 2", func() {
					// internal check for success within retry loop
					Expect(attempt2.SucceededCallCount()).To(Equal(1))

					attempt2.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt2.SucceededCallCount()).To(Equal(2))
				})
			})
		})
	})

	Context("when attempt 1 errors, and attempt 2 succeeds", func() {
		BeforeEach(func() {
			attempt1.RunReturns(errors.New("nope"))
			attempt2.SucceededReturns(true)
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns nil having only run the first and second attempts", func() {
				Expect(stepErr).ToNot(HaveOccurred())

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(1))
				Expect(attempt3.RunCallCount()).To(Equal(0))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 2", func() {
					// internal check for success within retry loop
					Expect(attempt2.SucceededCallCount()).To(Equal(1))

					attempt2.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt2.SucceededCallCount()).To(Equal(2))
				})
			})
		})
	})

	Context("when attempt 1 errors, and attempt 2 is interrupted", func() {
		BeforeEach(func() {
			attempt1.RunReturns(errors.New("nope"))
			attempt2.RunStub = func(c context.Context, r RunState) error {
				cancel()
				return c.Err()
			}
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns the context error having only run the first and second attempts", func() {
				Expect(stepErr).To(Equal(context.Canceled))

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(1))
				Expect(attempt3.RunCallCount()).To(Equal(0))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 2", func() {
					// internal check for success within retry loop
					Expect(attempt2.SucceededCallCount()).To(Equal(0))

					attempt2.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt2.SucceededCallCount()).To(Equal(1))
				})
			})
		})
	})

	Context("when attempt 1 errors, attempt 2 times out, and attempt 3 succeeds", func() {
		BeforeEach(func() {
			attempt1.RunReturns(errors.New("nope"))
			attempt2.RunStub = func(c context.Context, r RunState) error {
				timeout, subCancel := context.WithTimeout(c, 0)
				defer subCancel()
				<-timeout.Done()
				return timeout.Err()
			}
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns nil after running all 3 steps", func() {
				Expect(stepErr).ToNot(HaveOccurred())

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(1))
				Expect(attempt3.RunCallCount()).To(Equal(1))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 3", func() {
					// internal check for success within retry loop
					Expect(attempt3.SucceededCallCount()).To(Equal(1))

					attempt3.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt3.SucceededCallCount()).To(Equal(2))
				})
			})
		})
	})

	Context("when attempt 1 fails, attempt 2 fails, and attempt 3 succeeds", func() {
		BeforeEach(func() {
			attempt1.SucceededReturns(false)
			attempt2.SucceededReturns(false)
			attempt3.SucceededReturns(true)
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns nil after running all 3 steps", func() {
				Expect(stepErr).ToNot(HaveOccurred())

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(1))
				Expect(attempt3.RunCallCount()).To(Equal(1))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 3", func() {
					// internal check for success within retry loop
					Expect(attempt3.SucceededCallCount()).To(Equal(1))

					attempt3.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt3.SucceededCallCount()).To(Equal(2))
				})
			})
		})
	})

	Context("when attempt 1 fails, attempt 2 fails, and attempt 3 errors", func() {
		disaster := errors.New("nope")

		BeforeEach(func() {
			attempt1.SucceededReturns(false)
			attempt2.SucceededReturns(false)
			attempt3.RunReturns(disaster)
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns the error", func() {
				Expect(stepErr).To(Equal(disaster))

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(1))
				Expect(attempt3.RunCallCount()).To(Equal(1))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 3", func() {
					// no internal check for success within retry loop, since it errored
					Expect(attempt3.SucceededCallCount()).To(Equal(0))

					attempt3.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt3.SucceededCallCount()).To(Equal(1))
				})
			})
		})
	})

	Context("when attempt 1 fails, attempt 2 fails, and attempt 3 fails", func() {
		BeforeEach(func() {
			attempt1.SucceededReturns(false)
			attempt2.SucceededReturns(false)
			attempt3.SucceededReturns(true)
		})

		Describe("Run", func() {
			var stepErr error

			JustBeforeEach(func() {
				stepErr = step.Run(ctx, state)
			})

			It("returns nil having only run the first and second attempts", func() {
				Expect(stepErr).ToNot(HaveOccurred())

				Expect(attempt1.RunCallCount()).To(Equal(1))
				Expect(attempt2.RunCallCount()).To(Equal(1))
				Expect(attempt3.RunCallCount()).To(Equal(1))
			})

			Describe("Succeeded", func() {
				It("delegates to attempt 3", func() {
					// internal check for success within retry loop
					Expect(attempt3.SucceededCallCount()).To(Equal(1))

					attempt3.SucceededReturns(true)

					Expect(step.Succeeded()).To(BeTrue())

					Expect(attempt3.SucceededCallCount()).To(Equal(2))
				})
			})
		})
	})
})
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package websocket

import (
	"bufio"
	"fmt"
	"io"
	"net/http"
)

func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request, config *Config, handshake func(*Config, *http.Request) error) (conn *Conn, err error) {
	var hs serverHandshaker = &hybiServerHandshaker{Config: config}
	code, err := hs.ReadHandshake(buf.Reader, req)
	if err == ErrBadWebSocketVersion {
		fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
		fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion)
		buf.WriteString("\r\n")
		buf.WriteString(err.Error())
		buf.Flush()
		return
	}
	if err != nil {
		fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
		buf.WriteString("\r\n")
		buf.WriteString(err.Error())
		buf.Flush()
		return
	}
	if handshake != nil {
		err = handshake(config, req)
		if err != nil {
			code = http.StatusForbidden
			fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
			buf.WriteString("\r\n")
			buf.Flush()
			return
		}
	}
	err = hs.AcceptHandshake(buf.Writer)
	if err != nil {
		code = http.StatusBadRequest
		fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
		buf.WriteString("\r\n")
		buf.Flush()
		return
	}
	conn = hs.NewServerConn(buf, rwc, req)
	return
}

// Server represents a server of a WebSocket.
type Server struct {
	// Config is a WebSocket configuration for new WebSocket connection.
	Config

	// Handshake is an optional function in WebSocket handshake.
	// For example, you can check, or don't check Origin header.
	// Another example, you can select config.Protocol.
	Handshake func(*Config, *http.Request) error

	// Handler handles a WebSocket connection.
	Handler
}

// ServeHTTP implements the http.Handler interface for a WebSocket
func (s Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	s.serveWebSocket(w, req)
}

func (s Server) serveWebSocket(w http.ResponseWriter, req *http.Request) {
	rwc, buf, err := w.(http.Hijacker).Hijack()
	if err != nil {
		panic("Hijack failed: " + err.Error())
		return
	}
	// The server should abort the WebSocket connection if it finds
	// the client did not send a handshake that matches with protocol
	// specification.
	defer rwc.Close()
	conn, err := newServerConn(rwc, buf, req, &s.Config, s.Handshake)
	if err != nil {
		panic(err)
		return
	}
	if conn == nil {
		panic("unexpected nil conn")
	}
	s.Handler(conn)
}

// Handler is a simple interface to a WebSocket browser client.
// It checks if Origin header is valid URL by default.
// You might want to verify websocket.Conn.Config().Origin in the func.
// If you use Server instead of Handler, you could call websocket.Origin and
// check the origin in your Handshake func. So, if you want to accept
// non-browser client, which doesn't send Origin header, you could use Server
//. that doesn't check origin in its Handshake.
type Handler func(*Conn)

func checkOrigin(config *Config, req *http.Request) (err error) {
	config.Origin, err = Origin(config, req)
	if err == nil && config.Origin == nil {
		return fmt.Errorf("null origin")
	}
	return err
}

// ServeHTTP implements the http.Handler interface for a WebSocket
func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	s := Server{Handler: h, Handshake: checkOrigin}
	s.serveWebSocket(w, req)
}
<commit_msg>Dont stop connection if seems to be invalid (need further recheck<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package websocket

import (
	"bufio"
	"fmt"
	"io"
	"net/http"
)

func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request, config *Config, handshake func(*Config, *http.Request) error) (conn *Conn, err error) {
	var hs serverHandshaker = &hybiServerHandshaker{Config: config}
	code, err := hs.ReadHandshake(buf.Reader, req)
	if err == ErrBadWebSocketVersion {
		fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
		fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion)
		buf.WriteString("\r\n")
		buf.WriteString(err.Error())
		buf.Flush()
		return
	}
	if err != nil {
		fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
		buf.WriteString("\r\n")
		buf.WriteString(err.Error())
		buf.Flush()
		return
	}
	if handshake != nil {
		err = handshake(config, req)
		if err != nil {
			code = http.StatusForbidden
			fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
			buf.WriteString("\r\n")
			buf.Flush()
			return
		}
	}
	err = hs.AcceptHandshake(buf.Writer)
	if err != nil {
		code = http.StatusBadRequest
		fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
		buf.WriteString("\r\n")
		buf.Flush()
		return
	}
	conn = hs.NewServerConn(buf, rwc, req)
	return
}

// Server represents a server of a WebSocket.
type Server struct {
	// Config is a WebSocket configuration for new WebSocket connection.
	Config

	// Handshake is an optional function in WebSocket handshake.
	// For example, you can check, or don't check Origin header.
	// Another example, you can select config.Protocol.
	Handshake func(*Config, *http.Request) error

	// Handler handles a WebSocket connection.
	Handler
}

// ServeHTTP implements the http.Handler interface for a WebSocket
func (s Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	s.serveWebSocket(w, req)
}

func (s Server) serveWebSocket(w http.ResponseWriter, req *http.Request) {
	rwc, buf, err := w.(http.Hijacker).Hijack()
	if err != nil {
		panic("Hijack failed: " + err.Error())
		return
	}
	// The server should abort the WebSocket connection if it finds
	// the client did not send a handshake that matches with protocol
	// specification.
	defer rwc.Close()
	conn, err := newServerConn(rwc, buf, req, &s.Config, s.Handshake)
	if err != nil {
		panic(err)
		//return
	}
	if conn == nil {
		panic("unexpected nil conn")
	}
	s.Handler(conn)
}

// Handler is a simple interface to a WebSocket browser client.
// It checks if Origin header is valid URL by default.
// You might want to verify websocket.Conn.Config().Origin in the func.
// If you use Server instead of Handler, you could call websocket.Origin and
// check the origin in your Handshake func. So, if you want to accept
// non-browser client, which doesn't send Origin header, you could use Server
//. that doesn't check origin in its Handshake.
type Handler func(*Conn)

func checkOrigin(config *Config, req *http.Request) (err error) {
	config.Origin, err = Origin(config, req)
	if err == nil && config.Origin == nil {
		return fmt.Errorf("null origin")
	}
	return err
}

// ServeHTTP implements the http.Handler interface for a WebSocket
func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	s := Server{Handler: h, Handshake: checkOrigin}
	s.serveWebSocket(w, req)
}
<|endoftext|>


<commit_before>package php

import (
	"stephensearles.com/php/ast"
	"stephensearles.com/php/token"
)

func (p *Parser) parseIf() *ast.IfStmt {
	p.expect(token.OpenParen)
	n := &ast.IfStmt{}
	n.Condition = p.parseNextExpression()
	p.expect(token.CloseParen)

	p.next()
	n.TrueBranch = p.parseControlBlock(token.EndIf, token.ElseIf, token.Else)
	n.FalseBranch = ast.Block{}

	blockStyle := false
	switch p.current.typ {
	case token.ElseIf, token.Else, token.EndIf:
	default:
		p.next()
		blockStyle = true
	}

	switch p.current.typ {
	case token.ElseIf:
		n.FalseBranch = p.parseIf()
	case token.Else:
		p.next()
		if p.current.typ == token.If {
			n.FalseBranch = p.parseIf()
		} else {
			n.FalseBranch = p.parseControlBlock(token.EndIf)
		}
	default:
		if blockStyle {
			p.backup()
		}
	}

	return n
}

func (p *Parser) parseWhile() ast.Statement {
	p.expect(token.OpenParen)
	term := p.parseNextExpression()
	p.expect(token.CloseParen)
	p.next()
	block := p.parseControlBlock()
	return &ast.WhileStmt{
		Termination: term,
		LoopBlock:   block,
	}
}

func (p *Parser) parseForeach() ast.Statement {
	stmt := &ast.ForeachStmt{}
	p.expect(token.OpenParen)
	stmt.Source = p.parseNextExpression()
	p.expect(token.AsOperator)
	if p.peek().typ == token.AmpersandOperator {
		p.expect(token.AmpersandOperator)
	}
	p.expect(token.VariableOperator)
	p.next()
	first := ast.NewVariable(p.current.val)
	if p.peek().typ == token.ArrayKeyOperator {
		stmt.Key = first
		p.expect(token.ArrayKeyOperator)
		if p.peek().typ == token.AmpersandOperator {
			p.expect(token.AmpersandOperator)
		}
		p.expect(token.VariableOperator)
		p.next()
		stmt.Value = ast.NewVariable(p.current.val)
	} else {
		stmt.Value = first
	}
	p.expect(token.CloseParen)
	p.next()
	stmt.LoopBlock = p.parseControlBlock(token.EndForeach)
	return stmt
}

func (p *Parser) parseControlBlock(end ...token.Token) ast.Statement {
	// try to parse this in bash style, but it requires an end token
	if len(end) > 0 && p.current.typ == token.TernaryOperator2 {
		return p.parseStatementsUntil(end...)
	}
	return p.parseStmt()
}

func (p *Parser) parseFor() ast.Statement {
	stmt := &ast.ForStmt{}
	p.expect(token.OpenParen)
	stmt.Initialization = p.parseExpressionsUntil(token.Comma, token.StatementEnd)
	stmt.Termination = p.parseExpressionsUntil(token.Comma, token.StatementEnd)
	stmt.Iteration = p.parseExpressionsUntil(token.Comma, token.CloseParen)
	p.expectCurrent(token.CloseParen)
	p.next()
	stmt.LoopBlock = p.parseControlBlock(token.EndFor)
	return stmt
}

func (p *Parser) parseDo() ast.Statement {
	block := p.parseBlock()
	p.expect(token.While)
	p.expect(token.OpenParen)
	term := p.parseNextExpression()
	p.expect(token.CloseParen)
	p.expectStmtEnd()
	return &ast.DoWhileStmt{
		Termination: term,
		LoopBlock:   block,
	}
}

func (p *Parser) parseSwitch() ast.Statement {
	stmt := ast.SwitchStmt{}
	p.expect(token.OpenParen)
	stmt.Expression = p.parseExpression()
	p.expectCurrent(token.CloseParen)
	p.expect(token.BlockBegin, token.TernaryOperator2)
	p.next()
	for {
		switch p.current.typ {
		case token.Case:
			expr := p.parseNextExpression()
			p.expect(token.TernaryOperator2)
			p.next()
			stmt.Cases = append(stmt.Cases, &ast.SwitchCase{
				Expression: expr,
				Block:      *(p.parseSwitchBlock()),
			})
		case token.Default:
			p.expect(token.TernaryOperator2)
			p.next()
			stmt.DefaultCase = p.parseSwitchBlock()
		case token.BlockEnd, token.EndSwitch:
			return stmt
		default:
			p.errorf("Unexpected token. in switch statement:", p.current)
			return nil
		}
	}
}

func (p *Parser) parseSwitchBlock() *ast.Block {
	needBlockEnd := false
	if p.current.typ == token.BlockBegin {
		needBlockEnd = true
		p.next()
	}
	block := &ast.Block{
		Statements: make([]ast.Statement, 0),
	}
stmtLoop:
	for {
		switch p.current.typ {
		case token.BlockEnd:
			if needBlockEnd {
				needBlockEnd = false
				p.next()
			}
			fallthrough
		case token.Case, token.Default:
			break stmtLoop
		default:
			stmt := p.parseStmt()
			if stmt == nil {
				p.errorf("Invalid statement in switch block", p.current)
				break stmtLoop
			}
			block.Statements = append(block.Statements, stmt)
			p.next()
		}
	}
	if needBlockEnd {
		p.errorf("switch case needs block end")
	}
	return block
}
<commit_msg>Fixed the bash style while loop<commit_after>package php

import (
	"stephensearles.com/php/ast"
	"stephensearles.com/php/token"
)

func (p *Parser) parseIf() *ast.IfStmt {
	p.expect(token.OpenParen)
	n := &ast.IfStmt{}
	n.Condition = p.parseNextExpression()
	p.expect(token.CloseParen)

	p.next()
	n.TrueBranch = p.parseControlBlock(token.EndIf, token.ElseIf, token.Else)
	n.FalseBranch = ast.Block{}

	blockStyle := false
	switch p.current.typ {
	case token.ElseIf, token.Else, token.EndIf:
	default:
		p.next()
		blockStyle = true
	}

	switch p.current.typ {
	case token.ElseIf:
		n.FalseBranch = p.parseIf()
	case token.Else:
		p.next()
		if p.current.typ == token.If {
			n.FalseBranch = p.parseIf()
		} else {
			n.FalseBranch = p.parseControlBlock(token.EndIf)
		}
	default:
		if blockStyle {
			p.backup()
		}
	}

	return n
}

func (p *Parser) parseWhile() ast.Statement {
	p.expect(token.OpenParen)
	term := p.parseNextExpression()
	p.expect(token.CloseParen)
	p.next()
	block := p.parseControlBlock(token.EndWhile)
	return &ast.WhileStmt{
		Termination: term,
		LoopBlock:   block,
	}
}

func (p *Parser) parseForeach() ast.Statement {
	stmt := &ast.ForeachStmt{}
	p.expect(token.OpenParen)
	stmt.Source = p.parseNextExpression()
	p.expect(token.AsOperator)
	if p.peek().typ == token.AmpersandOperator {
		p.expect(token.AmpersandOperator)
	}
	p.expect(token.VariableOperator)
	p.next()
	first := ast.NewVariable(p.current.val)
	if p.peek().typ == token.ArrayKeyOperator {
		stmt.Key = first
		p.expect(token.ArrayKeyOperator)
		if p.peek().typ == token.AmpersandOperator {
			p.expect(token.AmpersandOperator)
		}
		p.expect(token.VariableOperator)
		p.next()
		stmt.Value = ast.NewVariable(p.current.val)
	} else {
		stmt.Value = first
	}
	p.expect(token.CloseParen)
	p.next()
	stmt.LoopBlock = p.parseControlBlock(token.EndForeach)
	return stmt
}

func (p *Parser) parseControlBlock(end ...token.Token) ast.Statement {
	// try to parse this in bash style, but it requires an end token
	if len(end) > 0 && p.current.typ == token.TernaryOperator2 {
		return p.parseStatementsUntil(end...)
	}
	return p.parseStmt()
}

func (p *Parser) parseFor() ast.Statement {
	stmt := &ast.ForStmt{}
	p.expect(token.OpenParen)
	stmt.Initialization = p.parseExpressionsUntil(token.Comma, token.StatementEnd)
	stmt.Termination = p.parseExpressionsUntil(token.Comma, token.StatementEnd)
	stmt.Iteration = p.parseExpressionsUntil(token.Comma, token.CloseParen)
	p.expectCurrent(token.CloseParen)
	p.next()
	stmt.LoopBlock = p.parseControlBlock(token.EndFor)
	return stmt
}

func (p *Parser) parseDo() ast.Statement {
	block := p.parseBlock()
	p.expect(token.While)
	p.expect(token.OpenParen)
	term := p.parseNextExpression()
	p.expect(token.CloseParen)
	p.expectStmtEnd()
	return &ast.DoWhileStmt{
		Termination: term,
		LoopBlock:   block,
	}
}

func (p *Parser) parseSwitch() ast.Statement {
	stmt := ast.SwitchStmt{}
	p.expect(token.OpenParen)
	stmt.Expression = p.parseExpression()
	p.expectCurrent(token.CloseParen)
	p.expect(token.BlockBegin, token.TernaryOperator2)
	p.next()
	for {
		switch p.current.typ {
		case token.Case:
			expr := p.parseNextExpression()
			p.expect(token.TernaryOperator2)
			p.next()
			stmt.Cases = append(stmt.Cases, &ast.SwitchCase{
				Expression: expr,
				Block:      *(p.parseSwitchBlock()),
			})
		case token.Default:
			p.expect(token.TernaryOperator2)
			p.next()
			stmt.DefaultCase = p.parseSwitchBlock()
		case token.BlockEnd, token.EndSwitch:
			return stmt
		default:
			p.errorf("Unexpected token. in switch statement:", p.current)
			return nil
		}
	}
}

func (p *Parser) parseSwitchBlock() *ast.Block {
	needBlockEnd := false
	if p.current.typ == token.BlockBegin {
		needBlockEnd = true
		p.next()
	}
	block := &ast.Block{
		Statements: make([]ast.Statement, 0),
	}
stmtLoop:
	for {
		switch p.current.typ {
		case token.BlockEnd:
			if needBlockEnd {
				needBlockEnd = false
				p.next()
			}
			fallthrough
		case token.Case, token.Default:
			break stmtLoop
		default:
			stmt := p.parseStmt()
			if stmt == nil {
				p.errorf("Invalid statement in switch block", p.current)
				break stmtLoop
			}
			block.Statements = append(block.Statements, stmt)
			p.next()
		}
	}
	if needBlockEnd {
		p.errorf("switch case needs block end")
	}
	return block
}
<|endoftext|>


<commit_before>package arm

import (
	"fmt"
	sysnum "github.com/lunixbochs/ghostrace/ghost/sys/num"
	uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"

	"github.com/lunixbochs/usercorn/go/kernel/common"
	"github.com/lunixbochs/usercorn/go/kernel/linux"
	"github.com/lunixbochs/usercorn/go/models"
	"github.com/lunixbochs/usercorn/go/models/cpu"
)

var LinuxRegs = []int{uc.ARM_REG_R0, uc.ARM_REG_R1, uc.ARM_REG_R2, uc.ARM_REG_R3, uc.ARM_REG_R4, uc.ARM_REG_R5, uc.ARM_REG_R6}

type ArmLinuxKernel struct {
	*linux.LinuxKernel
	tls uint64
}

func (k *ArmLinuxKernel) SetTls(addr uint64) {
	k.tls = addr
	k.U.RunAsm(0, "mcr p15, 0, r0, c13, c0, 3",
		map[int]uint64{uc.ARM_REG_R0: addr},
		[]int{uc.ARM_REG_R0},
	)
}

func setupTraps(u models.Usercorn, kernel *ArmLinuxKernel) error {
	// handle arm kernel traps
	// https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt
	if err := u.MemMap(0xffff0000, 0x10000, cpu.PROT_READ|cpu.PROT_EXEC); err != nil {
		return err
	}
	for addr := 0; addr < 0x10000; addr += 4 {
		// write "bx lr" to all kernel trap addresses so they will return
		bxlr := []byte{0x1e, 0xff, 0x2f, 0xe1}
		if err := u.MemWrite(0xffff0000+uint64(addr), bxlr); err != nil {
			return err
		}
	}
	_, err := u.HookAdd(cpu.HOOK_CODE, func(_ cpu.Cpu, addr uint64, size uint32) {
		switch addr {
		case 0xffff0fa0:
			// __kuser_memory_barrier
			// *shrug*
		case 0xffff0f60:
			// __kuser_cmpxchg64
			// TODO: DRY possible here?
			oldval, _ := u.RegRead(uc.ARM_REG_R0)
			newval, _ := u.RegRead(uc.ARM_REG_R1)
			ptr, _ := u.RegRead(uc.ARM_REG_R2)
			var tmp [8]byte
			var status uint64
			if err := u.MemReadInto(tmp[:], ptr); err != nil {
				// error
			} else if u.ByteOrder().Uint64(tmp[:]) == oldval {
				u.ByteOrder().PutUint64(tmp[:], newval)
				u.MemWrite(ptr, tmp[:])
				status = 1
			}
			u.RegWrite(uc.ARM_REG_R0, status)
		case 0xffff0fc0:
			// __kuser_cmpxchg
			// TODO: would this throw a segfault?
			// TODO: flags are not set
			oldval, _ := u.RegRead(uc.ARM_REG_R0)
			newval, _ := u.RegRead(uc.ARM_REG_R1)
			ptr, _ := u.RegRead(uc.ARM_REG_R2)
			var tmp [4]byte
			var status uint64
			if err := u.MemReadInto(tmp[:], ptr); err != nil {
				// error
			} else if u.UnpackAddr(tmp[:]) == oldval {
				u.PackAddr(tmp[:], newval)
				u.MemWrite(ptr, tmp[:])
				status = 1
			}
			u.RegWrite(uc.ARM_REG_R0, status)
		case 0xffff0fe0:
			// __kuser_get_tls
			u.RegWrite(uc.ARM_REG_R0, kernel.tls)
		case 0xffff0ffc:
			// __kuser_helper_version
			u.RegWrite(uc.ARM_REG_R0, 2)
		default:
			panic(fmt.Sprintf("unsupported kernel trap: 0x%x\n", addr))
		}
	}, 0xffff0000, 0xffffffff)
	return err
}

func LinuxKernels(u models.Usercorn) []interface{} {
	kernel := &ArmLinuxKernel{LinuxKernel: linux.NewKernel()}
	// TODO: LinuxInit needs to have a copy of the kernel
	// honestly init should be part of the kernel?
	if err := setupTraps(u, kernel); err != nil {
		panic(err)
	}
	return []interface{}{kernel}
}

func LinuxInit(u models.Usercorn, args, env []string) error {
	if err := EnableFPU(u); err != nil {
		return err
	}
	/*
		if err := EnterUsermode(u); err != nil {
			return err
		}
	*/
	return linux.StackInit(u, args, env)
}

func LinuxSyscall(u models.Usercorn, num int) {
	// TODO: EABI has a different syscall base (OABI is 0x900000)
	// TODO: does the generator handle this? it needs to.
	if num > 0x900000 {
		num -= 0x900000
	}
	name, _ := sysnum.Linux_arm[int(num)]
	ret, _ := u.Syscall(int(num), name, common.RegArgs(u, LinuxRegs))
	u.RegWrite(uc.ARM_REG_R0, ret)
}

func LinuxInterrupt(u models.Usercorn, intno uint32) {
	if intno == 2 {
		// TODO: thumb? issue #121
		pc, _ := u.RegRead(uc.ARM_REG_PC)
		var tmp [4]byte
		if err := u.MemReadInto(tmp[:], pc-4); err != nil {
			panic(err)
		}
		n := u.UnpackAddr(tmp[:]) & 0xffff
		if n > 0 {
			LinuxSyscall(u, int(n))
			return
		}

		// TODO: handle errors or something
		num, _ := u.RegRead(uc.ARM_REG_R7)
		LinuxSyscall(u, int(num))
		return
	}
	panic(fmt.Sprintf("unhandled ARM interrupt: %d", intno))
}

func init() {
	Arch.RegisterOS(&models.OS{
		Name:      "linux",
		Kernels:   LinuxKernels,
		Init:      LinuxInit,
		Interrupt: LinuxInterrupt,
	})
}
<commit_msg>fix arm linux kuser_cmpxchg success code<commit_after>package arm

import (
	"fmt"
	sysnum "github.com/lunixbochs/ghostrace/ghost/sys/num"
	uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"

	"github.com/lunixbochs/usercorn/go/kernel/common"
	"github.com/lunixbochs/usercorn/go/kernel/linux"
	"github.com/lunixbochs/usercorn/go/models"
	"github.com/lunixbochs/usercorn/go/models/cpu"
)

var LinuxRegs = []int{uc.ARM_REG_R0, uc.ARM_REG_R1, uc.ARM_REG_R2, uc.ARM_REG_R3, uc.ARM_REG_R4, uc.ARM_REG_R5, uc.ARM_REG_R6}

type ArmLinuxKernel struct {
	*linux.LinuxKernel
	tls uint64
}

func (k *ArmLinuxKernel) SetTls(addr uint64) {
	k.tls = addr
	k.U.RunAsm(0, "mcr p15, 0, r0, c13, c0, 3",
		map[int]uint64{uc.ARM_REG_R0: addr},
		[]int{uc.ARM_REG_R0},
	)
}

func setupTraps(u models.Usercorn, kernel *ArmLinuxKernel) error {
	// handle arm kernel traps
	// https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt
	if err := u.MemMap(0xffff0000, 0x10000, cpu.PROT_READ|cpu.PROT_EXEC); err != nil {
		return err
	}
	for addr := 0; addr < 0x10000; addr += 4 {
		// write "bx lr" to all kernel trap addresses so they will return
		bxlr := []byte{0x1e, 0xff, 0x2f, 0xe1}
		if err := u.MemWrite(0xffff0000+uint64(addr), bxlr); err != nil {
			return err
		}
	}
	_, err := u.HookAdd(cpu.HOOK_CODE, func(_ cpu.Cpu, addr uint64, size uint32) {
		switch addr {
		case 0xffff0fa0:
			// __kuser_memory_barrier
			// *shrug*
		case 0xffff0f60:
			// __kuser_cmpxchg64
			// TODO: DRY possible here?
			oldval, _ := u.RegRead(uc.ARM_REG_R0)
			newval, _ := u.RegRead(uc.ARM_REG_R1)
			ptr, _ := u.RegRead(uc.ARM_REG_R2)
			var tmp [8]byte
			var status uint64 = 1
			if err := u.MemReadInto(tmp[:], ptr); err != nil {
				// error
			} else if u.ByteOrder().Uint64(tmp[:]) == oldval {
				u.ByteOrder().PutUint64(tmp[:], newval)
				u.MemWrite(ptr, tmp[:])
				status = 0
			}
			u.RegWrite(uc.ARM_REG_R0, status)
		case 0xffff0fc0:
			// __kuser_cmpxchg
			// TODO: would this throw a segfault?
			// TODO: flags are not set
			oldval, _ := u.RegRead(uc.ARM_REG_R0)
			newval, _ := u.RegRead(uc.ARM_REG_R1)
			ptr, _ := u.RegRead(uc.ARM_REG_R2)
			var tmp [4]byte
			var status uint64 = 1
			if err := u.MemReadInto(tmp[:], ptr); err != nil {
				// error
			} else if u.UnpackAddr(tmp[:]) == oldval {
				u.PackAddr(tmp[:], newval)
				u.MemWrite(ptr, tmp[:])
				status = 0
			}
			u.RegWrite(uc.ARM_REG_R0, status)
		case 0xffff0fe0:
			// __kuser_get_tls
			u.RegWrite(uc.ARM_REG_R0, kernel.tls)
		case 0xffff0ffc:
			// __kuser_helper_version
			u.RegWrite(uc.ARM_REG_R0, 2)
		default:
			panic(fmt.Sprintf("unsupported kernel trap: 0x%x\n", addr))
		}
	}, 0xffff0000, 0xffffffff)
	return err
}

func LinuxKernels(u models.Usercorn) []interface{} {
	kernel := &ArmLinuxKernel{LinuxKernel: linux.NewKernel()}
	// TODO: LinuxInit needs to have a copy of the kernel
	// honestly init should be part of the kernel?
	if err := setupTraps(u, kernel); err != nil {
		panic(err)
	}
	return []interface{}{kernel}
}

func LinuxInit(u models.Usercorn, args, env []string) error {
	if err := EnableFPU(u); err != nil {
		return err
	}
	/*
		if err := EnterUsermode(u); err != nil {
			return err
		}
	*/
	return linux.StackInit(u, args, env)
}

func LinuxSyscall(u models.Usercorn, num int) {
	// TODO: EABI has a different syscall base (OABI is 0x900000)
	// TODO: does the generator handle this? it needs to.
	if num > 0x900000 {
		num -= 0x900000
	}
	name, _ := sysnum.Linux_arm[int(num)]
	ret, _ := u.Syscall(int(num), name, common.RegArgs(u, LinuxRegs))
	u.RegWrite(uc.ARM_REG_R0, ret)
}

func LinuxInterrupt(u models.Usercorn, intno uint32) {
	if intno == 2 {
		// TODO: thumb? issue #121
		pc, _ := u.RegRead(uc.ARM_REG_PC)
		var tmp [4]byte
		if err := u.MemReadInto(tmp[:], pc-4); err != nil {
			panic(err)
		}
		n := u.UnpackAddr(tmp[:]) & 0xffff
		if n > 0 {
			LinuxSyscall(u, int(n))
			return
		}

		// TODO: handle errors or something
		num, _ := u.RegRead(uc.ARM_REG_R7)
		LinuxSyscall(u, int(num))
		return
	}
	panic(fmt.Sprintf("unhandled ARM interrupt: %d", intno))
}

func init() {
	Arch.RegisterOS(&models.OS{
		Name:      "linux",
		Kernels:   LinuxKernels,
		Init:      LinuxInit,
		Interrupt: LinuxInterrupt,
	})
}
<|endoftext|>


<commit_before>// Copyright © 2017 NAME HERE <EMAIL ADDRESS>
// 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 cmd

import (
	"strings"

	"github.com/spf13/cobra"

	lib "github.com/johnny-morrice/godless"
)

// storeCmd represents the store command
var storeCmd = &cobra.Command{
	Use:   "store",
	Short: "The godless data store",
	Long: `Godless store commands to serve and inspect godless data.  To run a godless server, do:

	godless store serve`,
	Run: func(cmd *cobra.Command, args []string) {
		readPeers()
	},
}

var indexHash string
var peerNames string
var peers []lib.RemoteStoreAddress
var ipfsService string

func init() {
	RootCmd.AddCommand(storeCmd)

	storeCmd.PersistentFlags().StringVar(&indexHash, "index", "", "IPFS hash of godless index")
	storeCmd.PersistentFlags().StringVar(&peerNames, "peers", "", "Comma separated list of IPNS peer names")
	storeCmd.PersistentFlags().StringVar(&ipfsService, "ipfs", "http://localhost:5001", "IPFS webservice URL")
}

func readPeers() {
	splitNames := strings.Split(peerNames, ",")
	peers = make([]lib.RemoteStoreAddress, len(splitNames))

	for i, n := range splitNames {
		peers[i] = lib.IPFSPath(n)
	}
}
<commit_msg>Store command prints help<commit_after>// Copyright © 2017 NAME HERE <EMAIL ADDRESS>
// 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 cmd

import (
	"strings"

	"github.com/spf13/cobra"

	lib "github.com/johnny-morrice/godless"
)

// storeCmd represents the store command
var storeCmd = &cobra.Command{
	Use:   "store",
	Short: "The godless data store",
	Long: `Godless store commands to serve and inspect godless data.  To run a godless server, do:

	godless store serve`,
	Run: func(cmd *cobra.Command, args []string) {
		readPeers()

		err := cmd.Help()

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

var indexHash string
var peerNames string
var peers []lib.RemoteStoreAddress
var ipfsService string

func init() {
	RootCmd.AddCommand(storeCmd)

	storeCmd.PersistentFlags().StringVar(&indexHash, "index", "", "IPFS hash of godless index")
	storeCmd.PersistentFlags().StringVar(&peerNames, "peers", "", "Comma separated list of IPNS peer names")
	storeCmd.PersistentFlags().StringVar(&ipfsService, "ipfs", "http://localhost:5001", "IPFS webservice URL")
}

func readPeers() {
	splitNames := strings.Split(peerNames, ",")
	peers = make([]lib.RemoteStoreAddress, len(splitNames))

	for i, n := range splitNames {
		peers[i] = lib.IPFSPath(n)
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package log

// These tests are too simple.

import (
	"bufio";
	"os";
	"regexp";
	"testing";
)

const (
	Rdate		= `[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]`;
	Rtime		= `[0-9][0-9]:[0-9][0-9]:[0-9][0-9]`;
	Rmicroseconds	= `\.[0-9][0-9][0-9][0-9][0-9][0-9]`;
	Rline		= `[0-9]+:`;
	Rlongfile	= `/[A-Za-z0-9_/\-]+\.go:` + Rline;
	Rshortfile	= `[A-Za-z0-9_\-]+\.go:` + Rline;
)

type tester struct {
	flag	int;
	prefix	string;
	pattern	string;	// regexp that log output must match; we add ^ and expected_text$ always
}

var tests = []tester{
	// individual pieces:
	tester{0, "", ""},
	tester{0, "XXX", "XXX"},
	tester{Lok | Ldate, "", Rdate + " "},
	tester{Lok | Ltime, "", Rtime + " "},
	tester{Lok | Ltime | Lmicroseconds, "", Rtime + Rmicroseconds + " "},
	tester{Lok | Lmicroseconds, "", Rtime + Rmicroseconds + " "},	// microsec implies time
	tester{Lok | Llongfile, "", Rlongfile + " "},
	tester{Lok | Lshortfile, "", Rshortfile + " "},
	tester{Lok | Llongfile | Lshortfile, "", Rshortfile + " "},	// shortfile overrides longfile
	// everything at once:
	tester{Lok | Ldate | Ltime | Lmicroseconds | Llongfile, "XXX", "XXX" + Rdate + " " + Rtime + Rmicroseconds + " " + Rlongfile + " "},
	tester{Lok | Ldate | Ltime | Lmicroseconds | Lshortfile, "XXX", "XXX" + Rdate + " " + Rtime + Rmicroseconds + " " + Rshortfile + " "},
}

// Test using Log("hello", 23, "world") or using Logf("hello %d world", 23)
func testLog(t *testing.T, flag int, prefix string, pattern string, useLogf bool) {
	r, w, err1 := os.Pipe();
	if err1 != nil {
		t.Fatal("pipe", err1)
	}
	defer r.Close();
	defer w.Close();
	buf := bufio.NewReader(r);
	l := New(w, nil, prefix, flag);
	if useLogf {
		l.Logf("hello %d world", 23)
	} else {
		l.Log("hello", 23, "world")
	}
	line, err3 := buf.ReadString('\n');
	if err3 != nil {
		t.Fatal("log error", err3)
	}
	line = line[0 : len(line)-1];
	pattern = "^" + pattern + "hello 23 world$";
	matched, err4 := regexp.MatchString(pattern, line);
	if err4 != nil {
		t.Fatal("pattern did not compile:", err4)
	}
	if !matched {
		t.Errorf("log output should match %q is %q", pattern, line)
	}
}

func TestAllLog(t *testing.T) {
	for _, testcase := range tests {
		testLog(t, testcase.flag, testcase.prefix, testcase.pattern, false);
		testLog(t, testcase.flag, testcase.prefix, testcase.pattern, true);
	}
}
<commit_msg>log test: don't assume a fixed set of letters for $GOROOT<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package log

// These tests are too simple.

import (
	"bufio";
	"os";
	"regexp";
	"testing";
)

const (
	Rdate		= `[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]`;
	Rtime		= `[0-9][0-9]:[0-9][0-9]:[0-9][0-9]`;
	Rmicroseconds	= `\.[0-9][0-9][0-9][0-9][0-9][0-9]`;
	Rline		= `[0-9]+:`;
	Rlongfile	= `.*/[A-Za-z0-9_\-]+\.go:` + Rline;
	Rshortfile	= `[A-Za-z0-9_\-]+\.go:` + Rline;
)

type tester struct {
	flag	int;
	prefix	string;
	pattern	string;	// regexp that log output must match; we add ^ and expected_text$ always
}

var tests = []tester{
	// individual pieces:
	tester{0, "", ""},
	tester{0, "XXX", "XXX"},
	tester{Lok | Ldate, "", Rdate + " "},
	tester{Lok | Ltime, "", Rtime + " "},
	tester{Lok | Ltime | Lmicroseconds, "", Rtime + Rmicroseconds + " "},
	tester{Lok | Lmicroseconds, "", Rtime + Rmicroseconds + " "},	// microsec implies time
	tester{Lok | Llongfile, "", Rlongfile + " "},
	tester{Lok | Lshortfile, "", Rshortfile + " "},
	tester{Lok | Llongfile | Lshortfile, "", Rshortfile + " "},	// shortfile overrides longfile
	// everything at once:
	tester{Lok | Ldate | Ltime | Lmicroseconds | Llongfile, "XXX", "XXX" + Rdate + " " + Rtime + Rmicroseconds + " " + Rlongfile + " "},
	tester{Lok | Ldate | Ltime | Lmicroseconds | Lshortfile, "XXX", "XXX" + Rdate + " " + Rtime + Rmicroseconds + " " + Rshortfile + " "},
}

// Test using Log("hello", 23, "world") or using Logf("hello %d world", 23)
func testLog(t *testing.T, flag int, prefix string, pattern string, useLogf bool) {
	r, w, err1 := os.Pipe();
	if err1 != nil {
		t.Fatal("pipe", err1)
	}
	defer r.Close();
	defer w.Close();
	buf := bufio.NewReader(r);
	l := New(w, nil, prefix, flag);
	if useLogf {
		l.Logf("hello %d world", 23)
	} else {
		l.Log("hello", 23, "world")
	}
	line, err3 := buf.ReadString('\n');
	if err3 != nil {
		t.Fatal("log error", err3)
	}
	line = line[0 : len(line)-1];
	pattern = "^" + pattern + "hello 23 world$";
	matched, err4 := regexp.MatchString(pattern, line);
	if err4 != nil {
		t.Fatal("pattern did not compile:", err4)
	}
	if !matched {
		t.Errorf("log output should match %q is %q", pattern, line)
	}
}

func TestAllLog(t *testing.T) {
	for _, testcase := range tests {
		testLog(t, testcase.flag, testcase.prefix, testcase.pattern, false);
		testLog(t, testcase.flag, testcase.prefix, testcase.pattern, true);
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
 * Runtime type representation.
 *
 * The following files know the exact layout of these
 * data structures and must be kept in sync with this file:
 *
 *	../../cmd/gc/reflect.c
 *	../reflect/type.go
 *	type.h
 */

package runtime

import "unsafe"

// The compiler can only construct empty interface values at
// compile time; non-empty interface values get created
// during initialization.  Type is an empty interface
// so that the compiler can lay out references as data.
type Type interface{}

// All types begin with a few common fields needed for
// the interface runtime.
type commonType struct {
	size          uintptr // size in bytes
	hash          uint32  // hash of type; avoids computation in hash tables
	alg           uint8   // algorithm for copy+hash+cmp (../runtime/runtime.h:/AMEM)
	align         uint8   // alignment of variable with this type
	fieldAlign    uint8   // alignment of struct field with this type
	kind          uint8   // enumeration for C
	string        *string // string form; unnecessary  but undeniably useful
	*uncommonType         // (relatively) uncommon fields
}

// Values for commonType.kind.
const (
	kindBool = 1 + iota
	kindInt
	kindInt8
	kindInt16
	kindInt32
	kindInt64
	kindUint
	kindUint8
	kindUint16
	kindUint32
	kindUint64
	kindUintptr
	kindFloat
	kindFloat32
	kindFloat64
	kindArray
	kindChan
	kindFunc
	kindInterface
	kindMap
	kindPtr
	kindSlice
	kindString
	kindStruct
	kindUnsafePointer

	kindNoPointers = 1 << 7 // OR'ed into kind
)

// Method on non-interface type
type method struct {
	name    *string        // name of method
	pkgPath *string        // nil for exported Names; otherwise import path
	mtyp    *Type          // method type (without receiver)
	typ     *Type          // .(*FuncType) underneath (with receiver)
	ifn     unsafe.Pointer // fn used in interface call (one-word receiver)
	tfn     unsafe.Pointer // fn used for normal method call
}

// uncommonType is present only for types with names or methods
// (if T is a named type, the uncommonTypes for T and *T have methods).
// Using a pointer to this struct reduces the overall size required
// to describe an unnamed type with no methods.
type uncommonType struct {
	name    *string  // name of type
	pkgPath *string  // import path; nil for built-in types like int, string
	methods []method // methods associated with type
}

// BoolType represents a boolean type.
type BoolType commonType

// Float32Type represents a float32 type.
type Float32Type commonType

// Float64Type represents a float64 type.
type Float64Type commonType

// FloatType represents a float type.
type FloatType commonType

// Complex64Type represents a complex64 type.
type Complex64Type commonType

// Complex128Type represents a complex128 type.
type Complex128Type commonType

// ComplexType represents a complex type.
type ComplexType commonType

// Int16Type represents an int16 type.
type Int16Type commonType

// Int32Type represents an int32 type.
type Int32Type commonType

// Int64Type represents an int64 type.
type Int64Type commonType

// Int8Type represents an int8 type.
type Int8Type commonType

// IntType represents an int type.
type IntType commonType

// Uint16Type represents a uint16 type.
type Uint16Type commonType

// Uint32Type represents a uint32 type.
type Uint32Type commonType

// Uint64Type represents a uint64 type.
type Uint64Type commonType

// Uint8Type represents a uint8 type.
type Uint8Type commonType

// UintType represents a uint type.
type UintType commonType

// StringType represents a string type.
type StringType commonType

// UintptrType represents a uintptr type.
type UintptrType commonType

// UnsafePointerType represents an unsafe.Pointer type.
type UnsafePointerType commonType

// ArrayType represents a fixed array type.
type ArrayType struct {
	commonType
	elem *Type // array element type
	len  uintptr
}

// SliceType represents a slice type.
type SliceType struct {
	commonType
	elem *Type // slice element type
}

// ChanDir represents a channel type's direction.
type ChanDir int

const (
	RecvDir ChanDir             = 1 << iota // <-chan
	SendDir                                 // chan<-
	BothDir = RecvDir | SendDir             // chan
)

// ChanType represents a channel type.
type ChanType struct {
	commonType
	elem *Type   // channel element type
	dir  uintptr // channel direction (ChanDir)
}

// FuncType represents a function type.
type FuncType struct {
	commonType
	dotdotdot bool    // last input parameter is ...
	in        []*Type // input parameter types
	out       []*Type // output parameter types
}

// Method on interface type
type imethod struct {
	name    *string // name of method
	pkgPath *string // nil for exported Names; otherwise import path
	typ     *Type   // .(*FuncType) underneath
}

// InterfaceType represents an interface type.
type InterfaceType struct {
	commonType
	methods []imethod // sorted by hash
}

// MapType represents a map type.
type MapType struct {
	commonType
	key  *Type // map key type
	elem *Type // map element (value) type
}

// PtrType represents a pointer type.
type PtrType struct {
	commonType
	elem *Type // pointer element (pointed at) type
}

// Struct field
type structField struct {
	name    *string // nil for embedded fields
	pkgPath *string // nil for exported Names; otherwise import path
	typ     *Type   // type of field
	tag     *string // nil if no tag
	offset  uintptr // byte offset of field within struct
}

// StructType represents a struct type.
type StructType struct {
	commonType
	fields []structField // sorted by offset
}

/*
 * Must match iface.c:/Itab and compilers.
 */
type Itable struct {
	Itype  *Type // (*tab.inter).(*InterfaceType) is the interface type
	Type   *Type
	link   *Itable
	bad    int32
	unused int32
	Fn     [100000]uintptr // bigger than we'll ever see
}
<commit_msg>runtime: delete old types<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
 * Runtime type representation.
 *
 * The following files know the exact layout of these
 * data structures and must be kept in sync with this file:
 *
 *	../../cmd/gc/reflect.c
 *	../reflect/type.go
 *	type.h
 */

package runtime

import "unsafe"

// The compiler can only construct empty interface values at
// compile time; non-empty interface values get created
// during initialization.  Type is an empty interface
// so that the compiler can lay out references as data.
type Type interface{}

// All types begin with a few common fields needed for
// the interface runtime.
type commonType struct {
	size          uintptr // size in bytes
	hash          uint32  // hash of type; avoids computation in hash tables
	alg           uint8   // algorithm for copy+hash+cmp (../runtime/runtime.h:/AMEM)
	align         uint8   // alignment of variable with this type
	fieldAlign    uint8   // alignment of struct field with this type
	kind          uint8   // enumeration for C
	string        *string // string form; unnecessary  but undeniably useful
	*uncommonType         // (relatively) uncommon fields
}

// Values for commonType.kind.
const (
	kindBool = 1 + iota
	kindInt
	kindInt8
	kindInt16
	kindInt32
	kindInt64
	kindUint
	kindUint8
	kindUint16
	kindUint32
	kindUint64
	kindUintptr
	kindFloat
	kindFloat32
	kindFloat64
	kindArray
	kindChan
	kindFunc
	kindInterface
	kindMap
	kindPtr
	kindSlice
	kindString
	kindStruct
	kindUnsafePointer

	kindNoPointers = 1 << 7 // OR'ed into kind
)

// Method on non-interface type
type method struct {
	name    *string        // name of method
	pkgPath *string        // nil for exported Names; otherwise import path
	mtyp    *Type          // method type (without receiver)
	typ     *Type          // .(*FuncType) underneath (with receiver)
	ifn     unsafe.Pointer // fn used in interface call (one-word receiver)
	tfn     unsafe.Pointer // fn used for normal method call
}

// uncommonType is present only for types with names or methods
// (if T is a named type, the uncommonTypes for T and *T have methods).
// Using a pointer to this struct reduces the overall size required
// to describe an unnamed type with no methods.
type uncommonType struct {
	name    *string  // name of type
	pkgPath *string  // import path; nil for built-in types like int, string
	methods []method // methods associated with type
}

// BoolType represents a boolean type.
type BoolType commonType

// FloatType represents a float type.
type FloatType commonType

// ComplexType represents a complex type.
type ComplexType commonType

// IntType represents an int type.
type IntType commonType

// UintType represents a uint type.
type UintType commonType

// StringType represents a string type.
type StringType commonType

// UintptrType represents a uintptr type.
type UintptrType commonType

// UnsafePointerType represents an unsafe.Pointer type.
type UnsafePointerType commonType

// ArrayType represents a fixed array type.
type ArrayType struct {
	commonType
	elem *Type // array element type
	len  uintptr
}

// SliceType represents a slice type.
type SliceType struct {
	commonType
	elem *Type // slice element type
}

// ChanDir represents a channel type's direction.
type ChanDir int

const (
	RecvDir ChanDir             = 1 << iota // <-chan
	SendDir                                 // chan<-
	BothDir = RecvDir | SendDir             // chan
)

// ChanType represents a channel type.
type ChanType struct {
	commonType
	elem *Type   // channel element type
	dir  uintptr // channel direction (ChanDir)
}

// FuncType represents a function type.
type FuncType struct {
	commonType
	dotdotdot bool    // last input parameter is ...
	in        []*Type // input parameter types
	out       []*Type // output parameter types
}

// Method on interface type
type imethod struct {
	name    *string // name of method
	pkgPath *string // nil for exported Names; otherwise import path
	typ     *Type   // .(*FuncType) underneath
}

// InterfaceType represents an interface type.
type InterfaceType struct {
	commonType
	methods []imethod // sorted by hash
}

// MapType represents a map type.
type MapType struct {
	commonType
	key  *Type // map key type
	elem *Type // map element (value) type
}

// PtrType represents a pointer type.
type PtrType struct {
	commonType
	elem *Type // pointer element (pointed at) type
}

// Struct field
type structField struct {
	name    *string // nil for embedded fields
	pkgPath *string // nil for exported Names; otherwise import path
	typ     *Type   // type of field
	tag     *string // nil if no tag
	offset  uintptr // byte offset of field within struct
}

// StructType represents a struct type.
type StructType struct {
	commonType
	fields []structField // sorted by offset
}

/*
 * Must match iface.c:/Itab and compilers.
 */
type Itable struct {
	Itype  *Type // (*tab.inter).(*InterfaceType) is the interface type
	Type   *Type
	link   *Itable
	bad    int32
	unused int32
	Fn     [100000]uintptr // bigger than we'll ever see
}
<|endoftext|>