<commit_before>package raft

import (
  "fmt"
  "time"
)

// Global warmup state
var INIT string = "init"

// Internal struct
type State struct {
  // Status of raft:
  // INIT: raft is in warmup state, usually to make sure services are started
  // FOLLOWER: store logs, follow leader, vote for others
  // CANDIDATE: vote for themselves
  // LEADER: send logs, send heartbeats
  Status string // INIT

  // The currentTerm the server is
  CurrentTerm uint64 // 0

  // The candidateId that received vote in currentTerm
  VotedFor string // ""

  // The Id of this server.
  // It is a concatation of RPCExtHost and RPCExtPort
  // since there is only one network triplet per server.
  MyId string // "0.0.0.0:11321"

  // Channel to sync everyting
  C chan struct{}

  *Events
}

// Nicer method to get the current state than STATE.Status
func (s *State) Is() string {
  return s.Status
}

// Safely switch from a state to another
// This should only be called by the Raft package
func (s *State) Switch(state string) error {
  // If the state does not change, return
  if state == s.Is() {
    return nil
  }

  // Raft cannot be at any state other than FOLLOWER when
  // state is at INIT
  if s.Is() == INIT && state != FOLLOWER {
    return fmt.Errorf("State must be follower when status == INIT")
  }

  // Checking correct state has argument
  switch state {
    case FOLLOWER, CANDIDATE, LEADER:
      s.C <- struct{}{}
      defer func() {
        <- s.C
      }()
    default:
      return fmt.Errorf("Only supported operations: FOLLOWER, CANDIDATE or LEADER.")
  }

  // Make the switch
  // Call the function in the cases
  switch state {
    case FOLLOWER:
      <- time.Tick(100 * time.Millisecond)
    case CANDIDATE:
      <- time.Tick(300 * time.Millisecond)
    case LEADER:
      <- time.Tick(500 * time.Millisecond)
  }

  // Apply the status if the case bellow has been
  // correctly executed
  old := s.Status
  s.Status = state
  s.Exec("state::changed", old, state)

  return nil
}

type Node struct {
  Ip string
  Port uint64
}

type Cluster struct {
  Nodes map[string]Node
  C chan struct{}
}

func (c *Cluster) Add(n Node) (string, bool) {
  c.C <- struct{}{}
  defer func() {
    <- c.C
  }()

  name := fmt.Sprintf("%s:%d", n.Ip, n.Port)

  if _, ok := c.Nodes[name]; ok {
    return name, false
  }

  c.Nodes[name] = n

  return name, true
}

func NewCluster() *Cluster {
  cluster := &Cluster {
    C: make(chan struct{}, 1),
    Nodes: make(map[string]Node),
  }

  return cluster
}

type StateMachine struct {
  Storage *Storage
  RPC *RPC
  State *State
  Initialized bool

  Cluster *Cluster

  // Configuration of the state machine so it can be reused
  // by everyone.
  Configuration *StateMachineConfiguration

  // On every change call all the registred callbacks
  *Events // NewEvents()
}

// Initialize Init functions.
// Each function are executed into go routines.
// If some funcs are blocking Initialize will block,
// otherwise, goroutines are destroyed.
// If any errors are returned, Initialize will return,
// the error and by that, it will cause all goroutines
// to stop acting.
// Accepts a callback as argument so you know when init's done.
func (s *StateMachine) Initialize() error {
  if s.Initialized == true {
    err := fmt.Errorf("StateMachine is already initialized.")

    return err
  }

  if len(s.Cluster.Nodes) < 3 {
    err := fmt.Errorf("Cannot initialize when cluster size is < 3.")
    return err
  }

  errC := make(chan error)

  s.ExecSync("init::start", s, errC)

  // Funcs are initialized
  s.Initialized = true
  s.State.Switch(FOLLOWER)
  s.Exec("init::done")

  // TODO: catch ERR
  // Catch optionnal errors
  // It will block if some functions blocks
  //for _, _ = range s.Init {
    //err := <- errC
    //if err != nil {
      //s.Initialized = false
      //return err
    //}
  //}

  return nil
}

type StateMachineConfiguration struct {
  // The host addr to listen to
  RPCHost string // "0.0.0.0"

  // The port number to listen to
  RPCPort uint64 // 11321

  // The host addr to give to clients (in case of NAT)
  RPCExtHost string // NYI

  // The port number to give to clients (in case of NAT)
  RPCExtPort uint64 // NYI
}

// Create a state machine object that stores every
// component of Raft, use this object to start Raft.
// You also can overide fields before initialize the
// state machine.
// The functions of the state machine are stored in
// an array, and it's synchronized with channels to
// pass references.
func NewStateMachine(config *StateMachineConfiguration) (*StateMachine, error) {
  s := &StateMachine{
    Events: NewEvents(),
  }

  s.Initialized = false

  if config == nil {
    config = &StateMachineConfiguration{}
  }

  if config.RPCHost == "" {
    config.RPCHost = "0.0.0.0"
  }

  if config.RPCPort == 0 {
    config.RPCPort = 11321
  }

  s.Configuration = config

  s.Cluster = NewCluster()
  id, _ := s.Cluster.Add(Node{config.RPCHost, config.RPCPort})

  // Main core of Raft
  // Maintain the state of the state machine
  state := &State{
    // Initialize status to INIT to prevent Raft of
    // acting before every service has stated
    Status: INIT,

    CurrentTerm: 0,
    VotedFor: "",
    MyId: id,
    C: make(chan struct{}, 1),
    Events: s.Events,
  }

  s.State = state

  s.Once("init::start", func(args ...interface{}) {
    var err error

    s := args[0].(*StateMachine)
    errC := args[1].(chan error)

    storage, err := NewStorage(s.State)
    if err != nil {
      errC <- err
      return
    }

    s.Storage = storage

    err = storage.Start()
    if err != nil {
      errC <- err
      return
    }
  })

  s.Once("init::start", func(args ...interface{}) {
    var err error

    s := args[0].(*StateMachine)
    errC := args[1].(chan error)

    rpc, err := NewRPC(s)
    if err != nil {
      errC <- err
      return
    }

    s.RPC = rpc

    go func() {
      err = s.RPC.Start()
      if err != nil {
        errC <- err
        return
      }
    }()
  })

  s.On("timeout::elapsed", func(args ...interface{}) {
    s := args[0].(*StateMachine)

    fmt.Println("timeout elapsed!")
    s.State.Switch(CANDIDATE)
  })

  return s, nil
}
<commit_msg>Removed cluster min number because it can be fully operational with one node<commit_after>package raft

import (
  "fmt"
  "time"
)

// Global warmup state
var INIT string = "init"

// Internal struct
type State struct {
  // Status of raft:
  // INIT: raft is in warmup state, usually to make sure services are started
  // FOLLOWER: store logs, follow leader, vote for others
  // CANDIDATE: vote for themselves
  // LEADER: send logs, send heartbeats
  Status string // INIT

  // The currentTerm the server is
  CurrentTerm uint64 // 0

  // The candidateId that received vote in currentTerm
  VotedFor string // ""

  // The Id of this server.
  // It is a concatation of RPCExtHost and RPCExtPort
  // since there is only one network triplet per server.
  MyId string // "0.0.0.0:11321"

  // Channel to sync everyting
  C chan struct{}

  *Events
}

// Nicer method to get the current state than STATE.Status
func (s *State) Is() string {
  return s.Status
}

// Safely switch from a state to another
// This should only be called by the Raft package
func (s *State) Switch(state string) error {
  // If the state does not change, return
  if state == s.Is() {
    return nil
  }

  // Raft cannot be at any state other than FOLLOWER when
  // state is at INIT
  if s.Is() == INIT && state != FOLLOWER {
    return fmt.Errorf("State must be follower when status == INIT")
  }

  // Checking correct state has argument
  switch state {
    case FOLLOWER, CANDIDATE, LEADER:
      s.C <- struct{}{}
      defer func() {
        <- s.C
      }()
    default:
      return fmt.Errorf("Only supported operations: FOLLOWER, CANDIDATE or LEADER.")
  }

  // Make the switch
  // Call the function in the cases
  switch state {
    case FOLLOWER:
      <- time.Tick(100 * time.Millisecond)
    case CANDIDATE:
      <- time.Tick(300 * time.Millisecond)
    case LEADER:
      <- time.Tick(500 * time.Millisecond)
  }

  // Apply the status if the case bellow has been
  // correctly executed
  old := s.Status
  s.Status = state
  s.Exec("state::changed", old, state)

  return nil
}

type Node struct {
  Ip string
  Port uint64
}

// Cluster struct
// The node configuration of the server
// can be retreived with: sm.Cluster.Nodes[sm.MyId]
type Cluster struct {
  // Store all the nodes
  Nodes map[string]Node

  // Sync everything
  C chan struct{}
}

// Add a node to a cluster, the name of the node
// is the RPCIp:RPCPort
func (c *Cluster) Add(n Node) (string, bool) {
  c.C <- struct{}{}
  defer func() {
    <- c.C
  }()

  name := fmt.Sprintf("%s:%d", n.Ip, n.Port)

  if _, ok := c.Nodes[name]; ok {
    return name, false
  }

  c.Nodes[name] = n

  return name, true
}

func NewCluster() *Cluster {
  cluster := &Cluster {
    C: make(chan struct{}, 1),
    Nodes: make(map[string]Node),
  }

  return cluster
}

type StateMachine struct {
  Storage *Storage
  RPC *RPC
  State *State
  Initialized bool

  Cluster *Cluster

  // Configuration of the state machine so it can be reused
  // by everyone.
  Configuration *StateMachineConfiguration

  // On every change call all the registred callbacks
  *Events // NewEvents()
}

// Initialize Init functions.
// Each function are executed into go routines.
// If some funcs are blocking Initialize will block,
// otherwise, goroutines are destroyed.
// If any errors are returned, Initialize will return,
// the error and by that, it will cause all goroutines
// to stop acting.
// Accepts a callback as argument so you know when init's done.
func (s *StateMachine) Initialize() error {
  if s.Initialized == true {
    err := fmt.Errorf("StateMachine is already initialized.")

    return err
  }

  errC := make(chan error)

  s.ExecSync("init::start", s, errC)

  // Funcs are initialized
  s.Initialized = true
  s.State.Switch(FOLLOWER)
  s.Exec("init::done")

  // TODO: catch ERR
  // Catch optionnal errors
  // It will block if some functions blocks
  //for _, _ = range s.Init {
    //err := <- errC
    //if err != nil {
      //s.Initialized = false
      //return err
    //}
  //}

  return nil
}

type StateMachineConfiguration struct {
  // The host addr to listen to
  RPCHost string // "0.0.0.0"

  // The port number to listen to
  RPCPort uint64 // 11321

  // The host addr to give to clients (in case of NAT)
  RPCExtHost string // NYI

  // The port number to give to clients (in case of NAT)
  RPCExtPort uint64 // NYI
}

// Create a state machine object that stores every
// component of Raft, use this object to start Raft.
// You also can overide fields before initialize the
// state machine.
// The functions of the state machine are stored in
// an array, and it's synchronized with channels to
// pass references.
func NewStateMachine(config *StateMachineConfiguration) (*StateMachine, error) {
  s := &StateMachine{
    Events: NewEvents(),
  }

  s.Initialized = false

  if config == nil {
    config = &StateMachineConfiguration{}
  }

  if config.RPCHost == "" {
    config.RPCHost = "0.0.0.0"
  }

  if config.RPCPort == 0 {
    config.RPCPort = 11321
  }

  s.Configuration = config

  s.Cluster = NewCluster()
  id, _ := s.Cluster.Add(Node{config.RPCHost, config.RPCPort})

  // Main core of Raft
  // Maintain the state of the state machine
  state := &State{
    // Initialize status to INIT to prevent Raft of
    // acting before every service has stated
    Status: INIT,

    CurrentTerm: 0,
    VotedFor: "",
    MyId: id,
    C: make(chan struct{}, 1),
    Events: s.Events,
  }

  s.State = state

  s.Once("init::start", func(args ...interface{}) {
    var err error

    s := args[0].(*StateMachine)
    errC := args[1].(chan error)

    storage, err := NewStorage(s.State)
    if err != nil {
      errC <- err
      return
    }

    s.Storage = storage

    err = storage.Start()
    if err != nil {
      errC <- err
      return
    }
  })

  s.Once("init::start", func(args ...interface{}) {
    var err error

    s := args[0].(*StateMachine)
    errC := args[1].(chan error)

    rpc, err := NewRPC(s)
    if err != nil {
      errC <- err
      return
    }

    s.RPC = rpc

    go func() {
      err = s.RPC.Start()
      if err != nil {
        errC <- err
        return
      }
    }()
  })

  s.On("timeout::elapsed", func(args ...interface{}) {
    s := args[0].(*StateMachine)

    fmt.Println("timeout elapsed!")
    s.State.Switch(CANDIDATE)
  })

  return s, nil
}
<|endoftext|>


<commit_before>package tenho

import (
	"fmt"
	"math/rand"
	"sort"
	"time"
)

func Start() {
	start := time.Now()
	// 処理
	var i float64
	i = 0
	for {
		i++
		end := time.Now()
		diff := float64(end.Sub(start) / 1000 / 1000 / 1000)
		m := int(i / diff)
		out := 0
		if m >= 0 {
			out = m
		}
		fmt.Printf("\r")
		fmt.Printf("\r%v回試行  %v秒経過 %v回/秒", i, diff, out)
		seed := time.Now().UnixNano()
		var hai string
		var ok bool
		hai, ok = tryOnce(seed)
		fmt.Printf("%v", hai)
		if ok {
			break
		}
	}
	fmt.Printf("\n")
}

type Hand []int

func tryOnce(seed int64) (string, bool) {
	hand := ShuffledHand(seed)
	hai := hand.HaiString()
	ok := Solve(hand)
	return hai, ok
}

// http://d.hatena.ne.jp/hake/20150930/p1
func shuffle(hand Hand) {
	for i := len(hand); i > 1; i-- {
		j := rand.Intn(i) // 0 .. i-1 の乱数発生
		hand[i-1], hand[j] = hand[j], hand[i-1]
	}
}

func ShuffledHand(seed int64) Hand {
	rand.Seed(seed)

	// データ要素数指定、および初期データ作成
	size := 136
	hand := make(Hand, size, size)
	for i := 0; i < size; i++ {
		hand[i] = i / 4
	}

	// シャッフル
	shuffle(hand)

	return hand[:14]
}

// 牌文字への変換(スペース区切り)
func (c Hand) HaiString() string {
	// http://qiita.com/ruiu/items/2bb83b29baeae2433a79
	// サイズ0、内部バッファの長さ69の[]byteの値を割り当てる
	b := make([]byte, 0, 70)

	// bに文字列を追加
	for j := 0; j < 14; j++ {
		// コードポイント上、普通の麻雀牌はU+1F000からの34個。
		// U+1F000 is 'MAHJONG TILE EAST WIND' ('東')
		// https://codepoints.net/U+1F000
		b = append(b, string(c[j]+0x1F000)...) // appendするには...が必要
		// 自分のMacではスペース区切りでないとうまく表示されないためスペースを挿入する
		// U+0020 is 'SPACE'
		// https://codepoints.net/U+0020
		b = append(b, string(0x20)...) // appendするには...が必要
	}
	return string(b)
}

// あがり判定する
func Solve(hand Hand) bool {
	if hand.is_chitoitsu() {
		return true
	}
	suit_grouped_hand := hand.GroupSuit()
	//fmt.Printf("%v", suit_grouped_hand)

	return suit_grouped_hand.Solve()
}

type SuitGroup []int

type SuitsGroupedHand []SuitGroup

// スート分類
func (hand Hand) GroupSuit() SuitsGroupedHand {
	m := SuitsGroupedHand{{}, {}, {}, {}}
	for _, i := range hand {
		switch {
		case i < 7:
			m[0] = append(m[0], i)
		case i < 7+(9*1):
			m[1] = append(m[1], i-7)
		case i < 7+(9*2):
			m[2] = append(m[2], i-7-(9*1))
		case i < 7+(9*3):
			m[3] = append(m[3], i-7-(9*2))
		}
	}
	return m
}

func (m SuitsGroupedHand) Solve() bool {
	return m.a_pair_existible() && m.valid_33332()
}

func (m SuitsGroupedHand) a_pair_existible() bool {
	//スートのサイズを3で割った時
	//あまりが2であるスートグループが1つであること
	c := 0
	for _, a := range m {
		switch len(a) % 3 {
		case 0:
			// noop
		case 1:
			return false
		case 2:
			c++
		}
	}
	return c == 1
}

func (m SuitsGroupedHand) valid_33332() bool {
	for i := 0; i < 4; i++ {
		if !m[i].valid_suit_group(i) {
			return false
		}
	}
	return true
}

// 33332形を形成するスートグループがどうかを判定
func (a SuitGroup) valid_suit_group(i int) bool {
	// 対子が含まれているスートグループがただ1つある前提

	//ソート
	sort.Ints(a)
	if len(a)%3 == 2 {
		//ペアを探す
		pair_numbers := a.pairable_numbers()
		//ペア候補がなかったらぬける
		if len(pair_numbers) == 0 {
			return false
		}
		//ペア候補毎に繰り返し処理
		for _, v := range pair_numbers {
			//ペアとなる２枚を除去
			rest := SuitGroup{}
			c := 2
			for _, w := range a {
				// ペア候補以外は新スライスに入れる
				// ペア候補は３枚目以降は新スライスに入れる
				if w != v || c <= 0 {
					rest = append(rest, w)
				}
				if w == v {
					c--
				}
			}
			if rest.valid_3cards(i) {
				return true
			} else {
				continue
			}
		}
		return false
	} else if len(a)%3 == 0 {
		return a.valid_3cards(i)
	}
	// 到達しないはず
	panic("到達しないはず")
}

func (a SuitGroup) valid_3cards(i int) bool {
	// 刻子や順子のみで構成されている場合true
	// a is sorted
	// a.size % 3 is0
	// 引数は字牌のとき0
	ok := false
	for {
		a, ok = a.remove_kotsu()
		if ok {
			continue
		}
		if i > 0 {
			a, ok = a.remove_shuntsu()
			if ok {
				continue
			}
		}
		return len(a) == 0
	}
}

func (a SuitGroup) remove_kotsu() (SuitGroup, bool) {
	// 刻子を除去できればtrue
	// a is sorted
	retval := a
	if len(a) < 3 {
		return retval, false
	}
	if a[0] == a[1] && a[0] == a[2] {
		retval = a[3:]
		return retval, true
	}
	return retval, false
}

func (a SuitGroup) remove_shuntsu() (SuitGroup, bool) {
	// 順子を除去できればtrue
	// a is sorted
	rest := SuitGroup{}
	first := -1
	second := -1
	found := false
	for _, v := range a {
		if found {
			rest = append(rest, v)
			continue
		}
		if first == -1 {
			first = v
		} else if second == -1 && first+1 == v {
			second = v
		} else if second != -1 && first+2 == v {
			//flush
			first = -1
			second = -1
			found = true
		} else {
			rest = append(rest, v)
		}
	}
	return rest, found
}

func (a SuitGroup) pairable_numbers() SuitGroup {
	// a is sorted
	counter := []int{}
	x := 999 // 2つ前
	y := 999 // 1つ前
	for _, v := range a {
		if y == v && x != v {
			counter = append(counter, v)
		} else {
			y = v
		}
	}
	return counter
}

func (hand Hand) is_chitoitsu() bool {
	//カウンタ
	c := map[int]int{}

	for _, v := range hand {
		count, ok := c[v]
		if ok {
			if count == 1 {
				c[v] = 2
			} else {
				// c[v] == 2
				return false
			}
		} else {
			c[v] = 1
		}
		//8個チェック
		if len(c) >= 8 {
			return false
		}
	}
	return true
}
<commit_msg>Refactor<commit_after>package tenho

import (
	"fmt"
	"math/rand"
	"sort"
	"time"
)

func Start() {
	start := time.Now()
	// 処理
	var i float64
	i = 0
	for {
		i++
		end := time.Now()
		diff := float64(end.Sub(start) / 1000 / 1000 / 1000)
		m := int(i / diff)
		out := 0
		if m >= 0 {
			out = m
		}
		fmt.Printf("\r")
		fmt.Printf("\r%v回試行  %v秒経過 %v回/秒", i, diff, out)
		seed := time.Now().UnixNano()
		var hai string
		var ok bool
		hai, ok = tryOnce(seed)
		fmt.Printf("%v", hai)
		if ok {
			break
		}
	}
	fmt.Printf("\n")
}

type Hand []int

func tryOnce(seed int64) (string, bool) {
	hand := ShuffledHand(seed)
	hai := hand.HaiString()
	ok := Solve(hand)
	return hai, ok
}

// http://d.hatena.ne.jp/hake/20150930/p1
func shuffle(hand Hand) {
	for i := len(hand); i > 1; i-- {
		j := rand.Intn(i) // 0 .. i-1 の乱数発生
		hand[i-1], hand[j] = hand[j], hand[i-1]
	}
}

func ShuffledHand(seed int64) Hand {
	rand.Seed(seed)

	// データ要素数指定、および初期データ作成
	size := 136
	hand := make(Hand, size, size)
	for i := 0; i < size; i++ {
		hand[i] = i / 4
	}

	// シャッフル
	shuffle(hand)

	return hand[:14]
}

// 牌文字への変換(スペース区切り)
func (c Hand) HaiString() string {
	// http://qiita.com/ruiu/items/2bb83b29baeae2433a79
	// サイズ0、内部バッファの長さ69の[]byteの値を割り当てる
	b := make([]byte, 0, 70)

	// bに文字列を追加
	for j := 0; j < 14; j++ {
		// コードポイント上、普通の麻雀牌はU+1F000からの34個。
		// U+1F000 is 'MAHJONG TILE EAST WIND' ('東')
		// https://codepoints.net/U+1F000
		b = append(b, string(c[j]+0x1F000)...) // appendするには...が必要
		// 自分のMacではスペース区切りでないとうまく表示されないためスペースを挿入する
		// U+0020 is 'SPACE'
		// https://codepoints.net/U+0020
		b = append(b, string(0x20)...) // appendするには...が必要
	}
	return string(b)
}

// 七対子判定
func (hand Hand) is_chitoitsu() bool {
	//カウンタ
	c := map[int]int{}

	for _, v := range hand {
		count, ok := c[v]
		if ok {
			if count == 1 {
				c[v] = 2
			} else {
				// c[v] == 2
				return false
			}
		} else {
			c[v] = 1
		}
		//8個チェック
		if len(c) >= 8 {
			return false
		}
	}
	return true
}

// あがり判定する
func Solve(hand Hand) bool {
	if hand.is_chitoitsu() {
		return true
	}
	suit_grouped_hand := hand.GroupSuit()
	//fmt.Printf("%v", suit_grouped_hand)

	return suit_grouped_hand.Solve()
}

type SuitGroup []int

type SuitsGroupedHand []SuitGroup

// スート分類
func (hand Hand) GroupSuit() SuitsGroupedHand {
	m := SuitsGroupedHand{{}, {}, {}, {}}
	for _, i := range hand {
		switch {
		case i < 7:
			m[0] = append(m[0], i)
		case i < 7+(9*1):
			m[1] = append(m[1], i-7)
		case i < 7+(9*2):
			m[2] = append(m[2], i-7-(9*1))
		case i < 7+(9*3):
			m[3] = append(m[3], i-7-(9*2))
		}
	}
	return m
}

func (m SuitsGroupedHand) Solve() bool {
	return m.a_pair_existible() && m.valid_33332()
}

func (m SuitsGroupedHand) a_pair_existible() bool {
	//スートのサイズを3で割った時
	//あまりが2であるスートグループが1つであること
	c := 0
	for _, a := range m {
		switch len(a) % 3 {
		case 0:
			// noop
		case 1:
			return false
		case 2:
			c++
		}
	}
	return c == 1
}

func (m SuitsGroupedHand) valid_33332() bool {
	for i := 0; i < 4; i++ {
		if !m[i].valid_suit_group(i) {
			return false
		}
	}
	return true
}

// 33332形を形成するスートグループがどうかを判定
func (a SuitGroup) valid_suit_group(i int) bool {
	// 対子が含まれているスートグループがただ1つある前提

	//ソート
	sort.Ints(a)
	if len(a)%3 == 2 {
		//ペアを探す
		pair_numbers := a.pairable_numbers()
		//ペア候補がなかったらぬける
		if len(pair_numbers) == 0 {
			return false
		}
		//ペア候補毎に繰り返し処理
		for _, v := range pair_numbers {
			//ペアとなる２枚を除去
			rest := SuitGroup{}
			c := 2
			for _, w := range a {
				// ペア候補以外は新スライスに入れる
				// ペア候補は３枚目以降は新スライスに入れる
				if w != v || c <= 0 {
					rest = append(rest, w)
				}
				if w == v {
					c--
				}
			}
			if rest.valid_3cards(i) {
				return true
			} else {
				continue
			}
		}
		return false
	} else if len(a)%3 == 0 {
		return a.valid_3cards(i)
	}
	// 到達しないはず
	panic("到達しないはず")
}

func (a SuitGroup) valid_3cards(i int) bool {
	// 刻子や順子のみで構成されている場合true
	// a is sorted
	// a.size % 3 is0
	// 引数は字牌のとき0
	ok := false
	for {
		a, ok = a.remove_kotsu()
		if ok {
			continue
		}
		if i > 0 {
			a, ok = a.remove_shuntsu()
			if ok {
				continue
			}
		}
		return len(a) == 0
	}
}

func (a SuitGroup) remove_kotsu() (SuitGroup, bool) {
	// 刻子を除去できればtrue
	// a is sorted
	retval := a
	if len(a) < 3 {
		return retval, false
	}
	if a[0] == a[1] && a[0] == a[2] {
		retval = a[3:]
		return retval, true
	}
	return retval, false
}

func (a SuitGroup) remove_shuntsu() (SuitGroup, bool) {
	// 順子を除去できればtrue
	// a is sorted
	rest := SuitGroup{}
	first := -1
	second := -1
	found := false
	for _, v := range a {
		if found {
			rest = append(rest, v)
			continue
		}
		if first == -1 {
			first = v
		} else if second == -1 && first+1 == v {
			second = v
		} else if second != -1 && first+2 == v {
			//flush
			first = -1
			second = -1
			found = true
		} else {
			rest = append(rest, v)
		}
	}
	return rest, found
}

func (a SuitGroup) pairable_numbers() SuitGroup {
	// a is sorted
	counter := []int{}
	x := 999 // 2つ前
	y := 999 // 1つ前
	for _, v := range a {
		if y == v && x != v {
			counter = append(counter, v)
		} else {
			y = v
		}
	}
	return counter
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"time"
)

const SUCCESS_EXIT int = 0
const ERROR_EXIT int = 1
const LIMIT_WAIT_COUNT int = 540 // 20sec * 540 = 3 hours
const API_SERVER string = "https://api.vaddy.net"

type StartScan struct {
	ScanID string `json:"scan_id"`
}

type ScanResult struct {
	Status        string `json:"status"`
	AlertCount    int    `json:"alert_count"`
	ScanResultUrl string `json:"scan_result_url"`
}

func main() {
	fmt.Println("==== Start VAddy Scan ====")

	var auth_key, user, fqdn, crawl string = getApiParamsFromArgsOrEnv()

	scan_id := startScan(auth_key, user, fqdn, crawl)

	var wait_count int = 0
	for {
		checkScanResult(auth_key, user, fqdn, scan_id)

		time.Sleep(20 * time.Second) //wait 20 second
		wait_count++
		if wait_count > LIMIT_WAIT_COUNT {
			fmt.Println("Error: time out")
			os.Exit(ERROR_EXIT)
		}
	}
}

func getApiParamsFromArgsOrEnv() (string, string, string, string) {
	var auth_key, user, fqdn, crawl string
	if len(os.Args) < 4 {
		return getArgsFromEnv()
	}

	auth_key = os.Args[1]
	user = os.Args[2]
	fqdn = os.Args[3]
	if len(os.Args) >= 5 {
		crawl = os.Args[4]
	}
	return auth_key, user, fqdn, crawl
}

func getArgsFromEnv() (string, string, string, string) {
	var auth_key, user, fqdn, crawl string
	auth_key, ok1 := os.LookupEnv("VADDY_TOKEN")
	user, ok2 := os.LookupEnv("VADDY_USER")
	fqdn, ok3 := os.LookupEnv("VADDY_HOST")
	crawl, _ = os.LookupEnv("VADDY_CRAWL")

	if !ok1 || !ok2 || !ok3 {
		fmt.Println("Missing arguments or system env.")
		fmt.Println("USAGE: vaddy ApiKey UserId FQDN CrawlID(optional)")
		os.Exit(ERROR_EXIT)
	}
	return auth_key, user, fqdn, crawl
}

func startScan(auth_key string, user string, fqdn string, crawl string) string {
	values := url.Values{}
	values.Add("auth_key", auth_key)
	values.Add("user", user)
	values.Add("fqdn", fqdn)
	values.Add("action", "start")
	if len(crawl) > 0 {
		values.Add("crawl_id", crawl)
	}

	apiServer := getApiServerName()
	res, err := http.PostForm(apiServer+"/v1/scan", values)
	if err != nil {
		fmt.Println(err)
		os.Exit(ERROR_EXIT)
	}
	defer res.Body.Close()
	json_response := getResponseData(res)
	scanId := getScanId(json_response)
	//fmt.Println("scanId: " + scanId)
	return scanId
}

func getScanResult(auth_key string, user string, fqdn string, scan_id string) []byte {
	values := url.Values{}
	values.Add("auth_key", auth_key)
	values.Add("user", user)
	values.Add("fqdn", fqdn)
	values.Add("scan_id", scan_id)

	apiServer := getApiServerName()
	res, err := http.Get(apiServer + "/v1/scan/result?" + values.Encode())
	if err != nil {
		fmt.Println(err)
		os.Exit(ERROR_EXIT)
	}
	defer res.Body.Close()

	json_response := getResponseData(res)
	return json_response
}

func checkScanResult(auth_key string, user string, fqdn string, scan_id string) {
	json_response := getScanResult(auth_key, user, fqdn, scan_id)

	var scan_result ScanResult
	convertJsonToStruct(json_response, &scan_result)

	status := scan_result.Status
	switch status {
	case "scanning":
		fmt.Println(scan_result.Status)
	case "canceled":
		fmt.Println(scan_result.Status)
		os.Exit(ERROR_EXIT)
	case "finish":
		//fmt.Println(string(json_response) + "\n")
		fmt.Println("Server: " + fqdn)
		fmt.Println("scanId: " + scan_id)
		fmt.Println("Result URL: " + scan_result.ScanResultUrl)

		if scan_result.AlertCount > 0 {
			fmt.Print("Vulnerabilities: ")
			fmt.Println(scan_result.AlertCount)
			fmt.Println("Warning!!!")
			os.Exit(ERROR_EXIT)
		} else {
			fmt.Println("Scan Success. No vulnerabilities!")
			os.Exit(SUCCESS_EXIT)
		}
	}
}

func getResponseData(resp *http.Response) []byte {
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(string(body))
		os.Exit(ERROR_EXIT)
	}
	status_code := resp.StatusCode
	//fmt.Println(status_code)
	if status_code != 200 {
		fmt.Println("Network/Auth error\n" + string(body))
		os.Exit(ERROR_EXIT)
	}
	return []byte(body)
}

func getScanId(jsonByteData []byte) string {
	var scan_result StartScan
	convertJsonToStruct(jsonByteData, &scan_result)
	return scan_result.ScanID
}

func convertJsonToStruct(jsonByteData []byte, structData interface{}) {
	err := json.Unmarshal(jsonByteData, structData)
	if err != nil {
		fmt.Println(err)
		os.Exit(ERROR_EXIT)
	}
}

func getApiServerName() string {
	apiserver, ok := os.LookupEnv("VADDY_API_SERVER")
	if ok {
		return apiserver
	}
	return API_SERVER
}
<commit_msg>change package name<commit_after>package vaddy

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"time"
)

const SUCCESS_EXIT int = 0
const ERROR_EXIT int = 1
const LIMIT_WAIT_COUNT int = 540 // 20sec * 540 = 3 hours
const API_SERVER string = "https://api.vaddy.net"

type StartScan struct {
	ScanID string `json:"scan_id"`
}

type ScanResult struct {
	Status        string `json:"status"`
	AlertCount    int    `json:"alert_count"`
	ScanResultUrl string `json:"scan_result_url"`
}

func main() {
	fmt.Println("==== Start VAddy Scan ====")

	var auth_key, user, fqdn, crawl string = getApiParamsFromArgsOrEnv()

	scan_id := startScan(auth_key, user, fqdn, crawl)

	var wait_count int = 0
	for {
		checkScanResult(auth_key, user, fqdn, scan_id)

		time.Sleep(20 * time.Second) //wait 20 second
		wait_count++
		if wait_count > LIMIT_WAIT_COUNT {
			fmt.Println("Error: time out")
			os.Exit(ERROR_EXIT)
		}
	}
}

func getApiParamsFromArgsOrEnv() (string, string, string, string) {
	var auth_key, user, fqdn, crawl string
	if len(os.Args) < 4 {
		return getArgsFromEnv()
	}

	auth_key = os.Args[1]
	user = os.Args[2]
	fqdn = os.Args[3]
	if len(os.Args) >= 5 {
		crawl = os.Args[4]
	}
	return auth_key, user, fqdn, crawl
}

func getArgsFromEnv() (string, string, string, string) {
	var auth_key, user, fqdn, crawl string
	auth_key, ok1 := os.LookupEnv("VADDY_TOKEN")
	user, ok2 := os.LookupEnv("VADDY_USER")
	fqdn, ok3 := os.LookupEnv("VADDY_HOST")
	crawl, _ = os.LookupEnv("VADDY_CRAWL")

	if !ok1 || !ok2 || !ok3 {
		fmt.Println("Missing arguments or system env.")
		fmt.Println("USAGE: vaddy ApiKey UserId FQDN CrawlID(optional)")
		os.Exit(ERROR_EXIT)
	}
	return auth_key, user, fqdn, crawl
}

func startScan(auth_key string, user string, fqdn string, crawl string) string {
	values := url.Values{}
	values.Add("auth_key", auth_key)
	values.Add("user", user)
	values.Add("fqdn", fqdn)
	values.Add("action", "start")
	if len(crawl) > 0 {
		values.Add("crawl_id", crawl)
	}

	apiServer := getApiServerName()
	res, err := http.PostForm(apiServer+"/v1/scan", values)
	if err != nil {
		fmt.Println(err)
		os.Exit(ERROR_EXIT)
	}
	defer res.Body.Close()
	json_response := getResponseData(res)
	scanId := getScanId(json_response)
	//fmt.Println("scanId: " + scanId)
	return scanId
}

func getScanResult(auth_key string, user string, fqdn string, scan_id string) []byte {
	values := url.Values{}
	values.Add("auth_key", auth_key)
	values.Add("user", user)
	values.Add("fqdn", fqdn)
	values.Add("scan_id", scan_id)

	apiServer := getApiServerName()
	res, err := http.Get(apiServer + "/v1/scan/result?" + values.Encode())
	if err != nil {
		fmt.Println(err)
		os.Exit(ERROR_EXIT)
	}
	defer res.Body.Close()

	json_response := getResponseData(res)
	return json_response
}

func checkScanResult(auth_key string, user string, fqdn string, scan_id string) {
	json_response := getScanResult(auth_key, user, fqdn, scan_id)

	var scan_result ScanResult
	convertJsonToStruct(json_response, &scan_result)

	status := scan_result.Status
	switch status {
	case "scanning":
		fmt.Println(scan_result.Status)
	case "canceled":
		fmt.Println(scan_result.Status)
		os.Exit(ERROR_EXIT)
	case "finish":
		//fmt.Println(string(json_response) + "\n")
		fmt.Println("Server: " + fqdn)
		fmt.Println("scanId: " + scan_id)
		fmt.Println("Result URL: " + scan_result.ScanResultUrl)

		if scan_result.AlertCount > 0 {
			fmt.Print("Vulnerabilities: ")
			fmt.Println(scan_result.AlertCount)
			fmt.Println("Warning!!!")
			os.Exit(ERROR_EXIT)
		} else {
			fmt.Println("Scan Success. No vulnerabilities!")
			os.Exit(SUCCESS_EXIT)
		}
	}
}

func getResponseData(resp *http.Response) []byte {
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(string(body))
		os.Exit(ERROR_EXIT)
	}
	status_code := resp.StatusCode
	//fmt.Println(status_code)
	if status_code != 200 {
		fmt.Println("Network/Auth error\n" + string(body))
		os.Exit(ERROR_EXIT)
	}
	return []byte(body)
}

func getScanId(jsonByteData []byte) string {
	var scan_result StartScan
	convertJsonToStruct(jsonByteData, &scan_result)
	return scan_result.ScanID
}

func convertJsonToStruct(jsonByteData []byte, structData interface{}) {
	err := json.Unmarshal(jsonByteData, structData)
	if err != nil {
		fmt.Println(err)
		os.Exit(ERROR_EXIT)
	}
}

func getApiServerName() string {
	apiserver, ok := os.LookupEnv("VADDY_API_SERVER")
	if ok {
		return apiserver
	}
	return API_SERVER
}
<|endoftext|>


<commit_before>package encoding

import (
	"encoding/binary"
)

// EncInt64 encodes an int64 as a slice of 8 bytes.
func EncInt64(i int64) (b []byte) {
	b = make([]byte, 8)
	binary.LittleEndian.PutUint64(b, uint64(i))
	return
}

// DecInt64 decodes a slice of 8 bytes into an int64.
// If len(b) < 8, the slice is padded with zeros.
func DecInt64(b []byte) int64 {
	b2 := b
	if len(b) < 8 {
		b2 = make([]byte, 8)
		copy(b2, b)
	}
	return int64(binary.LittleEndian.Uint64(b2))
}

// EncUint64 encodes a uint64 as a slice of 8 bytes.
func EncUint64(i uint64) (b []byte) {
	b = make([]byte, 8)
	binary.LittleEndian.PutUint64(b, i)
	return
}

// DecUint64 decodes a slice of 8 bytes into a uint64.
// If len(b) < 8, the slice is padded with zeros.
func DecUint64(b []byte) uint64 {
	b2 := b
	if len(b) < 8 {
		b2 = make([]byte, 8)
		copy(b2, b)
	}
	return binary.LittleEndian.Uint64(b2)
}

// EncLen encodes a length (int) as a slice of 4 bytes.
func EncLen(length int) (b []byte) {
	b = make([]byte, 4)
	binary.LittleEndian.PutUint32(b, uint32(length))
	return
}

// DecLen decodes a slice of 4 bytes into an int.
// If len(b) < 8, the slice is padded with zeros.
func DecLen(b []byte) int {
	b2 := b
	if len(b) < 4 {
		b2 = make([]byte, 4)
		copy(b2, b)
	}
	return int(binary.LittleEndian.Uint32(b2))
}
<commit_msg>more concise integer decoding<commit_after>package encoding

import (
	"encoding/binary"
)

// EncInt64 encodes an int64 as a slice of 8 bytes.
func EncInt64(i int64) (b []byte) {
	b = make([]byte, 8)
	binary.LittleEndian.PutUint64(b, uint64(i))
	return
}

// DecInt64 decodes a slice of 8 bytes into an int64.
// If len(b) < 8, the slice is padded with zeros.
func DecInt64(b []byte) int64 {
	b2 := make([]byte, 8)
	copy(b2, b)
	return int64(binary.LittleEndian.Uint64(b2))
}

// EncUint64 encodes a uint64 as a slice of 8 bytes.
func EncUint64(i uint64) (b []byte) {
	b = make([]byte, 8)
	binary.LittleEndian.PutUint64(b, i)
	return
}

// DecUint64 decodes a slice of 8 bytes into a uint64.
// If len(b) < 8, the slice is padded with zeros.
func DecUint64(b []byte) uint64 {
	b2 := make([]byte, 8)
	copy(b2, b)
	return binary.LittleEndian.Uint64(b2)
}

// EncLen encodes a length (int) as a slice of 4 bytes.
func EncLen(length int) (b []byte) {
	b = make([]byte, 4)
	binary.LittleEndian.PutUint32(b, uint32(length))
	return
}

// DecLen decodes a slice of 4 bytes into an int.
// If len(b) < 8, the slice is padded with zeros.
func DecLen(b []byte) int {
	b2 := make([]byte, 4)
	copy(b2, b)
	return int(binary.LittleEndian.Uint32(b2))
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/gorilla/mux"
	"io/ioutil"
	"net/http"
	"strings"
	"wayang/wayang"
)

type Config struct {
	Database        string `json:"db"`
	DatabaseAddress string `json:"db_addr"`
	StaticConf      string `json:"static_conf"`
}

var (
	db wayang.DataStore
)

func main() {

	configPath := flag.String("conf", "./config.json", "Path to configuration file")
	listenAddr := flag.String("laddr", ":8000", "Address to listen on")
	flag.Parse()

	confData, err := ioutil.ReadFile(*configPath)
	if err != nil {
		fmt.Println("Failed to read configuration file:", *configPath)
		return
	}
	config := Config{}

	err = json.Unmarshal(confData, &config)
	if err != nil {
		fmt.Println("Failed to parse configuration file:", *configPath)
		return
	}

	r := mux.NewRouter()
	r.StrictSlash(true)

	if config.Database == "mongodb" {

		db, err = wayang.NewMongoStore(config.DatabaseAddress)
		if err != nil {
			fmt.Println(err)
			return
		}

		r.HandleFunc("/", indexPage).Methods("GET")
		r.HandleFunc("/", newMock).Methods("POST")
		r.HandleFunc("/{id:[0-9a-z]+}", optionsHandlerRoot).Methods("OPTIONS")
		r.HandleFunc("/{id:[0-9a-z]+}/{endpoint:[a-zA-Z0-9/]+}", optionsHandler).Methods("OPTIONS")
		r.HandleFunc("/{id:[0-9a-z]+}", mockRespondRoot).Methods("GET", "POST", "PUT", "PATCH", "DELETE")
		r.HandleFunc("/{id:[0-9a-z]+}/{endpoint:[a-zA-Z0-9/]+}", mockRespond).Methods("GET", "POST", "PUT", "PATCH", "DELETE")

	} else if config.Database == "static" {

		mock := wayang.Mock{}
		mockData, err := ioutil.ReadFile(config.StaticConf)
		if err != nil {
			fmt.Println("Failed to read static configuration file:", config.StaticConf)
			return
		}
		err = json.Unmarshal(mockData, &mock)
		if err != nil {
			fmt.Println("Failed to parse static configuration file:", config.StaticConf)
			return
		}

		db, err = wayang.NewStaticStore(mock)
		if err != nil {
			fmt.Println(err)
			return
		}

		r.HandleFunc("/", optionsHandlerRoot).Methods("OPTIONS")
		r.HandleFunc("/{endpoint:[a-zA-Z0-9/]+}", optionsHandler).Methods("OPTIONS")
		r.HandleFunc("/", mockRespondRoot).Methods("GET", "POST", "PUT", "PATCH", "DELETE")
		r.HandleFunc("/{endpoint:[a-zA-Z0-9/]+}", mockRespond).Methods("GET", "POST", "PUT", "PATCH", "DELETE")

	}
	defer db.Close()

	http.Handle("/", r)
	http.ListenAndServe(*listenAddr, nil)

}

func accessControlAllow(rw http.ResponseWriter, req *http.Request) {
	origin := req.Header.Get("Origin")
	if origin == "" {
		rw.Header().Set("Access-Control-Allow-Origin", "*")
	} else {
		rw.Header().Set("Access-Control-Allow-Origin", origin)
	}
}

func indexPage(rw http.ResponseWriter, req *http.Request) {
	accessControlAllow(rw, req)
	helpMessage := `Hi!
To create an endpoint, do a POST request to the current URL.
The request should contain JSON of the following format:
{
	"/": {
		"GET": {
			"some_key": "some_val"
		},
		"POST": {
			"some_key": {
				"some_other_key": "some_val"
			}
		}
	},
	"/other_endpoint": {
		"DELETE": {
			"key": "value"
		}
	}
}`
	rw.Write([]byte(helpMessage))
}

type NewMockResponse struct {
	Status string `json:"status"`
	Detail string `json:"detail,omitempty"`
	URL    string `json:"url,omitempty"`
}

func newMock(rw http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()
	accessControlAllow(rw, req)
	rw.Header().Set("Content-Type", "application/json")
	resp := NewMockResponse{}

	body, err := ioutil.ReadAll(req.Body)
	if err != nil {
		resp.URL = ""
		resp.Status = http.StatusText(http.StatusInternalServerError)
		resp.Detail = err.Error()
		rv, _ := json.Marshal(resp)
		http.Error(rw, string(rv), http.StatusInternalServerError)
		return
	}
	mock := wayang.Mock{}
	err = json.Unmarshal(body, &mock)
	if err != nil {
		resp.URL = ""
		resp.Status = http.StatusText(http.StatusBadRequest)
		resp.Detail = err.Error()
		rv, _ := json.Marshal(resp)
		http.Error(rw, string(rv), http.StatusBadRequest)
		return
	}

	// Ensure that all routes begin with a /
	for k, v := range mock {
		if k[:1] != "/" {
			mock["/"+k] = v
			delete(mock, k)
		}
	}

	// Ensure that all requests are in the right format
	for k, v := range mock {
		for kk, vv := range v {
			KK := strings.ToUpper(kk)
			if KK != "GET" &&
				KK != "POST" &&
				KK != "PUT" &&
				KK != "PATCH" &&
				KK != "DELETE" {
				resp.URL = ""
				resp.Status = http.StatusText(http.StatusBadRequest)
				resp.Detail = "Invalid key " + kk + " in JSON."
				rv, _ := json.Marshal(resp)
				http.Error(rw, string(rv), http.StatusBadRequest)
				return
			}
			if kk != KK {
				mock[k][KK] = vv
				delete(mock[k], kk)
			}
		}
	}

	fmt.Println(mock)

	id, err := db.NewMock(mock)
	if err != nil {
		resp.URL = ""
		resp.Status = http.StatusText(http.StatusInternalServerError)
		resp.Detail = err.Error()
		rv, _ := json.Marshal(resp)
		http.Error(rw, string(rv), http.StatusInternalServerError)
		return
	} else {
		resp.Status = "200 OK"
	}
	resp.URL = "http://" + req.Host + "/" + id

	rv, _ := json.Marshal(resp)

	rw.Write(rv)
}

func optionsHandlerRoot(rw http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	id := vars["id"]
	endpoint := "/"

	accessControlAllow(rw, req)
	processOptionsResponse(rw, req, id, endpoint)
}

func optionsHandler(rw http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	id := vars["id"]
	endpoint := "/" + vars["endpoint"]

	accessControlAllow(rw, req)
	processOptionsResponse(rw, req, id, endpoint)
}

func processOptionsResponse(rw http.ResponseWriter, req *http.Request, id string, endpoint string) {

	defer req.Body.Close()

	accessControlAllow(rw, req)
	ep, err := db.GetEndpoint(id, endpoint)
	if err != nil {
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}

	var allowedMethods []string
	allowedMethods = append(allowedMethods, "OPTIONS")
	for k, _ := range ep {
		allowedMethods = append(allowedMethods, k)
	}

	csv := strings.Join(allowedMethods, ",")
	rw.Header().Set("Allow", csv)
	rw.Header().Set("Access-Control-Allow-Methods", csv)

}

func mockRespondRoot(rw http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	id := vars["id"]
	endpoint := "/"

	accessControlAllow(rw, req)
	processEndpointResponse(rw, req, id, endpoint)
}

func mockRespond(rw http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	id := vars["id"]
	endpoint := "/" + vars["endpoint"]

	accessControlAllow(rw, req)
	processEndpointResponse(rw, req, id, endpoint)
}

func processEndpointResponse(rw http.ResponseWriter, req *http.Request, id string, endpoint string) {

	defer req.Body.Close()

	accessControlAllow(rw, req)
	ep, err := db.GetEndpoint(id, endpoint)
	if err != nil {
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}

	rw.Header().Set("Content-Type", "application/json")
	mockResponse := ep[req.Method]

	if len(mockResponse) == 0 {
		http.Error(rw, http.StatusText(http.StatusNotImplemented), http.StatusNotImplemented)
		return
	}

	rv, _ := json.Marshal(mockResponse)
	rw.Write([]byte(rv))

}
<commit_msg>Allow HTTP prefix matching.<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/gorilla/mux"
	"io/ioutil"
	"net/http"
	"strings"
	"wayang/wayang"
)

type Config struct {
	HTTPPrefix      string `json:"http_prefix"`
	Database        string `json:"db"`
	DatabaseAddress string `json:"db_addr"`
	StaticConf      string `json:"static_conf"`
}

var (
	db wayang.DataStore
)

func main() {

	configPath := flag.String("conf", "./config.json", "Path to configuration file")
	listenAddr := flag.String("laddr", ":8000", "Address to listen on")
	flag.Parse()

	confData, err := ioutil.ReadFile(*configPath)
	if err != nil {
		fmt.Println("Failed to read configuration file:", *configPath)
		return
	}
	config := Config{}
	config.HTTPPrefix = ""

	err = json.Unmarshal(confData, &config)
	if err != nil {
		fmt.Println("Failed to parse configuration file:", *configPath)
		return
	}

	r := mux.NewRouter()
	r.StrictSlash(true)

	if config.Database == "mongodb" {

		db, err = wayang.NewMongoStore(config.DatabaseAddress)
		if err != nil {
			fmt.Println(err)
			return
		}

		r.HandleFunc(config.HTTPPrefix+"/", indexPage).Methods("GET")
		r.HandleFunc(config.HTTPPrefix+"/", newMock).Methods("POST")
		r.HandleFunc(config.HTTPPrefix+"/{id:[0-9a-z]+}", optionsHandlerRoot).Methods("OPTIONS")
		r.HandleFunc(config.HTTPPrefix+"/{id:[0-9a-z]+}/{endpoint:[a-zA-Z0-9/]+}", optionsHandler).Methods("OPTIONS")
		r.HandleFunc(config.HTTPPrefix+"/{id:[0-9a-z]+}", mockRespondRoot).Methods("GET", "POST", "PUT", "PATCH", "DELETE")
		r.HandleFunc(config.HTTPPrefix+"/{id:[0-9a-z]+}/{endpoint:[a-zA-Z0-9/]+}", mockRespond).Methods("GET", "POST", "PUT", "PATCH", "DELETE")

	} else if config.Database == "static" {

		mock := wayang.Mock{}
		mockData, err := ioutil.ReadFile(config.StaticConf)
		if err != nil {
			fmt.Println("Failed to read static configuration file:", config.StaticConf)
			return
		}
		err = json.Unmarshal(mockData, &mock)
		if err != nil {
			fmt.Println("Failed to parse static configuration file:", config.StaticConf)
			return
		}

		db, err = wayang.NewStaticStore(mock)
		if err != nil {
			fmt.Println(err)
			return
		}

		r.HandleFunc(config.HTTPPrefix+"/", optionsHandlerRoot).Methods("OPTIONS")
		r.HandleFunc(config.HTTPPrefix+"/{endpoint:[a-zA-Z0-9/]+}", optionsHandler).Methods("OPTIONS")
		r.HandleFunc(config.HTTPPrefix+"/", mockRespondRoot).Methods("GET", "POST", "PUT", "PATCH", "DELETE")
		r.HandleFunc(config.HTTPPrefix+"/{endpoint:[a-zA-Z0-9/]+}", mockRespond).Methods("GET", "POST", "PUT", "PATCH", "DELETE")

	}
	defer db.Close()

	http.Handle("/", r)
	http.ListenAndServe(*listenAddr, nil)

}

func accessControlAllow(rw http.ResponseWriter, req *http.Request) {
	origin := req.Header.Get("Origin")
	if origin == "" {
		rw.Header().Set("Access-Control-Allow-Origin", "*")
	} else {
		rw.Header().Set("Access-Control-Allow-Origin", origin)
	}
}

func indexPage(rw http.ResponseWriter, req *http.Request) {
	accessControlAllow(rw, req)
	helpMessage := `Hi!
To create an endpoint, do a POST request to the current URL.
The request should contain JSON of the following format:
{
	"/": {
		"GET": {
			"some_key": "some_val"
		},
		"POST": {
			"some_key": {
				"some_other_key": "some_val"
			}
		}
	},
	"/other_endpoint": {
		"DELETE": {
			"key": "value"
		}
	}
}`
	rw.Write([]byte(helpMessage))
}

type NewMockResponse struct {
	Status string `json:"status"`
	Detail string `json:"detail,omitempty"`
	URL    string `json:"url,omitempty"`
}

func newMock(rw http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()
	accessControlAllow(rw, req)
	rw.Header().Set("Content-Type", "application/json")
	resp := NewMockResponse{}

	body, err := ioutil.ReadAll(req.Body)
	if err != nil {
		resp.URL = ""
		resp.Status = http.StatusText(http.StatusInternalServerError)
		resp.Detail = err.Error()
		rv, _ := json.Marshal(resp)
		http.Error(rw, string(rv), http.StatusInternalServerError)
		return
	}
	mock := wayang.Mock{}
	err = json.Unmarshal(body, &mock)
	if err != nil {
		resp.URL = ""
		resp.Status = http.StatusText(http.StatusBadRequest)
		resp.Detail = err.Error()
		rv, _ := json.Marshal(resp)
		http.Error(rw, string(rv), http.StatusBadRequest)
		return
	}

	// Ensure that all routes begin with a /
	for k, v := range mock {
		if k[:1] != "/" {
			mock["/"+k] = v
			delete(mock, k)
		}
	}

	// Ensure that all requests are in the right format
	for k, v := range mock {
		for kk, vv := range v {
			KK := strings.ToUpper(kk)
			if KK != "GET" &&
				KK != "POST" &&
				KK != "PUT" &&
				KK != "PATCH" &&
				KK != "DELETE" {
				resp.URL = ""
				resp.Status = http.StatusText(http.StatusBadRequest)
				resp.Detail = "Invalid key " + kk + " in JSON."
				rv, _ := json.Marshal(resp)
				http.Error(rw, string(rv), http.StatusBadRequest)
				return
			}
			if kk != KK {
				mock[k][KK] = vv
				delete(mock[k], kk)
			}
		}
	}

	fmt.Println(mock)

	id, err := db.NewMock(mock)
	if err != nil {
		resp.URL = ""
		resp.Status = http.StatusText(http.StatusInternalServerError)
		resp.Detail = err.Error()
		rv, _ := json.Marshal(resp)
		http.Error(rw, string(rv), http.StatusInternalServerError)
		return
	} else {
		resp.Status = "200 OK"
	}
	resp.URL = "http://" + req.Host + "/" + id

	rv, _ := json.Marshal(resp)

	rw.Write(rv)
}

func optionsHandlerRoot(rw http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	id := vars["id"]
	endpoint := "/"

	accessControlAllow(rw, req)
	processOptionsResponse(rw, req, id, endpoint)
}

func optionsHandler(rw http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	id := vars["id"]
	endpoint := "/" + vars["endpoint"]

	accessControlAllow(rw, req)
	processOptionsResponse(rw, req, id, endpoint)
}

func processOptionsResponse(rw http.ResponseWriter, req *http.Request, id string, endpoint string) {

	defer req.Body.Close()

	accessControlAllow(rw, req)
	ep, err := db.GetEndpoint(id, endpoint)
	if err != nil {
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}

	var allowedMethods []string
	allowedMethods = append(allowedMethods, "OPTIONS")
	for k, _ := range ep {
		allowedMethods = append(allowedMethods, k)
	}

	csv := strings.Join(allowedMethods, ",")
	rw.Header().Set("Allow", csv)
	rw.Header().Set("Access-Control-Allow-Methods", csv)

}

func mockRespondRoot(rw http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	id := vars["id"]
	endpoint := "/"

	accessControlAllow(rw, req)
	processEndpointResponse(rw, req, id, endpoint)
}

func mockRespond(rw http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	id := vars["id"]
	endpoint := "/" + vars["endpoint"]

	accessControlAllow(rw, req)
	processEndpointResponse(rw, req, id, endpoint)
}

func processEndpointResponse(rw http.ResponseWriter, req *http.Request, id string, endpoint string) {

	defer req.Body.Close()

	accessControlAllow(rw, req)
	ep, err := db.GetEndpoint(id, endpoint)
	if err != nil {
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}

	rw.Header().Set("Content-Type", "application/json")
	mockResponse := ep[req.Method]

	if len(mockResponse) == 0 {
		http.Error(rw, http.StatusText(http.StatusNotImplemented), http.StatusNotImplemented)
		return
	}

	rv, _ := json.Marshal(mockResponse)
	rw.Write([]byte(rv))

}
<|endoftext|>


<commit_before>package eval

import (
	"errors"
	"fmt"
	"os"
	"syscall"

	"github.com/elves/elvish/util"
)

// FdNil is a special impossible fd value used for "close fd" in
// syscall.ProcAttr.Files.
const fdNil uintptr = ^uintptr(0)

var ErrCdNoArg = errors.New("implicit cd accepts no arguments")

// ExternalCmd is an external command.
type ExternalCmd struct {
	Name string
}

func (ExternalCmd) Kind() string {
	return "fn"
}

func (e ExternalCmd) Repr(int) string {
	return "<external " + e.Name + " >"
}

// Call calls an external command.
func (e ExternalCmd) Call(ec *EvalCtx, argVals []Value) {
	if util.DontSearch(e.Name) {
		stat, err := os.Stat(e.Name)
		if err == nil && stat.IsDir() {
			// implicit cd
			if len(argVals) > 0 {
				throw(ErrCdNoArg)
			}
			cdInner(e.Name, ec)
			return
		}
	}

	files := make([]uintptr, len(ec.ports))
	for i, port := range ec.ports {
		if port == nil || port.File == nil {
			files[i] = fdNil
		} else {
			files[i] = port.File.Fd()
		}
	}

	args := make([]string, len(argVals)+1)
	for i, a := range argVals {
		// NOTE Maybe we should enfore string arguments instead of coercing all
		// args into string
		args[i+1] = ToString(a)
	}

	sys := syscall.SysProcAttr{}
	if ec.Stub != nil && ec.Stub.Alive() {
		sys.Setpgid = true
		sys.Pgid = ec.Stub.Process().Pid
	}
	attr := syscall.ProcAttr{Env: os.Environ(), Files: files[:], Sys: &sys}

	path, err := ec.Search(e.Name)
	if err != nil {
		throw(err)
	}

	// XXX Discard all channel inputs, so that writes from the previous form in
	// the pipeline don't block.
	stopDiscard := make(chan struct{})
	if ec.ports[0].Chan != nil {
		ch := ec.ports[0].Chan
		go func() {
			for {
				select {
				case <-ch:
				case <-stopDiscard:
					return
				}
			}
		}()
	}

	args[0] = path
	pid, err := syscall.ForkExec(path, args, &attr)
	if err != nil {
		throw(errors.New("forkExec: " + err.Error()))
	}

	var ws syscall.WaitStatus
	_, err = syscall.Wait4(pid, &ws, syscall.WUNTRACED, nil)
	close(stopDiscard)

	if err != nil {
		throw(fmt.Errorf("wait: %s", err.Error()))
	} else {
		maybeThrow(NewExternalCmdExit(ws, pid))
	}
}
<commit_msg>In ExternalCmd.Call, don't loop forever after input channel gets closed.<commit_after>package eval

import (
	"errors"
	"fmt"
	"os"
	"syscall"

	"github.com/elves/elvish/util"
)

// FdNil is a special impossible fd value used for "close fd" in
// syscall.ProcAttr.Files.
const fdNil uintptr = ^uintptr(0)

var ErrCdNoArg = errors.New("implicit cd accepts no arguments")

// ExternalCmd is an external command.
type ExternalCmd struct {
	Name string
}

func (ExternalCmd) Kind() string {
	return "fn"
}

func (e ExternalCmd) Repr(int) string {
	return "<external " + e.Name + " >"
}

// Call calls an external command.
func (e ExternalCmd) Call(ec *EvalCtx, argVals []Value) {
	if util.DontSearch(e.Name) {
		stat, err := os.Stat(e.Name)
		if err == nil && stat.IsDir() {
			// implicit cd
			if len(argVals) > 0 {
				throw(ErrCdNoArg)
			}
			cdInner(e.Name, ec)
			return
		}
	}

	files := make([]uintptr, len(ec.ports))
	for i, port := range ec.ports {
		if port == nil || port.File == nil {
			files[i] = fdNil
		} else {
			files[i] = port.File.Fd()
		}
	}

	args := make([]string, len(argVals)+1)
	for i, a := range argVals {
		// NOTE Maybe we should enfore string arguments instead of coercing all
		// args into string
		args[i+1] = ToString(a)
	}

	sys := syscall.SysProcAttr{}
	if ec.Stub != nil && ec.Stub.Alive() {
		sys.Setpgid = true
		sys.Pgid = ec.Stub.Process().Pid
	}
	attr := syscall.ProcAttr{Env: os.Environ(), Files: files[:], Sys: &sys}

	path, err := ec.Search(e.Name)
	if err != nil {
		throw(err)
	}

	// XXX Discard all channel inputs, so that writes from the previous form in
	// the pipeline don't block.
	stopDiscard := make(chan struct{})
	if ec.ports[0].Chan != nil {
		ch := ec.ports[0].Chan
		go func() {
			for {
				select {
				case v := <-ch:
					if v == nil {
						return
					}
				case <-stopDiscard:
					return
				}
			}
		}()
	}

	args[0] = path
	pid, err := syscall.ForkExec(path, args, &attr)
	if err != nil {
		throw(errors.New("forkExec: " + err.Error()))
	}

	var ws syscall.WaitStatus
	_, err = syscall.Wait4(pid, &ws, syscall.WUNTRACED, nil)
	close(stopDiscard)

	if err != nil {
		throw(fmt.Errorf("wait: %s", err.Error()))
	} else {
		maybeThrow(NewExternalCmdExit(ws, pid))
	}
}
<|endoftext|>


<commit_before>package peergrouper_test

import (
	"testing"

	gc "launchpad.net/gocheck"

	coretesting "launchpad.net/juju-core/testing"
	"launchpad.net/juju-core/testing/testbase"
	"launchpad.net/juju-core/worker/peergrouper"
)

func Test(t *testing.T) { gc.TestingT(t) }

type InitiateSuite struct {
	testbase.LoggingSuite
}

var _ = gc.Suite(&InitiateSuite{})

// TODO(natefinch) add a test that InitiateMongoServer works when
// we support upgrading of existing environments.

func (s *InitiateSuite) TestInitiateReplicaSet(c *gc.C) {
	var err error
	inst := &coretesting.MgoInstance{Params: []string{"--replSet", "juju"}}
	err = inst.Start(true)
	c.Assert(err, gc.IsNil)

	info := inst.DialInfo()

	err = peergrouper.MaybeInitiateMongoServer(peergrouper.InitiateMongoParams{
		DialInfo:       info,
		MemberHostPort: inst.Addr(),
	})
	c.Assert(err, gc.IsNil)

	// This would return a mgo.QueryError if a ReplicaSet
	// configuration already existed but we tried to created
	// one with replicaset.Initiate again.
	err = peergrouper.MaybeInitiateMongoServer(peergrouper.InitiateMongoParams{
		DialInfo:       info,
		MemberHostPort: inst.Addr(),
	})
	c.Assert(err, gc.IsNil)

	// TODO test login
}
<commit_msg>worker/peergrouper: remove spurious TestingT call<commit_after>package peergrouper_test

import (
	gc "launchpad.net/gocheck"

	coretesting "launchpad.net/juju-core/testing"
	"launchpad.net/juju-core/testing/testbase"
	"launchpad.net/juju-core/worker/peergrouper"
)

type InitiateSuite struct {
	testbase.LoggingSuite
}

var _ = gc.Suite(&InitiateSuite{})

// TODO(natefinch) add a test that InitiateMongoServer works when
// we support upgrading of existing environments.

func (s *InitiateSuite) TestInitiateReplicaSet(c *gc.C) {
	var err error
	inst := &coretesting.MgoInstance{Params: []string{"--replSet", "juju"}}
	err = inst.Start(true)
	c.Assert(err, gc.IsNil)

	info := inst.DialInfo()

	err = peergrouper.MaybeInitiateMongoServer(peergrouper.InitiateMongoParams{
		DialInfo:       info,
		MemberHostPort: inst.Addr(),
	})
	c.Assert(err, gc.IsNil)

	// This would return a mgo.QueryError if a ReplicaSet
	// configuration already existed but we tried to created
	// one with replicaset.Initiate again.
	err = peergrouper.MaybeInitiateMongoServer(peergrouper.InitiateMongoParams{
		DialInfo:       info,
		MemberHostPort: inst.Addr(),
	})
	c.Assert(err, gc.IsNil)

	// TODO test login
}
<|endoftext|>


<commit_before>package xmpp

import (
	"bytes"
	"encoding/xml"
	"fmt"
)

const (
	IQTypeGet    = "get"
	IQTypeSet    = "set"
	IQTypeResult = "result"
	IQTypeError  = "error"

	MessageTypeNormal = "normal"
	MessageTypeChat   = "chat"
	MessageTypeError  = "error"
)

// XMPP <iq/> stanza.
type Iq struct {
	XMLName xml.Name `xml:"iq"`
	Id      string   `xml:"id,attr"`
	Type    string   `xml:"type,attr"`
	To      string   `xml:"to,attr,omitempty"`
	From    string   `xml:"from,attr,omitempty"`
	Payload string   `xml:",innerxml"`
	Error   *Error   `xml:"error"`
}

// Encode the value to an XML string and set as the payload. See xml.Marshal
// for how the value is encoded.
func (iq *Iq) PayloadEncode(v interface{}) error {
	bytes, err := xml.Marshal(v)
	if err != nil {
		return err
	}
	iq.Payload = string(bytes)
	return nil
}

// Decode the payload (an XML string) into the given value. See xml.Unmarshal
// for how the value is decoded.
func (iq *Iq) PayloadDecode(v interface{}) error {
	return xml.Unmarshal([]byte(iq.Payload), v)
}

// Return the name of the payload element.
func (iq *Iq) PayloadName() (name xml.Name) {
	dec := xml.NewDecoder(bytes.NewBufferString(iq.Payload))
	tok, err := dec.Token()
	if err != nil {
		return
	}
	start, ok := tok.(xml.StartElement)
	if !ok {
		return
	}
	return start.Name
}

// Create a response Iq. The Id is kept, To and From are reversed, Type is set
// to the given value.
func (iq *Iq) Response(type_ string) *Iq {
	return &Iq{Id: iq.Id, Type: type_, From: iq.To, To: iq.From}
}

// XMPP <message/> stanza.
type Message struct {
	XMLName xml.Name `xml:"message"`
	Id      string   `xml:"id,attr,omitempty"`
	Type    string   `xml:"type,attr,omitempty"`
	To      string   `xml:"to,attr,omitempty"`
	From    string   `xml:"from,attr,omitempty"`
	Subject string   `xml:"subject,omitempty"`
	Body    string   `xml:"body,omitempty"`
	Thread  string   `xml:"thread,omitempty"`
	Error   *Error   `xml:"error"`
	Confir  *Confirm `xml:"confirm"`
}

// XMPP <presence/> stanza.
type Presence struct {
	XMLName xml.Name `xml:"presence"`
	Id      string   `xml:"id,attr,omitempty"`
	Type    string   `xml:"type,attr,omitempty"`
	To      string   `xml:"to,attr,omitempty"`
	From    string   `xml:"from,attr,omitempty"`
	Show    string   `xml:"show"`            // away, chat, dnd, xa
	Status  string   `xml:"status"`          // sb []clientText
	Photo   string   `xml:"photo,omitempty"` // Avatar
	Nick    string   `xml:"nick,omitempty"`  // Nickname
}

// XMPP <error/>. May occur as a top-level stanza or embedded in another
// stanza, e.g. an <iq type="error"/>.
type Error struct {
	XMLName xml.Name `xml:"error"`
	Type    string   `xml:"type,attr"`
	Payload string   `xml:",innerxml"`
}

func (e Error) Error() string {
	if text := e.Text(); text == "" {
		return fmt.Sprintf("[%s] %s", e.Type, e.Condition().Local)
	} else {
		return fmt.Sprintf("[%s] %s, %s", e.Type, e.Condition().Local, text)
	}
	panic("unreachable")
}

type errorText struct {
	XMLName xml.Name
	Text    string `xml:",chardata"`
}

// Create a new Error instance using the args as the payload.
func NewError(errorType string, condition ErrorCondition, text string) *Error {

	// Build payload.
	buf := new(bytes.Buffer)
	writeXMLStartElement(buf, &xml.StartElement{
		Name: xml.Name{"", condition.Local},
		Attr: []xml.Attr{
			{xml.Name{"", "xmlns"}, condition.Space},
		},
	})
	writeXMLEndElement(buf, &xml.EndElement{Name: xml.Name{"", condition.Local}})
	enc := xml.NewEncoder(buf)
	if text != "" {
		enc.Encode(errorText{xml.Name{condition.Space, "text"}, text})
	}

	return &Error{Type: errorType, Payload: string(buf.Bytes())}
}

// Return the error text from the payload, or "" if not present.
func (e Error) Text() string {
	dec := xml.NewDecoder(bytes.NewBufferString(e.Payload))
	next := startElementIter(dec)
	for start := next(); start != nil; {
		if start.Name.Local == "text" {
			text := errorText{}
			dec.DecodeElement(&text, start)
			return text.Text
		}
		dec.Skip()
		start = next()
	}
	return ""
}

// Return the error condition from the payload.
func (e Error) Condition() ErrorCondition {
	dec := xml.NewDecoder(bytes.NewBufferString(e.Payload))
	next := startElementIter(dec)
	for start := next(); start != nil; {
		if start.Name.Local != "text" && (start.Name.Space == nsErrorStanzas || start.Name.Space == nsErrorStreams) {
			return ErrorCondition(start.Name)
		}
		dec.Skip()
		start = next()
	}
	return ErrorCondition{}
}

// Error condition.
type ErrorCondition xml.Name

// Stanza errors.
var (
	FeatureNotImplemented = ErrorCondition{nsErrorStanzas, "feature-not-implemented"}
	RemoteServerNotFound  = ErrorCondition{nsErrorStanzas, "remote-server-not-found"}
	ServiceUnavailable    = ErrorCondition{nsErrorStanzas, "service-unavailable"}
)
<commit_msg>Add not authorized error condition<commit_after>package xmpp

import (
	"bytes"
	"encoding/xml"
	"fmt"
)

const (
	IQTypeGet    = "get"
	IQTypeSet    = "set"
	IQTypeResult = "result"
	IQTypeError  = "error"

	MessageTypeNormal = "normal"
	MessageTypeChat   = "chat"
	MessageTypeError  = "error"
)

// XMPP <iq/> stanza.
type Iq struct {
	XMLName xml.Name `xml:"iq"`
	Id      string   `xml:"id,attr"`
	Type    string   `xml:"type,attr"`
	To      string   `xml:"to,attr,omitempty"`
	From    string   `xml:"from,attr,omitempty"`
	Payload string   `xml:",innerxml"`
	Error   *Error   `xml:"error"`
}

// Encode the value to an XML string and set as the payload. See xml.Marshal
// for how the value is encoded.
func (iq *Iq) PayloadEncode(v interface{}) error {
	bytes, err := xml.Marshal(v)
	if err != nil {
		return err
	}
	iq.Payload = string(bytes)
	return nil
}

// Decode the payload (an XML string) into the given value. See xml.Unmarshal
// for how the value is decoded.
func (iq *Iq) PayloadDecode(v interface{}) error {
	return xml.Unmarshal([]byte(iq.Payload), v)
}

// Return the name of the payload element.
func (iq *Iq) PayloadName() (name xml.Name) {
	dec := xml.NewDecoder(bytes.NewBufferString(iq.Payload))
	tok, err := dec.Token()
	if err != nil {
		return
	}
	start, ok := tok.(xml.StartElement)
	if !ok {
		return
	}
	return start.Name
}

// Create a response Iq. The Id is kept, To and From are reversed, Type is set
// to the given value.
func (iq *Iq) Response(type_ string) *Iq {
	return &Iq{Id: iq.Id, Type: type_, From: iq.To, To: iq.From}
}

// XMPP <message/> stanza.
type Message struct {
	XMLName xml.Name `xml:"message"`
	Id      string   `xml:"id,attr,omitempty"`
	Type    string   `xml:"type,attr,omitempty"`
	To      string   `xml:"to,attr,omitempty"`
	From    string   `xml:"from,attr,omitempty"`
	Subject string   `xml:"subject,omitempty"`
	Body    string   `xml:"body,omitempty"`
	Thread  string   `xml:"thread,omitempty"`
	Error   *Error   `xml:"error"`
	Confir  *Confirm `xml:"confirm"`
}

// XMPP <presence/> stanza.
type Presence struct {
	XMLName xml.Name `xml:"presence"`
	Id      string   `xml:"id,attr,omitempty"`
	Type    string   `xml:"type,attr,omitempty"`
	To      string   `xml:"to,attr,omitempty"`
	From    string   `xml:"from,attr,omitempty"`
	Show    string   `xml:"show"`            // away, chat, dnd, xa
	Status  string   `xml:"status"`          // sb []clientText
	Photo   string   `xml:"photo,omitempty"` // Avatar
	Nick    string   `xml:"nick,omitempty"`  // Nickname
}

// XMPP <error/>. May occur as a top-level stanza or embedded in another
// stanza, e.g. an <iq type="error"/>.
type Error struct {
	XMLName xml.Name `xml:"error"`
	Type    string   `xml:"type,attr"`
	Payload string   `xml:",innerxml"`
}

func (e Error) Error() string {
	if text := e.Text(); text == "" {
		return fmt.Sprintf("[%s] %s", e.Type, e.Condition().Local)
	} else {
		return fmt.Sprintf("[%s] %s, %s", e.Type, e.Condition().Local, text)
	}
	panic("unreachable")
}

type errorText struct {
	XMLName xml.Name
	Text    string `xml:",chardata"`
}

// Create a new Error instance using the args as the payload.
func NewError(errorType string, condition ErrorCondition, text string) *Error {

	// Build payload.
	buf := new(bytes.Buffer)
	writeXMLStartElement(buf, &xml.StartElement{
		Name: xml.Name{"", condition.Local},
		Attr: []xml.Attr{
			{xml.Name{"", "xmlns"}, condition.Space},
		},
	})
	writeXMLEndElement(buf, &xml.EndElement{Name: xml.Name{"", condition.Local}})
	enc := xml.NewEncoder(buf)
	if text != "" {
		enc.Encode(errorText{xml.Name{condition.Space, "text"}, text})
	}

	return &Error{Type: errorType, Payload: string(buf.Bytes())}
}

// Return the error text from the payload, or "" if not present.
func (e Error) Text() string {
	dec := xml.NewDecoder(bytes.NewBufferString(e.Payload))
	next := startElementIter(dec)
	for start := next(); start != nil; {
		if start.Name.Local == "text" {
			text := errorText{}
			dec.DecodeElement(&text, start)
			return text.Text
		}
		dec.Skip()
		start = next()
	}
	return ""
}

// Return the error condition from the payload.
func (e Error) Condition() ErrorCondition {
	dec := xml.NewDecoder(bytes.NewBufferString(e.Payload))
	next := startElementIter(dec)
	for start := next(); start != nil; {
		if start.Name.Local != "text" && (start.Name.Space == nsErrorStanzas || start.Name.Space == nsErrorStreams) {
			return ErrorCondition(start.Name)
		}
		dec.Skip()
		start = next()
	}
	return ErrorCondition{}
}

// Error condition.
type ErrorCondition xml.Name

// Stanza errors.
var (
	FeatureNotImplemented = ErrorCondition{nsErrorStanzas, "feature-not-implemented"}
	RemoteServerNotFound  = ErrorCondition{nsErrorStanzas, "remote-server-not-found"}
	ServiceUnavailable    = ErrorCondition{nsErrorStanzas, "service-unavailable"}
	NotAuthorized         = ErrorCondition{nsErrorStanzas, "not-authorized"}
)
<|endoftext|>


<commit_before>package rest

import "socialapi/models"

func CreateAccount(a *models.Account) (*models.Account, error) {
	a.Nick = a.OldId
	acc, err := sendModel("POST", "/account", a)
	if err != nil {
		return nil, err
	}

	return acc.(*models.Account), nil
}
<commit_msg>Social: add method to create account in mongo & pg<commit_after>package rest

import (
	kodingmodels "koding/db/models"
	"koding/db/mongodb/modelhelper"
	"labix.org/v2/mgo/bson"
	"socialapi/models"
)

func CreateAccount(a *models.Account) (*models.Account, error) {
	a.Nick = a.OldId
	acc, err := sendModel("POST", "/account", a)
	if err != nil {
		return nil, err
	}

	return acc.(*models.Account), nil
}

func CreateAccountInBothDbs() (*models.Account, error) {
	accId := bson.NewObjectId()
	accHex := accId.Hex()

	oldAcc := &kodingmodels.Account{
		Id: accId,
		Profile: struct {
			Nickname  string `bson:"nickname"`
			FirstName string `bson:"firstName"`
			LastName  string `bson:"lastName"`
			Hash      string `bson:"hash"`
		}{
			Nickname: accHex,
		},
	}

	err := modelhelper.CreateAccount(oldAcc)
	if err != nil {
		return nil, err
	}

	oldUser := &kodingmodels.User{
		ObjectId:       bson.NewObjectId(),
		Password:       accHex,
		Salt:           accHex,
		Name:           accHex,
		Email:          accHex,
		EmailFrequency: kodingmodels.EmailFrequency{},
	}

	err = modelhelper.CreateUser(oldUser)
	if err != nil {
		return nil, err
	}

	a := models.NewAccount()
	a.Nick = accHex
	a.OldId = accHex

	acc, err := sendModel("POST", "/account", a)

	if err != nil {
		return nil, err
	}

	return acc.(*models.Account), nil
}
<|endoftext|>


<commit_before>package metainfo

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/anacrolix/torrent/bencode"
)

func testFileNodesMatch(t *testing.T, file string, nodes []Node) {
	mi, err := LoadFromFile(file)
	require.NoError(t, err)
	assert.EqualValues(t, nodes, mi.Nodes)
}

func TestNodesListStrings(t *testing.T) {
	testFileNodesMatch(t, "testdata/trackerless.torrent", []Node{
		"udp://tracker.openbittorrent.com:80",
		"udp://tracker.openbittorrent.com:80",
	})
}

func TestNodesListPairsBEP5(t *testing.T) {
	testFileNodesMatch(t, "testdata/issue_65a.torrent", []Node{
		"185.34.3.132:5680",
		"185.34.3.103:12340",
		"94.209.253.165:47232",
		"78.46.103.11:34319",
		"195.154.162.70:55011",
		"185.34.3.137:3732",
	})
	testFileNodesMatch(t, "testdata/issue_65b.torrent", []Node{
		"95.211.203.130:6881",
		"84.72.116.169:6889",
		"204.83.98.77:7000",
		"101.187.175.163:19665",
		"37.187.118.32:6881",
		"83.128.223.71:23865",
	})
}

func testMarshalMetainfo(t *testing.T, expected string, mi MetaInfo) {
	b, err := bencode.Marshal(mi)
	assert.NoError(t, err)
	assert.EqualValues(t, expected, string(b))
}

func TestMarshalMetainfoNodes(t *testing.T) {
	testMarshalMetainfo(t, "d4:infod4:name0:12:piece lengthi0e6:piecesleee", MetaInfo{})
	testMarshalMetainfo(t, "d4:infod4:name0:12:piece lengthi0e6:pieceslee5:nodesl12:1.2.3.4:555514:not a hostportee", MetaInfo{
		Nodes: []Node{"1.2.3.4:5555", "not a hostport"},
	})
}
<commit_msg>metainfo: Check for error unmarshalling bad nodes contents from a metainfo<commit_after>package metainfo

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/anacrolix/torrent/bencode"
)

func testFileNodesMatch(t *testing.T, file string, nodes []Node) {
	mi, err := LoadFromFile(file)
	require.NoError(t, err)
	assert.EqualValues(t, nodes, mi.Nodes)
}

func TestNodesListStrings(t *testing.T) {
	testFileNodesMatch(t, "testdata/trackerless.torrent", []Node{
		"udp://tracker.openbittorrent.com:80",
		"udp://tracker.openbittorrent.com:80",
	})
}

func TestNodesListPairsBEP5(t *testing.T) {
	testFileNodesMatch(t, "testdata/issue_65a.torrent", []Node{
		"185.34.3.132:5680",
		"185.34.3.103:12340",
		"94.209.253.165:47232",
		"78.46.103.11:34319",
		"195.154.162.70:55011",
		"185.34.3.137:3732",
	})
	testFileNodesMatch(t, "testdata/issue_65b.torrent", []Node{
		"95.211.203.130:6881",
		"84.72.116.169:6889",
		"204.83.98.77:7000",
		"101.187.175.163:19665",
		"37.187.118.32:6881",
		"83.128.223.71:23865",
	})
}

func testMarshalMetainfo(t *testing.T, expected string, mi MetaInfo) {
	b, err := bencode.Marshal(mi)
	assert.NoError(t, err)
	assert.EqualValues(t, expected, string(b))
}

func TestMarshalMetainfoNodes(t *testing.T) {
	testMarshalMetainfo(t, "d4:infod4:name0:12:piece lengthi0e6:piecesleee", MetaInfo{})
	testMarshalMetainfo(t, "d4:infod4:name0:12:piece lengthi0e6:pieceslee5:nodesl12:1.2.3.4:555514:not a hostportee", MetaInfo{
		Nodes: []Node{"1.2.3.4:5555", "not a hostport"},
	})
}

func TestUnmarshalBadMetainfoNodes(t *testing.T) {
	var mi MetaInfo
	// Should barf on the integer in the nodes list.
	err := bencode.Unmarshal([]byte("d5:nodesl1:ai42eee"), &mi)
	require.Error(t, err)
}
<|endoftext|>


<commit_before>// Package ssd1306 contains an SSD1306 OLED driver.
package ssd1306

import (
	"fmt"
	"image"

	"golang.org/x/exp/io/i2c"
	"golang.org/x/exp/io/i2c/driver"
)

const (
	ssd1306_LCDWIDTH  = 128
	ssd1306_LCDHEIGHT = 64

	Address = 0x3C // Address is the I2C address of the device.

	// On or off registers.
	ssd1306_DISPLAY_ON  = 0xAF
	ssd1306_DISPLAY_OFF = 0xAE

	// Scrolling registers.
	ssd1306_ACTIVATE_SCROLL                      = 0x2F
	ssd1306_DEACTIVATE_SCROLL                    = 0x2E
	ssd1306_SET_VERTICAL_SCROLL_AREA             = 0xA3
	ssd1306_RIGHT_HORIZONTAL_SCROLL              = 0x26
	ssd1306_LEFT_HORIZONTAL_SCROLL               = 0x27
	ssd1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL = 0x29
	ssd1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL  = 0x2A
)

// OLED represents an SSD1306 OLED display.
type OLED struct {
	dev *i2c.Device

	w   int    // width of the display
	h   int    // height of the display
	buf []byte // each pixel is represented by a bit
}

var initSeq = []byte{
	0xae,
	0x00 | 0x00, // row offset
	0x10 | 0x00, // column offset
	0xd5, 0x40,
	0xa8, ssd1306_LCDHEIGHT - 1,
	0xd3, 0x00, // set display offset to no offset
	0x40 | 0,
	0x8d, 0x14,
	0x20, 0x0,

	0xA0 | 0x1,
	0xC8,
	0xda, 0x12,
	0x81, 0x9f, // set contast
	0x9d, 0xf1,
	0xdb, 0x40,
	0xa4, 0xa6,

	0x2E,
	0xaf,
}

// Open opens an SSD1306 OLED display. Once not in use, it needs to
// be close by calling Close.
// The default width is 128, height is 64 if zero values are given.
func Open(o driver.Opener) (*OLED, error) {
	w := ssd1306_LCDWIDTH
	h := ssd1306_LCDHEIGHT
	dev, err := i2c.Open(o)
	if err != nil {
		return nil, err
	}
	if err := dev.Write(initSeq); err != nil {
		return nil, err
	}
	buf := make([]byte, w*(h/8)+1)
	buf[0] = 0x40 // start frame of pixel data
	return &OLED{dev: dev, w: w, h: h, buf: buf}, nil
}

// On turns on the display if it is off.
func (o *OLED) On() error {
	return o.dev.Write([]byte{ssd1306_DISPLAY_ON})
}

// Off turns off the display if it is on.
func (o *OLED) Off() error {
	return o.dev.Write([]byte{ssd1306_DISPLAY_OFF})
}

// Clear clears the entire display.
func (o *OLED) Clear() error {
	for i := 1; i < len(o.buf); i++ {
		o.buf[i] = 0
	}
	return o.Draw()
}

func (o *OLED) SetPixel(x, y int, v byte) error {
	if x >= o.w || y >= o.h {
		return fmt.Errorf("(x=%v, y=%v) is out of bounds on this %vx%v display", x, y, o.w, o.h)
	}
	if v > 1 {
		return fmt.Errorf("value needs to be either 0 or 1; given %v", v)
	}
	i := 1 + x + (y/8)*o.w
	if v == byte(0) {
		o.buf[i] &= ^(1 << uint((y & 7)))
	} else {
		o.buf[i] |= 1 << uint((y & 7))
	}
	return nil
}

// DrawImage draws an image on the OLED display starting from x, y.
func (o *OLED) DrawImage(x int, img image.Image) error {
	panic("not implemented")
}

func (o *OLED) Draw() error {
	if err := o.dev.Write([]byte{
		0x21, 0, ssd1306_LCDWIDTH - 1,
		0x22, 0, 7,
	}); err != nil { // the write mode
		return err
	}
	return o.dev.Write(o.buf)
}

// StartScroll starts scrolling in the horizontal direction starting from
// startY column to endY column.
func (o *OLED) EnableScroll(startY, endY int) error {
	panic("not implemented")
}

// StopStrolls stops the scrolling on the display.
func (o *OLED) DisableScroll() error {
	panic("not implemented")
}

// Width returns the display width.
func (o *OLED) Width() int { return o.w }

// Height returns the display height.
func (o *OLED) Height() int { return o.h }

// Close closes the display.
func (o *OLED) Close() error {
	return o.dev.Close()
}
<commit_msg>minor godoc improvement<commit_after>// Package ssd1306 contains an SSD1306 OLED display driver.
package ssd1306

import (
	"fmt"
	"image"

	"golang.org/x/exp/io/i2c"
	"golang.org/x/exp/io/i2c/driver"
)

const (
	ssd1306_LCDWIDTH  = 128
	ssd1306_LCDHEIGHT = 64

	Address = 0x3C // Address is the I2C address of the device.

	// On or off registers.
	ssd1306_DISPLAY_ON  = 0xAF
	ssd1306_DISPLAY_OFF = 0xAE

	// Scrolling registers.
	ssd1306_ACTIVATE_SCROLL                      = 0x2F
	ssd1306_DEACTIVATE_SCROLL                    = 0x2E
	ssd1306_SET_VERTICAL_SCROLL_AREA             = 0xA3
	ssd1306_RIGHT_HORIZONTAL_SCROLL              = 0x26
	ssd1306_LEFT_HORIZONTAL_SCROLL               = 0x27
	ssd1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL = 0x29
	ssd1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL  = 0x2A
)

// OLED represents an SSD1306 OLED display.
type OLED struct {
	dev *i2c.Device

	w   int    // width of the display
	h   int    // height of the display
	buf []byte // each pixel is represented by a bit
}

var initSeq = []byte{
	0xae,
	0x00 | 0x00, // row offset
	0x10 | 0x00, // column offset
	0xd5, 0x40,
	0xa8, ssd1306_LCDHEIGHT - 1,
	0xd3, 0x00, // set display offset to no offset
	0x40 | 0,
	0x8d, 0x14,
	0x20, 0x0,

	0xA0 | 0x1,
	0xC8,
	0xda, 0x12,
	0x81, 0x9f, // set contast
	0x9d, 0xf1,
	0xdb, 0x40,
	0xa4, 0xa6,

	0x2E,
	0xaf,
}

// Open opens an SSD1306 OLED display. Once not in use, it needs to
// be close by calling Close.
// The default width is 128, height is 64 if zero values are given.
func Open(o driver.Opener) (*OLED, error) {
	w := ssd1306_LCDWIDTH
	h := ssd1306_LCDHEIGHT
	dev, err := i2c.Open(o)
	if err != nil {
		return nil, err
	}
	if err := dev.Write(initSeq); err != nil {
		return nil, err
	}
	buf := make([]byte, w*(h/8)+1)
	buf[0] = 0x40 // start frame of pixel data
	return &OLED{dev: dev, w: w, h: h, buf: buf}, nil
}

// On turns on the display if it is off.
func (o *OLED) On() error {
	return o.dev.Write([]byte{ssd1306_DISPLAY_ON})
}

// Off turns off the display if it is on.
func (o *OLED) Off() error {
	return o.dev.Write([]byte{ssd1306_DISPLAY_OFF})
}

// Clear clears the entire display.
func (o *OLED) Clear() error {
	for i := 1; i < len(o.buf); i++ {
		o.buf[i] = 0
	}
	return o.Draw()
}

func (o *OLED) SetPixel(x, y int, v byte) error {
	if x >= o.w || y >= o.h {
		return fmt.Errorf("(x=%v, y=%v) is out of bounds on this %vx%v display", x, y, o.w, o.h)
	}
	if v > 1 {
		return fmt.Errorf("value needs to be either 0 or 1; given %v", v)
	}
	i := 1 + x + (y/8)*o.w
	if v == byte(0) {
		o.buf[i] &= ^(1 << uint((y & 7)))
	} else {
		o.buf[i] |= 1 << uint((y & 7))
	}
	return nil
}

// DrawImage draws an image on the OLED display starting from x, y.
func (o *OLED) DrawImage(x int, img image.Image) error {
	panic("not implemented")
}

func (o *OLED) Draw() error {
	if err := o.dev.Write([]byte{
		0x21, 0, ssd1306_LCDWIDTH - 1,
		0x22, 0, 7,
	}); err != nil { // the write mode
		return err
	}
	return o.dev.Write(o.buf)
}

// StartScroll starts scrolling in the horizontal direction starting from
// startY column to endY column.
func (o *OLED) EnableScroll(startY, endY int) error {
	panic("not implemented")
}

// StopStrolls stops the scrolling on the display.
func (o *OLED) DisableScroll() error {
	panic("not implemented")
}

// Width returns the display width.
func (o *OLED) Width() int { return o.w }

// Height returns the display height.
func (o *OLED) Height() int { return o.h }

// Close closes the display.
func (o *OLED) Close() error {
	return o.dev.Close()
}
<|endoftext|>


<commit_before>package main

import (
	"reflect"
	"regexp"
	"testing"
)

var genMatcherTests = []struct {
	src string
	dst *regexp.Regexp
}{
	// one branch
	{`abc`, regexp.MustCompile(`(abc)`)},
	{`abcdef`, regexp.MustCompile(`(abcdef)`)},

	// multiple branches
	{`a,b`, regexp.MustCompile(`(a|b)`)},
	{`a,bc,def`, regexp.MustCompile(`(a|bc|def)`)},

	// use escape
	{`a\,b`, regexp.MustCompile(`(a,b)`)},
	{`a\,bc\,def`, regexp.MustCompile(`(a,bc,def)`)},

	// multiple branches with escape
	{`a\,b,c`, regexp.MustCompile(`(a,b|c)`)},
	{`a,bc\,def`, regexp.MustCompile(`(a|bc,def)`)},

	// regexp quote
	{`a+b`, regexp.MustCompile(`(a\+b)`)},
	{`(a|bc)*def`, regexp.MustCompile(`(\(a\|bc\)\*def)`)},

	// unquote special values
	{`a\\bc`, regexp.MustCompile("(a\\\\bc)")},
	{`a\tb\,c`, regexp.MustCompile("(a\tb,c)")},
	{`a\tbc\n\ndef`, regexp.MustCompile("(a\tbc\n\ndef)")},

	// multiple sequenses
	{`a~b`, regexp.MustCompile("(a)(b)")},
	{`a~bc~def`, regexp.MustCompile("(a)(bc)(def)")},
	{`a,b~c`, regexp.MustCompile("(a|b)(c)")},
}

func TestGenMatcher(t *testing.T) {
	for _, test := range genMatcherTests {
		expect := test.dst
		actual, err := newMatcher(test.src)
		if err != nil {
			t.Errorf("NewSubvert(%q) returns %q, want nil",
				test.src, err)
		}
		if !reflect.DeepEqual(actual, expect) {
			t.Errorf("%q: got %q, want %q",
				test.src, actual, expect)
		}
	}
}
<commit_msg>Add case of escape sequense in for newMatcher<commit_after>package main

import (
	"reflect"
	"regexp"
	"testing"
)

var genMatcherTests = []struct {
	src string
	dst *regexp.Regexp
}{
	// one branch
	{`abc`, regexp.MustCompile(`(abc)`)},
	{`abcdef`, regexp.MustCompile(`(abcdef)`)},

	// multiple branches
	{`a,b`, regexp.MustCompile(`(a|b)`)},
	{`a,bc,def`, regexp.MustCompile(`(a|bc|def)`)},

	// use escape
	{`a\,b`, regexp.MustCompile(`(a,b)`)},
	{`a\,bc\,def`, regexp.MustCompile(`(a,bc,def)`)},

	// multiple branches with escape
	{`a\,b,c`, regexp.MustCompile(`(a,b|c)`)},
	{`a,bc\,def`, regexp.MustCompile(`(a|bc,def)`)},

	// regexp quote
	{`a+b`, regexp.MustCompile(`(a\+b)`)},
	{`(a|bc)*def`, regexp.MustCompile(`(\(a\|bc\)\*def)`)},

	// unquote special values
	{`a\\bc`, regexp.MustCompile("(a\\\\bc)")},
	{`a\tb\,c`, regexp.MustCompile("(a\tb,c)")},
	{`a\tbc\n\ndef`, regexp.MustCompile("(a\tbc\n\ndef)")},

	// multiple sequenses
	{`a~b`, regexp.MustCompile("(a)(b)")},
	{`a~bc~def`, regexp.MustCompile("(a)(bc)(def)")},
	{`a,b~c`, regexp.MustCompile("(a|b)(c)")},

	// multiple sequenses with escape
	{`a~b\~c`, regexp.MustCompile("(a)(b~c)")},
	{`a~\~bc\~~def`, regexp.MustCompile("(a)(~bc~)(def)")},
	{`a\,b,c~d,e\~f`, regexp.MustCompile("(a,b|c)(d|e~f)")},
}

func TestGenMatcher(t *testing.T) {
	for _, test := range genMatcherTests {
		expect := test.dst
		actual, err := newMatcher(test.src)
		if err != nil {
			t.Errorf("NewSubvert(%q) returns %q, want nil",
				test.src, err)
		}
		if !reflect.DeepEqual(actual, expect) {
			t.Errorf("%q: got %q, want %q",
				test.src, actual, expect)
		}
	}
}
<|endoftext|>


<commit_before>package sstable

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	"hash/crc32"
	"io"
	"os"
	"sort"

	"code.google.com/p/snappy-go/snappy"
)

const (
	maxBlockHandleLength = 20
	footerLength         = maxBlockHandleLength*2 + 8
	magicNumber          = 0xdb4775248b80fb57
	blockTrailerSize     = 5
	maskDelta            = 0xa282ead8
	noCompression        = 0
	snappyCompression    = 1
)

type blockHandle struct {
	offset, length uint64
}

func blockHandleFrom(data []byte) (blockHandle, []byte, error) {
	remaining := data
	var read int
	var b blockHandle
	b.offset, read = binary.Uvarint(data)
	if read == 0 {
		return b, nil, errors.New("could not read offset")
	}
	remaining = remaining[read:]
	b.length, read = binary.Uvarint(data[read:])
	if read == 0 {
		return b, nil, errors.New("could not read length")
	}
	remaining = remaining[read:]
	return b, remaining, nil
}

type footer struct {
	metaindex, index blockHandle
}

func footerFrom(data []byte) (*footer, error) {
	if len(data) != footerLength {
		return nil, fmt.Errorf("invalid footer length %v", len(data))
	}
	magic := binary.LittleEndian.Uint64(data[40:])
	if magic != magicNumber {
		return nil, fmt.Errorf("invalid magic number %x", magic)
	}
	var f footer
	var err error
	f.metaindex, data, err = blockHandleFrom(data)
	if err != nil {
		return nil, fmt.Errorf("could not read metaindex handle: %v", err)
	}
	f.index, _, err = blockHandleFrom(data)
	if err != nil {
		return nil, fmt.Errorf("could not read index handle: %v", err)
	}
	return &f, nil
}

func unmaskCRC(crc uint32) uint32 {
	crc -= maskDelta
	return ((crc >> 17) | (crc << 15))
}

func readBlock(f io.ReaderAt, b blockHandle) ([]byte, error) {
	actualLength := int64(b.length) + blockTrailerSize
	out := make([]byte, actualLength)
	n, err := f.ReadAt(out, int64(b.offset))
	if int64(n) != actualLength {
		return nil, fmt.Errorf("could not read %d bytes at offset %d, read %d: %v",
			int64(b.length), b.offset, n, err)
	}
	wantCRC := unmaskCRC(binary.LittleEndian.Uint32(out[int(b.length)+1:]))
	gotCRC := crc32.Checksum(out[:int(b.length)+1], crc32.MakeTable(crc32.Castagnoli))
	if gotCRC != wantCRC {
		return nil, fmt.Errorf("crc mismatch, got %x want %x", gotCRC, wantCRC)
	}
	switch out[int(b.length)] {
	case noCompression:
		return out[:int(b.length)], nil
	case snappyCompression:
		decoded, err := snappy.Decode(nil, out[:int(b.length)])
		if err != nil {
			return nil, fmt.Errorf("unable to snappy decompress: %v", err)
		}
		return decoded, nil
	default:
		return nil, fmt.Errorf("invalid compression type %d", out[int(b.length)])
	}
}

type Table struct {
	name   string
	f      *os.File
	footer *footer
	index  *block
}

func NewTable(filename string) (*Table, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, fmt.Errorf("could not open %q: %v", filename, err)
	}
	t := &Table{name: filename, f: f}
	defer func() {
		if f != nil {
			f.Close()
		}
	}()
	stat, err := f.Stat()
	if err != nil {
		return nil, fmt.Errorf("could not stat: %v", err)
	}
	size := stat.Size()
	var footerBytes [footerLength]byte
	if n, err := f.ReadAt(footerBytes[:], size-footerLength); n != footerLength {
		return nil, fmt.Errorf("could not read footer bytes: %v", err)
	} else if t.footer, err = footerFrom(footerBytes[:]); err != nil {
		return nil, fmt.Errorf("could not decode footer: %v", err)
	}

	indexBlock, err := t.newBlock(t.footer.index)
	if err != nil {
		return nil, fmt.Errorf("could not read index block: %v", err)
	}
	t.index = indexBlock
	/*
	  metaBlock, err := readBlock(f, t.footer.metaindex)
	  if err != nil {
	    return nil, fmt.Errorf("could not read metaindex block: %v", err)
	  }
	*/
	f = nil
	return t, nil
}

func (t *Table) Close() error {
	return t.f.Close()
}

type block struct {
	data                  []byte
	restarts, numRestarts int
}

func (t *Table) newBlock(b blockHandle) (*block, error) {
	data, err := readBlock(t.f, b)
	if err != nil {
		return nil, err
	}
	var blk block
	blk.data = data
	if len(data) < 4 {
		return nil, fmt.Errorf("block too small: %v", data)
	}
	blk.numRestarts = int(binary.LittleEndian.Uint32(data[len(data)-4:]))
	if len(data)-4 < blk.numRestarts*4 {
		return nil, fmt.Errorf("block too small (%d) for %d restarts:\n%v", len(data), blk.numRestarts, hex.Dump(data))
	}
	blk.restarts = len(data) - blk.numRestarts*4 - 4
	return &blk, nil
}

func (b *block) iter() *blockIterator {
	return &blockIterator{block: b}
}

type blockIterator struct {
	*block
	key, value []byte
	current    int
	err        error
}

func (b *blockIterator) Err() error {
	return b.err
}

func (b *blockIterator) Key() []byte {
	return b.key
}
func (b *blockIterator) Value() []byte {
	return b.value
}

func (b *block) restartPoint(index int) int {
	if index > b.numRestarts {
		panic("invalid restart")
	}
	return int(binary.LittleEndian.Uint32(b.data[b.restarts+index*4:]))
}

func (b *blockIterator) seekToRestart(index int) {
	offset := b.restartPoint(index)
	b.current = offset
	b.value = b.data[b.current:b.current]
}

func (b *blockIterator) decodeNext() (sharedKey, unsharedKey, val, offset int, err error) {
	offset = b.current
	num, n := binary.Uvarint(b.data[offset:])
	if n == 0 {
		err = errors.New("could not get sharedKey")
		return
	}
	offset += n
	sharedKey = int(num)
	num, n = binary.Uvarint(b.data[offset:])
	if n == 0 {
		err = errors.New("could not get unsharedKey")
		return
	}
	offset += n
	unsharedKey = int(num)
	num, n = binary.Uvarint(b.data[offset:])
	if n == 0 {
		err = errors.New("could not get val")
		return
	}
	offset += n
	val = int(num)
	if sharedKey > len(b.key) {
		err = fmt.Errorf("sharedKey %v > key length %v", sharedKey, len(b.key))
	} else if unsharedKey+val+b.current > b.restarts {
		err = errors.New("total size greater than block space allows")
	}
	return
}

type Iter interface {
	Next() bool
	Key() []byte
	Value() []byte
	Err() error
}

func (b *blockIterator) Next() bool {
	if b.current >= b.restarts {
		return false
	}
	sharedKey, unsharedKey, val, offset, err := b.decodeNext()
	if err != nil {
		b.err = err
		return b.nope()
	}
	b.current = offset
	if sharedKey > len(b.key) {
		b.err = fmt.Errorf("shared key too long")
		return false
	}
	b.key = append(b.key[:sharedKey], b.data[b.current:b.current+unsharedKey]...)
	b.current += unsharedKey
	b.value = b.data[b.current : b.current+val]
	b.current += val
	return true
}

func (b *blockIterator) nope() bool {
	b.current = b.restarts
	return false
}

// Seek to the first key >= target.
func (b *blockIterator) Seek(target []byte) {
	n := sort.Search(b.numRestarts, func(index int) bool {
		b.seekToRestart(index)
		sharedKey, unsharedKey, _, offset, err := b.decodeNext()
		if err != nil {
			b.err = err
		}
		if b.err != nil || sharedKey != 0 {
			return true
		}
		key := b.data[offset : offset+unsharedKey]
		return bytes.Compare(key, target) >= 0
	})
	if b.err != nil {
		b.nope()
		return
	}
	if n > 0 {
		n--
	}
	b.seekToRestart(n)
	for b.err == nil {
		last := *b
		last.key = append([]byte(nil), last.key...)
		if !b.Next() {
			return
		}
		if bytes.Compare(b.Key(), target) >= 0 {
			*b = last
			return
		}
	}
}

type twoLevelIterator struct {
	tbl   *Table
	index *blockIterator
	data  *blockIterator
	err   error
}

func (t *twoLevelIterator) Err() error {
	return t.err
}

func (t *twoLevelIterator) nextDataBlock() bool {
	if !t.index.Next() {
		t.index = nil
		return false
	}
	handle, _, err := blockHandleFrom(t.index.Value())
	if err != nil {
		t.err = err
		return false
	}
	dataBlock, err := t.tbl.newBlock(handle)
	if err != nil {
		t.err = err
		return false
	}
	t.data = dataBlock.iter()
	return true
}

func (t *twoLevelIterator) Seek(target []byte) {
	t.index.Seek(target)
	t.nextDataBlock()
	t.data.Seek(target)
}

func (t *twoLevelIterator) Next() bool {
	if t.err != nil || t.index == nil {
		return false
	}
	for {
		if t.data.Next() {
			return true
		}
		if err := t.data.Err(); err != nil {
			t.err = err
			return false
		}
		if !t.nextDataBlock() {
			return false
		}
	}
}

func (t *twoLevelIterator) Key() []byte {
	return t.data.Key()
}

func (t *twoLevelIterator) Value() []byte {
	return t.data.Value()
}

func (t *Table) Iter(start []byte) Iter {
	iter := &twoLevelIterator{
		tbl:   t,
		index: t.index.iter(),
	}
	iter.Seek(start)
	return iter
}
<commit_msg>Add licencing and comments to sstable implementation.<commit_after>// Copyright 2014 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 sstable provides read-only functionality for iterating over leveldb
// tables (sorted-string or 'ss' tables).
package sstable

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	"hash/crc32"
	"io"
	"os"
	"sort"

	"code.google.com/p/snappy-go/snappy"
)

const (
	maxBlockHandleLength = 20
	footerLength         = maxBlockHandleLength*2 + 8
	magicNumber          = 0xdb4775248b80fb57
	blockTrailerSize     = 5
	maskDelta            = 0xa282ead8
	noCompression        = 0
	snappyCompression    = 1
)

type blockHandle struct {
	offset, length uint64
}

func blockHandleFrom(data []byte) (blockHandle, []byte, error) {
	remaining := data
	var read int
	var b blockHandle
	b.offset, read = binary.Uvarint(data)
	if read == 0 {
		return b, nil, errors.New("could not read offset")
	}
	remaining = remaining[read:]
	b.length, read = binary.Uvarint(data[read:])
	if read == 0 {
		return b, nil, errors.New("could not read length")
	}
	remaining = remaining[read:]
	return b, remaining, nil
}

type footer struct {
	metaindex, index blockHandle
}

func footerFrom(data []byte) (*footer, error) {
	if len(data) != footerLength {
		return nil, fmt.Errorf("invalid footer length %v", len(data))
	}
	magic := binary.LittleEndian.Uint64(data[40:])
	if magic != magicNumber {
		return nil, fmt.Errorf("invalid magic number %x", magic)
	}
	var f footer
	var err error
	f.metaindex, data, err = blockHandleFrom(data)
	if err != nil {
		return nil, fmt.Errorf("could not read metaindex handle: %v", err)
	}
	f.index, _, err = blockHandleFrom(data)
	if err != nil {
		return nil, fmt.Errorf("could not read index handle: %v", err)
	}
	return &f, nil
}

func unmaskCRC(crc uint32) uint32 {
	crc -= maskDelta
	return ((crc >> 17) | (crc << 15))
}

func readBlock(f io.ReaderAt, b blockHandle) ([]byte, error) {
	actualLength := int64(b.length) + blockTrailerSize
	out := make([]byte, actualLength)
	n, err := f.ReadAt(out, int64(b.offset))
	if int64(n) != actualLength {
		return nil, fmt.Errorf("could not read %d bytes at offset %d, read %d: %v",
			int64(b.length), b.offset, n, err)
	}
	wantCRC := unmaskCRC(binary.LittleEndian.Uint32(out[int(b.length)+1:]))
	gotCRC := crc32.Checksum(out[:int(b.length)+1], crc32.MakeTable(crc32.Castagnoli))
	if gotCRC != wantCRC {
		return nil, fmt.Errorf("crc mismatch, got %x want %x", gotCRC, wantCRC)
	}
	switch out[int(b.length)] {
	case noCompression:
		return out[:int(b.length)], nil
	case snappyCompression:
		decoded, err := snappy.Decode(nil, out[:int(b.length)])
		if err != nil {
			return nil, fmt.Errorf("unable to snappy decompress: %v", err)
		}
		return decoded, nil
	default:
		return nil, fmt.Errorf("invalid compression type %d", out[int(b.length)])
	}
}

// Table exposes a single on-disk table for querying.
type Table struct {
	name   string
	f      *os.File
	footer *footer
	index  *block
}

// NewTable opens the named file as an on-disk sstable.
func NewTable(filename string) (*Table, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, fmt.Errorf("could not open %q: %v", filename, err)
	}
	t := &Table{name: filename, f: f}
	defer func() {
		if f != nil {
			f.Close()
		}
	}()
	stat, err := f.Stat()
	if err != nil {
		return nil, fmt.Errorf("could not stat: %v", err)
	}
	size := stat.Size()
	var footerBytes [footerLength]byte
	if n, err := f.ReadAt(footerBytes[:], size-footerLength); n != footerLength {
		return nil, fmt.Errorf("could not read footer bytes: %v", err)
	} else if t.footer, err = footerFrom(footerBytes[:]); err != nil {
		return nil, fmt.Errorf("could not decode footer: %v", err)
	}

	indexBlock, err := t.newBlock(t.footer.index)
	if err != nil {
		return nil, fmt.Errorf("could not read index block: %v", err)
	}
	t.index = indexBlock
	// TODO:  we do nothing with the meta-index... should we?
	f = nil
	return t, nil
}

// Close closes the underlying table.
func (t *Table) Close() error {
	return t.f.Close()
}

type block struct {
	data                  []byte
	restarts, numRestarts int
}

func (t *Table) newBlock(b blockHandle) (*block, error) {
	data, err := readBlock(t.f, b)
	if err != nil {
		return nil, err
	}
	var blk block
	blk.data = data
	if len(data) < 4 {
		return nil, fmt.Errorf("block too small: %v", data)
	}
	blk.numRestarts = int(binary.LittleEndian.Uint32(data[len(data)-4:]))
	if len(data)-4 < blk.numRestarts*4 {
		return nil, fmt.Errorf("block too small (%d) for %d restarts:\n%v", len(data), blk.numRestarts, hex.Dump(data))
	}
	blk.restarts = len(data) - blk.numRestarts*4 - 4
	return &blk, nil
}

func (b *block) iter() *blockIterator {
	return &blockIterator{block: b}
}

type blockIterator struct {
	*block
	key, value []byte
	current    int
	err        error
}

func (b *blockIterator) Err() error {
	return b.err
}

func (b *blockIterator) Key() []byte {
	return b.key
}
func (b *blockIterator) Value() []byte {
	return b.value
}

func (b *block) restartPoint(index int) int {
	if index > b.numRestarts {
		panic("invalid restart")
	}
	return int(binary.LittleEndian.Uint32(b.data[b.restarts+index*4:]))
}

func (b *blockIterator) seekToRestart(index int) {
	offset := b.restartPoint(index)
	b.current = offset
	b.value = b.data[b.current:b.current]
}

func (b *blockIterator) decodeNext() (sharedKey, unsharedKey, val, offset int, err error) {
	offset = b.current
	num, n := binary.Uvarint(b.data[offset:])
	if n == 0 {
		err = errors.New("could not get sharedKey")
		return
	}
	offset += n
	sharedKey = int(num)
	num, n = binary.Uvarint(b.data[offset:])
	if n == 0 {
		err = errors.New("could not get unsharedKey")
		return
	}
	offset += n
	unsharedKey = int(num)
	num, n = binary.Uvarint(b.data[offset:])
	if n == 0 {
		err = errors.New("could not get val")
		return
	}
	offset += n
	val = int(num)
	if sharedKey > len(b.key) {
		err = fmt.Errorf("sharedKey %v > key length %v", sharedKey, len(b.key))
	} else if unsharedKey+val+b.current > b.restarts {
		err = errors.New("total size greater than block space allows")
	}
	return
}

// Iter provides a simple iteration interface over a table.  Each iterator is
// not safe for concurrent access, but any number of iterators may be used
// concurrently.
//
// Usage:
//   iter := tbl.Iter(startKey)
//   for iter.Next() {
//     fmt.Println(iter.Key(), iter.Value())
//   }
//   if err := iter.Err(); err != nil {
//     fmt.Println("ERR:", err)
//   }
type Iter interface {
	// Next advances the iterator.
	Next() bool
	// Key provides the current key of the iterator.  This slice is invalidated by
	// each Next call.
	Key() []byte
	// Value provides the current value of the iterator.  This slice is invalidated by
	// each Next call.
	Value() []byte
	// Err returns any error the iterator has encountered.  If Err would return a
	// non-nil error, then Next() will also return false.
	Err() error
}

func (b *blockIterator) Next() bool {
	if b.current >= b.restarts {
		return false
	}
	sharedKey, unsharedKey, val, offset, err := b.decodeNext()
	if err != nil {
		b.err = err
		return b.nope()
	}
	b.current = offset
	if sharedKey > len(b.key) {
		b.err = fmt.Errorf("shared key too long")
		return false
	}
	b.key = append(b.key[:sharedKey], b.data[b.current:b.current+unsharedKey]...)
	b.current += unsharedKey
	b.value = b.data[b.current : b.current+val]
	b.current += val
	return true
}

func (b *blockIterator) nope() bool {
	b.current = b.restarts
	return false
}

// Seek to the first key >= target.
func (b *blockIterator) Seek(target []byte) {
	n := sort.Search(b.numRestarts, func(index int) bool {
		b.seekToRestart(index)
		sharedKey, unsharedKey, _, offset, err := b.decodeNext()
		if err != nil {
			b.err = err
		}
		if b.err != nil || sharedKey != 0 {
			return true
		}
		key := b.data[offset : offset+unsharedKey]
		return bytes.Compare(key, target) >= 0
	})
	if b.err != nil {
		b.nope()
		return
	}
	if n > 0 {
		n--
	}
	b.seekToRestart(n)
	for b.err == nil {
		last := *b
		last.key = append([]byte(nil), last.key...)
		if !b.Next() {
			return
		}
		if bytes.Compare(b.Key(), target) >= 0 {
			*b = last
			return
		}
	}
}

type twoLevelIterator struct {
	tbl   *Table
	index *blockIterator
	data  *blockIterator
	err   error
}

func (t *twoLevelIterator) Err() error {
	return t.err
}

func (t *twoLevelIterator) nextDataBlock() bool {
	if !t.index.Next() {
		t.index = nil
		return false
	}
	handle, _, err := blockHandleFrom(t.index.Value())
	if err != nil {
		t.err = err
		return false
	}
	dataBlock, err := t.tbl.newBlock(handle)
	if err != nil {
		t.err = err
		return false
	}
	t.data = dataBlock.iter()
	return true
}

func (t *twoLevelIterator) Seek(target []byte) {
	t.index.Seek(target)
	t.nextDataBlock()
	t.data.Seek(target)
}

func (t *twoLevelIterator) Next() bool {
	if t.err != nil || t.index == nil {
		return false
	}
	for {
		if t.data.Next() {
			return true
		}
		if err := t.data.Err(); err != nil {
			t.err = err
			return false
		}
		if !t.nextDataBlock() {
			return false
		}
	}
}

func (t *twoLevelIterator) Key() []byte {
	return t.data.Key()
}

func (t *twoLevelIterator) Value() []byte {
	return t.data.Value()
}

// Iter creates a new iterator over the table, starting at the given key.
func (t *Table) Iter(start []byte) Iter {
	iter := &twoLevelIterator{
		tbl:   t,
		index: t.index.iter(),
	}
	iter.Seek(start)
	return iter
}
<|endoftext|>