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

package compact

import (
	"bytes"
	"errors"
	"fmt"
	"math/bits"
)

// HashFn computes an internal node's hash using the hashes of its child nodes.
type HashFn func(left, right []byte) []byte

// VisitFn visits the (level, index) node with the specified hash. The level is
// the distance from the node down to the leaves, and index is its horizontal
// position within the level. For example, see the diagram below where the
// nodes of a 4-leaves tree are numbered with [<level> <index>] labels.
//
//            [2 0]
//           /     \
//        [1 0]   [1 1]
//       /   \     /   \
//   [0 0] [0 1] [0 2] [0 3]
type VisitFn func(level uint, index uint64, hash []byte)

// RangeFactory allows creating compact ranges with the specified hash
// function, which must not be nil, and must not be changed.
type RangeFactory struct {
	Hash HashFn
}

// NewRange creates a Range for [begin, end) with the given set of hashes. The
// hashes correspond to the roots of the minimal set of perfect sub-trees
// covering the [begin, end) leaves range, ordered left to right.
func (f *RangeFactory) NewRange(begin, end uint64, hashes [][]byte) (*Range, error) {
	if end < begin {
		return nil, fmt.Errorf("invalid range: end=%d, want >= %d", end, begin)
	}
	left, right := decompose(begin, end)
	ones := bits.OnesCount64(left) + bits.OnesCount64(right)
	if ln := len(hashes); ln != ones {
		return nil, fmt.Errorf("invalid hashes: got %d values, want %d", ln, ones)
	}
	return &Range{f: f, begin: begin, end: end, hashes: hashes}, nil
}

// NewEmptyRange returns a new Range for an empty [begin, begin) range. The
// value of begin defines where the range will start growing from when entries
// are appended to it.
func (f *RangeFactory) NewEmptyRange(begin uint64) *Range {
	return &Range{f: f, begin: begin, end: begin}
}

// Range represents a compact Merkle tree range for leaf indices [begin, end).
//
// It contains the minimal set of perfect subtrees whose leaves comprise this
// range. The structure is efficiently mergeable with with other compact ranges
// that share one of the endpoints with it.
//
// TODO(pavelkalinnikov): Add document with more details on how it works, and
// what it can be used for.
type Range struct {
	f      *RangeFactory
	begin  uint64
	end    uint64
	hashes [][]byte
}

// Begin returns the first index covered by the range (inclusive).
func (r *Range) Begin() uint64 {
	return r.begin
}

// End returns the last index covered by the range (exclusive).
func (r *Range) End() uint64 {
	return r.end
}

// Hashes returns sub-tree hashes corresponding to the minimal set of perfect
// sub-trees covering the [begin, end) range, ordered left to right.
func (r *Range) Hashes() [][]byte {
	return r.hashes
}

// Append extends the compact range by appending the passed in hash to it. It
// uses the tree hasher to calculate hashes of newly created nodes, and reports
// them through the visitor function (if non-nil).
func (r *Range) Append(hash []byte, visitor VisitFn) error {
	return r.appendImpl(r.end+1, hash, nil, visitor)
}

// AppendRange extends the compact range by merging in the other compact range
// from the right. It uses the tree hasher to calculate hashes of newly created
// nodes, and reports them through the visitor function (if non-nil).
func (r *Range) AppendRange(other *Range, visitor VisitFn) error {
	if other.f != r.f {
		return errors.New("incompatible ranges")
	}
	if got, want := other.begin, r.end; got != want {
		return fmt.Errorf("ranges are disjoint: other.begin=%d, want %d", got, want)
	}
	if len(other.hashes) == 0 { // The other range is empty, merging is trivial.
		return nil
	}
	return r.appendImpl(other.end, other.hashes[0], other.hashes[1:], visitor)
}

// GetRootHash returns the root hash of the Merkle tree represented by
// this compact range. Requires the range to start at index 0. If the
// range is empty, returns nil.
func (r *Range) GetRootHash() ([]byte, error) {
	if r.begin != 0 {
		return nil, fmt.Errorf("begin=%d, want 0", r.begin)
	}
	ln := len(r.hashes)
	if ln == 0 {
		return nil, nil
	}
	hash := r.hashes[ln-1]
	for i := ln - 2; i >= 0; i-- {
		hash = r.f.Hash(r.hashes[i], hash)
	}
	return hash, nil
}

// Equal compares two Ranges for equality.
func (r *Range) Equal(other *Range) bool {
	if r.f != other.f || r.begin != other.begin || r.end != other.end {
		return false
	}
	if len(r.hashes) != len(other.hashes) {
		return false
	}
	for i := range r.hashes {
		if !bytes.Equal(r.hashes[i], other.hashes[i]) {
			return false
		}
	}
	return true
}

// appendImpl extends the compact range by merging the [r.end, end) compact
// range into it. The other compact range is decomposed into a seed hash and
// all the other hashes (possibly none). The method uses the tree hasher to
// calculate hashes of newly created nodes, and reports them through the
// visitor function (if non-nil).
func (r *Range) appendImpl(end uint64, seed []byte, hashes [][]byte, visitor VisitFn) error {
	// Bits [low, high) of r.end encode the merge path, i.e. the sequence of node
	// merges that transforms the two compact ranges into one.
	low, high := getMergePath(r.begin, r.end, end)
	if high < low {
		high = low
	}
	index := r.end >> low
	// Now bits [0, high-low) of index encode the merge path.

	// The number of one bits in index is the number of nodes from the left range
	// that will be merged, and zero bits correspond to the nodes in the right
	// range. Below we make sure that both ranges have enough hashes, which can
	// be false only in case the data is corrupted in some way.
	ones := bits.OnesCount64(index & (1<<(high-low) - 1))
	if ln := len(r.hashes); ln < ones {
		return fmt.Errorf("corrupted lhs range: got %d hashes, want >= %d", ln, ones)
	}
	if ln, zeros := len(hashes), int(high-low)-ones; ln < zeros {
		return fmt.Errorf("corrupted rhs range: got %d hashes, want >= %d", ln+1, zeros+1)
	}

	// Some of the trailing nodes of the left compact range, and some of the
	// leading nodes of the right range, are sequentially merged with the seed,
	// according to the mask. All new nodes are reported through the visitor.
	idx1, idx2 := len(r.hashes), 0
	for h := low; h < high; h++ {
		if index&1 == 0 {
			seed = r.f.Hash(seed, hashes[idx2])
			idx2++
		} else {
			idx1--
			seed = r.f.Hash(r.hashes[idx1], seed)
		}
		index >>= 1
		if visitor != nil {
			visitor(h+1, index, seed)
		}
	}

	// All nodes from both ranges that have not been merged are bundled together
	// with the "merged" seed node.
	r.hashes = append(append(r.hashes[:idx1], seed), hashes[idx2:]...)
	r.end = end
	return nil
}

// getMergePath returns the merging path between the compact range [begin, mid)
// and [mid, end). The path is represented as a range of bits within mid, with
// bit indices [low, high). A bit value of 1 on level i of mid means that the
// node on this level merges with the corresponding node in the left compact
// range, whereas 0 represents merging with the right compact range. If the
// path is empty then high <= low.
//
// The output is not specified if begin <= mid <= end doesn't hold, but the
// function never panics.
func getMergePath(begin, mid, end uint64) (uint, uint) {
	low := bits.TrailingZeros64(mid)
	high := 64
	if begin != 0 {
		high = bits.Len64(mid ^ (begin - 1))
	}
	if high2 := bits.Len64((mid - 1) ^ end); high2 < high {
		high = high2
	}
	return uint(low), uint(high - 1)
}

// decompose splits the [begin, end) range into a minimal number of sub-ranges,
// each of which is of the form [m * 2^k, (m+1) * 2^k), i.e. of length 2^k, for
// some integers m, k >= 0.
//
// The sequence of sizes is returned encoded as bitmasks left and right, where:
//  - a 1 bit in a bitmask denotes a sub-range of the corresponding size 2^k
//  - left mask bits in LSB-to-MSB order encode the left part of the sequence
//  - right mask bits in MSB-to-LSB order encode the right part
//
// The corresponding values of m are not returned (they can be calculated from
// begin and the sub-range sizes).
//
// For example, (begin, end) values of (0b110, 0b11101) would indicate a
// sequence of tree sizes: 2,8; 8,4,1.
//
// The output is not specified if begin > end, but the function never panics.
func decompose(begin, end uint64) (uint64, uint64) {
	// Special case, as the code below works only if begin != 0, or end < 2^63.
	if begin == 0 {
		return 0, end
	}
	xbegin := begin - 1
	// Find where paths to leaves #begin-1 and #end diverge, and mask the upper
	// bits away, as only the nodes strictly below this point are in the range.
	d := bits.Len64(xbegin^end) - 1
	mask := uint64(1)<<uint(d) - 1
	// The left part of the compact range consists of all nodes strictly below
	// and to the right from the path to leaf #begin-1, corresponding to zero
	// bits in the masked part of begin-1. Likewise, the right part consists of
	// nodes below and to the left from the path to leaf #end, corresponding to
	// ones in the masked part of end.
	return ^xbegin & mask, end & mask
}
<commit_msg>Fix typo (#1513)<commit_after>// Copyright 2019 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package compact

import (
	"bytes"
	"errors"
	"fmt"
	"math/bits"
)

// HashFn computes an internal node's hash using the hashes of its child nodes.
type HashFn func(left, right []byte) []byte

// VisitFn visits the (level, index) node with the specified hash. The level is
// the distance from the node down to the leaves, and index is its horizontal
// position within the level. For example, see the diagram below where the
// nodes of a 4-leaves tree are numbered with [<level> <index>] labels.
//
//            [2 0]
//           /     \
//        [1 0]   [1 1]
//       /   \     /   \
//   [0 0] [0 1] [0 2] [0 3]
type VisitFn func(level uint, index uint64, hash []byte)

// RangeFactory allows creating compact ranges with the specified hash
// function, which must not be nil, and must not be changed.
type RangeFactory struct {
	Hash HashFn
}

// NewRange creates a Range for [begin, end) with the given set of hashes. The
// hashes correspond to the roots of the minimal set of perfect sub-trees
// covering the [begin, end) leaves range, ordered left to right.
func (f *RangeFactory) NewRange(begin, end uint64, hashes [][]byte) (*Range, error) {
	if end < begin {
		return nil, fmt.Errorf("invalid range: end=%d, want >= %d", end, begin)
	}
	left, right := decompose(begin, end)
	ones := bits.OnesCount64(left) + bits.OnesCount64(right)
	if ln := len(hashes); ln != ones {
		return nil, fmt.Errorf("invalid hashes: got %d values, want %d", ln, ones)
	}
	return &Range{f: f, begin: begin, end: end, hashes: hashes}, nil
}

// NewEmptyRange returns a new Range for an empty [begin, begin) range. The
// value of begin defines where the range will start growing from when entries
// are appended to it.
func (f *RangeFactory) NewEmptyRange(begin uint64) *Range {
	return &Range{f: f, begin: begin, end: begin}
}

// Range represents a compact Merkle tree range for leaf indices [begin, end).
//
// It contains the minimal set of perfect subtrees whose leaves comprise this
// range. The structure is efficiently mergeable with other compact ranges that
// share one of the endpoints with it.
//
// TODO(pavelkalinnikov): Add document with more details on how it works, and
// what it can be used for.
type Range struct {
	f      *RangeFactory
	begin  uint64
	end    uint64
	hashes [][]byte
}

// Begin returns the first index covered by the range (inclusive).
func (r *Range) Begin() uint64 {
	return r.begin
}

// End returns the last index covered by the range (exclusive).
func (r *Range) End() uint64 {
	return r.end
}

// Hashes returns sub-tree hashes corresponding to the minimal set of perfect
// sub-trees covering the [begin, end) range, ordered left to right.
func (r *Range) Hashes() [][]byte {
	return r.hashes
}

// Append extends the compact range by appending the passed in hash to it. It
// uses the tree hasher to calculate hashes of newly created nodes, and reports
// them through the visitor function (if non-nil).
func (r *Range) Append(hash []byte, visitor VisitFn) error {
	return r.appendImpl(r.end+1, hash, nil, visitor)
}

// AppendRange extends the compact range by merging in the other compact range
// from the right. It uses the tree hasher to calculate hashes of newly created
// nodes, and reports them through the visitor function (if non-nil).
func (r *Range) AppendRange(other *Range, visitor VisitFn) error {
	if other.f != r.f {
		return errors.New("incompatible ranges")
	}
	if got, want := other.begin, r.end; got != want {
		return fmt.Errorf("ranges are disjoint: other.begin=%d, want %d", got, want)
	}
	if len(other.hashes) == 0 { // The other range is empty, merging is trivial.
		return nil
	}
	return r.appendImpl(other.end, other.hashes[0], other.hashes[1:], visitor)
}

// GetRootHash returns the root hash of the Merkle tree represented by
// this compact range. Requires the range to start at index 0. If the
// range is empty, returns nil.
func (r *Range) GetRootHash() ([]byte, error) {
	if r.begin != 0 {
		return nil, fmt.Errorf("begin=%d, want 0", r.begin)
	}
	ln := len(r.hashes)
	if ln == 0 {
		return nil, nil
	}
	hash := r.hashes[ln-1]
	for i := ln - 2; i >= 0; i-- {
		hash = r.f.Hash(r.hashes[i], hash)
	}
	return hash, nil
}

// Equal compares two Ranges for equality.
func (r *Range) Equal(other *Range) bool {
	if r.f != other.f || r.begin != other.begin || r.end != other.end {
		return false
	}
	if len(r.hashes) != len(other.hashes) {
		return false
	}
	for i := range r.hashes {
		if !bytes.Equal(r.hashes[i], other.hashes[i]) {
			return false
		}
	}
	return true
}

// appendImpl extends the compact range by merging the [r.end, end) compact
// range into it. The other compact range is decomposed into a seed hash and
// all the other hashes (possibly none). The method uses the tree hasher to
// calculate hashes of newly created nodes, and reports them through the
// visitor function (if non-nil).
func (r *Range) appendImpl(end uint64, seed []byte, hashes [][]byte, visitor VisitFn) error {
	// Bits [low, high) of r.end encode the merge path, i.e. the sequence of node
	// merges that transforms the two compact ranges into one.
	low, high := getMergePath(r.begin, r.end, end)
	if high < low {
		high = low
	}
	index := r.end >> low
	// Now bits [0, high-low) of index encode the merge path.

	// The number of one bits in index is the number of nodes from the left range
	// that will be merged, and zero bits correspond to the nodes in the right
	// range. Below we make sure that both ranges have enough hashes, which can
	// be false only in case the data is corrupted in some way.
	ones := bits.OnesCount64(index & (1<<(high-low) - 1))
	if ln := len(r.hashes); ln < ones {
		return fmt.Errorf("corrupted lhs range: got %d hashes, want >= %d", ln, ones)
	}
	if ln, zeros := len(hashes), int(high-low)-ones; ln < zeros {
		return fmt.Errorf("corrupted rhs range: got %d hashes, want >= %d", ln+1, zeros+1)
	}

	// Some of the trailing nodes of the left compact range, and some of the
	// leading nodes of the right range, are sequentially merged with the seed,
	// according to the mask. All new nodes are reported through the visitor.
	idx1, idx2 := len(r.hashes), 0
	for h := low; h < high; h++ {
		if index&1 == 0 {
			seed = r.f.Hash(seed, hashes[idx2])
			idx2++
		} else {
			idx1--
			seed = r.f.Hash(r.hashes[idx1], seed)
		}
		index >>= 1
		if visitor != nil {
			visitor(h+1, index, seed)
		}
	}

	// All nodes from both ranges that have not been merged are bundled together
	// with the "merged" seed node.
	r.hashes = append(append(r.hashes[:idx1], seed), hashes[idx2:]...)
	r.end = end
	return nil
}

// getMergePath returns the merging path between the compact range [begin, mid)
// and [mid, end). The path is represented as a range of bits within mid, with
// bit indices [low, high). A bit value of 1 on level i of mid means that the
// node on this level merges with the corresponding node in the left compact
// range, whereas 0 represents merging with the right compact range. If the
// path is empty then high <= low.
//
// The output is not specified if begin <= mid <= end doesn't hold, but the
// function never panics.
func getMergePath(begin, mid, end uint64) (uint, uint) {
	low := bits.TrailingZeros64(mid)
	high := 64
	if begin != 0 {
		high = bits.Len64(mid ^ (begin - 1))
	}
	if high2 := bits.Len64((mid - 1) ^ end); high2 < high {
		high = high2
	}
	return uint(low), uint(high - 1)
}

// decompose splits the [begin, end) range into a minimal number of sub-ranges,
// each of which is of the form [m * 2^k, (m+1) * 2^k), i.e. of length 2^k, for
// some integers m, k >= 0.
//
// The sequence of sizes is returned encoded as bitmasks left and right, where:
//  - a 1 bit in a bitmask denotes a sub-range of the corresponding size 2^k
//  - left mask bits in LSB-to-MSB order encode the left part of the sequence
//  - right mask bits in MSB-to-LSB order encode the right part
//
// The corresponding values of m are not returned (they can be calculated from
// begin and the sub-range sizes).
//
// For example, (begin, end) values of (0b110, 0b11101) would indicate a
// sequence of tree sizes: 2,8; 8,4,1.
//
// The output is not specified if begin > end, but the function never panics.
func decompose(begin, end uint64) (uint64, uint64) {
	// Special case, as the code below works only if begin != 0, or end < 2^63.
	if begin == 0 {
		return 0, end
	}
	xbegin := begin - 1
	// Find where paths to leaves #begin-1 and #end diverge, and mask the upper
	// bits away, as only the nodes strictly below this point are in the range.
	d := bits.Len64(xbegin^end) - 1
	mask := uint64(1)<<uint(d) - 1
	// The left part of the compact range consists of all nodes strictly below
	// and to the right from the path to leaf #begin-1, corresponding to zero
	// bits in the masked part of begin-1. Likewise, the right part consists of
	// nodes below and to the left from the path to leaf #end, corresponding to
	// ones in the masked part of end.
	return ^xbegin & mask, end & mask
}
<|endoftext|>


<commit_before>package messages

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"github.com/bitspill/json-patch"
	"log"
	"strings"
)

func HandleOIP041Edit(o Oip041, txid string, block int, dbtx *sql.Tx) error {

	// ToDo: This is super ugly
	patch := UnSquashPatch(strings.Replace(string(o.Edit.Patch), `"path":"/`, `"path":"/artifact/`, -1))
	fmt.Printf("Patch:\n%s\n", patch)
	obj, err := jsonpatch.DecodePatch([]byte(patch))
	if err != nil {
		log.Fatalf("Failed to decode patch:\n%v", err)
	}

	// ToDo: Check the signature... but first decide what to sign

	stmtstr := `SELECT json,txid,publisher
		FROM oip_artifact WHERE txid=? LIMIT 1`

	stmt, err := dbtx.Prepare(stmtstr)
	if err != nil {
		fmt.Println("RIP Handle Edit 1")
		log.Fatal(err)
	}
	row := stmt.QueryRow(o.Edit.TxID)

	var sJSON string
	var publisher string
	var txID string

	err = row.Scan(&sJSON, &txID, &publisher)
	if err != nil {
		fmt.Println("RIP Handle Edit 2")
		log.Fatal(err)
	}
	stmt.Close()

	fmt.Printf("Pre-Patch:\n%s\n", sJSON)
	out, err := obj.Apply([]byte(sJSON))
	if err != nil {
		fmt.Printf("Failed to apply patch:\n%v\n", err)
		return err
	}
	fmt.Printf("Post-Patch Result:\n%s\n", string(out))

	stmtstr = `UPDATE oip_artifact SET json=? WHERE txid=?`
	// ToDo: apply update to searchable meta-data
	stmt, err = dbtx.Prepare(stmtstr)
	if err != nil {
		fmt.Println("exit 600")
		log.Fatal(err)
	}

	_, stmterr := stmt.Exec(string(out), o.Edit.TxID)
	if stmterr != nil {
		fmt.Println("exit 601")
		log.Fatal(stmterr)
	}

	stmt.Close()

	return nil
}

/*
var oip041_edit_example_obj Oip041 = Oip041{
	Edit: Oip041Edit{
		Add: map[string]string{
			"payment.tokens": "FREEBIEOFTHEWEEK:\"1\"",
		},
		Edit: map[string]string{
			"files[0].dname": "Throwing Stones",
			"files[0].fname": "1 - Throwing Stones.mp3",
		},
		Remove: []string{
			"tokens.LTBCOIN",
		},
		Timestamp: 1234,
		TxID:      "96bad8e17f908da4c695c58b0f843a03928e338b361b3035ed16a864eafc31a2",
	},
	Signature: "<SignatureOfSomething>",
}
*/

func updateField(key string, value string, txid string, dbtx *sql.Tx) error {
	return ErrNotImplemented

	stmtstr := `UPDATE oip_artifact SET ?=? WHERE txid=?`

	stmt, err := dbtx.Prepare(stmtstr)
	if err != nil {
		fmt.Println("RIP Update Field 1")
		log.Fatal(err)
	}

	_, stmterr := stmt.Exec(key, value, txid)
	if err != nil {
		fmt.Println("RIP Update Field 1")
		log.Fatal(stmterr)
	}

	stmt.Close()

	return nil
}

func UnSquashPatch(sp string) string {
	var p map[string][]map[string]*json.RawMessage // yikes
	var up jsonpatch.Patch

	err := json.Unmarshal([]byte(sp), &p)
	fmt.Println(err)

	// op="Add", arr="Array of actions"
	for op, arr := range p {
		// _="index", act="Action object"
		for _, act := range arr {
			o := json.RawMessage([]byte(`"` + op + `"`))
			act["op"] = &o
			up = append(up, act)
		}
	}

	fmt.Println(up)
	usp, err := json.Marshal(&up)
	fmt.Println(err)
	return string(usp)
}
<commit_msg>Handle errors during patch unsquash<commit_after>package messages

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"github.com/bitspill/json-patch"
	"log"
	"strings"
)

func HandleOIP041Edit(o Oip041, txid string, block int, dbtx *sql.Tx) error {

	// ToDo: This is super ugly
	err, patch := UnSquashPatch(strings.Replace(string(o.Edit.Patch), `"path":"/`, `"path":"/artifact/`, -1))
	if err != nil {
		return err
	}

	fmt.Printf("Patch:\n%s\n", patch)
	obj, err := jsonpatch.DecodePatch([]byte(patch))
	if err != nil {
		log.Fatalf("Failed to decode patch:\n%v", err)
	}

	// ToDo: Check the signature... but first decide what to sign

	stmtstr := `SELECT json,txid,publisher
		FROM oip_artifact WHERE txid=? LIMIT 1`

	stmt, err := dbtx.Prepare(stmtstr)
	if err != nil {
		fmt.Println("RIP Handle Edit 1")
		log.Fatal(err)
	}
	row := stmt.QueryRow(o.Edit.TxID)

	var sJSON string
	var publisher string
	var txID string

	err = row.Scan(&sJSON, &txID, &publisher)
	if err != nil {
		fmt.Println("RIP Handle Edit 2")
		log.Fatal(err)
	}
	stmt.Close()

	fmt.Printf("Pre-Patch:\n%s\n", sJSON)
	out, err := obj.Apply([]byte(sJSON))
	if err != nil {
		fmt.Printf("Failed to apply patch:\n%v\n", err)
		return err
	}
	fmt.Printf("Post-Patch Result:\n%s\n", string(out))

	stmtstr = `UPDATE oip_artifact SET json=? WHERE txid=?`
	// ToDo: apply update to searchable meta-data
	stmt, err = dbtx.Prepare(stmtstr)
	if err != nil {
		fmt.Println("exit 600")
		log.Fatal(err)
	}

	_, stmterr := stmt.Exec(string(out), o.Edit.TxID)
	if stmterr != nil {
		fmt.Println("exit 601")
		log.Fatal(stmterr)
	}

	stmt.Close()

	return nil
}

/*
var oip041_edit_example_obj Oip041 = Oip041{
	Edit: Oip041Edit{
		Add: map[string]string{
			"payment.tokens": "FREEBIEOFTHEWEEK:\"1\"",
		},
		Edit: map[string]string{
			"files[0].dname": "Throwing Stones",
			"files[0].fname": "1 - Throwing Stones.mp3",
		},
		Remove: []string{
			"tokens.LTBCOIN",
		},
		Timestamp: 1234,
		TxID:      "96bad8e17f908da4c695c58b0f843a03928e338b361b3035ed16a864eafc31a2",
	},
	Signature: "<SignatureOfSomething>",
}
*/

func updateField(key string, value string, txid string, dbtx *sql.Tx) error {
	return ErrNotImplemented

	stmtstr := `UPDATE oip_artifact SET ?=? WHERE txid=?`

	stmt, err := dbtx.Prepare(stmtstr)
	if err != nil {
		fmt.Println("RIP Update Field 1")
		log.Fatal(err)
	}

	_, stmterr := stmt.Exec(key, value, txid)
	if err != nil {
		fmt.Println("RIP Update Field 1")
		log.Fatal(stmterr)
	}

	stmt.Close()

	return nil
}

func UnSquashPatch(sp string) (error, string) {
	var p map[string][]map[string]*json.RawMessage // yikes
	var up jsonpatch.Patch

	err := json.Unmarshal([]byte(sp), &p)
	if err != nil {
		return err, ""
	}

	// op="Add", arr="Array of actions"
	for op, arr := range p {
		// _="index", act="Action object"
		for _, act := range arr {
			o := json.RawMessage([]byte(`"` + op + `"`))
			act["op"] = &o
			up = append(up, act)
		}
	}

	fmt.Println(up)
	usp, err := json.Marshal(&up)
	fmt.Println(err)
	return nil, string(usp)
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes 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 discovery

import (
	"net/http"

	"github.com/emicklei/go-restful"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	utilnet "k8s.io/apimachinery/pkg/util/net"
	"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
	"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
)

// legacyRootAPIHandler creates a webservice serving api group discovery.
type legacyRootAPIHandler struct {
	// addresses is used to build cluster IPs for discovery.
	addresses   Addresses
	apiPrefix   string
	serializer  runtime.NegotiatedSerializer
	apiVersions []string
}

func NewLegacyRootAPIHandler(addresses Addresses, serializer runtime.NegotiatedSerializer, apiPrefix string, apiVersions []string) *legacyRootAPIHandler {
	// Because in release 1.1, /apis returns response with empty APIVersion, we
	// use stripVersionNegotiatedSerializer to keep the response backwards
	// compatible.
	serializer = stripVersionNegotiatedSerializer{serializer}

	return &legacyRootAPIHandler{
		addresses:   addresses,
		apiPrefix:   apiPrefix,
		serializer:  serializer,
		apiVersions: apiVersions,
	}
}

// AddApiWebService adds a service to return the supported api versions at the legacy /api.
func (s *legacyRootAPIHandler) WebService() *restful.WebService {
	mediaTypes, _ := negotiation.MediaTypesForSerializer(s.serializer)
	ws := new(restful.WebService)
	ws.Path(s.apiPrefix)
	ws.Doc("get available API versions")
	ws.Route(ws.GET("/").To(s.handle).
		Doc("get available API versions").
		Operation("getAPIVersions").
		Produces(mediaTypes...).
		Consumes(mediaTypes...).
		Writes(metav1.APIVersions{}))
	return ws
}

func (s *legacyRootAPIHandler) handle(req *restful.Request, resp *restful.Response) {
	clientIP := utilnet.GetClientIP(req.Request)
	apiVersions := &metav1.APIVersions{
		ServerAddressByClientCIDRs: s.addresses.ServerAddressByClientCIDRs(clientIP),
		Versions:                   s.apiVersions,
	}

	responsewriters.WriteObjectNegotiated(s.serializer, schema.GroupVersion{}, resp.ResponseWriter, req.Request, http.StatusOK, apiVersions)
}
<commit_msg>UPSTREAM: 00000: disambiguate operation names for legacy discovery<commit_after>/*
Copyright 2017 The Kubernetes 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 discovery

import (
	"net/http"

	"github.com/emicklei/go-restful"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	utilnet "k8s.io/apimachinery/pkg/util/net"
	"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
	"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
)

// legacyRootAPIHandler creates a webservice serving api group discovery.
type legacyRootAPIHandler struct {
	// addresses is used to build cluster IPs for discovery.
	addresses   Addresses
	apiPrefix   string
	serializer  runtime.NegotiatedSerializer
	apiVersions []string
}

func NewLegacyRootAPIHandler(addresses Addresses, serializer runtime.NegotiatedSerializer, apiPrefix string, apiVersions []string) *legacyRootAPIHandler {
	// Because in release 1.1, /apis returns response with empty APIVersion, we
	// use stripVersionNegotiatedSerializer to keep the response backwards
	// compatible.
	serializer = stripVersionNegotiatedSerializer{serializer}

	return &legacyRootAPIHandler{
		addresses:   addresses,
		apiPrefix:   apiPrefix,
		serializer:  serializer,
		apiVersions: apiVersions,
	}
}

// AddApiWebService adds a service to return the supported api versions at the legacy /api.
func (s *legacyRootAPIHandler) WebService() *restful.WebService {
	mediaTypes, _ := negotiation.MediaTypesForSerializer(s.serializer)
	ws := new(restful.WebService)
	ws.Path(s.apiPrefix)
	ws.Doc("get available API versions")
	ws.Route(ws.GET("/").To(s.handle).
		Doc("get available API versions").
		Operation("getLegacyAPIVersions").
		Produces(mediaTypes...).
		Consumes(mediaTypes...).
		Writes(metav1.APIVersions{}))
	return ws
}

func (s *legacyRootAPIHandler) handle(req *restful.Request, resp *restful.Response) {
	clientIP := utilnet.GetClientIP(req.Request)
	apiVersions := &metav1.APIVersions{
		ServerAddressByClientCIDRs: s.addresses.ServerAddressByClientCIDRs(clientIP),
		Versions:                   s.apiVersions,
	}

	responsewriters.WriteObjectNegotiated(s.serializer, schema.GroupVersion{}, resp.ResponseWriter, req.Request, http.StatusOK, apiVersions)
}
<|endoftext|>


<commit_before>package server

import (
	"github.com/smancke/guble/protocol"
	"github.com/smancke/guble/server/auth"
	"github.com/smancke/guble/store"
	"runtime"
	"strings"
	"time"
)

// Router interface provides mechanism for PubSub messaging
type Router interface {
	KVStore() (store.KVStore, error)
	AccessManager() (auth.AccessManager, error)
	MessageStore() (store.MessageStore, error)

	Subscribe(r *Route) (*Route, error)
	Unsubscribe(r *Route)
	HandleMessage(message *protocol.Message) error
}

// Helper struct to pass `Route` to subscription channel and provide a
// notification channel
type subRequest struct {
	route      *Route
	doneNotify chan bool
}

type router struct {
	// mapping the path to the route slice
	routes          map[protocol.Path][]Route
	messageIn       chan *protocol.Message
	subscribeChan   chan subRequest
	unsubscribeChan chan subRequest
	stop            chan bool

	// external services
	accessManager auth.AccessManager
	messageStore  store.MessageStore
	kvStore       store.KVStore
}

// NewRouter returns a pointer to Router
func NewRouter(
	accessManager auth.AccessManager,
	messageStore store.MessageStore,
	kvStore store.KVStore) Router {
	return &router{
		routes:          make(map[protocol.Path][]Route),
		messageIn:       make(chan *protocol.Message, 500),
		subscribeChan:   make(chan subRequest, 10),
		unsubscribeChan: make(chan subRequest, 10),
		stop:            make(chan bool, 1),

		accessManager: accessManager,
		messageStore:  messageStore,
		kvStore:       kvStore,
	}
}

func (router *router) Start() error {
	if router.accessManager == nil {
		panic("AccessManager not set. Cannot start.")
	}

	go func() {
		for {
			func() {
				defer protocol.PanicLogger()

				select {
				case message := <-router.messageIn:
					router.handleMessage(message)
					runtime.Gosched()
				case subscriber := <-router.subscribeChan:
					router.subscribe(subscriber.route)
					subscriber.doneNotify <- true
				case unsubscriber := <-router.unsubscribeChan:
					router.unsubscribe(unsubscriber.route)
					unsubscriber.doneNotify <- true
				case <-router.stop:
					router.closeAllRoutes()
					protocol.Debug("stopping message router")
					break
				}
			}()
		}
	}()

	return nil
}

// Stop stops the router by closing the stop channel
func (router *router) Stop() error {
	close(router.stop)
	return nil
}

// Subscribe adds a route to the subscribers.
// If there is already a route with same Application Id and Path, it will be replaced.
func (router *router) Subscribe(r *Route) (*Route, error) {
	protocol.Debug("subscribe %v, %v, %v", router.accessManager, r.UserID, r.Path)
	accessAllowed := router.accessManager.IsAllowed(auth.READ, r.UserID, r.Path)
	if !accessAllowed {
		return r, &PermissionDeniedError{r.UserID, auth.READ, r.Path}
	}
	req := subRequest{
		route:      r,
		doneNotify: make(chan bool),
	}
	router.subscribeChan <- req
	<-req.doneNotify
	return r, nil
}

func (router *router) subscribe(r *Route) {
	protocol.Info("subscribe applicationID=%v, path=%v", r.ApplicationID, r.Path)

	routeList, present := router.routes[r.Path]
	if !present {
		routeList = []Route{}
		router.routes[r.Path] = routeList
	}

	// try to remove, to avoid double subscriptions of the same app
	routeList = remove(routeList, r)

	router.routes[r.Path] = append(routeList, *r)
}

func (router *router) Unsubscribe(r *Route) {
	req := subRequest{
		route:      r,
		doneNotify: make(chan bool),
	}
	router.unsubscribeChan <- req
	<-req.doneNotify
}

func (router *router) unsubscribe(r *Route) {
	protocol.Info("unsubscribe applicationID=%v, path=%v", r.ApplicationID, r.Path)
	routeList, present := router.routes[r.Path]
	if !present {
		return
	}
	router.routes[r.Path] = remove(routeList, r)
	if len(router.routes[r.Path]) == 0 {
		delete(router.routes, r.Path)
	}
}

func (router *router) HandleMessage(message *protocol.Message) error {
	protocol.Debug("Route.HandleMessage: %v %v", message.UserID, message.Path)
	if !router.accessManager.IsAllowed(auth.WRITE, message.UserID, message.Path) {
		return &PermissionDeniedError{message.UserID, auth.WRITE, message.Path}
	}

	return router.storeMessage(message)
}

// Assign the new message id and store it and handle by passing the stored message
// to the messageIn channel
func (router *router) storeMessage(msg *protocol.Message) error {
	txCallback := func(msgId uint64) []byte {
		msg.ID = msgId
		msg.Time = time.Now().Unix()
		return msg.Bytes()
	}

	if err := router.messageStore.StoreTx(msg.Path.Partition(), txCallback); err != nil {
		protocol.Err("error storing message in partition %v: %v", msg.Path.Partition(), err)
		return err
	}

	if float32(len(router.messageIn))/float32(cap(router.messageIn)) > 0.9 {
		protocol.Warn("router.messageIn channel very full: current=%v, max=%v\n", len(router.messageIn), cap(router.messageIn))
		time.Sleep(time.Millisecond)
	}

	router.messageIn <- msg
	return nil
}

func (router *router) handleMessage(message *protocol.Message) {
	if protocol.InfoEnabled() {
		protocol.Info("routing message: %v", message.Metadata())
	}

	for currentRoutePath, currentRouteList := range router.routes {
		if matchesTopic(message.Path, currentRoutePath) {
			for _, route := range currentRouteList {
				router.deliverMessage(route, message)
			}
		}
	}
}

func (router *router) deliverMessage(route Route, message *protocol.Message) {
	defer protocol.PanicLogger()
	select {
	case route.C <- MsgAndRoute{Message: message, Route: &route}:
	// fine, we could send the message
	default:
		protocol.Info("queue was full, closing delivery for route=%v to applicationID=%v", route.Path, route.ApplicationID)
		close(route.C)
		router.unsubscribe(&route)
	}
}

func (router *router) closeAllRoutes() {
	for _, currentRouteList := range router.routes {
		for _, route := range currentRouteList {
			close(route.C)
			router.unsubscribe(&route)
		}
	}
}

func copyOf(message []byte) []byte {
	messageCopy := make([]byte, len(message))
	copy(messageCopy, message)
	return messageCopy
}

// Test wether the supplied routePath matches the message topic
func matchesTopic(messagePath, routePath protocol.Path) bool {
	messagePathLen := len(string(messagePath))
	routePathLen := len(string(routePath))
	return strings.HasPrefix(string(messagePath), string(routePath)) &&
		(messagePathLen == routePathLen ||
			(messagePathLen > routePathLen && string(messagePath)[routePathLen] == '/'))
}

// remove a route from the supplied list,
// based on same ApplicationID id and same path
func remove(slice []Route, route *Route) []Route {
	position := -1
	for p, r := range slice {
		if r.ApplicationID == route.ApplicationID && r.Path == route.Path {
			position = p
		}
	}
	if position == -1 {
		return slice
	}
	return append(slice[:position], slice[position+1:]...)
}

// AccessManager returns the `accessManager` provided for the router
func (router *router) AccessManager() (auth.AccessManager, error) {
	if router.accessManager == nil {
		return nil, ErrServiceNotProvided
	}
	return router.accessManager, nil
}

// MessageStore returns the `messageStore` provided for the router
func (router *router) MessageStore() (store.MessageStore, error) {
	if router.messageStore == nil {
		return nil, ErrServiceNotProvided
	}
	return router.messageStore, nil
}

// KVStore returns the `kvStore` provided for the router
func (router *router) KVStore() (store.KVStore, error) {
	if router.kvStore == nil {
		return nil, ErrServiceNotProvided
	}
	return router.kvStore, nil
}
<commit_msg>adding check for router<commit_after>package server

import (
	"github.com/smancke/guble/protocol"
	"github.com/smancke/guble/server/auth"
	"github.com/smancke/guble/store"
	"runtime"
	"strings"
	"time"
	"github.com/docker/distribution/health"
)

// Router interface provides mechanism for PubSub messaging
type Router interface {
	health.Checker
	KVStore() (store.KVStore, error)
	AccessManager() (auth.AccessManager, error)
	MessageStore() (store.MessageStore, error)

	Subscribe(r *Route) (*Route, error)
	Unsubscribe(r *Route)
	HandleMessage(message *protocol.Message) error
}

// Helper struct to pass `Route` to subscription channel and provide a
// notification channel
type subRequest struct {
	route      *Route
	doneNotify chan bool
}

type router struct {
	// mapping the path to the route slice
	routes          map[protocol.Path][]Route
	messageIn       chan *protocol.Message
	subscribeChan   chan subRequest
	unsubscribeChan chan subRequest
	stop            chan bool

	// external services
	accessManager auth.AccessManager
	messageStore  store.MessageStore
	kvStore       store.KVStore
}

// NewRouter returns a pointer to Router
func NewRouter(
	accessManager auth.AccessManager,
	messageStore store.MessageStore,
	kvStore store.KVStore) Router {
	return &router{
		routes:          make(map[protocol.Path][]Route),
		messageIn:       make(chan *protocol.Message, 500),
		subscribeChan:   make(chan subRequest, 10),
		unsubscribeChan: make(chan subRequest, 10),
		stop:            make(chan bool, 1),

		accessManager: accessManager,
		messageStore:  messageStore,
		kvStore:       kvStore,
	}
}

func (router *router) Start() error {
	if router.accessManager == nil {
		panic("AccessManager not set. Cannot start.")
	}

	go func() {
		for {
			func() {
				defer protocol.PanicLogger()

				select {
				case message := <-router.messageIn:
					router.handleMessage(message)
					runtime.Gosched()
				case subscriber := <-router.subscribeChan:
					router.subscribe(subscriber.route)
					subscriber.doneNotify <- true
				case unsubscriber := <-router.unsubscribeChan:
					router.unsubscribe(unsubscriber.route)
					unsubscriber.doneNotify <- true
				case <-router.stop:
					router.closeAllRoutes()
					protocol.Debug("stopping message router")
					break
				}
			}()
		}
	}()

	return nil
}

// Stop stops the router by closing the stop channel
func (router *router) Stop() error {
	close(router.stop)
	return nil
}

func (outer *router) Check() error {
	return nil
}

// Subscribe adds a route to the subscribers.
// If there is already a route with same Application Id and Path, it will be replaced.
func (router *router) Subscribe(r *Route) (*Route, error) {
	protocol.Debug("subscribe %v, %v, %v", router.accessManager, r.UserID, r.Path)
	accessAllowed := router.accessManager.IsAllowed(auth.READ, r.UserID, r.Path)
	if !accessAllowed {
		return r, &PermissionDeniedError{r.UserID, auth.READ, r.Path}
	}
	req := subRequest{
		route:      r,
		doneNotify: make(chan bool),
	}
	router.subscribeChan <- req
	<-req.doneNotify
	return r, nil
}

func (router *router) subscribe(r *Route) {
	protocol.Info("subscribe applicationID=%v, path=%v", r.ApplicationID, r.Path)

	routeList, present := router.routes[r.Path]
	if !present {
		routeList = []Route{}
		router.routes[r.Path] = routeList
	}

	// try to remove, to avoid double subscriptions of the same app
	routeList = remove(routeList, r)

	router.routes[r.Path] = append(routeList, *r)
}

func (router *router) Unsubscribe(r *Route) {
	req := subRequest{
		route:      r,
		doneNotify: make(chan bool),
	}
	router.unsubscribeChan <- req
	<-req.doneNotify
}

func (router *router) unsubscribe(r *Route) {
	protocol.Info("unsubscribe applicationID=%v, path=%v", r.ApplicationID, r.Path)
	routeList, present := router.routes[r.Path]
	if !present {
		return
	}
	router.routes[r.Path] = remove(routeList, r)
	if len(router.routes[r.Path]) == 0 {
		delete(router.routes, r.Path)
	}
}

func (router *router) HandleMessage(message *protocol.Message) error {
	protocol.Debug("Route.HandleMessage: %v %v", message.UserID, message.Path)
	if !router.accessManager.IsAllowed(auth.WRITE, message.UserID, message.Path) {
		return &PermissionDeniedError{message.UserID, auth.WRITE, message.Path}
	}

	return router.storeMessage(message)
}

// Assign the new message id and store it and handle by passing the stored message
// to the messageIn channel
func (router *router) storeMessage(msg *protocol.Message) error {
	txCallback := func(msgId uint64) []byte {
		msg.ID = msgId
		msg.Time = time.Now().Unix()
		return msg.Bytes()
	}

	if err := router.messageStore.StoreTx(msg.Path.Partition(), txCallback); err != nil {
		protocol.Err("error storing message in partition %v: %v", msg.Path.Partition(), err)
		return err
	}

	if float32(len(router.messageIn))/float32(cap(router.messageIn)) > 0.9 {
		protocol.Warn("router.messageIn channel very full: current=%v, max=%v\n", len(router.messageIn), cap(router.messageIn))
		time.Sleep(time.Millisecond)
	}

	router.messageIn <- msg
	return nil
}

func (router *router) handleMessage(message *protocol.Message) {
	if protocol.InfoEnabled() {
		protocol.Info("routing message: %v", message.Metadata())
	}

	for currentRoutePath, currentRouteList := range router.routes {
		if matchesTopic(message.Path, currentRoutePath) {
			for _, route := range currentRouteList {
				router.deliverMessage(route, message)
			}
		}
	}
}

func (router *router) deliverMessage(route Route, message *protocol.Message) {
	defer protocol.PanicLogger()
	select {
	case route.C <- MsgAndRoute{Message: message, Route: &route}:
	// fine, we could send the message
	default:
		protocol.Info("queue was full, closing delivery for route=%v to applicationID=%v", route.Path, route.ApplicationID)
		close(route.C)
		router.unsubscribe(&route)
	}
}

func (router *router) closeAllRoutes() {
	for _, currentRouteList := range router.routes {
		for _, route := range currentRouteList {
			close(route.C)
			router.unsubscribe(&route)
		}
	}
}

func copyOf(message []byte) []byte {
	messageCopy := make([]byte, len(message))
	copy(messageCopy, message)
	return messageCopy
}

// Test wether the supplied routePath matches the message topic
func matchesTopic(messagePath, routePath protocol.Path) bool {
	messagePathLen := len(string(messagePath))
	routePathLen := len(string(routePath))
	return strings.HasPrefix(string(messagePath), string(routePath)) &&
		(messagePathLen == routePathLen ||
			(messagePathLen > routePathLen && string(messagePath)[routePathLen] == '/'))
}

// remove a route from the supplied list,
// based on same ApplicationID id and same path
func remove(slice []Route, route *Route) []Route {
	position := -1
	for p, r := range slice {
		if r.ApplicationID == route.ApplicationID && r.Path == route.Path {
			position = p
		}
	}
	if position == -1 {
		return slice
	}
	return append(slice[:position], slice[position+1:]...)
}

// AccessManager returns the `accessManager` provided for the router
func (router *router) AccessManager() (auth.AccessManager, error) {
	if router.accessManager == nil {
		return nil, ErrServiceNotProvided
	}
	return router.accessManager, nil
}

// MessageStore returns the `messageStore` provided for the router
func (router *router) MessageStore() (store.MessageStore, error) {
	if router.messageStore == nil {
		return nil, ErrServiceNotProvided
	}
	return router.messageStore, nil
}

// KVStore returns the `kvStore` provided for the router
func (router *router) KVStore() (store.KVStore, error) {
	if router.kvStore == nil {
		return nil, ErrServiceNotProvided
	}
	return router.kvStore, nil
}
<|endoftext|>


<commit_before>/**
* ArithServer
 */

package main

import (
	"fmt"
	"net/rpc"
	"errors"
	"net/http"
	"github.com/goDB/single-server/data"
)

type Server struct {

}

var dataStore data.Store

func initialize(){
	dataStore.M = make(map[string]int)
}

func (t *Server) Put(keyValue *data.KeyValue, reply *int) error {
	dataStore.M[keyValue.K.String]=keyValue.V.Value
	return nil
}

func (t *Server) Get(key *data.Key, value *data.Val) error {
	val,ok := dataStore.M[key.String]
	if !ok {
		return errors.New("key not present")
	}
	value.Value = val
	return nil
}

func main() {
	dataStore.M = make(map[string]int)
	dataServer := new(Server)
	rpc.Register(dataServer)
	rpc.HandleHTTP()
	err := http.ListenAndServe(":1234", nil)
	if err != nil {
		fmt.Println(err.Error())
	}
}
<commit_msg>Update server.go<commit_after>/**
Code reference: http://jan.newmarch.name/go/rpc/chapter-rpc.html
*/

package main

import (
	"fmt"
	"net/rpc"
	"errors"
	"net/http"
	"github.com/goDB/single-server/data"
)

type Server struct {

}

var dataStore data.Store

func initialize(){
	dataStore.M = make(map[string]int)
}

func (t *Server) Put(keyValue *data.KeyValue, reply *int) error {
	dataStore.M[keyValue.K.String]=keyValue.V.Value
	return nil
}

func (t *Server) Get(key *data.Key, value *data.Val) error {
	val,ok := dataStore.M[key.String]
	if !ok {
		return errors.New("key not present")
	}
	value.Value = val
	return nil
}

func main() {
	dataStore.M = make(map[string]int)
	dataServer := new(Server)
	rpc.Register(dataServer)
	rpc.HandleHTTP()
	err := http.ListenAndServe(":1234", nil)
	if err != nil {
		fmt.Println(err.Error())
	}
}
<|endoftext|>


<commit_before>// Copyright 2012 Apcera Inc. All rights reserved.

package server

import (
	"bufio"
	"encoding/json"
	"fmt"
	"net"
	"os"
	"os/signal"
	"sync/atomic"
	"time"

	"github.com/apcera/gnatsd/hashmap"
	"github.com/apcera/gnatsd/sublist"
)

type Options struct {
	Host          string
	Port          int
	Trace         bool
	Debug         bool
	NoLog         bool
	NoSigs        bool
	Logtime       bool
	MaxConn       int
	Username      string
	Password      string
	Authorization string
}

type Info struct {
	Id           string `json:"server_id"`
	Version      string `json:"version"`
	Host         string `json:"host"`
	Port         int    `json:"port"`
	AuthRequired bool   `json:"auth_required"`
	SslRequired  bool   `json:"ssl_required"`
	MaxPayload   int    `json:"max_payload"`
}

type Server struct {
	info     Info
	infoJson []byte
	sl       *sublist.Sublist
	gcid     uint64
	opts     *Options
	trace    bool
	debug    bool
	running  bool
	listener net.Listener
	clients  map[uint64]*client
}

func processOptions(opt *Options) {
	// Setup non-standard Go defaults
	if opt.Host == "" {
		opt.Host = DEFAULT_HOST
	}
	if opt.Port == 0 {
		opt.Port = DEFAULT_PORT
	}
	if opt.MaxConn == 0 {
		opt.MaxConn = DEFAULT_MAX_CONNECTIONS
	}
}

func New(opts *Options) *Server {
	processOptions(opts)
	info := Info{
		Id:           genId(),
		Version:      VERSION,
		Host:         opts.Host,
		Port:         opts.Port,
		AuthRequired: false,
		SslRequired:  false,
		MaxPayload:   MAX_PAYLOAD_SIZE,
	}
	// Check for Auth items
	if opts.Username != "" || opts.Authorization != "" {
		info.AuthRequired = true
	}
	s := &Server{
		info:  info,
		sl:    sublist.New(),
		opts:  opts,
		debug: opts.Debug,
		trace: opts.Trace,
	}
	// Setup logging with flags
	s.LogInit()

	// For tracing clients
	s.clients = make(map[uint64]*client)

	// Generate the info json
	b, err := json.Marshal(s.info)
	if err != nil {
		Fatalf("Err marshalling INFO JSON: %+v\n", err)
	}
	s.infoJson = []byte(fmt.Sprintf("INFO %s %s", b, CR_LF))

	s.handleSignals()

	return s
}

// Signal Handling
func (s *Server) handleSignals() {
	if s.opts.NoSigs {
		return
	}
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for sig := range c {
			Debugf("Trapped Signal; %v", sig)
			// FIXME, trip running?
			Log("Server Exiting..")
			os.Exit(0)
		}
	}()
}

// Shutdown will shutdown the server instance by kicking out the AcceptLoop
// and closing all associated clients.
func (s *Server) Shutdown() {
	s.running = false
	// Close client connections
	for _, c := range s.clients {
		c.closeConnection()
	}
	// Kick AcceptLoop()
	if s.listener != nil {
		s.listener.Close()
		s.listener = nil
	}
}

func (s *Server) AcceptLoop() {
	Logf("Starting nats-server version %s on port %d", VERSION, s.opts.Port)

	hp := fmt.Sprintf("%s:%d", s.opts.Host, s.opts.Port)
	l, e := net.Listen("tcp", hp)
	if e != nil {
		Fatalf("Error listening on port: %d - %v", s.opts.Port, e)
		return
	}

	// Setup state that can enable shutdown
	s.listener = l
	s.running = true

	for s.running {
		conn, err := s.listener.Accept()
		if err != nil {
			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				Logf("Accept error: %v", err)
			}
			continue
		}
		s.createClient(conn)
	}
	Log("Server Exiting..")
}

func clientConnStr(conn net.Conn) interface{} {
	if ip, ok := conn.(*net.TCPConn); ok {
		addr := ip.RemoteAddr().(*net.TCPAddr)
		return []string{fmt.Sprintf("%v, %d", addr.IP, addr.Port)}
	}
	return "N/A"
}

func (s *Server) createClient(conn net.Conn) *client {
	c := &client{srv: s, conn: conn, opts: defaultOpts}
	c.cid = atomic.AddUint64(&s.gcid, 1)

	c.bw = bufio.NewWriterSize(c.conn, defaultBufSize)
	c.subs = hashmap.New()

	// This is to track pending clients that have data to be flushed
	// after we process inbound msgs from our own connection.
	c.pcd = make(map[*client]struct{})

	Debug("Client connection created", clientConnStr(conn), c.cid)

	if ip, ok := conn.(*net.TCPConn); ok {
		ip.SetReadBuffer(defaultBufSize)
	}

	s.sendInfo(c)
	go c.readLoop()
	if s.info.AuthRequired {
		c.atmr = time.AfterFunc(AUTH_TIMEOUT, func() { c.authViolation() })
	}
	// Register with the server.
	s.clients[c.cid] = c
	return c
}

func (s *Server) sendInfo(c *client) {
	// FIXME, err
	c.conn.Write(s.infoJson)
}

// Check auth and return boolean indicating if client is ok
func (s *Server) checkAuth(c *client) bool {
	if !s.info.AuthRequired {
		return true
	}
	// We require auth here, check the client
	// Authorization tokens trump username/password
	if s.opts.Authorization != "" {
		return s.opts.Authorization == c.opts.Authorization
	} else if s.opts.Username != c.opts.Username ||
		s.opts.Password != c.opts.Password {
		return false
	}
	return true
}

func (s *Server) removeClient(c *client) {
	delete(s.clients, c.cid)
}<commit_msg>Wait on Shutdown()<commit_after>// Copyright 2012 Apcera Inc. All rights reserved.

package server

import (
	"bufio"
	"encoding/json"
	"fmt"
	"net"
	"os"
	"os/signal"
	"sync/atomic"
	"time"

	"github.com/apcera/gnatsd/hashmap"
	"github.com/apcera/gnatsd/sublist"
)

type Options struct {
	Host          string
	Port          int
	Trace         bool
	Debug         bool
	NoLog         bool
	NoSigs        bool
	Logtime       bool
	MaxConn       int
	Username      string
	Password      string
	Authorization string
}

type Info struct {
	Id           string `json:"server_id"`
	Version      string `json:"version"`
	Host         string `json:"host"`
	Port         int    `json:"port"`
	AuthRequired bool   `json:"auth_required"`
	SslRequired  bool   `json:"ssl_required"`
	MaxPayload   int    `json:"max_payload"`
}

type Server struct {
	info     Info
	infoJson []byte
	sl       *sublist.Sublist
	gcid     uint64
	opts     *Options
	trace    bool
	debug    bool
	running  bool
	listener net.Listener
	clients  map[uint64]*client
	done     chan bool
}

func processOptions(opt *Options) {
	// Setup non-standard Go defaults
	if opt.Host == "" {
		opt.Host = DEFAULT_HOST
	}
	if opt.Port == 0 {
		opt.Port = DEFAULT_PORT
	}
	if opt.MaxConn == 0 {
		opt.MaxConn = DEFAULT_MAX_CONNECTIONS
	}
}

func New(opts *Options) *Server {
	processOptions(opts)
	info := Info{
		Id:           genId(),
		Version:      VERSION,
		Host:         opts.Host,
		Port:         opts.Port,
		AuthRequired: false,
		SslRequired:  false,
		MaxPayload:   MAX_PAYLOAD_SIZE,
	}
	// Check for Auth items
	if opts.Username != "" || opts.Authorization != "" {
		info.AuthRequired = true
	}
	s := &Server{
		info:  info,
		sl:    sublist.New(),
		opts:  opts,
		debug: opts.Debug,
		trace: opts.Trace,
		done:  make(chan bool, 1),
	}
	// Setup logging with flags
	s.LogInit()

	// For tracing clients
	s.clients = make(map[uint64]*client)

	// Generate the info json
	b, err := json.Marshal(s.info)
	if err != nil {
		Fatalf("Err marshalling INFO JSON: %+v\n", err)
	}
	s.infoJson = []byte(fmt.Sprintf("INFO %s %s", b, CR_LF))

	s.handleSignals()

	return s
}

// Signal Handling
func (s *Server) handleSignals() {
	if s.opts.NoSigs {
		return
	}
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for sig := range c {
			Debugf("Trapped Signal; %v", sig)
			// FIXME, trip running?
			Log("Server Exiting..")
			os.Exit(0)
		}
	}()
}

// Shutdown will shutdown the server instance by kicking out the AcceptLoop
// and closing all associated clients.
func (s *Server) Shutdown() {
	s.running = false
	// Close client connections
	for _, c := range s.clients {
		c.closeConnection()
	}
	// Kick AcceptLoop()
	if s.listener != nil {
		s.listener.Close()
		s.listener = nil
	}
	<-s.done
}

func (s *Server) AcceptLoop() {
	Logf("Starting nats-server version %s on port %d", VERSION, s.opts.Port)

	hp := fmt.Sprintf("%s:%d", s.opts.Host, s.opts.Port)
	l, e := net.Listen("tcp", hp)
	if e != nil {
		Fatalf("Error listening on port: %d - %v", s.opts.Port, e)
		return
	}

	// Setup state that can enable shutdown
	s.listener = l
	s.running = true

	for s.running {
		conn, err := s.listener.Accept()
		if err != nil {
			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				Logf("Accept error: %v", err)
			}
			continue
		}
		s.createClient(conn)
	}
	s.done <- true
	Log("Server Exiting..")
}

func clientConnStr(conn net.Conn) interface{} {
	if ip, ok := conn.(*net.TCPConn); ok {
		addr := ip.RemoteAddr().(*net.TCPAddr)
		return []string{fmt.Sprintf("%v, %d", addr.IP, addr.Port)}
	}
	return "N/A"
}

func (s *Server) createClient(conn net.Conn) *client {
	c := &client{srv: s, conn: conn, opts: defaultOpts}
	c.cid = atomic.AddUint64(&s.gcid, 1)

	c.bw = bufio.NewWriterSize(c.conn, defaultBufSize)
	c.subs = hashmap.New()

	// This is to track pending clients that have data to be flushed
	// after we process inbound msgs from our own connection.
	c.pcd = make(map[*client]struct{})

	Debug("Client connection created", clientConnStr(conn), c.cid)

	if ip, ok := conn.(*net.TCPConn); ok {
		ip.SetReadBuffer(defaultBufSize)
	}

	s.sendInfo(c)
	go c.readLoop()
	if s.info.AuthRequired {
		c.atmr = time.AfterFunc(AUTH_TIMEOUT, func() { c.authViolation() })
	}
	// Register with the server.
	s.clients[c.cid] = c
	return c
}

func (s *Server) sendInfo(c *client) {
	// FIXME, err
	c.conn.Write(s.infoJson)
}

// Check auth and return boolean indicating if client is ok
func (s *Server) checkAuth(c *client) bool {
	if !s.info.AuthRequired {
		return true
	}
	// We require auth here, check the client
	// Authorization tokens trump username/password
	if s.opts.Authorization != "" {
		return s.opts.Authorization == c.opts.Authorization
	} else if s.opts.Username != c.opts.Username ||
		s.opts.Password != c.opts.Password {
		return false
	}
	return true
}

func (s *Server) removeClient(c *client) {
	delete(s.clients, c.cid)
}<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"flag"
	"fmt"
	_ "github.com/lib/pq"
	"io/ioutil"
	"regexp"
	"github.com/kylelemons/go-gypsy/yaml"
	"log"
)

var (
        dry     =       flag.Bool("dry", false, "dry run: show what will be run but do not execute statements")
        environment = flag.String("environment", "", "Environment to run in, e.g. staging, production")
	config      = flag.String("config", "./config/database.yml", "database configuration file")
	db *sql.DB
)

func init() {
	flag.Parse()

	log.Printf("running in %s environment, configuration file %s", *environment, *config)
	settings := yaml.ConfigFile(*config)

	// setup database connection
	driver, err := settings.Get(fmt.Sprintf("%s.driver", *environment))
	if err != nil {
		log.Fatal("error loading db driver", err)
	}

	connstr, err := settings.Get(fmt.Sprintf("%s.connstr", *environment))
	if err != nil {
		log.Fatal("error loading db connstr", err)
	}

	_db, err := sql.Open(driver, connstr)
	if err != nil {
		log.Fatal("Cannot open database connection", err)
	}

	log.Printf("database connstr: %s", connstr)

	db = _db
}

func main() {
	// tool to migrate the database
	// This is very immature code.
	//
	// Usage:
	//
	// go run bin/migrate.go 		# apply migrations
	// go run bin/migrate.go --dry=true 	# show what will be run, do not execute statements.
	//
	// TODO:
	// - rollback
	// - transactional migrations
	// - show output of migration
	// - decent error handling

	// load all migrations and find version numbers
	file_list, err := ioutil.ReadDir("db/")
	if err != nil {
		fmt.Println("error loading directory list", err)
	}

	all_migrations := make(map[string]string)

	re := regexp.MustCompile(`\A(\d+)[^\.]+\.sql\z`)
	for _, item := range file_list {
		if matches := re.FindSubmatch([]byte(item.Name())); matches != nil {
			all_migrations[string(matches[1])] = item.Name()
		}
	}

	fmt.Println("found versions: ", all_migrations)

	// find migrations to apply
	rows, err := db.Query("SELECT * FROM schema_info ORDER BY version DESC;")
	if err != nil {
		fmt.Println("error loading applied migrations", err)
	}

	var applied_migrations []string
	for rows.Next() {
		var version string
		_ = rows.Scan(&version)
		applied_migrations = append(applied_migrations, version)
	}

	fmt.Println("migrations already applied: ", applied_migrations)

	for _, version := range applied_migrations {
		delete(all_migrations, version)
	}

	fmt.Println("migrations that will be applied: ", all_migrations)

	// apply migrations
	for version, migration := range all_migrations {
		// MIGRATE!
		raw_sql, err := ioutil.ReadFile("db/" + migration)
		if err != nil {
			fmt.Printf("error reading %s: %s\n", migration, err)
		}

		fmt.Printf("===== executing migration %s =====\n\n%s\n\n", migration, string(raw_sql))

		if !*dry {
			_, err = db.Exec(string(raw_sql))
			if err != nil {
				fmt.Printf("error migrating %s: %s", migration, err)
				return
			}

			fmt.Println("===== completed migration =====", migration)

			_, err = db.Exec("INSERT INTO schema_info (version) VALUES ($1);", version)
			if err != nil {
				fmt.Printf("error migrating %s: %s", migration, err)
			}
		}
	}
}
<commit_msg>update sample usage<commit_after>package main

import (
	"database/sql"
	"flag"
	"fmt"
	_ "github.com/lib/pq"
	"io/ioutil"
	"regexp"
	"github.com/kylelemons/go-gypsy/yaml"
	"log"
)

var (
        dry     =       flag.Bool("dry", false, "dry run: show what will be run but do not execute statements")
        environment = flag.String("environment", "", "Environment to run in, e.g. staging, production")
	config      = flag.String("config", "./config/database.yml", "database configuration file")
	db *sql.DB
)

func init() {
	flag.Parse()

	log.Printf("running in %s environment, configuration file %s", *environment, *config)
	settings := yaml.ConfigFile(*config)

	// setup database connection
	driver, err := settings.Get(fmt.Sprintf("%s.driver", *environment))
	if err != nil {
		log.Fatal("error loading db driver", err)
	}

	connstr, err := settings.Get(fmt.Sprintf("%s.connstr", *environment))
	if err != nil {
		log.Fatal("error loading db connstr", err)
	}

	_db, err := sql.Open(driver, connstr)
	if err != nil {
		log.Fatal("Cannot open database connection", err)
	}

	log.Printf("database connstr: %s", connstr)

	db = _db
}

func main() {
	// tool to migrate the database
	// This is very immature code.
	//
	// Usage:
	//
	// go run bin/migrate.go --environment=development 		# apply migrations
	// go run bin/migrate.go --environment=development --dry=true 	# show what will be run, do not execute statements.
	//
	// TODO:
	// - rollback
	// - transactional migrations
	// - show output of migration
	// - decent error handling

	// load all migrations and find version numbers
	file_list, err := ioutil.ReadDir("db/")
	if err != nil {
		fmt.Println("error loading directory list", err)
	}

	all_migrations := make(map[string]string)

	re := regexp.MustCompile(`\A(\d+)[^\.]+\.sql\z`)
	for _, item := range file_list {
		if matches := re.FindSubmatch([]byte(item.Name())); matches != nil {
			all_migrations[string(matches[1])] = item.Name()
		}
	}

	fmt.Println("found versions: ", all_migrations)

	// find migrations to apply
	rows, err := db.Query("SELECT * FROM schema_info ORDER BY version DESC;")
	if err != nil {
		fmt.Println("error loading applied migrations", err)
	}

	var applied_migrations []string
	for rows.Next() {
		var version string
		_ = rows.Scan(&version)
		applied_migrations = append(applied_migrations, version)
	}

	fmt.Println("migrations already applied: ", applied_migrations)

	for _, version := range applied_migrations {
		delete(all_migrations, version)
	}

	fmt.Println("migrations that will be applied: ", all_migrations)

	// apply migrations
	for version, migration := range all_migrations {
		// MIGRATE!
		raw_sql, err := ioutil.ReadFile("db/" + migration)
		if err != nil {
			fmt.Printf("error reading %s: %s\n", migration, err)
		}

		fmt.Printf("===== executing migration %s =====\n\n%s\n\n", migration, string(raw_sql))

		if !*dry {
			_, err = db.Exec(string(raw_sql))
			if err != nil {
				fmt.Printf("error migrating %s: %s", migration, err)
				return
			}

			fmt.Println("===== completed migration =====", migration)

			_, err = db.Exec("INSERT INTO schema_info (version) VALUES ($1);", version)
			if err != nil {
				fmt.Printf("error migrating %s: %s", migration, err)
			}
		}
	}
}
<|endoftext|>


<commit_before>package gorethink

import (
	"fmt"
	"strconv"
	"strings"

	p "github.com/dancannon/gorethink/ql2"
)

type OptArgs interface {
	toMap() map[string]interface{}
}
type termsList []Term
type termsObj map[string]Term
type Term struct {
	name     string
	rootTerm bool
	termType p.Term_TermType
	data     interface{}
	args     []Term
	optArgs  map[string]Term
}

// build takes the query tree and prepares it to be sent as a JSON
// expression
func (t Term) build() interface{} {
	switch t.termType {
	case p.Term_DATUM:
		return t.data
	case p.Term_MAKE_OBJ:
		res := map[string]interface{}{}
		for k, v := range t.optArgs {
			res[k] = v.build()
		}
		return res
	case p.Term_BINARY:
		if len(t.args) == 0 {
			return map[string]interface{}{
				"$reql_type$": "BINARY",
				"data":        t.data,
			}
		}
	}

	args := []interface{}{}
	optArgs := map[string]interface{}{}

	for _, v := range t.args {
		args = append(args, v.build())
	}

	for k, v := range t.optArgs {
		optArgs[k] = v.build()
	}

	return []interface{}{int(t.termType), args, optArgs}
}

// String returns a string representation of the query tree
func (t Term) String() string {
	switch t.termType {
	case p.Term_MAKE_ARRAY:
		return fmt.Sprintf("[%s]", strings.Join(argsToStringSlice(t.args), ", "))
	case p.Term_MAKE_OBJ:
		return fmt.Sprintf("{%s}", strings.Join(optArgsToStringSlice(t.optArgs), ", "))
	case p.Term_FUNC:
		// Get string representation of each argument
		args := []string{}
		for _, v := range t.args[0].args {
			args = append(args, fmt.Sprintf("var_%d", v.data))
		}

		return fmt.Sprintf("func(%s r.Term) r.Term { return %s }",
			strings.Join(args, ", "),
			t.args[1].String(),
		)
	case p.Term_VAR:
		return fmt.Sprintf("var_%s", t.args[0])
	case p.Term_IMPLICIT_VAR:
		return "r.Row"
	case p.Term_DATUM:
		switch v := t.data.(type) {
		case string:
			return strconv.Quote(v)
		default:
			return fmt.Sprintf("%v", v)
		}
	case p.Term_BINARY:
		if len(t.args) == 0 {
			return fmt.Sprintf("r.binary(<data>)")
		}
	}

	if t.rootTerm {
		return fmt.Sprintf("r.%s(%s)", t.name, strings.Join(allArgsToStringSlice(t.args, t.optArgs), ", "))
	}
	return fmt.Sprintf("%s.%s(%s)", t.args[0].String(), t.name, strings.Join(allArgsToStringSlice(t.args[1:], t.optArgs), ", "))
}

type WriteResponse struct {
	Errors        int      `gorethink:"errors"`
	Created       int      `gorethink:"created"`
	Inserted      int      `gorethink:"inserted"`
	Updated       int      `gorethink:"updadte"`
	Unchanged     int      `gorethink:"unchanged"`
	Replaced      int      `gorethink:"replaced"`
	Renamed       int      `gorethink:"renamed"`
	Skipped       int      `gorethink:"skipped"`
	Deleted       int      `gorethink:"deleted"`
	GeneratedKeys []string `gorethink:"generated_keys"`
	FirstError    string   `gorethink:"first_error"` // populated if Errors > 0
	Changes       []WriteChanges
}

type WriteChanges struct {
	NewValue interface{} `gorethink:"new_val"`
	OldValue interface{} `gorethink:"old_val"`
}

type RunOpts struct {
	Db             interface{} `gorethink:"db,omitempty"`
	Profile        interface{} `gorethink:"profile,omitempty"`
	UseOutdated    interface{} `gorethink:"use_outdated,omitempty"`
	ArrayLimit     interface{} `gorethink:"array_limit,omitempty"`
	TimeFormat     interface{} `gorethink:"time_format,omitempty"`
	GroupFormat    interface{} `gorethink:"group_format,omitempty"`
	BinaryFormat   interface{} `gorethink:"binary_format,omitempty"`
	GeometryFormat interface{} `gorethink:"geometry_format,omitempty"`
	BatchConf      BatchOpts   `gorethink:"batch_conf,omitempty"`
}

type BatchOpts struct {
	MinBatchRows              interface{} `gorethink:"min_batch_rows,omitempty"`
	MaxBatchRows              interface{} `gorethink:"max_batch_rows,omitempty"`
	MaxBatchBytes             interface{} `gorethink:"max_batch_bytes,omitempty"`
	MaxBatchSeconds           interface{} `gorethink:"max_batch_seconds,omitempty"`
	FirstBatchScaledownFactor interface{} `gorethink:"first_batch_scaledown_factor,omitempty"`
}

func (o *RunOpts) toMap() map[string]interface{} {
	return optArgsToMap(o)
}

// Run runs a query using the given connection.
//
//	rows, err := query.Run(sess)
//	if err != nil {
//		// error
//	}
//
//  var doc MyDocumentType
//	for rows.Next(&doc) {
//      // Do something with document
//	}
func (t Term) Run(s *Session, optArgs ...RunOpts) (*Cursor, error) {
	opts := map[string]interface{}{}
	if len(optArgs) >= 1 {
		opts = optArgs[0].toMap()
	}

	q := newStartQuery(s, t, opts)

	return s.pool.Query(q)
}

// RunWrite runs a query using the given connection but unlike Run automatically
// scans the result into a variable of type WriteResponse. This function should be used
// if you are running a write query (such as Insert,  Update, TableCreate, etc...)
//
//	res, err := r.Db("database").Table("table").Insert(doc).RunWrite(sess)
func (t Term) RunWrite(s *Session, optArgs ...RunOpts) (WriteResponse, error) {
	var response WriteResponse
	res, err := t.Run(s, optArgs...)
	if err == nil {
		err = res.One(&response)
	}
	return response, err
}

// ExecOpts inherits its options from RunOpts, the only difference is the
// addition of the NoReply field.
//
// When NoReply is true it causes the driver not to wait to receive the result
// and return immediately.
type ExecOpts struct {
	Db             interface{} `gorethink:"db,omitempty"`
	Profile        interface{} `gorethink:"profile,omitempty"`
	UseOutdated    interface{} `gorethink:"use_outdated,omitempty"`
	ArrayLimit     interface{} `gorethink:"array_limit,omitempty"`
	TimeFormat     interface{} `gorethink:"time_format,omitempty"`
	GroupFormat    interface{} `gorethink:"group_format,omitempty"`
	BinaryFormat   interface{} `gorethink:"binary_format,omitempty"`
	GeometryFormat interface{} `gorethink:"geometry_format,omitempty"`
	BatchConf      BatchOpts   `gorethink:"batch_conf,omitempty"`

	NoReply interface{} `gorethink:"noreply,omitempty"`
}

func (o *ExecOpts) toMap() map[string]interface{} {
	return optArgsToMap(o)
}

// Exec runs the query but does not return the result. Exec will still wait for
// the response to be received unless the NoReply field is true.
//
//	res, err := r.Db("database").Table("table").Insert(doc).Exec(sess, r.ExecOpts{
//		NoReply: true,
//	})
func (t Term) Exec(s *Session, optArgs ...ExecOpts) error {
	opts := map[string]interface{}{}
	if len(optArgs) >= 1 {
		opts = optArgs[0].toMap()
	}

	q := newStartQuery(s, t, opts)

	return s.pool.Exec(q)
}

func newStartQuery(s *Session, t Term, opts map[string]interface{}) Query {
	queryOpts := map[string]interface{}{}
	for k, v := range opts {
		queryOpts[k] = Expr(v).build()
	}
	if s.opts.Database != "" {
		queryOpts["db"] = Db(s.opts.Database).build()
	}

	// Construct query
	return Query{
		Type: p.Query_START,
		Term: &t,
		Opts: queryOpts,
	}
}
<commit_msg>Updated WriteResponse struct<commit_after>package gorethink

import (
	"fmt"
	"strconv"
	"strings"

	p "github.com/dancannon/gorethink/ql2"
)

type OptArgs interface {
	toMap() map[string]interface{}
}
type termsList []Term
type termsObj map[string]Term
type Term struct {
	name     string
	rootTerm bool
	termType p.Term_TermType
	data     interface{}
	args     []Term
	optArgs  map[string]Term
}

// build takes the query tree and prepares it to be sent as a JSON
// expression
func (t Term) build() interface{} {
	switch t.termType {
	case p.Term_DATUM:
		return t.data
	case p.Term_MAKE_OBJ:
		res := map[string]interface{}{}
		for k, v := range t.optArgs {
			res[k] = v.build()
		}
		return res
	case p.Term_BINARY:
		if len(t.args) == 0 {
			return map[string]interface{}{
				"$reql_type$": "BINARY",
				"data":        t.data,
			}
		}
	}

	args := []interface{}{}
	optArgs := map[string]interface{}{}

	for _, v := range t.args {
		args = append(args, v.build())
	}

	for k, v := range t.optArgs {
		optArgs[k] = v.build()
	}

	return []interface{}{int(t.termType), args, optArgs}
}

// String returns a string representation of the query tree
func (t Term) String() string {
	switch t.termType {
	case p.Term_MAKE_ARRAY:
		return fmt.Sprintf("[%s]", strings.Join(argsToStringSlice(t.args), ", "))
	case p.Term_MAKE_OBJ:
		return fmt.Sprintf("{%s}", strings.Join(optArgsToStringSlice(t.optArgs), ", "))
	case p.Term_FUNC:
		// Get string representation of each argument
		args := []string{}
		for _, v := range t.args[0].args {
			args = append(args, fmt.Sprintf("var_%d", v.data))
		}

		return fmt.Sprintf("func(%s r.Term) r.Term { return %s }",
			strings.Join(args, ", "),
			t.args[1].String(),
		)
	case p.Term_VAR:
		return fmt.Sprintf("var_%s", t.args[0])
	case p.Term_IMPLICIT_VAR:
		return "r.Row"
	case p.Term_DATUM:
		switch v := t.data.(type) {
		case string:
			return strconv.Quote(v)
		default:
			return fmt.Sprintf("%v", v)
		}
	case p.Term_BINARY:
		if len(t.args) == 0 {
			return fmt.Sprintf("r.binary(<data>)")
		}
	}

	if t.rootTerm {
		return fmt.Sprintf("r.%s(%s)", t.name, strings.Join(allArgsToStringSlice(t.args, t.optArgs), ", "))
	}
	return fmt.Sprintf("%s.%s(%s)", t.args[0].String(), t.name, strings.Join(allArgsToStringSlice(t.args[1:], t.optArgs), ", "))
}

type WriteResponse struct {
	Errors        int      `gorethink:"errors"`
	Created       int      `gorethink:"created"`
	Inserted      int      `gorethink:"inserted"`
	Updated       int      `gorethink:"updadte"`
	Unchanged     int      `gorethink:"unchanged"`
	Replaced      int      `gorethink:"replaced"`
	Renamed       int      `gorethink:"renamed"`
	Skipped       int      `gorethink:"skipped"`
	Deleted       int      `gorethink:"deleted"`
	DBsCreated    int      `gorethink:"dbs_created"`
	TablesCreated int      `gorethink:"tables_created"`
	DBsDropped    int      `gorethink:"dbs_dropped"`
	TablesDropped int      `gorethink:"tables_dropped"`
	ConfigChanges int      `gorethink:"config_changes"`
	GeneratedKeys []string `gorethink:"generated_keys"`
	FirstError    string   `gorethink:"first_error"` // populated if Errors > 0
	Changes       []WriteChanges
}

type WriteChanges struct {
	NewValue interface{} `gorethink:"new_val"`
	OldValue interface{} `gorethink:"old_val"`
}

type RunOpts struct {
	Db             interface{} `gorethink:"db,omitempty"`
	Profile        interface{} `gorethink:"profile,omitempty"`
	UseOutdated    interface{} `gorethink:"use_outdated,omitempty"`
	ArrayLimit     interface{} `gorethink:"array_limit,omitempty"`
	TimeFormat     interface{} `gorethink:"time_format,omitempty"`
	GroupFormat    interface{} `gorethink:"group_format,omitempty"`
	BinaryFormat   interface{} `gorethink:"binary_format,omitempty"`
	GeometryFormat interface{} `gorethink:"geometry_format,omitempty"`
	BatchConf      BatchOpts   `gorethink:"batch_conf,omitempty"`
}

type BatchOpts struct {
	MinBatchRows              interface{} `gorethink:"min_batch_rows,omitempty"`
	MaxBatchRows              interface{} `gorethink:"max_batch_rows,omitempty"`
	MaxBatchBytes             interface{} `gorethink:"max_batch_bytes,omitempty"`
	MaxBatchSeconds           interface{} `gorethink:"max_batch_seconds,omitempty"`
	FirstBatchScaledownFactor interface{} `gorethink:"first_batch_scaledown_factor,omitempty"`
}

func (o *RunOpts) toMap() map[string]interface{} {
	return optArgsToMap(o)
}

// Run runs a query using the given connection.
//
//	rows, err := query.Run(sess)
//	if err != nil {
//		// error
//	}
//
//  var doc MyDocumentType
//	for rows.Next(&doc) {
//      // Do something with document
//	}
func (t Term) Run(s *Session, optArgs ...RunOpts) (*Cursor, error) {
	opts := map[string]interface{}{}
	if len(optArgs) >= 1 {
		opts = optArgs[0].toMap()
	}

	q := newStartQuery(s, t, opts)

	return s.pool.Query(q)
}

// RunWrite runs a query using the given connection but unlike Run automatically
// scans the result into a variable of type WriteResponse. This function should be used
// if you are running a write query (such as Insert,  Update, TableCreate, etc...)
//
//	res, err := r.Db("database").Table("table").Insert(doc).RunWrite(sess)
func (t Term) RunWrite(s *Session, optArgs ...RunOpts) (WriteResponse, error) {
	var response WriteResponse
	res, err := t.Run(s, optArgs...)
	if err == nil {
		err = res.One(&response)
	}
	return response, err
}

// ExecOpts inherits its options from RunOpts, the only difference is the
// addition of the NoReply field.
//
// When NoReply is true it causes the driver not to wait to receive the result
// and return immediately.
type ExecOpts struct {
	Db             interface{} `gorethink:"db,omitempty"`
	Profile        interface{} `gorethink:"profile,omitempty"`
	UseOutdated    interface{} `gorethink:"use_outdated,omitempty"`
	ArrayLimit     interface{} `gorethink:"array_limit,omitempty"`
	TimeFormat     interface{} `gorethink:"time_format,omitempty"`
	GroupFormat    interface{} `gorethink:"group_format,omitempty"`
	BinaryFormat   interface{} `gorethink:"binary_format,omitempty"`
	GeometryFormat interface{} `gorethink:"geometry_format,omitempty"`
	BatchConf      BatchOpts   `gorethink:"batch_conf,omitempty"`

	NoReply interface{} `gorethink:"noreply,omitempty"`
}

func (o *ExecOpts) toMap() map[string]interface{} {
	return optArgsToMap(o)
}

// Exec runs the query but does not return the result. Exec will still wait for
// the response to be received unless the NoReply field is true.
//
//	res, err := r.Db("database").Table("table").Insert(doc).Exec(sess, r.ExecOpts{
//		NoReply: true,
//	})
func (t Term) Exec(s *Session, optArgs ...ExecOpts) error {
	opts := map[string]interface{}{}
	if len(optArgs) >= 1 {
		opts = optArgs[0].toMap()
	}

	q := newStartQuery(s, t, opts)

	return s.pool.Exec(q)
}

func newStartQuery(s *Session, t Term, opts map[string]interface{}) Query {
	queryOpts := map[string]interface{}{}
	for k, v := range opts {
		queryOpts[k] = Expr(v).build()
	}
	if s.opts.Database != "" {
		queryOpts["db"] = Db(s.opts.Database).build()
	}

	// Construct query
	return Query{
		Type: p.Query_START,
		Term: &t,
		Opts: queryOpts,
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"time"

	"github.com/PuerkitoBio/goquery"
	"github.com/briandowns/spinner"
	"github.com/fatih/color"
	proxier "golang.org/x/net/proxy"
)

var (
	voiceURL = "https://dict.youdao.com/dictvoice?audio=%s&type=2"
)

func query(words []string, withVoice, withMore, isMulti bool) {
	var url string
	var doc *goquery.Document
	var voiceBody io.ReadCloser

	queryString := strings.Join(words, " ")
	voiceString := strings.Join(words, "+")

	isChinese := isChinese(queryString)

	if isChinese {
		url = "http://dict.youdao.com/w/eng/%s"
	} else {
		url = "http://dict.youdao.com/w/%s"
	}

	//Init spinner
	s := spinner.New(spinner.CharSets[35], 100*time.Millisecond)
	s.Prefix = "Querying... "
	s.Color("green")
	s.Start()

	//Check proxy
	if proxy != "" {
		client := &http.Client{}
		dialer, err := proxier.SOCKS5("tcp", proxy, nil, proxier.Direct)

		if err != nil {
			color.Red("Can't connect to the proxy: %s", err)
			os.Exit(1)
		}

		httpTransport := &http.Transport{}
		client.Transport = httpTransport
		httpTransport.Dial = dialer.Dial

		resp, err := client.Get(fmt.Sprintf(url, queryString))

		if err != nil {
			color.Red("Query failed with err: %s", err.Error())
			os.Exit(1)
		}

		doc, _ = goquery.NewDocumentFromResponse(resp)

		if withVoice && isAvailableOS() {
			if resp, err := client.Get(fmt.Sprintf(voiceURL, voiceString)); err == nil {
				voiceBody = resp.Body
			}
		}
	} else {
		var err error
		doc, err = goquery.NewDocument(fmt.Sprintf(url, queryString))

		if err != nil {
			log.Fatal(err)
			os.Exit(1)
		}

		if withVoice && isAvailableOS() {
			if resp, err := http.Get(fmt.Sprintf(voiceURL, voiceString)); err == nil {
				voiceBody = resp.Body
			}
		}
	}

	s.Stop()

	if isChinese {
		// Find the result
		fmt.Println()
		doc.Find(".trans-container > ul > p > span.contentTitle").Each(func(i int, s *goquery.Selection) {
			color.Green("    %s", s.Find(".search-js").Text())
		})
	} else {

		// Check for typos
		if hint := getHint(doc); hint != nil {
			color.Blue("\r\n    word '%s' not found, do you mean?", queryString)
			fmt.Println()
			for _, guess := range hint {
				color.Green("    %s", guess[0])
				color.Magenta("    %s", guess[1])
			}
			fmt.Println()
			return
		}

		// Find the pronounce
		if !isMulti {
			color.Green("\r\n    %s", getPronounce(doc))
		}

		// Find the result
		result := doc.Find("div#phrsListTab > div.trans-container > ul").Text()
		color.Green(result)
	}

	// Show examples
	sentences := getSentences(words, doc, isChinese, withMore)
	if len(sentences) > 0 {
		fmt.Println()
		for i, sentence := range sentences {
			color.Green(" %2d.%s", i, sentence[0])
			color.Magenta("    %s", sentence[1])
		}
		fmt.Println()
	}

	if withVoice && isAvailableOS() {
		playVoice(voiceBody)
	}
}

func playVoice(body io.ReadCloser) {
	tmpfile, err := ioutil.TempFile("", "ydict")
	if err != nil {
		log.Fatal(err)
	}

	defer os.Remove(tmpfile.Name()) // clean up

	data, err := ioutil.ReadAll(body)

	if _, err := tmpfile.Write(data); err != nil {
		log.Fatal(err)
	}

	if err := tmpfile.Close(); err != nil {
		fmt.Println(err)
	}

	cmd := exec.Command("mpg123", tmpfile.Name())

	if err := cmd.Start(); err != nil {
		fmt.Println(err)
	}

	if err := cmd.Wait(); err != nil {
		fmt.Println(err)
	}
}

func getPronounce(doc *goquery.Document) string {
	var pronounce string
	doc.Find("div.baav > span.pronounce").Each(func(i int, s *goquery.Selection) {

		if i == 0 {
			p := fmt.Sprintf("英: %s    ", s.Find("span.phonetic").Text())
			pronounce += p
		}

		if i == 1 {
			p := fmt.Sprintf("美: %s", s.Find("span.phonetic").Text())
			pronounce += p
		}
	})

	return pronounce
}

func getHint(doc *goquery.Document) [][]string {
	typos := doc.Find(".typo-rel")
	if typos.Length() == 0 {
		return nil
	}
	result := [][]string{}
	typos.Each(func(_ int, s *goquery.Selection) {
		word := strings.TrimSpace(s.Find("a").Text())
		s.Children().Remove()
		mean := strings.TrimSpace(s.Text())
		result = append(result, []string{word, mean})
	})
	return result
}

func getSentences(words []string, doc *goquery.Document, isChinese, withMore bool) [][]string {
	result := [][]string{}
	if withMore {
		url := fmt.Sprintf("http://dict.youdao.com/example/blng/eng/%s", strings.Join(words, "_"))
		var err error
		doc, err = goquery.NewDocument(url)
		if err != nil {
			return result
		}
	}
	doc.Find("#bilingual ul li").Each(func(_ int, s *goquery.Selection) {
		r := []string{}
		s.Children().Each(func(ii int, ss *goquery.Selection) {
			// Ignore source
			if ii == 2 {
				return
			}
			var sentence string
			ss.Children().Each(func(iii int, sss *goquery.Selection) {
				if text := strings.TrimSpace(sss.Text()); text != "" {
					addSpace := (ii == 1 && isChinese) || (ii == 0 && !isChinese) && iii != 0 && text != "."
					if addSpace {
						text = " " + text
					}
					sentence += text
				}
			})
			r = append(r, sentence)
		})
		if len(r) == 2 {
			result = append(result, r)
		}
	})
	return result
}
<commit_msg>let example sentences starts from 1<commit_after>package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"time"

	"github.com/PuerkitoBio/goquery"
	"github.com/briandowns/spinner"
	"github.com/fatih/color"
	proxier "golang.org/x/net/proxy"
)

var (
	voiceURL = "https://dict.youdao.com/dictvoice?audio=%s&type=2"
)

func query(words []string, withVoice, withMore, isMulti bool) {
	var url string
	var doc *goquery.Document
	var voiceBody io.ReadCloser

	queryString := strings.Join(words, " ")
	voiceString := strings.Join(words, "+")

	isChinese := isChinese(queryString)

	if isChinese {
		url = "http://dict.youdao.com/w/eng/%s"
	} else {
		url = "http://dict.youdao.com/w/%s"
	}

	//Init spinner
	s := spinner.New(spinner.CharSets[35], 100*time.Millisecond)
	s.Prefix = "Querying... "
	s.Color("green")
	s.Start()

	//Check proxy
	if proxy != "" {
		client := &http.Client{}
		dialer, err := proxier.SOCKS5("tcp", proxy, nil, proxier.Direct)

		if err != nil {
			color.Red("Can't connect to the proxy: %s", err)
			os.Exit(1)
		}

		httpTransport := &http.Transport{}
		client.Transport = httpTransport
		httpTransport.Dial = dialer.Dial

		resp, err := client.Get(fmt.Sprintf(url, queryString))

		if err != nil {
			color.Red("Query failed with err: %s", err.Error())
			os.Exit(1)
		}

		doc, _ = goquery.NewDocumentFromResponse(resp)

		if withVoice && isAvailableOS() {
			if resp, err := client.Get(fmt.Sprintf(voiceURL, voiceString)); err == nil {
				voiceBody = resp.Body
			}
		}
	} else {
		var err error
		doc, err = goquery.NewDocument(fmt.Sprintf(url, queryString))

		if err != nil {
			log.Fatal(err)
			os.Exit(1)
		}

		if withVoice && isAvailableOS() {
			if resp, err := http.Get(fmt.Sprintf(voiceURL, voiceString)); err == nil {
				voiceBody = resp.Body
			}
		}
	}

	s.Stop()

	if isChinese {
		// Find the result
		fmt.Println()
		doc.Find(".trans-container > ul > p > span.contentTitle").Each(func(i int, s *goquery.Selection) {
			color.Green("    %s", s.Find(".search-js").Text())
		})
	} else {

		// Check for typos
		if hint := getHint(doc); hint != nil {
			color.Blue("\r\n    word '%s' not found, do you mean?", queryString)
			fmt.Println()
			for _, guess := range hint {
				color.Green("    %s", guess[0])
				color.Magenta("    %s", guess[1])
			}
			fmt.Println()
			return
		}

		// Find the pronounce
		if !isMulti {
			color.Green("\r\n    %s", getPronounce(doc))
		}

		// Find the result
		result := doc.Find("div#phrsListTab > div.trans-container > ul").Text()
		color.Green(result)
	}

	// Show examples
	sentences := getSentences(words, doc, isChinese, withMore)
	if len(sentences) > 0 {
		fmt.Println()
		for i, sentence := range sentences {
			color.Green(" %2d.%s", i+1, sentence[0])
			color.Magenta("    %s", sentence[1])
		}
		fmt.Println()
	}

	if withVoice && isAvailableOS() {
		playVoice(voiceBody)
	}
}

func playVoice(body io.ReadCloser) {
	tmpfile, err := ioutil.TempFile("", "ydict")
	if err != nil {
		log.Fatal(err)
	}

	defer os.Remove(tmpfile.Name()) // clean up

	data, err := ioutil.ReadAll(body)

	if _, err := tmpfile.Write(data); err != nil {
		log.Fatal(err)
	}

	if err := tmpfile.Close(); err != nil {
		fmt.Println(err)
	}

	cmd := exec.Command("mpg123", tmpfile.Name())

	if err := cmd.Start(); err != nil {
		fmt.Println(err)
	}

	if err := cmd.Wait(); err != nil {
		fmt.Println(err)
	}
}

func getPronounce(doc *goquery.Document) string {
	var pronounce string
	doc.Find("div.baav > span.pronounce").Each(func(i int, s *goquery.Selection) {

		if i == 0 {
			p := fmt.Sprintf("英: %s    ", s.Find("span.phonetic").Text())
			pronounce += p
		}

		if i == 1 {
			p := fmt.Sprintf("美: %s", s.Find("span.phonetic").Text())
			pronounce += p
		}
	})

	return pronounce
}

func getHint(doc *goquery.Document) [][]string {
	typos := doc.Find(".typo-rel")
	if typos.Length() == 0 {
		return nil
	}
	result := [][]string{}
	typos.Each(func(_ int, s *goquery.Selection) {
		word := strings.TrimSpace(s.Find("a").Text())
		s.Children().Remove()
		mean := strings.TrimSpace(s.Text())
		result = append(result, []string{word, mean})
	})
	return result
}

func getSentences(words []string, doc *goquery.Document, isChinese, withMore bool) [][]string {
	result := [][]string{}
	if withMore {
		url := fmt.Sprintf("http://dict.youdao.com/example/blng/eng/%s", strings.Join(words, "_"))
		var err error
		doc, err = goquery.NewDocument(url)
		if err != nil {
			return result
		}
	}
	doc.Find("#bilingual ul li").Each(func(_ int, s *goquery.Selection) {
		r := []string{}
		s.Children().Each(func(ii int, ss *goquery.Selection) {
			// Ignore source
			if ii == 2 {
				return
			}
			var sentence string
			ss.Children().Each(func(iii int, sss *goquery.Selection) {
				if text := strings.TrimSpace(sss.Text()); text != "" {
					addSpace := (ii == 1 && isChinese) || (ii == 0 && !isChinese) && iii != 0 && text != "."
					if addSpace {
						text = " " + text
					}
					sentence += text
				}
			})
			r = append(r, sentence)
		})
		if len(r) == 2 {
			result = append(result, r)
		}
	})
	return result
}
<|endoftext|>