<commit_before>package main

import (
   "fmt"
   "io/ioutil"
   "encoding/json"
   "net"
   "os"
   "qlib"
   "sync"
   "time"
)

var sId chan int // recycles client ids back to main()
var sTimeout error = &tTimeoutError{}

func main() {
   aDb, err := NewUserDb("./userdb")
   if err != nil { panic(err) }

   qlib.UDb = aDb
   qlib.Init("qstore")
   sId = make(chan int, 10)

   fmt.Printf("Starting Test Pass\n")
   sId <- 111111
   sId <- 222222
   for a := 0; true; a++ {
      aDawdle := a == 1
      qlib.NewLink(NewTc(<-sId, aDawdle))
   }
}

const ( _=iota; eRegister; eAddNode; eLogin; eListEdit; ePost; ePing; eAck )

type tTestClient struct {
   id, to int // who i am, who i send to
   count int // msg number
   noLogin bool // test login timeout feature
   ack chan int // writer tells reader to issue ack to qlib
   closed bool // when about to shut down
   readDeadline time.Time // set by qlib
}

func NewTc(i int, iNoLogin bool) *tTestClient {
   return &tTestClient{
      id: i, to: i+111111,
      noLogin: iNoLogin,
      ack: make(chan int,10),
   }
}

func (o *tTestClient) Read(buf []byte) (int, error) {
   if o.count % 10 == 9 {
      return 0, &net.OpError{Op:"log out"}
   }

   var aDlC <-chan time.Time
   if !o.readDeadline.IsZero() {
      aDl := time.NewTimer(o.readDeadline.Sub(time.Now()))
      defer aDl.Stop()
      aDlC = aDl.C
   }

   aUnit := 200 * time.Millisecond; if o.noLogin { aUnit = 6 * time.Second }
   aTmr := time.NewTimer(aUnit)
   defer aTmr.Stop()

   var aHead map[string]interface{}
   var aData string

   select {
   case <-o.ack:
      aHead = tMsg{"Op":eAck, "Id":"n", "Type":"n"}
   case <-aTmr.C:
      o.count++
      if o.noLogin {
         aHead = tMsg{}
      } else if o.count == 1 {
         aHead = tMsg{"Op":eLogin, "Uid":"u"+fmt.Sprint(o.id), "NodeId":fmt.Sprint(o.id)}
      } else {
         aHead = tMsg{"Op":ePost, "Id":"n", "For":[]string{"u"+fmt.Sprint(o.to)}}
         aData = fmt.Sprintf(" |msg %d|", o.count)
      }
   case <-aDlC:
      return 0, &net.OpError{Op:"timeout",Err:sTimeout}
   }

   aMsg := qlib.PackMsg(aHead, []byte(aData))
   fmt.Printf("%d testclient.read %s\n", o.id, string(aMsg))
   return copy(buf, aMsg), nil
}

func (o *tTestClient) Write(buf []byte) (int, error) {
   if o.closed {
      fmt.Printf("%d testclient.write was closed\n", o.id)
      return 0, &net.OpError{Op:"closed"}
   }

   aTmr := time.NewTimer(2 * time.Second)

   select {
   case o.ack <- 1:
      aTmr.Stop()
   case <-aTmr.C:
      fmt.Printf("%d testclient.write timed out on ack\n", o.id)
      return 0, &net.OpError{Op:"noack"}
   }

   fmt.Printf("%d testclient.write got %s\n", o.id, string(buf))
   return len(buf), nil
}

func (o *tTestClient) SetReadDeadline(i time.Time) error {
   o.readDeadline = i
   return nil
}

func (o *tTestClient) Close() error {
   o.closed = true;
   time.AfterFunc(10*time.Millisecond, func(){ sId <- o.id })
   return nil
}

func (o *tTestClient) LocalAddr() net.Addr { return &net.UnixAddr{"e", "a"} }
func (o *tTestClient) RemoteAddr() net.Addr { return &net.UnixAddr{"e", "a"} }
func (o *tTestClient) SetDeadline(time.Time) error { return nil }
func (o *tTestClient) SetWriteDeadline(time.Time) error { return nil }

type tTimeoutError struct{}
func (o *tTimeoutError) Error() string   { return "i/o timeout" }
func (o *tTimeoutError) Timeout() bool   { return true }
func (o *tTimeoutError) Temporary() bool { return true }

type tMsg map[string]interface{}

//: these are instructions/guidance comments
//: you'll implement the public api to add/edit userdb records
//: for all ops, you look up a record in cache,
//:   and if not there call getRecord and cache the result
//:   lookups are done with aObj := o.Uid[iUid] (or o.Alias, o.List)
//: for add/edit ops, you then modify the cache object, then call putRecord
//: locking
//:   cache read ops are done inside o.xyzDoor.RLock/RUnlock()
//:   cache add/delete ops are done inside o.xyzDoor.Lock/Unlock()
//:   Uid and List object updates are done inside aObj.door.Lock/Unlock()
//: records are stored as files in subdirectories of o.root: uid, alias, list
//:   uid/* & list/* files are json format
//:   alias/* files are symlinks to Uid

type tUserDb struct {
   root string // top-level directory
   temp string // temp subdirectory; write files here first
   uidDoor, alsDoor, lstDoor sync.RWMutex // protect cache during update

   // cache records here
   Uid map[string]tUser
   Alias map[string]string // value is Uid
   List map[string]tList
}

type tUser struct {
   door sync.RWMutex
   Nodes map[string]int // value is NodeRef
   Aliases []tAlias // public names for the user
}

type tAlias struct {
   En string // in english
   Nat string // in whatever language
}

type tList struct {
   door sync.RWMutex
   Uid map[string]tMember
}

type tMember struct {
   Alias string // invited/joined by this Alias
   Joined bool // use a date here?
}

//type tUserDbErr string
//func (o tUserDbErr) Error() string { return string(o) }

type tType string
const (
   eTuid   tType = "uid"
   eTalias tType = "alias"
   eTlist  tType = "list"
)

func NewUserDb(iPath string) (*tUserDb, error) {
   for _, a := range [...]tType{ "temp", eTuid, eTalias, eTlist } {
      err := os.MkdirAll(iPath + "/" + string(a), 0700)
      if err != nil { return nil, err }
   }

   aDb := new(tUserDb)
   aDb.root = iPath+"/"
   aDb.temp = aDb.root + "temp"
   aDb.Uid = make(map[string]tUser)
   aDb.Alias = make(map[string]string)
   aDb.List = make(map[string]tList)

   return aDb, nil
}

func (o *tUserDb) Test() error {
   //: exercise the api, print diagnostics
   //: invoke from main() before tTestClient loop; stop program if tests fail
   return nil
}

//: below is the public api

func (o *tUserDb) AddUser(iUid, iNewNode string, iAliases []string) (aAliases []string, err error) {
   //: add user if iUid not in db
   return []string{}, nil
}

func (o *tUserDb) SetAliases(iUid, iNode string, iAliases []string) (aAliases []string, err error) {
   //: replace aliases if iUid in db and has iNode, and iAliases elements are unique
   return []string{}, nil
}

func (o *tUserDb) AddNode(iUid, iNode, iNewNode string) (aNodeRef int, err error) {
   //: add iNewNode if iUid in db and has iNode
   return 0, nil
}

func (o *tUserDb) DropNode(iUid, iNode string) error {
   //: delete iNode if iUid in db and has iNode
   return nil
}

//func (o *tUserDb) DropUser(iUid string) error {
//   return nil
//}

func (o *tUserDb) Verify(iUid, iNode string) (aNodeRef int, err error) {
   //: return noderef if iUid in db and has iNode
   // trivial implementation for qlib testing
   o.Uid[iUid] = tUser{Nodes: map[string]int{iNode:0}}
   return 0, nil
}

func (o *tUserDb) GetNodes(iUid string) (aNodes []string, err error) {
   //: return noderefs if iUid in db
   // trivial implementation for qlib testing
   for aN,_ := range o.Uid[iUid].Nodes {
      aNodes = append(aNodes, aN)
   }
   return aNodes, nil
}

func (o *tUserDb) Lookup(iAlias string) (aUid string, err error) {
   //: return uid if iAlias in db
   return "", nil
}

func (o *tUserDb) ListInvite(iList, iBy, iAlias string) error {
   //: if iAlias in db, and iBy in db & iList (or make iList and add iBy), list iAlias
   return nil
}

func (o *tUserDb) ListJoin(iList, iAlias, iUid string) (aAlias string, err error) {
   //: return listed alias if iList in db and iUid in iList, list iAlias if != ""
   return "", nil
}

func (o *tUserDb) ListDrop(iList, iBy, iUid string) error {
   //: remove iUid from iList if iBy in iList
   return nil
}

func (o *tUserDb) ListLookup(iList, iBy string) (aUids []string, err error) {
   //: return uids if iBy in list
   return []string{}, nil
}

// pull a file into a cache object
func (o *tUserDb) getRecord(iType tType, iId string) (interface{}, error) {
   var err error
   var aObj interface{}
   aPath := o.root + string(iType) + "/" + iId

   // in case putRecord was interrupted
   err = os.Link(aPath + ".tmp", aPath)
   if err != nil {
      if !os.IsExist(err) && !os.IsNotExist(err) { return nil, err }
   } else {
      fmt.Println("getRecord: finished transaction for "+aPath)
   }

   switch (iType) {
   default:
      panic("getRecord: unexpected type "+iType)
   case "alias":
      aLn, err := os.Readlink(aPath)
      if err != nil {
         if os.IsNotExist(err) { return nil, nil }
         return nil, err
      }
      return &aLn, nil
   case "uid":  aObj = &tUser{}
   case "list": aObj = &tList{}
   }

   aBuf, err := ioutil.ReadFile(aPath)
   if err != nil {
      if os.IsNotExist(err) { return nil, nil }
      return nil, err
   }

   err = json.Unmarshal(aBuf, aObj)
   return aObj, err
}

// save cache object to disk. getRecord must be called before this
func (o *tUserDb) putRecord(iType tType, iId string, iObj interface{}) error {
   var err error
   aPath := o.root + string(iType) + "/" + iId
   aTemp := o.temp + string(iType) + "_" + iId

   err = os.Remove(aPath + ".tmp")
   if err == nil {
      fmt.Println("putRecord: removed residual .tmp file for "+aPath)
   }

   switch (iType) {
   default:
      panic("putRecord: unexpected type "+iType)
   case "alias":
      err = os.Symlink(iObj.(string), aPath + ".tmp")
      if err != nil { return err }
      return o.commitDir(iType, aPath)
   case "uid", "list":
   }

   aBuf, err := json.Marshal(iObj)
   if err != nil { return err }

   aFd, err := os.OpenFile(aTemp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
   if err != nil { return err }
   defer aFd.Close()

   for aPos,aLen := 0,0; aPos < len(aBuf); aPos += aLen {
      aLen, err = aFd.Write(aBuf[aPos:])
      if err != nil { return err }
   }

   err = aFd.Sync()
   if err != nil { return err }

   err = os.Link(aTemp, aPath + ".tmp")
   if err != nil { return err }
   err = os.Remove(aTemp)
   if err != nil { return err }

   return o.commitDir(iType, aPath)
}

// sync the directory and set the filename
func (o *tUserDb) commitDir(iType tType, iPath string) error {
   aFd, err := os.Open(o.root + string(iType))
   if err != nil { return err }
   defer aFd.Close()
   err = aFd.Sync()
   if err != nil { return err }

   err = os.Remove(iPath)
   if err != nil && !os.IsNotExist(err) { return err }
   err = os.Rename(iPath + ".tmp", iPath)
   return err
}

<commit_msg>testclient: rename noLogin to deferLogin<commit_after>package main

import (
   "fmt"
   "io/ioutil"
   "encoding/json"
   "net"
   "os"
   "qlib"
   "sync"
   "time"
)

var sId chan int // recycles client ids back to main()
var sTimeout error = &tTimeoutError{}

func main() {
   aDb, err := NewUserDb("./userdb")
   if err != nil { panic(err) }

   qlib.UDb = aDb
   qlib.Init("qstore")
   sId = make(chan int, 10)

   fmt.Printf("Starting Test Pass\n")
   sId <- 111111
   sId <- 222222
   for a := 0; true; a++ {
      aDawdle := a == 1
      qlib.NewLink(NewTc(<-sId, aDawdle))
   }
}

const ( _=iota; eRegister; eAddNode; eLogin; eListEdit; ePost; ePing; eAck )

type tTestClient struct {
   id, to int // who i am, who i send to
   count int // msg number
   deferLogin bool // test login timeout feature
   ack chan int // writer tells reader to issue ack to qlib
   closed bool // when about to shut down
   readDeadline time.Time // set by qlib
}

func NewTc(i int, iDawdle bool) *tTestClient {
   return &tTestClient{
      id: i, to: i+111111,
      deferLogin: iDawdle,
      ack: make(chan int,10),
   }
}

func (o *tTestClient) Read(buf []byte) (int, error) {
   if o.count % 10 == 9 {
      return 0, &net.OpError{Op:"log out"}
   }

   var aDlC <-chan time.Time
   if !o.readDeadline.IsZero() {
      aDl := time.NewTimer(o.readDeadline.Sub(time.Now()))
      defer aDl.Stop()
      aDlC = aDl.C
   }

   aUnit := 200 * time.Millisecond; if o.deferLogin { aUnit = 6 * time.Second }
   aTmr := time.NewTimer(aUnit)
   defer aTmr.Stop()

   var aHead map[string]interface{}
   var aData string

   select {
   case <-o.ack:
      aHead = tMsg{"Op":eAck, "Id":"n", "Type":"n"}
   case <-aTmr.C:
      o.count++
      if o.deferLogin {
         aHead = tMsg{}
      } else if o.count == 1 {
         aHead = tMsg{"Op":eLogin, "Uid":"u"+fmt.Sprint(o.id), "NodeId":fmt.Sprint(o.id)}
      } else {
         aHead = tMsg{"Op":ePost, "Id":"n", "For":[]string{"u"+fmt.Sprint(o.to)}}
         aData = fmt.Sprintf(" |msg %d|", o.count)
      }
   case <-aDlC:
      return 0, &net.OpError{Op:"timeout",Err:sTimeout}
   }

   aMsg := qlib.PackMsg(aHead, []byte(aData))
   fmt.Printf("%d testclient.read %s\n", o.id, string(aMsg))
   return copy(buf, aMsg), nil
}

func (o *tTestClient) Write(buf []byte) (int, error) {
   if o.closed {
      fmt.Printf("%d testclient.write was closed\n", o.id)
      return 0, &net.OpError{Op:"closed"}
   }

   aTmr := time.NewTimer(2 * time.Second)

   select {
   case o.ack <- 1:
      aTmr.Stop()
   case <-aTmr.C:
      fmt.Printf("%d testclient.write timed out on ack\n", o.id)
      return 0, &net.OpError{Op:"noack"}
   }

   fmt.Printf("%d testclient.write got %s\n", o.id, string(buf))
   return len(buf), nil
}

func (o *tTestClient) SetReadDeadline(i time.Time) error {
   o.readDeadline = i
   return nil
}

func (o *tTestClient) Close() error {
   o.closed = true;
   time.AfterFunc(10*time.Millisecond, func(){ sId <- o.id })
   return nil
}

func (o *tTestClient) LocalAddr() net.Addr { return &net.UnixAddr{"e", "a"} }
func (o *tTestClient) RemoteAddr() net.Addr { return &net.UnixAddr{"e", "a"} }
func (o *tTestClient) SetDeadline(time.Time) error { return nil }
func (o *tTestClient) SetWriteDeadline(time.Time) error { return nil }

type tTimeoutError struct{}
func (o *tTimeoutError) Error() string   { return "i/o timeout" }
func (o *tTimeoutError) Timeout() bool   { return true }
func (o *tTimeoutError) Temporary() bool { return true }

type tMsg map[string]interface{}

//: these are instructions/guidance comments
//: you'll implement the public api to add/edit userdb records
//: for all ops, you look up a record in cache,
//:   and if not there call getRecord and cache the result
//:   lookups are done with aObj := o.Uid[iUid] (or o.Alias, o.List)
//: for add/edit ops, you then modify the cache object, then call putRecord
//: locking
//:   cache read ops are done inside o.xyzDoor.RLock/RUnlock()
//:   cache add/delete ops are done inside o.xyzDoor.Lock/Unlock()
//:   Uid and List object updates are done inside aObj.door.Lock/Unlock()
//: records are stored as files in subdirectories of o.root: uid, alias, list
//:   uid/* & list/* files are json format
//:   alias/* files are symlinks to Uid

type tUserDb struct {
   root string // top-level directory
   temp string // temp subdirectory; write files here first
   uidDoor, alsDoor, lstDoor sync.RWMutex // protect cache during update

   // cache records here
   Uid map[string]tUser
   Alias map[string]string // value is Uid
   List map[string]tList
}

type tUser struct {
   door sync.RWMutex
   Nodes map[string]int // value is NodeRef
   Aliases []tAlias // public names for the user
}

type tAlias struct {
   En string // in english
   Nat string // in whatever language
}

type tList struct {
   door sync.RWMutex
   Uid map[string]tMember
}

type tMember struct {
   Alias string // invited/joined by this Alias
   Joined bool // use a date here?
}

//type tUserDbErr string
//func (o tUserDbErr) Error() string { return string(o) }

type tType string
const (
   eTuid   tType = "uid"
   eTalias tType = "alias"
   eTlist  tType = "list"
)

func NewUserDb(iPath string) (*tUserDb, error) {
   for _, a := range [...]tType{ "temp", eTuid, eTalias, eTlist } {
      err := os.MkdirAll(iPath + "/" + string(a), 0700)
      if err != nil { return nil, err }
   }

   aDb := new(tUserDb)
   aDb.root = iPath+"/"
   aDb.temp = aDb.root + "temp"
   aDb.Uid = make(map[string]tUser)
   aDb.Alias = make(map[string]string)
   aDb.List = make(map[string]tList)

   return aDb, nil
}

func (o *tUserDb) Test() error {
   //: exercise the api, print diagnostics
   //: invoke from main() before tTestClient loop; stop program if tests fail
   return nil
}

//: below is the public api

func (o *tUserDb) AddUser(iUid, iNewNode string, iAliases []string) (aAliases []string, err error) {
   //: add user if iUid not in db
   return []string{}, nil
}

func (o *tUserDb) SetAliases(iUid, iNode string, iAliases []string) (aAliases []string, err error) {
   //: replace aliases if iUid in db and has iNode, and iAliases elements are unique
   return []string{}, nil
}

func (o *tUserDb) AddNode(iUid, iNode, iNewNode string) (aNodeRef int, err error) {
   //: add iNewNode if iUid in db and has iNode
   return 0, nil
}

func (o *tUserDb) DropNode(iUid, iNode string) error {
   //: delete iNode if iUid in db and has iNode
   return nil
}

//func (o *tUserDb) DropUser(iUid string) error {
//   return nil
//}

func (o *tUserDb) Verify(iUid, iNode string) (aNodeRef int, err error) {
   //: return noderef if iUid in db and has iNode
   // trivial implementation for qlib testing
   o.Uid[iUid] = tUser{Nodes: map[string]int{iNode:0}}
   return 0, nil
}

func (o *tUserDb) GetNodes(iUid string) (aNodes []string, err error) {
   //: return noderefs if iUid in db
   // trivial implementation for qlib testing
   for aN,_ := range o.Uid[iUid].Nodes {
      aNodes = append(aNodes, aN)
   }
   return aNodes, nil
}

func (o *tUserDb) Lookup(iAlias string) (aUid string, err error) {
   //: return uid if iAlias in db
   return "", nil
}

func (o *tUserDb) ListInvite(iList, iBy, iAlias string) error {
   //: if iAlias in db, and iBy in db & iList (or make iList and add iBy), list iAlias
   return nil
}

func (o *tUserDb) ListJoin(iList, iAlias, iUid string) (aAlias string, err error) {
   //: return listed alias if iList in db and iUid in iList, list iAlias if != ""
   return "", nil
}

func (o *tUserDb) ListDrop(iList, iBy, iUid string) error {
   //: remove iUid from iList if iBy in iList
   return nil
}

func (o *tUserDb) ListLookup(iList, iBy string) (aUids []string, err error) {
   //: return uids if iBy in list
   return []string{}, nil
}

// pull a file into a cache object
func (o *tUserDb) getRecord(iType tType, iId string) (interface{}, error) {
   var err error
   var aObj interface{}
   aPath := o.root + string(iType) + "/" + iId

   // in case putRecord was interrupted
   err = os.Link(aPath + ".tmp", aPath)
   if err != nil {
      if !os.IsExist(err) && !os.IsNotExist(err) { return nil, err }
   } else {
      fmt.Println("getRecord: finished transaction for "+aPath)
   }

   switch (iType) {
   default:
      panic("getRecord: unexpected type "+iType)
   case "alias":
      aLn, err := os.Readlink(aPath)
      if err != nil {
         if os.IsNotExist(err) { return nil, nil }
         return nil, err
      }
      return &aLn, nil
   case "uid":  aObj = &tUser{}
   case "list": aObj = &tList{}
   }

   aBuf, err := ioutil.ReadFile(aPath)
   if err != nil {
      if os.IsNotExist(err) { return nil, nil }
      return nil, err
   }

   err = json.Unmarshal(aBuf, aObj)
   return aObj, err
}

// save cache object to disk. getRecord must be called before this
func (o *tUserDb) putRecord(iType tType, iId string, iObj interface{}) error {
   var err error
   aPath := o.root + string(iType) + "/" + iId
   aTemp := o.temp + string(iType) + "_" + iId

   err = os.Remove(aPath + ".tmp")
   if err == nil {
      fmt.Println("putRecord: removed residual .tmp file for "+aPath)
   }

   switch (iType) {
   default:
      panic("putRecord: unexpected type "+iType)
   case "alias":
      err = os.Symlink(iObj.(string), aPath + ".tmp")
      if err != nil { return err }
      return o.commitDir(iType, aPath)
   case "uid", "list":
   }

   aBuf, err := json.Marshal(iObj)
   if err != nil { return err }

   aFd, err := os.OpenFile(aTemp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
   if err != nil { return err }
   defer aFd.Close()

   for aPos,aLen := 0,0; aPos < len(aBuf); aPos += aLen {
      aLen, err = aFd.Write(aBuf[aPos:])
      if err != nil { return err }
   }

   err = aFd.Sync()
   if err != nil { return err }

   err = os.Link(aTemp, aPath + ".tmp")
   if err != nil { return err }
   err = os.Remove(aTemp)
   if err != nil { return err }

   return o.commitDir(iType, aPath)
}

// sync the directory and set the filename
func (o *tUserDb) commitDir(iType tType, iPath string) error {
   aFd, err := os.Open(o.root + string(iType))
   if err != nil { return err }
   defer aFd.Close()
   err = aFd.Sync()
   if err != nil { return err }

   err = os.Remove(iPath)
   if err != nil && !os.IsNotExist(err) { return err }
   err = os.Rename(iPath + ".tmp", iPath)
   return err
}
<|endoftext|>


<commit_before>package critbitgo

import (
	"io"
	"net"
)

// IP routing table.
type Net struct {
	trie *Trie
}

func (n *Net) AddCIDR(s string, value interface{}) error {
	key, err := netCidrToKey(s)
	if err != nil {
		return err
	}
	return n.trie.Set(key, value)
}

func (n *Net) DeleteCIDR(s string) bool {
	key, err := netCidrToKey(s)
	if err != nil {
		return false
	}
	return n.trie.Delete(key)
}

func (n *Net) GetCIDR(s string) (value interface{}, err error) {
	key, err := netCidrToKey(s)
	if err == nil {
		if node := n.trie.search(key); node != nil {
			value = node.value
		}
	}
	return
}

func (n *Net) MatchCIDR(s string) (cidr string, value interface{}, err error) {
	key, err := netCidrToKey(s)
	if err == nil {
		if node := match(n.trie.root, key, false); node != nil {
			cidr = netKeyToCidr(node.key)
			value = node.value
		}
	}
	return
}

func match(p *node, key []byte, backtracking bool) *node {
	if p.internal {
		var direction int
		if p.offset == len(key)-2 {
			// selecting the larger side when comparing the mask
			direction = 1
		} else if backtracking {
			direction = 0
		} else {
			direction = p.direction(key)
		}

		if c := match(p.child[direction], key, backtracking); c != nil {
			return c
		}
		if direction == 1 {
			// search other node
			return match(p.child[0], key, true)
		}
		return nil
	} else {
		nlen := len(p.key)
		if nlen != len(key) {
			return nil
		}

		// check mask
		mask := p.key[nlen-2]
		if mask > key[nlen-2] {
			return nil
		}

		// compare both keys with mask
		div := int(mask / 8)
		for i := 0; i < div; i++ {
			if p.key[i] != key[i] {
				return nil
			}
		}
		if mod := uint(mask % 8); mod > 0 {
			bit := 8 - mod
			if p.key[div] != key[div]&(0xff>>bit<<bit) {
				return nil
			}
		}
		return p
	}
}

func (n *Net) Clear() {
	n.trie.Clear()
}

func (n *Net) Size() int {
	return n.trie.Size()
}

func (n *Net) Dump(w io.Writer) {
	n.trie.Dump(w)
}

func NewNet() *Net {
	t := NewTrie()
	return &Net{t}
}

func netCidrToKey(s string) ([]byte, error) {
	_, ipnet, err := net.ParseCIDR(s)
	if err != nil {
		return nil, err
	}
	ones, _ := ipnet.Mask.Size()
	// +--------------+------+--------------+
	// | ip address.. | mask | termination  |
	// +--------------+------+--------------+
	return append(append(ipnet.IP, byte(ones)), 0xff), nil
}

func netKeyToCidr(k []byte) string {
	iplen := len(k) - 2
	ipnet := &net.IPNet{
		IP:   net.IP(k[:iplen]),
		Mask: net.CIDRMask(int(k[iplen]), iplen*8),
	}
	return ipnet.String()
}
<commit_msg>change a little bit<commit_after>package critbitgo

import (
	"net"
)

// IP routing table.
type Net struct {
	trie *Trie
}

func (n *Net) AddCIDR(s string, value interface{}) error {
	key, err := netCidrToKey(s)
	if err != nil {
		return err
	}
	return n.trie.Set(key, value)
}

func (n *Net) DeleteCIDR(s string) bool {
	key, err := netCidrToKey(s)
	if err != nil {
		return false
	}
	return n.trie.Delete(key)
}

func (n *Net) GetCIDR(s string) (value interface{}, err error) {
	key, err := netCidrToKey(s)
	if err == nil {
		if node := n.trie.search(key); node != nil {
			value = node.value
		}
	}
	return
}

func (n *Net) MatchCIDR(s string) (cidr string, value interface{}, err error) {
	key, err := netCidrToKey(s)
	if err == nil {
		if node := match(n.trie.root, key, false); node != nil {
			cidr = netKeyToCidr(node.key)
			value = node.value
		}
	}
	return
}

func match(p *node, key []byte, backtracking bool) *node {
	if p.internal {
		var direction int
		if p.offset == len(key)-2 {
			// selecting the larger side when comparing the mask
			direction = 1
		} else if backtracking {
			direction = 0
		} else {
			direction = p.direction(key)
		}

		if c := match(p.child[direction], key, backtracking); c != nil {
			return c
		}
		if direction == 1 {
			// search other node
			return match(p.child[0], key, true)
		}
		return nil
	} else {
		nlen := len(p.key)
		if nlen != len(key) {
			return nil
		}

		// check mask
		mask := p.key[nlen-2]
		if mask > key[nlen-2] {
			return nil
		}

		// compare both keys with mask
		div := int(mask >> 3)
		for i := 0; i < div; i++ {
			if p.key[i] != key[i] {
				return nil
			}
		}
		if mod := uint(mask & 0x07); mod > 0 {
			bit := 8 - mod
			if p.key[div] != key[div]&(0xff>>bit<<bit) {
				return nil
			}
		}
		return p
	}
}

func (n *Net) Clear() {
	n.trie.Clear()
}

func (n *Net) Size() int {
	return n.trie.Size()
}

func NewNet() *Net {
	return &Net{NewTrie()}
}

func netCidrToKey(s string) ([]byte, error) {
	_, ipnet, err := net.ParseCIDR(s)
	if err != nil {
		return nil, err
	}
	ones, _ := ipnet.Mask.Size()
	// +--------------+------+--------------+
	// | ip address.. | mask | termination  |
	// +--------------+------+--------------+
	return append(append(ipnet.IP, byte(ones)), 0xff), nil
}

func netKeyToCidr(k []byte) string {
	iplen := len(k) - 2
	ipnet := &net.IPNet{
		IP:   net.IP(k[:iplen]),
		Mask: net.CIDRMask(int(k[iplen]), iplen*8),
	}
	return ipnet.String()
}
<|endoftext|>


<commit_before>package gothink

import (
    "encoding/json"
    "io/ioutil"
)

type Net interface {
    Epoch()
}

type Layer struct {
    Activation  string
    Weights     [][]float64
}

/*
A feed forward type neural network
*/
type FFNet struct {
    //Net
    Layers []Layer
}

func NewFFNet (filepath string) (*FFNet, error) {
    b, err := ioutil.ReadFile(filepath)

    if err != nil {
        panic(err)
    }

    ff := FFNet{}
    return &ff, json.Unmarshal(b, &ff)
}

func (ff *FFNet) ToJson (filepath string) ([]byte, error) {
    if filepath != "" {
        d, err := json.Marshal(&ff)

        if err != nil{
            panic(err)
        }

        err1 := ioutil.WriteFile(filepath, d, 0644)

        return d, err1
    }
    return json.Marshal(&ff)
}

/*
func EncFFNet () ([]byte, error) {
    f := FFNet{}

    f.Layers = make(map[string]interface{})

    f.Layers["one"] = []float64{.5, .2}
    f.Layers["two"] = []float64{.0, .1}
    return json.Marshal(f)
}
*/
<commit_msg>Start layer evaluation functionality<commit_after>package gothink

import (
    "encoding/json"
    "io/ioutil"
)

type Net interface {
    Epoch()
}

type Layer struct {
    Activation  string
    Weights     [][]float64
}

func (L *Layer) Eval () {
    sem := make(chan empty )
    for i, _ := range L.Weights {
        go func () {
            sum = 0
            for _, n := range L.Weights[i] {
                sum += n
            }
            sigmoid(&L.Weights[i])
        }
    }
}

func sigmoid (L *Layer) {
    return 1.0 / (1.0 + math.Exp(-sum))
}

/*
A feed forward type neural network
*/
type FFNet struct {
    //Net
    Layers []Layer
}

func NewFFNet (filepath string) (*FFNet, error) {
    b, err := ioutil.ReadFile(filepath)
    if err != nil {
        panic(err)
    }

    ff := FFNet{}
    return &ff, json.Unmarshal(b, &ff)
}

func (ff *FFNet) ToJson (filepath string) ([]byte, error) {
    if filepath != "" {
        d, err := json.Marshal(&ff)

        if err != nil{
            panic(err)
        }

        err1 := ioutil.WriteFile(filepath, d, 0644)

        return d, err1
    }
    return json.Marshal(&ff)
}
<|endoftext|>


<commit_before>package suite

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"html/template"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"k8s.io/api/apps/v1beta2"
	coreV1 "k8s.io/api/core/v1"
	rbacV1 "k8s.io/api/rbac/v1"
	apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
	apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/util/yaml"
	"k8s.io/apimachinery/pkg/watch"
	"k8s.io/client-go/kubernetes"
	appsv1beta2 "k8s.io/client-go/kubernetes/typed/apps/v1beta2"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/util/workqueue"
)

var config *rest.Config

type Params struct {
	Image string
}

var serviceAccountTemplate = `
apiVersion: v1
kind: ServiceAccount
metadata:
  name: e2e-service-account
`

var clusterRoleTemplate = `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: e2e-test-role
rules:
`

var clusterRoleCRDTemplate = `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: e2e-test-role-crd
rules:
- apiGroups: ["apiextensions.k8s.io"]
  resources: ["customresourcedefinitions"]
  verbs: ["*"]
- apiGroups: ["", "apps"]
  resources: ["deployments", "services" ]
  verbs: ["*"]
- apiGroups: ["es.matt-tyler.github.com"]
  resources: ["clusters"]
  verbs: ["*"]
`

var clusterRoleBindingTemplate = `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: e2e-test-role-cluster-binding
roleRef:
  kind: ClusterRole
  name: e2e-test-role-crd
  apiGroup: rbac.authorization.k8s.io
`

var deploymentTemplate = `
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: elasticsearch-operator
spec:
  replicas: 1
  selector:
    matchLabels:
      app: elasticsearch-operator
  template:
    metadata:
      labels:
        app: elasticsearch-operator
    spec:
      serviceAccountName: e2e-service-account
      containers:
      - name: elasticsearch-operator
        image: {{.Image}}
`

func createClusterRoles(clientset kubernetes.Interface) ([]*rbacV1.ClusterRole, error) {
	clusterRole := &rbacV1.ClusterRole{}
	roles := []*rbacV1.ClusterRole{}

	clusterRoleJSON, err := yaml.ToJSON([]byte(clusterRoleTemplate))
	if err != nil {
		return nil, err
	}

	if err := json.Unmarshal(clusterRoleJSON, &clusterRole); err != nil {
		return nil, err
	}

	role, err := clientset.RbacV1().ClusterRoles().Create(clusterRole)
	if err != nil {
		return nil, err
	}
	roles = append(roles, role)

	clusterRoleJSON, err = yaml.ToJSON([]byte(clusterRoleCRDTemplate))
	if err != nil {
		return nil, err
	}

	if err := json.Unmarshal(clusterRoleJSON, &clusterRole); err != nil {
		return nil, err
	}

	role, err = clientset.RbacV1().ClusterRoles().Create(clusterRole)
	if err != nil {
		return nil, err
	}

	return append(roles, role), nil
}

func deleteClusterRole(clusterRole *rbacV1.ClusterRole, clientset kubernetes.Interface) error {
	return clientset.RbacV1().ClusterRoles().Delete(clusterRole.Name, nil)
}

func createServiceAccount(namespace string, clientset kubernetes.Interface) (*coreV1.ServiceAccount, error) {
	serviceAccount := &coreV1.ServiceAccount{}

	buf := &bytes.Buffer{}
	p := struct {
		Namespace string
	}{namespace}

	tmpl := template.Must(template.New("").Parse(serviceAccountTemplate))
	err := tmpl.Execute(buf, p)
	if err != nil {
		return nil, err
	}

	serviceAccountJSON, err := yaml.ToJSON(buf.Bytes())
	if err != nil {
		return nil, err
	}

	if err := json.Unmarshal(serviceAccountJSON, &serviceAccount); err != nil {
		return nil, err
	}

	return clientset.CoreV1().ServiceAccounts(namespace).Create(serviceAccount)
}

func deleteServiceAccount(serviceAccount *coreV1.ServiceAccount, clientset kubernetes.Interface) error {
	return clientset.CoreV1().ServiceAccounts(serviceAccount.Namespace).Delete(serviceAccount.Name, nil)
}

func createClusterRoleBinding(serviceAccount *coreV1.ServiceAccount, clientset kubernetes.Interface) (*rbacV1.ClusterRoleBinding, error) {
	clusterRoleBinding := &rbacV1.ClusterRoleBinding{}

	clusterRoleBindingJSON, err := yaml.ToJSON([]byte(clusterRoleBindingTemplate))
	if err != nil {
		return nil, err
	}

	if err := json.Unmarshal(clusterRoleBindingJSON, &clusterRoleBinding); err != nil {
		return nil, err
	}

	clusterRoleBinding.Subjects = []rbacV1.Subject{{
		Kind:      "ServiceAccount",
		Name:      serviceAccount.Name,
		Namespace: serviceAccount.Namespace,
		APIGroup:  "",
	}}

	return clientset.RbacV1().ClusterRoleBindings().Create(clusterRoleBinding)
}

func deleteClusterRoleBinding(clusterRoleBinding *rbacV1.ClusterRoleBinding, clientset kubernetes.Interface) error {
	return clientset.RbacV1().ClusterRoleBindings().Delete(clusterRoleBinding.Name, nil)
}

// Setup registers the custom resource definition/s
func Setup(c *rest.Config, image string) error {

	config = c

	// TODO: Use CopyConfig when bumping client-go to >= 4.0

	apiextensionsclientset := apiextensionsclient.NewForConfigOrDie(CopyConfig(config))

	queue := workqueue.New()

	informer := cache.NewSharedIndexInformer(
		&cache.ListWatch{
			ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
				return apiextensionsclientset.ApiextensionsV1beta1().
					CustomResourceDefinitions().List(metav1.ListOptions{})
			},
			WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
				return apiextensionsclientset.ApiextensionsV1beta1().
					CustomResourceDefinitions().Watch(metav1.ListOptions{})
			},
		},
		&apiextensionsv1beta1.CustomResourceDefinition{},
		0,
		cache.Indexers{},
	)

	informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			if key, err := cache.MetaNamespaceKeyFunc(obj); err == nil {
				queue.Add(key)
			}
		},
		DeleteFunc: func(obj interface{}) {
			if key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj); err == nil {
				queue.Add(key)
			}
		},
	})

	ctx, cancel := context.WithCancel(context.Background())

	go informer.Run(ctx.Done())

	if !cache.WaitForCacheSync(ctx.Done(), informer.HasSynced) {
		cancel()
		return errors.New("Failed waiting for cache sync")
	}

	var deployment *v1beta2.Deployment

	clusterRoles := []*rbacV1.ClusterRole{}
	var serviceAccount *coreV1.ServiceAccount
	var clusterRoleBinding *rbacV1.ClusterRoleBinding

	BeforeSuite(func() {
		var err error

		k8s := kubernetes.NewForConfigOrDie(CopyConfig(config))
		clusterRoles, err = createClusterRoles(k8s)
		Expect(err).NotTo(HaveOccurred())

		serviceAccount, err = createServiceAccount("default", k8s)
		Expect(err).NotTo(HaveOccurred())

		clusterRoleBinding, err = createClusterRoleBinding(serviceAccount, k8s)
		Expect(err).NotTo(HaveOccurred())

		clientset := appsv1beta2.NewForConfigOrDie(CopyConfig(config))

		deploymentClient := clientset.Deployments(metav1.NamespaceDefault)

		buf := &bytes.Buffer{}
		p := &Params{
			image,
		}

		tmpl := template.Must(template.New("").Parse(deploymentTemplate))
		err = tmpl.Execute(buf, p)
		Expect(err).NotTo(HaveOccurred())

		deploymentJSON, err := yaml.ToJSON(buf.Bytes())
		Expect(err).NotTo(HaveOccurred())

		err = json.Unmarshal(deploymentJSON, &deployment)
		Expect(err).NotTo(HaveOccurred())

		deployment, err = deploymentClient.Create(deployment)
		Expect(err).NotTo(HaveOccurred())

		timeout := time.After(time.Second * 10)

		for {
			select {
			case <-timeout:
				Fail("Creating custom resource definition exceeded timeout")
			default:
				key, _ := queue.Get()
				defer queue.Done(key)

				_, exists, err := informer.GetIndexer().GetByKey(key.(string))
				if err != nil {
					Fail(err.Error())
				}

				if exists {
					return
				}
			}
		}
	})

	AfterSuite(func() {
		clientset := appsv1beta2.NewForConfigOrDie(CopyConfig(config))

		deploymentClient := clientset.Deployments(metav1.NamespaceDefault)

		deletePolicy := metav1.DeletePropagationForeground
		err := deploymentClient.Delete(deployment.Name, &metav1.DeleteOptions{
			PropagationPolicy: &deletePolicy,
		})
		Expect(err).NotTo(HaveOccurred())

		timeout := time.After(time.Second * 10)
		for {
			select {
			case <-timeout:
				Fail("Deleting custom resource definition exceeded time out.")
			default:
				key, _ := queue.Get()
				defer queue.Done(key)

				_, exists, err := informer.GetIndexer().GetByKey(key.(string))
				if err != nil {
					Fail(err.Error())
				}

				if !exists {
					k8s := kubernetes.NewForConfigOrDie(CopyConfig(config))

					if clusterRoleBinding != nil {
						_ = deleteClusterRoleBinding(clusterRoleBinding, k8s)
					}

					if serviceAccount != nil {
						_ = deleteServiceAccount(serviceAccount, k8s)
					}

					for _, role := range clusterRoles {
						_ = deleteClusterRole(role, k8s)
					}

					cancel()
					queue.ShutDown()
					return
				}
			}
		}
	})

	return nil
}

func CopyConfig(config *rest.Config) *rest.Config {
	return &rest.Config{
		Host:          config.Host,
		APIPath:       config.APIPath,
		Prefix:        config.Prefix,
		ContentConfig: config.ContentConfig,
		Username:      config.Username,
		Password:      config.Password,
		BearerToken:   config.BearerToken,
		Impersonate: rest.ImpersonationConfig{
			Groups:   config.Impersonate.Groups,
			Extra:    config.Impersonate.Extra,
			UserName: config.Impersonate.UserName,
		},
		AuthProvider:        config.AuthProvider,
		AuthConfigPersister: config.AuthConfigPersister,
		TLSClientConfig: rest.TLSClientConfig{
			Insecure:   config.TLSClientConfig.Insecure,
			ServerName: config.TLSClientConfig.ServerName,
			CertFile:   config.TLSClientConfig.CertFile,
			KeyFile:    config.TLSClientConfig.KeyFile,
			CAFile:     config.TLSClientConfig.CAFile,
			CertData:   config.TLSClientConfig.CertData,
			KeyData:    config.TLSClientConfig.KeyData,
			CAData:     config.TLSClientConfig.CAData,
		},
		UserAgent:     config.UserAgent,
		Transport:     config.Transport,
		WrapTransport: config.WrapTransport,
		QPS:           config.QPS,
		Burst:         config.Burst,
		RateLimiter:   config.RateLimiter,
		Timeout:       config.Timeout,
	}
}
<commit_msg>bump deployment version<commit_after>package suite

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"html/template"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"k8s.io/api/apps/v1beta2"
	coreV1 "k8s.io/api/core/v1"
	rbacV1 "k8s.io/api/rbac/v1"
	apiextensionsv1beta2 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta2"
	apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/util/yaml"
	"k8s.io/apimachinery/pkg/watch"
	"k8s.io/client-go/kubernetes"
	appsv1beta2 "k8s.io/client-go/kubernetes/typed/apps/v1beta2"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/util/workqueue"
)

var config *rest.Config

type Params struct {
	Image string
}

var serviceAccountTemplate = `
apiVersion: v1
kind: ServiceAccount
metadata:
  name: e2e-service-account
`

var clusterRoleTemplate = `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: e2e-test-role
rules:
`

var clusterRoleCRDTemplate = `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: e2e-test-role-crd
rules:
- apiGroups: ["apiextensions.k8s.io"]
  resources: ["customresourcedefinitions"]
  verbs: ["*"]
- apiGroups: ["", "apps"]
  resources: ["deployments", "services" ]
  verbs: ["*"]
- apiGroups: ["es.matt-tyler.github.com"]
  resources: ["clusters"]
  verbs: ["*"]
`

var clusterRoleBindingTemplate = `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: e2e-test-role-cluster-binding
roleRef:
  kind: ClusterRole
  name: e2e-test-role-crd
  apiGroup: rbac.authorization.k8s.io
`

var deploymentTemplate = `
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: elasticsearch-operator
spec:
  replicas: 1
  selector:
    matchLabels:
      app: elasticsearch-operator
  template:
    metadata:
      labels:
        app: elasticsearch-operator
    spec:
      serviceAccountName: e2e-service-account
      containers:
      - name: elasticsearch-operator
        image: {{.Image}}
`

func createClusterRoles(clientset kubernetes.Interface) ([]*rbacV1.ClusterRole, error) {
	clusterRole := &rbacV1.ClusterRole{}
	roles := []*rbacV1.ClusterRole{}

	clusterRoleJSON, err := yaml.ToJSON([]byte(clusterRoleTemplate))
	if err != nil {
		return nil, err
	}

	if err := json.Unmarshal(clusterRoleJSON, &clusterRole); err != nil {
		return nil, err
	}

	role, err := clientset.RbacV1().ClusterRoles().Create(clusterRole)
	if err != nil {
		return nil, err
	}
	roles = append(roles, role)

	clusterRoleJSON, err = yaml.ToJSON([]byte(clusterRoleCRDTemplate))
	if err != nil {
		return nil, err
	}

	if err := json.Unmarshal(clusterRoleJSON, &clusterRole); err != nil {
		return nil, err
	}

	role, err = clientset.RbacV1().ClusterRoles().Create(clusterRole)
	if err != nil {
		return nil, err
	}

	return append(roles, role), nil
}

func deleteClusterRole(clusterRole *rbacV1.ClusterRole, clientset kubernetes.Interface) error {
	return clientset.RbacV1().ClusterRoles().Delete(clusterRole.Name, nil)
}

func createServiceAccount(namespace string, clientset kubernetes.Interface) (*coreV1.ServiceAccount, error) {
	serviceAccount := &coreV1.ServiceAccount{}

	buf := &bytes.Buffer{}
	p := struct {
		Namespace string
	}{namespace}

	tmpl := template.Must(template.New("").Parse(serviceAccountTemplate))
	err := tmpl.Execute(buf, p)
	if err != nil {
		return nil, err
	}

	serviceAccountJSON, err := yaml.ToJSON(buf.Bytes())
	if err != nil {
		return nil, err
	}

	if err := json.Unmarshal(serviceAccountJSON, &serviceAccount); err != nil {
		return nil, err
	}

	return clientset.CoreV1().ServiceAccounts(namespace).Create(serviceAccount)
}

func deleteServiceAccount(serviceAccount *coreV1.ServiceAccount, clientset kubernetes.Interface) error {
	return clientset.CoreV1().ServiceAccounts(serviceAccount.Namespace).Delete(serviceAccount.Name, nil)
}

func createClusterRoleBinding(serviceAccount *coreV1.ServiceAccount, clientset kubernetes.Interface) (*rbacV1.ClusterRoleBinding, error) {
	clusterRoleBinding := &rbacV1.ClusterRoleBinding{}

	clusterRoleBindingJSON, err := yaml.ToJSON([]byte(clusterRoleBindingTemplate))
	if err != nil {
		return nil, err
	}

	if err := json.Unmarshal(clusterRoleBindingJSON, &clusterRoleBinding); err != nil {
		return nil, err
	}

	clusterRoleBinding.Subjects = []rbacV1.Subject{{
		Kind:      "ServiceAccount",
		Name:      serviceAccount.Name,
		Namespace: serviceAccount.Namespace,
		APIGroup:  "",
	}}

	return clientset.RbacV1().ClusterRoleBindings().Create(clusterRoleBinding)
}

func deleteClusterRoleBinding(clusterRoleBinding *rbacV1.ClusterRoleBinding, clientset kubernetes.Interface) error {
	return clientset.RbacV1().ClusterRoleBindings().Delete(clusterRoleBinding.Name, nil)
}

// Setup registers the custom resource definition/s
func Setup(c *rest.Config, image string) error {

	config = c

	// TODO: Use CopyConfig when bumping client-go to >= 4.0

	apiextensionsclientset := apiextensionsclient.NewForConfigOrDie(CopyConfig(config))

	queue := workqueue.New()

	informer := cache.NewSharedIndexInformer(
		&cache.ListWatch{
			ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
				return apiextensionsclientset.ApiextensionsV1beta2().
					CustomResourceDefinitions().List(metav1.ListOptions{})
			},
			WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
				return apiextensionsclientset.ApiextensionsV1beta2().
					CustomResourceDefinitions().Watch(metav1.ListOptions{})
			},
		},
		&apiextensionsv1beta2.CustomResourceDefinition{},
		0,
		cache.Indexers{},
	)

	informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			if key, err := cache.MetaNamespaceKeyFunc(obj); err == nil {
				queue.Add(key)
			}
		},
		DeleteFunc: func(obj interface{}) {
			if key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj); err == nil {
				queue.Add(key)
			}
		},
	})

	ctx, cancel := context.WithCancel(context.Background())

	go informer.Run(ctx.Done())

	if !cache.WaitForCacheSync(ctx.Done(), informer.HasSynced) {
		cancel()
		return errors.New("Failed waiting for cache sync")
	}

	var deployment *v1beta2.Deployment

	clusterRoles := []*rbacV1.ClusterRole{}
	var serviceAccount *coreV1.ServiceAccount
	var clusterRoleBinding *rbacV1.ClusterRoleBinding

	BeforeSuite(func() {
		var err error

		k8s := kubernetes.NewForConfigOrDie(CopyConfig(config))
		clusterRoles, err = createClusterRoles(k8s)
		Expect(err).NotTo(HaveOccurred())

		serviceAccount, err = createServiceAccount("default", k8s)
		Expect(err).NotTo(HaveOccurred())

		clusterRoleBinding, err = createClusterRoleBinding(serviceAccount, k8s)
		Expect(err).NotTo(HaveOccurred())

		clientset := appsv1beta2.NewForConfigOrDie(CopyConfig(config))

		deploymentClient := clientset.Deployments(metav1.NamespaceDefault)

		buf := &bytes.Buffer{}
		p := &Params{
			image,
		}

		tmpl := template.Must(template.New("").Parse(deploymentTemplate))
		err = tmpl.Execute(buf, p)
		Expect(err).NotTo(HaveOccurred())

		deploymentJSON, err := yaml.ToJSON(buf.Bytes())
		Expect(err).NotTo(HaveOccurred())

		err = json.Unmarshal(deploymentJSON, &deployment)
		Expect(err).NotTo(HaveOccurred())

		deployment, err = deploymentClient.Create(deployment)
		Expect(err).NotTo(HaveOccurred())

		timeout := time.After(time.Second * 10)

		for {
			select {
			case <-timeout:
				Fail("Creating custom resource definition exceeded timeout")
			default:
				key, _ := queue.Get()
				defer queue.Done(key)

				_, exists, err := informer.GetIndexer().GetByKey(key.(string))
				if err != nil {
					Fail(err.Error())
				}

				if exists {
					return
				}
			}
		}
	})

	AfterSuite(func() {
		clientset := appsv1beta2.NewForConfigOrDie(CopyConfig(config))

		deploymentClient := clientset.Deployments(metav1.NamespaceDefault)

		deletePolicy := metav1.DeletePropagationForeground
		err := deploymentClient.Delete(deployment.Name, &metav1.DeleteOptions{
			PropagationPolicy: &deletePolicy,
		})
		Expect(err).NotTo(HaveOccurred())

		timeout := time.After(time.Second * 10)
		for {
			select {
			case <-timeout:
				Fail("Deleting custom resource definition exceeded time out.")
			default:
				key, _ := queue.Get()
				defer queue.Done(key)

				_, exists, err := informer.GetIndexer().GetByKey(key.(string))
				if err != nil {
					Fail(err.Error())
				}

				if !exists {
					k8s := kubernetes.NewForConfigOrDie(CopyConfig(config))

					if clusterRoleBinding != nil {
						_ = deleteClusterRoleBinding(clusterRoleBinding, k8s)
					}

					if serviceAccount != nil {
						_ = deleteServiceAccount(serviceAccount, k8s)
					}

					for _, role := range clusterRoles {
						_ = deleteClusterRole(role, k8s)
					}

					cancel()
					queue.ShutDown()
					return
				}
			}
		}
	})

	return nil
}

func CopyConfig(config *rest.Config) *rest.Config {
	return &rest.Config{
		Host:          config.Host,
		APIPath:       config.APIPath,
		Prefix:        config.Prefix,
		ContentConfig: config.ContentConfig,
		Username:      config.Username,
		Password:      config.Password,
		BearerToken:   config.BearerToken,
		Impersonate: rest.ImpersonationConfig{
			Groups:   config.Impersonate.Groups,
			Extra:    config.Impersonate.Extra,
			UserName: config.Impersonate.UserName,
		},
		AuthProvider:        config.AuthProvider,
		AuthConfigPersister: config.AuthConfigPersister,
		TLSClientConfig: rest.TLSClientConfig{
			Insecure:   config.TLSClientConfig.Insecure,
			ServerName: config.TLSClientConfig.ServerName,
			CertFile:   config.TLSClientConfig.CertFile,
			KeyFile:    config.TLSClientConfig.KeyFile,
			CAFile:     config.TLSClientConfig.CAFile,
			CertData:   config.TLSClientConfig.CertData,
			KeyData:    config.TLSClientConfig.KeyData,
			CAData:     config.TLSClientConfig.CAData,
		},
		UserAgent:     config.UserAgent,
		Transport:     config.Transport,
		WrapTransport: config.WrapTransport,
		QPS:           config.QPS,
		Burst:         config.Burst,
		RateLimiter:   config.RateLimiter,
		Timeout:       config.Timeout,
	}
}
<|endoftext|>


<commit_before>package git

/*
#include <git2.h>
#include <git2/errors.h>

extern int _go_git_odb_foreach(git_odb *db, void *payload);
*/
import "C"
import (
	"unsafe"
	"reflect"
	"runtime"
)

type Odb struct {
	ptr *C.git_odb
}

func (v *Odb) Exists(oid *Oid) bool {
	ret := C.git_odb_exists(v.ptr, oid.toC())
	return ret != 0
}

func (v *Odb) Write(data []byte, otype ObjectType) (oid *Oid, err error) {
	oid = new(Oid)
	hdr := (*reflect.SliceHeader)(unsafe.Pointer(&data))

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_odb_write(oid.toC(), v.ptr, unsafe.Pointer(hdr.Data), C.size_t(hdr.Len), C.git_otype(otype))

	if ret < 0 {
		err = LastError()
	}

	return
}

func (v *Odb) Read(oid *Oid) (obj *OdbObject, err error) {
	obj = new(OdbObject)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_odb_read(&obj.ptr, v.ptr, oid.toC())
	if ret < 0 {
		return nil, LastError()
	}

	runtime.SetFinalizer(obj, (*OdbObject).Free)
	return
}

//export odbForEachCb
func odbForEachCb(id *C.git_oid, payload unsafe.Pointer) int {
	ch := *(*chan *Oid)(payload)
	oid := newOidFromC(id)
	// Because the channel is unbuffered, we never read our own data. If ch is
	// readable, the user has sent something on it, which means we should
	// abort.
	select {
	case ch <- oid:
	case <-ch:
			return -1
	}
	return 0;
}

func (v *Odb) forEachWrap(ch chan *Oid) {
	C._go_git_odb_foreach(v.ptr, unsafe.Pointer(&ch))
	close(ch)
}

func (v *Odb) ForEach() chan *Oid {
	ch := make(chan *Oid, 0)
	go v.forEachWrap(ch)
	return ch
}

// NewReadStream opens a read stream from the ODB. Reading from it will give you the
// contents of the object.
func (v *Odb) NewReadStream(id *Oid) (*OdbReadStream, error) {
	stream := new(OdbReadStream)
	ret := C.git_odb_open_rstream(&stream.ptr, v.ptr, id.toC())
	if ret < 0 {
		return nil, LastError()
	}

	runtime.SetFinalizer(stream, (*OdbReadStream).Free)
	return stream, nil
}

// NewWriteStream opens a write stream to the ODB, which allows you to
// create a new object in the database. The size and type must be
// known in advance
func (v *Odb) NewWriteStream(size int, otype ObjectType) (*OdbWriteStream, error) {
	stream := new(OdbWriteStream)
	ret := C.git_odb_open_wstream(&stream.ptr, v.ptr, C.size_t(size), C.git_otype(otype))
	if ret < 0 {
		return nil, LastError()
	}

	runtime.SetFinalizer(stream, (*OdbWriteStream).Free)
	return stream, nil
}

type OdbObject struct {
	ptr *C.git_odb_object
}

func (v *OdbObject) Free() {
	runtime.SetFinalizer(v, nil)
	C.git_odb_object_free(v.ptr)
}

func (object *OdbObject) Id() (oid *Oid) {
	return newOidFromC(C.git_odb_object_id(object.ptr))
}

func (object *OdbObject) Len() (len uint64) {
	return uint64(C.git_odb_object_size(object.ptr))
}

func (object *OdbObject) Data() (data []byte) {
	var c_blob unsafe.Pointer = C.git_odb_object_data(object.ptr)
	var blob []byte

	len := int(C.git_odb_object_size(object.ptr))

	sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&blob)))
	sliceHeader.Cap = len
	sliceHeader.Len = len
	sliceHeader.Data = uintptr(c_blob)

	return blob
}

type OdbReadStream struct {
	ptr *C.git_odb_stream
}

// Read reads from the stream
func (stream *OdbReadStream) Read(data []byte) (int, error) {
	header := (*reflect.SliceHeader)(unsafe.Pointer(&data))
	ptr := (*C.char)(unsafe.Pointer(header.Data))
	size := C.size_t(header.Cap)
	ret := C.git_odb_stream_read(stream.ptr, ptr, size)
	if ret < 0 {
		return 0, LastError()
	}

	header.Len = int(ret)

	return len(data), nil
}

// Close is a dummy function in order to implement the Closer and
// ReadCloser interfaces
func (stream *OdbReadStream) Close() error {
	return nil
}

func (stream *OdbReadStream) Free() {
	runtime.SetFinalizer(stream, nil)
	C.git_odb_stream_free(stream.ptr)
}

type OdbWriteStream struct {
	ptr *C.git_odb_stream
	Id Oid
}

// Write writes to the stream
func (stream *OdbWriteStream) Write(data []byte) (int, error) {
	header := (*reflect.SliceHeader)(unsafe.Pointer(&data))
	ptr := (*C.char)(unsafe.Pointer(header.Data))
	size := C.size_t(header.Len)

	ret := C.git_odb_stream_write(stream.ptr, ptr, size)
	if ret < 0 {
		return 0, LastError()
	}

	return len(data), nil
}

// Close signals that all the data has been written and stores the
// resulting object id in the stream's Id field.
func (stream *OdbWriteStream) Close() error {
	ret := C.git_odb_stream_finalize_write(stream.Id.toC(), stream.ptr)
	if ret < 0 {
		return LastError()
	}

	return nil
}

func (stream *OdbWriteStream) Free() {
	runtime.SetFinalizer(stream, nil)
	C.git_odb_stream_free(stream.ptr)
}
<commit_msg>Add Odb hash function.<commit_after>package git

/*
#include <git2.h>
#include <git2/errors.h>

extern int _go_git_odb_foreach(git_odb *db, void *payload);
*/
import "C"
import (
	"unsafe"
	"reflect"
	"runtime"
)

type Odb struct {
	ptr *C.git_odb
}

func (v *Odb) Exists(oid *Oid) bool {
	ret := C.git_odb_exists(v.ptr, oid.toC())
	return ret != 0
}

func (v *Odb) Write(data []byte, otype ObjectType) (oid *Oid, err error) {
	oid = new(Oid)
	hdr := (*reflect.SliceHeader)(unsafe.Pointer(&data))

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_odb_write(oid.toC(), v.ptr, unsafe.Pointer(hdr.Data), C.size_t(hdr.Len), C.git_otype(otype))

	if ret < 0 {
		err = LastError()
	}

	return
}

func (v *Odb) Read(oid *Oid) (obj *OdbObject, err error) {
	obj = new(OdbObject)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_odb_read(&obj.ptr, v.ptr, oid.toC())
	if ret < 0 {
		return nil, LastError()
	}

	runtime.SetFinalizer(obj, (*OdbObject).Free)
	return
}

//export odbForEachCb
func odbForEachCb(id *C.git_oid, payload unsafe.Pointer) int {
	ch := *(*chan *Oid)(payload)
	oid := newOidFromC(id)
	// Because the channel is unbuffered, we never read our own data. If ch is
	// readable, the user has sent something on it, which means we should
	// abort.
	select {
	case ch <- oid:
	case <-ch:
			return -1
	}
	return 0;
}

func (v *Odb) forEachWrap(ch chan *Oid) {
	C._go_git_odb_foreach(v.ptr, unsafe.Pointer(&ch))
	close(ch)
}

func (v *Odb) ForEach() chan *Oid {
	ch := make(chan *Oid, 0)
	go v.forEachWrap(ch)
	return ch
}

// Hash determines the object-ID (sha1) of a data buffer.
func (v *Odb) Hash(data []byte, otype ObjectType) (oid *Oid, err error) {
	oid = new(Oid)
	header := (*reflect.SliceHeader)(unsafe.Pointer(&data))
	ptr := (*C.char)(unsafe.Pointer(header.Data))

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_odb_hash(oid.toC(), unsafe.Pointer(ptr), C.size_t(header.Len), C.git_otype(otype));
	if ret < 0 {
		err = LastError()
	}
	return
}

// NewReadStream opens a read stream from the ODB. Reading from it will give you the
// contents of the object.
func (v *Odb) NewReadStream(id *Oid) (*OdbReadStream, error) {
	stream := new(OdbReadStream)
	ret := C.git_odb_open_rstream(&stream.ptr, v.ptr, id.toC())
	if ret < 0 {
		return nil, LastError()
	}

	runtime.SetFinalizer(stream, (*OdbReadStream).Free)
	return stream, nil
}

// NewWriteStream opens a write stream to the ODB, which allows you to
// create a new object in the database. The size and type must be
// known in advance
func (v *Odb) NewWriteStream(size int, otype ObjectType) (*OdbWriteStream, error) {
	stream := new(OdbWriteStream)
	ret := C.git_odb_open_wstream(&stream.ptr, v.ptr, C.size_t(size), C.git_otype(otype))
	if ret < 0 {
		return nil, LastError()
	}

	runtime.SetFinalizer(stream, (*OdbWriteStream).Free)
	return stream, nil
}

type OdbObject struct {
	ptr *C.git_odb_object
}

func (v *OdbObject) Free() {
	runtime.SetFinalizer(v, nil)
	C.git_odb_object_free(v.ptr)
}

func (object *OdbObject) Id() (oid *Oid) {
	return newOidFromC(C.git_odb_object_id(object.ptr))
}

func (object *OdbObject) Len() (len uint64) {
	return uint64(C.git_odb_object_size(object.ptr))
}

func (object *OdbObject) Data() (data []byte) {
	var c_blob unsafe.Pointer = C.git_odb_object_data(object.ptr)
	var blob []byte

	len := int(C.git_odb_object_size(object.ptr))

	sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&blob)))
	sliceHeader.Cap = len
	sliceHeader.Len = len
	sliceHeader.Data = uintptr(c_blob)

	return blob
}

type OdbReadStream struct {
	ptr *C.git_odb_stream
}

// Read reads from the stream
func (stream *OdbReadStream) Read(data []byte) (int, error) {
	header := (*reflect.SliceHeader)(unsafe.Pointer(&data))
	ptr := (*C.char)(unsafe.Pointer(header.Data))
	size := C.size_t(header.Cap)
	ret := C.git_odb_stream_read(stream.ptr, ptr, size)
	if ret < 0 {
		return 0, LastError()
	}

	header.Len = int(ret)

	return len(data), nil
}

// Close is a dummy function in order to implement the Closer and
// ReadCloser interfaces
func (stream *OdbReadStream) Close() error {
	return nil
}

func (stream *OdbReadStream) Free() {
	runtime.SetFinalizer(stream, nil)
	C.git_odb_stream_free(stream.ptr)
}

type OdbWriteStream struct {
	ptr *C.git_odb_stream
	Id Oid
}

// Write writes to the stream
func (stream *OdbWriteStream) Write(data []byte) (int, error) {
	header := (*reflect.SliceHeader)(unsafe.Pointer(&data))
	ptr := (*C.char)(unsafe.Pointer(header.Data))
	size := C.size_t(header.Len)

	ret := C.git_odb_stream_write(stream.ptr, ptr, size)
	if ret < 0 {
		return 0, LastError()
	}

	return len(data), nil
}

// Close signals that all the data has been written and stores the
// resulting object id in the stream's Id field.
func (stream *OdbWriteStream) Close() error {
	ret := C.git_odb_stream_finalize_write(stream.Id.toC(), stream.ptr)
	if ret < 0 {
		return LastError()
	}

	return nil
}

func (stream *OdbWriteStream) Free() {
	runtime.SetFinalizer(stream, nil)
	C.git_odb_stream_free(stream.ptr)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"github.com/rneugeba/virtsock/go/vsock"
	"log"
	"net"
	"os"
	"proxy/libproxy"
	"strings"
)

func onePort() {
	host, port, container := parseHostContainerAddrs()

	vsockP, err := libproxy.NewVsockProxy(&vsock.VsockAddr{Port: uint(port)}, container)
	if err != nil {
		sendError(err)
	}
	ipP, err := libproxy.NewIPProxy(host, container)
	if err != nil {
		sendError(err)
	}

	ctl, err := exposePort(host, container)
	if err != nil {
		sendError(err)
	}

	go handleStopSignals(ipP)
	// TODO: avoid this line if we are running in a TTY
	sendOK()
	go ipP.Run()
	vsockP.Run()
	ctl.Close() // ensure ctl remains alive and un-GCed until here
	os.Exit(0)
}

func exposePort(host net.Addr, container net.Addr) (*os.File, error) {
	name := host.Network() + ":" + host.String() + ":" + container.Network() + ":" + container.String()
	log.Printf("exposePort %s\n", name)
	err := os.Mkdir("/port/"+name, 0)
	if err != nil {
		log.Printf("Failed to mkdir /port/%s: %#v\n", name, err)
		return nil, err
	}
	ctl, err := os.OpenFile("/port/"+name+"/ctl", os.O_RDWR, 0)
	if err != nil {
		log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err)
		return nil, err
	}
	_, err = ctl.WriteString(fmt.Sprintf("%s", name))
	if err != nil {
		log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err)
		return nil, err
	}
	_, err = ctl.Seek(0, 0)
	if err != nil {
		log.Printf("Failed to seek on /port/%s/ctl: %#v\n", name, err)
		return nil, err
	}
	results := make([]byte, 100)
	count, err := ctl.Read(results)
	if err != nil {
		log.Printf("Failed to read from /port/%s/ctl: %#v\n", name, err)
		return nil, err
	}
	// We deliberately keep the control file open since 9P clunk
	// will trigger a shutdown on the host side.

	response := string(results[0:count])
	if strings.HasPrefix(response, "ERROR ") {
		os.Remove("/port/" + name + "/ctl")
		response = strings.Trim(response[6:], " \t\r\n")
		return nil, errors.New(response)
	}
	// Hold on to a reference to prevent premature GC and close
	return ctl, nil
}
<commit_msg>proxy: remove the dynamic vsock port allocation<commit_after>package main

import (
	"errors"
	"fmt"
	"log"
	"net"
	"os"
	"proxy/libproxy"
	"strings"
)

func onePort() {
	host, _, container := parseHostContainerAddrs()

	ipP, err := libproxy.NewIPProxy(host, container)
	if err != nil {
		sendError(err)
	}

	ctl, err := exposePort(host, container)
	if err != nil {
		sendError(err)
	}

	go handleStopSignals(ipP)
	// TODO: avoid this line if we are running in a TTY
	sendOK()
	ipP.Run()
	ctl.Close() // ensure ctl remains alive and un-GCed until here
	os.Exit(0)
}

func exposePort(host net.Addr, container net.Addr) (*os.File, error) {
	name := host.Network() + ":" + host.String() + ":" + container.Network() + ":" + container.String()
	log.Printf("exposePort %s\n", name)
	err := os.Mkdir("/port/"+name, 0)
	if err != nil {
		log.Printf("Failed to mkdir /port/%s: %#v\n", name, err)
		return nil, err
	}
	ctl, err := os.OpenFile("/port/"+name+"/ctl", os.O_RDWR, 0)
	if err != nil {
		log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err)
		return nil, err
	}
	_, err = ctl.WriteString(fmt.Sprintf("%s", name))
	if err != nil {
		log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err)
		return nil, err
	}
	_, err = ctl.Seek(0, 0)
	if err != nil {
		log.Printf("Failed to seek on /port/%s/ctl: %#v\n", name, err)
		return nil, err
	}
	results := make([]byte, 100)
	count, err := ctl.Read(results)
	if err != nil {
		log.Printf("Failed to read from /port/%s/ctl: %#v\n", name, err)
		return nil, err
	}
	// We deliberately keep the control file open since 9P clunk
	// will trigger a shutdown on the host side.

	response := string(results[0:count])
	if strings.HasPrefix(response, "ERROR ") {
		os.Remove("/port/" + name + "/ctl")
		response = strings.Trim(response[6:], " \t\r\n")
		return nil, errors.New(response)
	}
	// Hold on to a reference to prevent premature GC and close
	return ctl, nil
}
<|endoftext|>


<commit_before>/**
 * Copyright 2015 Comcast Cable Communications Management, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   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 jtl

import (
	"encoding/json"
	"sync"

	. "github.com/Comcast/eel/eel/util"
)

// handleEvent processes an event (usually from the work queue) by selecting the correct handlers, applying the appropriate transformations and then sending off the tranformed event via appropriate publisher(s).
func handleEvent(ctx Context, stats *ServiceStats, event *JDoc, raw string, debug bool, syncExec bool) interface{} {
	debuginfo := make([]interface{}, 0)
	ctx.AddLogValue("destination", "unknown")
	handlers := GetHandlerFactory(ctx).GetHandlersForEvent(ctx, event)
	if len(handlers) == 0 {
		ctx.Log().Info("action", "no_matching_handlers")
		ctx.Log().Debug("debug_action", "no_matching_handlers", "payload", event.GetOriginalObject())
	}
	initialCtx := ctx
	ctx = ctx.SubContext()
	var wg sync.WaitGroup
	// add missing debug logs if any
	logParams := GetConfig(ctx).LogParams
	if logParams != nil {
		for k, v := range logParams {
			//if ctx.LogValue(k) == nil {
			ev := event.ParseExpression(ctx, v)
			ctx.AddLogValue(k, ev)
			//}
		}
	}
	for _, handler := range handlers {
		//TODO: validate JSON schema
		ctx.AddLogValue("topic", handler.Topic)
		ctx.AddLogValue("tenant", handler.TenantId)
		ctx.AddLogValue("handler", handler.Name)
		publishers, err := handler.ProcessEvent(initialCtx.SubContext(), event)
		if err != nil {
			ctx.Log().Error("error_type", "transformation", "cause", "bad_transformation", "handler", handler.Name, "tenant", handler.TenantId, "trace.in.data", event.GetOriginalObject(), "error", err.Error())
			ctx.Log().Metric("bad_transformation", M_Namespace, "xrs", M_Metric, "bad_transformation", M_Unit, "Count", M_Dims, "app="+AppId+"&env="+EnvName+"&instance="+InstanceName+"&destination="+ctx.LogValue("destination").(string), M_Val, 1.0)
			stats.IncErrors()
			continue
		}
		for _, publisher := range publishers {
			dc := ctx.Value(EelDuplicateChecker).(DuplicateChecker)
			if dc.GetTtl() > 0 && dc.IsDuplicate(ctx, []byte(publisher.GetUrl()+"\n"+publisher.GetPayload())) {
				ctx.Log().Info("action", "dropping_duplicate", "handler", handler.Name, "tenant", handler.TenantId)
				ctx.Log().Metric("dropping_duplicate", M_Namespace, "xrs", M_Metric, "dropping_duplicate", M_Unit, "Count", M_Dims, "app="+AppId+"&env="+EnvName+"&instance="+InstanceName+"&destination="+ctx.LogValue("destination").(string), M_Val, 1.0)
				continue
			}
			// trace header
			traceHeaderKey := GetConfig(ctx).HttpTransactionHeader
			if publisher.GetHeaders() == nil {
				publisher.SetHeaders(make(map[string]string, 0))
			}
			if publisher.GetHeaders()[traceHeaderKey] == "" && ctx.LogValue("tx.traceId") != nil {
				publisher.GetHeaders()[traceHeaderKey] = ctx.LogValue("tx.traceId").(string)
			}
			ctx.AddLogValue("tx.traceId", publisher.GetHeaders()[traceHeaderKey])
			ctx.AddValue("tx.traceId", publisher.GetHeaders()[traceHeaderKey])
			// other log params
			ctx.AddLogValue("trace.out.url", publisher.GetUrl())
			//ctx.AddLogValue("trace.in.data", event.GetOriginalObject())
			//ctx.AddLogValue("trace.out.data", publisher.GetPayload())
			ctx.AddLogValue("trace.out.protocol", publisher.GetProtocol())
			//ctx.AddLogValue("trace.out.path", publisher.GetPath())
			ctx.AddLogValue("trace.out.headers", publisher.GetHeaders())
			ctx.AddLogValue("trace.out.protocol", publisher.GetProtocol())
			//ctx.AddLogValue("trace.out.endpoint", publisher.GetEndpoint())
			ctx.AddLogValue("trace.out.verb", publisher.GetVerb())
			ctx.AddLogValue("trace.out.url", publisher.GetUrl())
			if syncExec {
				// no need to call out to endpoint in sync mode
				debuginfo = append(debuginfo, publisher.GetPayloadParsed().GetOriginalObject())
			} else if debug {
				// sequential execution to collect debug info
				_, err := publisher.Publish()
				AddLatencyLog(ctx, stats, "stat.eel.time")
				ctx.AddLogValue("trace.out.endpoint", publisher.GetEndpoint())
				ctx.AddLogValue("trace.out.url", publisher.GetUrl())
				if err != nil {
					ctx.Log().Error("error_type", "publish_event", "error", err.Error(), "cause", "publish_event")
					ctx.Log().Metric("publish_failed", M_Namespace, "xrs", M_Metric, "publish_failed", M_Unit, "Count", M_Dims, "app="+AppId+"&env="+EnvName+"&instance="+InstanceName+"&destination="+ctx.LogValue("destination").(string), M_Val, 1.0)
					stats.IncErrors()
				} else {
					ctx.Log().Info("action", "published_event")
					ctx.Log().Metric("published_event", M_Namespace, "xrs", M_Metric, "published_event", M_Unit, "Count", M_Dims, "app="+AppId+"&env="+EnvName+"&instance="+InstanceName+"&destination="+ctx.LogValue("destination").(string), M_Val, 1.0)
					stats.IncOutCount()
				}
				de := make(map[string]interface{}, 0)
				de["trace.out.endpoint"] = publisher.GetEndpoint()
				de["trace.out.path"] = publisher.GetPath()
				de["trace.out.headers"] = publisher.GetHeaders()
				de["trace.out.protocol"] = publisher.GetProtocol()
				de["trace.out.verb"] = publisher.GetVerb()
				de["trace.out.url"] = publisher.GetUrl()
				if publisher.GetPayload() != "" {
					data := make(map[string]interface{})
					err := json.Unmarshal([]byte(publisher.GetPayload()), &data)
					if err == nil {
						de["trace.out.data"] = data
					} else {
						de["trace.out.data"] = publisher.GetPayload()
					}
				} else {
					de["trace.out.data"] = ""
				}
				de["trace.in.data"] = event.GetOriginalObject()
				de["tenant.id"] = handler.TenantId
				de["handler"] = handler.Name
				de["api"] = publisher.GetApi()
				de["tx.id"] = ctx.Id()
				de["tx.traceId"] = publisher.GetHeaders()[traceHeaderKey]
				if errs := publisher.GetErrors(); errs != nil {
					de["tx.errors"] = errs
				}
				debuginfo = append(debuginfo, de)
			} else {
				//c := ctx
				//p := publisher
				wg.Add(1)
				go func(c Context, p EventPublisher) {
					defer wg.Done()
					_, err := p.Publish()
					AddLatencyLog(c, stats, "stat.eel.time")
					//c.AddLogValue("trace.out.endpoint", p.GetEndpoint())
					c.AddLogValue("trace.out.url", p.GetUrl())
					if err != nil {
						c.Log().Error("error_type", "publish_event", "error", err.Error(), "cause", "publish_event")
						c.Log().Metric("publish_failed", M_Namespace, "xrs", M_Metric, "publish_failed", M_Unit, "Count", M_Dims, "app="+AppId+"&env="+EnvName+"&instance="+InstanceName+"&destination="+ctx.LogValue("destination").(string), M_Val, 1.0)
						stats.IncErrors()
					} else {
						c.Log().Info("action", "published_event")
						c.Log().Metric("published_event", M_Namespace, "xrs", M_Metric, "published_event", M_Unit, "Count", M_Dims, "app="+AppId+"&env="+EnvName+"&instance="+InstanceName+"&destination="+ctx.LogValue("destination").(string), M_Val, 1.0)
						stats.IncOutCount()
					}
				}(ctx.SubContext(), publisher)
			}
		}
	}
	wg.Wait()
	return debuginfo
}
<commit_msg>evaluate debug log params early<commit_after>/**
 * Copyright 2015 Comcast Cable Communications Management, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   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 jtl

import (
	"encoding/json"
	"sync"

	. "github.com/Comcast/eel/eel/util"
)

// handleEvent processes an event (usually from the work queue) by selecting the correct handlers, applying the appropriate transformations and then sending off the tranformed event via appropriate publisher(s).
func handleEvent(ctx Context, stats *ServiceStats, event *JDoc, raw string, debug bool, syncExec bool) interface{} {
	debuginfo := make([]interface{}, 0)
	ctx.AddLogValue("destination", "unknown")
	// add missing debug logs if any
	logParams := GetConfig(ctx).LogParams
	if logParams != nil {
		for k, v := range logParams {
			//if ctx.LogValue(k) == nil {
			ev := event.ParseExpression(ctx, v)
			ctx.AddLogValue(k, ev)
			//}
		}
	}
	handlers := GetHandlerFactory(ctx).GetHandlersForEvent(ctx, event)
	if len(handlers) == 0 {
		ctx.Log().Info("action", "no_matching_handlers")
		ctx.Log().Debug("debug_action", "no_matching_handlers", "payload", event.GetOriginalObject())
	}
	initialCtx := ctx
	ctx = ctx.SubContext()
	var wg sync.WaitGroup
	for _, handler := range handlers {
		//TODO: validate JSON schema
		ctx.AddLogValue("topic", handler.Topic)
		ctx.AddLogValue("tenant", handler.TenantId)
		ctx.AddLogValue("handler", handler.Name)
		publishers, err := handler.ProcessEvent(initialCtx.SubContext(), event)
		if err != nil {
			ctx.Log().Error("error_type", "transformation", "cause", "bad_transformation", "handler", handler.Name, "tenant", handler.TenantId, "trace.in.data", event.GetOriginalObject(), "error", err.Error())
			ctx.Log().Metric("bad_transformation", M_Namespace, "xrs", M_Metric, "bad_transformation", M_Unit, "Count", M_Dims, "app="+AppId+"&env="+EnvName+"&instance="+InstanceName+"&destination="+ctx.LogValue("destination").(string), M_Val, 1.0)
			stats.IncErrors()
			continue
		}
		for _, publisher := range publishers {
			dc := ctx.Value(EelDuplicateChecker).(DuplicateChecker)
			if dc.GetTtl() > 0 && dc.IsDuplicate(ctx, []byte(publisher.GetUrl()+"\n"+publisher.GetPayload())) {
				ctx.Log().Info("action", "dropping_duplicate", "handler", handler.Name, "tenant", handler.TenantId)
				ctx.Log().Metric("dropping_duplicate", M_Namespace, "xrs", M_Metric, "dropping_duplicate", M_Unit, "Count", M_Dims, "app="+AppId+"&env="+EnvName+"&instance="+InstanceName+"&destination="+ctx.LogValue("destination").(string), M_Val, 1.0)
				continue
			}
			// trace header
			traceHeaderKey := GetConfig(ctx).HttpTransactionHeader
			if publisher.GetHeaders() == nil {
				publisher.SetHeaders(make(map[string]string, 0))
			}
			if publisher.GetHeaders()[traceHeaderKey] == "" && ctx.LogValue("tx.traceId") != nil {
				publisher.GetHeaders()[traceHeaderKey] = ctx.LogValue("tx.traceId").(string)
			}
			ctx.AddLogValue("tx.traceId", publisher.GetHeaders()[traceHeaderKey])
			ctx.AddValue("tx.traceId", publisher.GetHeaders()[traceHeaderKey])
			// other log params
			ctx.AddLogValue("trace.out.url", publisher.GetUrl())
			//ctx.AddLogValue("trace.in.data", event.GetOriginalObject())
			//ctx.AddLogValue("trace.out.data", publisher.GetPayload())
			ctx.AddLogValue("trace.out.protocol", publisher.GetProtocol())
			//ctx.AddLogValue("trace.out.path", publisher.GetPath())
			ctx.AddLogValue("trace.out.headers", publisher.GetHeaders())
			ctx.AddLogValue("trace.out.protocol", publisher.GetProtocol())
			//ctx.AddLogValue("trace.out.endpoint", publisher.GetEndpoint())
			ctx.AddLogValue("trace.out.verb", publisher.GetVerb())
			ctx.AddLogValue("trace.out.url", publisher.GetUrl())
			if syncExec {
				// no need to call out to endpoint in sync mode
				debuginfo = append(debuginfo, publisher.GetPayloadParsed().GetOriginalObject())
			} else if debug {
				// sequential execution to collect debug info
				_, err := publisher.Publish()
				AddLatencyLog(ctx, stats, "stat.eel.time")
				ctx.AddLogValue("trace.out.endpoint", publisher.GetEndpoint())
				ctx.AddLogValue("trace.out.url", publisher.GetUrl())
				if err != nil {
					ctx.Log().Error("error_type", "publish_event", "error", err.Error(), "cause", "publish_event")
					ctx.Log().Metric("publish_failed", M_Namespace, "xrs", M_Metric, "publish_failed", M_Unit, "Count", M_Dims, "app="+AppId+"&env="+EnvName+"&instance="+InstanceName+"&destination="+ctx.LogValue("destination").(string), M_Val, 1.0)
					stats.IncErrors()
				} else {
					ctx.Log().Info("action", "published_event")
					ctx.Log().Metric("published_event", M_Namespace, "xrs", M_Metric, "published_event", M_Unit, "Count", M_Dims, "app="+AppId+"&env="+EnvName+"&instance="+InstanceName+"&destination="+ctx.LogValue("destination").(string), M_Val, 1.0)
					stats.IncOutCount()
				}
				de := make(map[string]interface{}, 0)
				de["trace.out.endpoint"] = publisher.GetEndpoint()
				de["trace.out.path"] = publisher.GetPath()
				de["trace.out.headers"] = publisher.GetHeaders()
				de["trace.out.protocol"] = publisher.GetProtocol()
				de["trace.out.verb"] = publisher.GetVerb()
				de["trace.out.url"] = publisher.GetUrl()
				if publisher.GetPayload() != "" {
					data := make(map[string]interface{})
					err := json.Unmarshal([]byte(publisher.GetPayload()), &data)
					if err == nil {
						de["trace.out.data"] = data
					} else {
						de["trace.out.data"] = publisher.GetPayload()
					}
				} else {
					de["trace.out.data"] = ""
				}
				de["trace.in.data"] = event.GetOriginalObject()
				de["tenant.id"] = handler.TenantId
				de["handler"] = handler.Name
				de["api"] = publisher.GetApi()
				de["tx.id"] = ctx.Id()
				de["tx.traceId"] = publisher.GetHeaders()[traceHeaderKey]
				if errs := publisher.GetErrors(); errs != nil {
					de["tx.errors"] = errs
				}
				debuginfo = append(debuginfo, de)
			} else {
				//c := ctx
				//p := publisher
				wg.Add(1)
				go func(c Context, p EventPublisher) {
					defer wg.Done()
					_, err := p.Publish()
					AddLatencyLog(c, stats, "stat.eel.time")
					//c.AddLogValue("trace.out.endpoint", p.GetEndpoint())
					c.AddLogValue("trace.out.url", p.GetUrl())
					if err != nil {
						c.Log().Error("error_type", "publish_event", "error", err.Error(), "cause", "publish_event")
						c.Log().Metric("publish_failed", M_Namespace, "xrs", M_Metric, "publish_failed", M_Unit, "Count", M_Dims, "app="+AppId+"&env="+EnvName+"&instance="+InstanceName+"&destination="+ctx.LogValue("destination").(string), M_Val, 1.0)
						stats.IncErrors()
					} else {
						c.Log().Info("action", "published_event")
						c.Log().Metric("published_event", M_Namespace, "xrs", M_Metric, "published_event", M_Unit, "Count", M_Dims, "app="+AppId+"&env="+EnvName+"&instance="+InstanceName+"&destination="+ctx.LogValue("destination").(string), M_Val, 1.0)
						stats.IncOutCount()
					}
				}(ctx.SubContext(), publisher)
			}
		}
	}
	wg.Wait()
	return debuginfo
}
<|endoftext|>


<commit_before>// pat.go

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"strings"

	"github.com/charlesetc/pat/display"
	"github.com/charlesetc/pat/editor"
	"github.com/charlesetc/pat/input"
	"github.com/charlesetc/pat/stack"
	"github.com/nsf/termbox-go"
)

var Log func([]rune)
var files []string // filenames
// var editors []*editor // editors for the filenames
var ed *editor.Editor // the current editor.
var commandHistory *stack.Stack

func lineCommand(command string) (bool, []string, int) {
	var parsed bool
	var output []string
	var numberParsed int
	switch {
	case len(command) == 0:
		parsed = false
	case strings.ContainsRune(command, ','):
		strs := strings.SplitN(command, ",", 2)
		_, err1 := strconv.Atoi(strs[0])
		n, err2 := strconv.Atoi(strs[1])
		if (err1 != nil && strs[0] != "") || (err2 != nil && strs[1] != "$" && strs[1] != "") {
			parsed = false
			break
		}
		parsed = true
		output = []string{",", strs[0], strs[1]}
		numberParsed = len(strs[0]) + 1 + len(strconv.Itoa(n))
		if len(strs[1]) == 0 {
			numberParsed-- // because "" translates to 0
		}
	default:
		n, err := strconv.Atoi(command)
		parsed = err == nil
		numberParsed = len(strconv.Itoa(n))
		output = []string{"line", command}
	}

	return parsed, output, numberParsed
}

func parseLine(line string) [][]string {
	commands := make([][]string, 0)

	// this works, it might be ugly, but it works.
	line = strings.Replace(line, "\\/", "&#sslash;", -1)
	line = strings.Replace(line, "/", "&#slash;", -1)
	line = strings.Replace(line, "&#sslash;", "/", -1)
	lines := strings.Split(line, "&#slash;")
	var i int
	var command []string
	var c string

Lines:
	for i < len(lines) {
		c = lines[i]
		c = strings.Replace(c, " ", "", -1) // Get rid of space

		isLineCommand, lineResult, numberParsed := lineCommand(c)

		switch {

		case isLineCommand:
			command = lineResult
			lines[i] = lines[i][:numberParsed]
			if numberParsed < len(c) {
				i--
			}
		case c == "color":
			display.RandomColor()
			return [][]string{}
		case c == "d":
			command = []string{c}

		// Parse ?re?
		case len(c) > 0 && c[0] == '?':
			command = []string{"?", c[1 : len(c)-1]}
			break

		// Do nothing at the end.
		case i == len(lines)-1:
			break Lines

		// Parse S
		case c == "s":
			command = []string{c, lines[i+1], lines[i+2]}
			i += 2
		// Everything else gets one argument.
		default:
			command = []string{c, lines[i+1]}
			i++ // One argument
		}
		i++ // for itself
		commands = append(commands, command)
	}

	LogS(fmt.Sprint(commands))

	return commands
}

func makeLog() func([]rune) {
	file, err := os.Create(".log")
	if err != nil {
		panic(err)
	}
	return func(input []rune) {
		file.WriteString(string(input))
		if input[len(input)-1] != '\n' {
			file.WriteString("\n")
		}
		file.Sync()
	}
}

func LogS(str string) {
	Log([]rune(str))
}

func Exit() {
	LogS("Exiting now")
	display.Reset()
	os.Exit(0)
}

func Poll() {
	for {
		e := termbox.PollEvent()

		// LogS(fmt.Sprintf("%d", e.Key))

		switch {
		case e.Type == termbox.EventResize:
			display.Resize()
			display.Draw()

		case e.Key == termbox.KeyCtrlA: // Control-A
			input.CursorAtBeginning()
		case e.Key == termbox.KeyCtrlE: // Control-E
			input.CursorAtEnd()
		case e.Key == termbox.KeyCtrlC: // Control-C
			Exit()

			// Scrolling
		case e.Key == termbox.KeyCtrlN:
			display.ScrollDown()
		case e.Key == termbox.KeyCtrlP:
			display.ScrollUp()

		case e.Key == termbox.KeyEsc:
			input.Reset()
		case e.Key == termbox.KeySpace: //Space
			input.AddRune(' ')
			input.Draw()
		case e.Key == termbox.KeyEnter: // Return
			runes := input.Runes()
			commandHistory.Add(runes)
			input.Reset()
			if len(runes) == 0 {
				break
			}

			commands := parseLine(string(runes))
			for _, command := range commands {
				ed.Command(command[0], command[1:])
			}

			display.ShowFile([]rune(ed.String()))
			display.Highlight(ed.Highlights())
			display.Draw()

		// // Arrow keys
		// Cursor Movement
		case e.Key == termbox.KeyArrowLeft:
			input.CursorLeft()
		case e.Key == termbox.KeyArrowRight:
			input.CursorRight()
		case e.Key == termbox.KeyArrowUp:
			past, err := commandHistory.Pop()
			if err != nil {
				// Empty stack.
				// show alert later.
				break
			}
			input.Reset()
			input.SetRunes(past.([]rune))
			input.Draw()
			break
		case e.Key == termbox.KeyArrowDown:
			input.Reset()
			past, err := commandHistory.UnPop()
			if err != nil {
				// Empty stack.
				// show alert later.
				break
			}
			input.SetRunes(past.([]rune))
			input.Draw()
			break

		// Delete Key
		case e.Key == termbox.KeyBackspace || e.Key == termbox.KeyBackspace2 || e.Key == termbox.KeyDelete:
			input.Backspace()
			input.Draw()
		case e.Key == 0: // All other normal chars
			input.AddRune(e.Ch)
			input.Draw()
		}
	}
}

func contains(strings []string, match string) bool {
	for _, str := range strings {
		if str == match {
			return true
		}
	}
	return false
}

func init() {
	flags := make([]string, 0)
	files = make([]string, 0)

	for _, arg := range os.Args[1:] {
		if arg[0] == '-' {
			flags = append(flags, arg)
			continue
		}
		files = append(files, arg)
	}

	if contains(flags, "-v") || contains(flags, "--version") {
		fmt.Println("The Glorious Pat Text Editor : v0.0.1")
		os.Exit(0)
	} else if contains(flags, "-rc") {
		fmt.Println("Yay Recurse Center!")
		os.Exit(0)
	}

	if len(files) == 0 {
		fmt.Println("usage: pat [file]")
		os.Exit(0)
	}

	display.Init(!(contains(flags, "--bottom") || contains(flags, "-b"))) // topbar
	commandHistory = stack.New()

	Log = makeLog()
	display.Log = Log
	display.LogS = LogS
	input.Log = Log
	input.LogS = LogS
	editor.LogS = LogS
}

func main() {
	defer display.Reset()

	bytes, err := ioutil.ReadFile(files[0])
	if err != nil {
		panic(err)
	}

	ed = editor.NewEditor(bytes)

	display.Show([]rune(string(bytes)), []rune{})
	display.Draw()
	Poll()
}
<commit_msg>'s' command<commit_after>// pat.go

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"strings"

	"github.com/charlesetc/pat/display"
	"github.com/charlesetc/pat/editor"
	"github.com/charlesetc/pat/input"
	"github.com/charlesetc/pat/stack"
	"github.com/nsf/termbox-go"
)

var Log func([]rune)
var files []string // filenames
// var editors []*editor // editors for the filenames
var ed *editor.Editor // the current editor.
var commandHistory *stack.Stack

func lineCommand(command string) (bool, []string, int) {
	var parsed bool
	var output []string
	var numberParsed int
	switch {
	case len(command) == 0:
		parsed = false
	case strings.ContainsRune(command, ','):
		strs := strings.SplitN(command, ",", 2)
		_, err1 := strconv.Atoi(strs[0])
		n, err2 := strconv.Atoi(strs[1])
		if (err1 != nil && strs[0] != "") || (err2 != nil && strs[1] != "$" && strs[1] != "") {
			parsed = false
			break
		}
		parsed = true
		output = []string{",", strs[0], strs[1]}
		numberParsed = len(strs[0]) + 1 + len(strconv.Itoa(n))
		if len(strs[1]) == 0 {
			numberParsed-- // because "" translates to 0
		}
	default:
		n, err := strconv.Atoi(command)
		parsed = err == nil
		numberParsed = len(strconv.Itoa(n))
		output = []string{"line", command}
	}

	return parsed, output, numberParsed
}

func parseLine(line string) [][]string {
	commands := make([][]string, 0)

	// this works, it might be ugly, but it works.
	line = strings.Replace(line, "\\/", "&#sslash;", -1)
	line = strings.Replace(line, "/", "&#slash;", -1)
	line = strings.Replace(line, "&#sslash;", "/", -1)
	lines := strings.Split(line, "&#slash;")
	var i int
	var command []string
	var c string

Lines:
	for i < len(lines) {
		c = lines[i]
		c = strings.Replace(c, " ", "", -1) // Get rid of space

		isLineCommand, lineResult, numberParsed := lineCommand(c)

		switch {

		case isLineCommand:
			command = lineResult
			lines[i] = lines[i][:numberParsed]
			if numberParsed < len(c) {
				i--
			}
		case c == "color":
			display.RandomColor()
			return [][]string{}
		case c == "d":
			command = []string{c}

		// Parse ?re?
		case len(c) > 0 && c[0] == '?':
			command = []string{"?", c[1 : len(c)-1]}
			break

		// Do nothing at the end.
		case i == len(lines)-1:
			break Lines

		// Parse S
		case c == "s":
			command1 := []string{"x", lines[i+1]}
			commands = append(commands, command1)
			command = []string{"c", lines[i+2]}
			i += 2
		// Everything else gets one argument.
		default:
			command = []string{c, lines[i+1]}
			i++ // One argument
		}
		i++ // for itself
		commands = append(commands, command)
	}

	LogS(fmt.Sprint(commands))

	return commands
}

func makeLog() func([]rune) {
	file, err := os.Create(".log")
	if err != nil {
		panic(err)
	}
	return func(input []rune) {
		file.WriteString(string(input))
		if input[len(input)-1] != '\n' {
			file.WriteString("\n")
		}
		file.Sync()
	}
}

func LogS(str string) {
	Log([]rune(str))
}

func Exit() {
	LogS("Exiting now")
	display.Reset()
	os.Exit(0)
}

func Poll() {
	for {
		e := termbox.PollEvent()

		// LogS(fmt.Sprintf("%d", e.Key))

		switch {
		case e.Type == termbox.EventResize:
			display.Resize()
			display.Draw()

		case e.Key == termbox.KeyCtrlA: // Control-A
			input.CursorAtBeginning()
		case e.Key == termbox.KeyCtrlE: // Control-E
			input.CursorAtEnd()
		case e.Key == termbox.KeyCtrlC: // Control-C
			Exit()

			// Scrolling
		case e.Key == termbox.KeyCtrlN:
			display.ScrollDown()
		case e.Key == termbox.KeyCtrlP:
			display.ScrollUp()

		case e.Key == termbox.KeyEsc:
			input.Reset()
		case e.Key == termbox.KeySpace: //Space
			input.AddRune(' ')
			input.Draw()
		case e.Key == termbox.KeyEnter: // Return
			runes := input.Runes()
			commandHistory.Add(runes)
			input.Reset()
			if len(runes) == 0 {
				break
			}

			commands := parseLine(string(runes))
			for _, command := range commands {
				ed.Command(command[0], command[1:])
			}

			display.ShowFile([]rune(ed.String()))
			display.Highlight(ed.Highlights())
			display.Draw()

		// // Arrow keys
		// Cursor Movement
		case e.Key == termbox.KeyArrowLeft:
			input.CursorLeft()
		case e.Key == termbox.KeyArrowRight:
			input.CursorRight()
		case e.Key == termbox.KeyArrowUp:
			past, err := commandHistory.Pop()
			if err != nil {
				// Empty stack.
				// show alert later.
				break
			}
			input.Reset()
			input.SetRunes(past.([]rune))
			input.Draw()
			break
		case e.Key == termbox.KeyArrowDown:
			input.Reset()
			past, err := commandHistory.UnPop()
			if err != nil {
				// Empty stack.
				// show alert later.
				break
			}
			input.SetRunes(past.([]rune))
			input.Draw()
			break

		// Delete Key
		case e.Key == termbox.KeyBackspace || e.Key == termbox.KeyBackspace2 || e.Key == termbox.KeyDelete:
			input.Backspace()
			input.Draw()
		case e.Key == 0: // All other normal chars
			input.AddRune(e.Ch)
			input.Draw()
		}
	}
}

func contains(strings []string, match string) bool {
	for _, str := range strings {
		if str == match {
			return true
		}
	}
	return false
}

func init() {
	flags := make([]string, 0)
	files = make([]string, 0)

	for _, arg := range os.Args[1:] {
		if arg[0] == '-' {
			flags = append(flags, arg)
			continue
		}
		files = append(files, arg)
	}

	if contains(flags, "-v") || contains(flags, "--version") {
		fmt.Println("The Glorious Pat Text Editor : v0.0.1")
		os.Exit(0)
	} else if contains(flags, "-rc") {
		fmt.Println("Yay Recurse Center!")
		os.Exit(0)
	}

	if len(files) == 0 {
		fmt.Println("usage: pat [file]")
		os.Exit(0)
	}

	display.Init(!(contains(flags, "--bottom") || contains(flags, "-b"))) // topbar
	commandHistory = stack.New()

	Log = makeLog()
	display.Log = Log
	display.LogS = LogS
	input.Log = Log
	input.LogS = LogS
	editor.LogS = LogS
}

func main() {
	defer display.Reset()

	bytes, err := ioutil.ReadFile(files[0])
	if err != nil {
		panic(err)
	}

	ed = editor.NewEditor(bytes)

	display.Show([]rune(string(bytes)), []rune{})
	display.Draw()
	Poll()
}
<|endoftext|>


<commit_before>package engine

import (
	"errors"
	"fmt"
	"log"
	"math/rand"
	"regexp"
	"strings"

	"github.com/coreos/coreinit/job"
	"github.com/coreos/coreinit/machine"
	"github.com/coreos/coreinit/registry"
)

type Scheduler struct {
}

func NewScheduler() *Scheduler {
	return &Scheduler{}
}

func (scheduler *Scheduler) BuildSchedule(jobs []job.Job, machines map[string]machine.Machine, reg *registry.Registry) (Schedule, error) {
	schedule := NewScheduleFromJobs(jobs)
	err := scheduler.finalizeSchedule(&schedule, machines, reg)
	return schedule, err
}

func (scheduler *Scheduler) finalizeSchedule(schedule *Schedule, machines map[string]machine.Machine, reg *registry.Registry) error {
	decide := func(j *job.Job) *machine.Machine {
		var mach *machine.Machine
		// If the Job being scheduled is a systemd service unit, we assume we
		// can put it anywhere. If not, we must find the machine where the
		// Job's related service file is currently scheduled.
		if j.Type == "systemd-service" {
			mach = pickRandomMachine(machines)
		} else {
			// This is intended to match a standard filetype (i.e. '.socket' in 'web.socket')
			re := regexp.MustCompile("\\.(.[a-z]*)$")
			serviceName := re.ReplaceAllString(j.Name, ".service")

			// Check if the corresponding systemd-service job is referenced in the schedule
			// we're actively finalizing
			for j2, m := range *schedule {
				if serviceName == j2.Name {
					mach = m
				}
			}

			if mach == nil {
				service, _ := job.NewJob(serviceName, nil, nil)
				//TODO: Remove registry access from the scheduler
				if state := reg.GetJobState(service); state != nil {
					mach = state.Machine
				}
			}

			if mach == nil {
				log.Printf("Unable to schedule job %s since corresponding "+
					"service job %s could not be found", j.Name, serviceName)
			}
		}

		if mach == nil {
			log.Printf("Not scheduling job %s", j.Name)
			return nil
		} else {
			log.Println("Scheduling job", j.Name, "to machine", mach.BootId)
			return mach
		}
	}

	var undecided []job.Job
	for j, m := range *schedule {
		// The schedule may come in partially-completed. We assume any previous
		// decisions cannot be changed.
		if m == nil {
			undecided = append(undecided, j)
		}
	}

	// Iterate over the submitted set of undecided jobs up to N+1 times where N=len(jobs).
	// We assume that N+1 is the theoretical maximum number of attempts that we could possibly
	// take. This is not proven to be true...
	iterMax := len(undecided) + 1

	for i := 0; i < iterMax; i++ {
		decisions := 0

		for i := 0; i < len(undecided); i++ {
			job := undecided[i-decisions]
			mach := decide(&job)
			if mach != nil {
				(*schedule)[job] = mach
				undecided = append(undecided[0:i-decisions], undecided[i-decisions+1:]...)
				decisions++
			}
		}
	}

	if len(undecided) > 0 {
		return errors.New("Unable to decide how to schedule all jobs")
	}

	return nil
}

func pickRandomMachine(machines map[string]machine.Machine) *machine.Machine {
	machineKeySlice := make([]string, len(machines))
	idx := 0
	for k := range machines {
		machineKeySlice[idx] = k
		idx++
	}
	target := machineKeySlice[rand.Intn(len(machineKeySlice))]
	machine := machines[target]
	return &machine
}

type Schedule map[job.Job]*machine.Machine

func NewSchedule() Schedule {
	schedule := make(Schedule, 0)
	return schedule
}

func NewScheduleFromJobs(jobs []job.Job) Schedule {
	schedule := make(Schedule, 0)
	for _, job := range jobs {
		schedule[job] = nil
	}
	return schedule
}

func (self *Schedule) Add(j job.Job, m machine.Machine) {
	(*self)[j] = &m
}

func (self *Schedule) String() string {
	entries := make([]string, len(*self))
	idx := 0
	for j, m := range *self {
		entries[idx] = fmt.Sprintf("job=%s machine=%s", j.Name, m.BootId)
		idx++
	}
	return strings.Join(entries, ", ")
}
<commit_msg>refactor(Scheduler): Publicize Scheduler.FinalizeSchedule method<commit_after>package engine

import (
	"errors"
	"fmt"
	"log"
	"math/rand"
	"regexp"
	"strings"

	"github.com/coreos/coreinit/job"
	"github.com/coreos/coreinit/machine"
	"github.com/coreos/coreinit/registry"
)

type Scheduler struct {
}

func NewScheduler() *Scheduler {
	return &Scheduler{}
}

func (scheduler *Scheduler) BuildSchedule(jobs []job.Job, machines map[string]machine.Machine, reg *registry.Registry) (Schedule, error) {
	schedule := NewScheduleFromJobs(jobs)
	err := scheduler.FinalizeSchedule(&schedule, machines, reg)
	return schedule, err
}

func (scheduler *Scheduler) FinalizeSchedule(schedule *Schedule, machines map[string]machine.Machine, reg *registry.Registry) error {
	decide := func(j *job.Job) *machine.Machine {
		var mach *machine.Machine
		// If the Job being scheduled is a systemd service unit, we assume we
		// can put it anywhere. If not, we must find the machine where the
		// Job's related service file is currently scheduled.
		if j.Type == "systemd-service" {
			mach = pickRandomMachine(machines)
		} else {
			// This is intended to match a standard filetype (i.e. '.socket' in 'web.socket')
			re := regexp.MustCompile("\\.(.[a-z]*)$")
			serviceName := re.ReplaceAllString(j.Name, ".service")

			// Check if the corresponding systemd-service job is referenced in the schedule
			// we're actively finalizing
			for j2, m := range *schedule {
				if serviceName == j2.Name {
					mach = m
				}
			}

			if mach == nil {
				service, _ := job.NewJob(serviceName, nil, nil)
				//TODO: Remove registry access from the scheduler
				if state := reg.GetJobState(service); state != nil {
					mach = state.Machine
				}
			}

			if mach == nil {
				log.Printf("Unable to schedule job %s since corresponding "+
					"service job %s could not be found", j.Name, serviceName)
			}
		}

		if mach == nil {
			log.Printf("Not scheduling job %s", j.Name)
			return nil
		} else {
			log.Println("Scheduling job", j.Name, "to machine", mach.BootId)
			return mach
		}
	}

	var undecided []job.Job
	for j, m := range *schedule {
		// The schedule may come in partially-completed. We assume any previous
		// decisions cannot be changed.
		if m == nil {
			undecided = append(undecided, j)
		}
	}

	// Iterate over the submitted set of undecided jobs up to N+1 times where N=len(jobs).
	// We assume that N+1 is the theoretical maximum number of attempts that we could possibly
	// take. This is not proven to be true...
	iterMax := len(undecided) + 1

	for i := 0; i < iterMax; i++ {
		decisions := 0

		for i := 0; i < len(undecided); i++ {
			job := undecided[i-decisions]
			mach := decide(&job)
			if mach != nil {
				(*schedule)[job] = mach
				undecided = append(undecided[0:i-decisions], undecided[i-decisions+1:]...)
				decisions++
			}
		}
	}

	if len(undecided) > 0 {
		return errors.New("Unable to decide how to schedule all jobs")
	}

	return nil
}

func pickRandomMachine(machines map[string]machine.Machine) *machine.Machine {
	machineKeySlice := make([]string, len(machines))
	idx := 0
	for k := range machines {
		machineKeySlice[idx] = k
		idx++
	}
	target := machineKeySlice[rand.Intn(len(machineKeySlice))]
	machine := machines[target]
	return &machine
}

type Schedule map[job.Job]*machine.Machine

func NewSchedule() Schedule {
	schedule := make(Schedule, 0)
	return schedule
}

func NewScheduleFromJobs(jobs []job.Job) Schedule {
	schedule := make(Schedule, 0)
	for _, job := range jobs {
		schedule[job] = nil
	}
	return schedule
}

func (self *Schedule) Add(j job.Job, m machine.Machine) {
	(*self)[j] = &m
}

func (self *Schedule) String() string {
	entries := make([]string, len(*self))
	idx := 0
	for j, m := range *self {
		entries[idx] = fmt.Sprintf("job=%s machine=%s", j.Name, m.BootId)
		idx++
	}
	return strings.Join(entries, ", ")
}
<|endoftext|>