<commit_before>package proctl

import (
	"bytes"
	"os/exec"
	"syscall"
	"testing"
)

func dataAtAddr(pid int, addr uint64) ([]byte, error) {
	data := make([]byte, 1)
	_, err := syscall.PtracePeekData(pid, uintptr(addr), data)
	if err != nil {
		return nil, err
	}

	return data, nil
}

func StartTestProcess(name string) (*exec.Cmd, error) {
	cmd := exec.Command("../fixtures/" + name)

	err := cmd.Start()
	if err != nil {
		return nil, err
	}

	return cmd, nil
}

func TestAttachProcess(t *testing.T) {
	cmd, err := StartTestProcess("testprog")
	if err != nil {
		t.Fatal("Starting test process:", err)
	}

	pid := cmd.Process.Pid
	p, err := NewDebugProcess(pid)
	if err != nil {
		t.Fatal("NewDebugProcess():", err)
	}

	if !p.ProcessState.Sys().(syscall.WaitStatus).Stopped() {
		t.Errorf("Process was not stopped correctly")
	}

	cmd.Process.Kill()
}

func TestStep(t *testing.T) {
	cmd, err := StartTestProcess("testprog")
	if err != nil {
		t.Fatal("Starting test process:", err)
	}

	pid := cmd.Process.Pid
	p, err := NewDebugProcess(pid)
	if err != nil {
		t.Fatal("NewDebugProcess():", err)
	}

	regs, err := p.Registers()
	if err != nil {
		t.Fatal("Registers():", err, pid)
	}

	rip := regs.PC()

	err = p.Step()
	if err != nil {
		t.Fatal("Step():", err)
	}

	regs, err = p.Registers()
	if err != nil {
		t.Fatal("Registers():", err)
	}

	if rip >= regs.PC() {
		t.Errorf("Expected %#v to be greater than %#v", regs.PC(), rip)
	}

	cmd.Process.Kill()
}

func TestContinue(t *testing.T) {
	cmd, err := StartTestProcess("continuetestprog")
	if err != nil {
		t.Fatal("Starting test process:", err)
	}

	pid := cmd.Process.Pid
	p, err := NewDebugProcess(pid)
	if err != nil {
		t.Fatal("NewDebugProcess():", err)
	}

	if p.ProcessState.Exited() {
		t.Fatal("Process already exited")
	}

	err = p.Continue()
	if err != nil {
		t.Fatal("Continue():", err)
	}

	if !p.ProcessState.Success() {
		t.Fatal("Process did not exit successfully")
	}
}

func TestBreakPoint(t *testing.T) {
	cmd, err := StartTestProcess("testprog")
	if err != nil {
		t.Fatal("Starting test process:", err)
	}

	pid := cmd.Process.Pid
	p, err := NewDebugProcess(pid)
	if err != nil {
		t.Fatal("NewDebugProcess():", err)
	}

	sleepytimefunc := p.GoSymTable.LookupFunc("main.sleepytime")
	sleepyaddr := sleepytimefunc.Entry

	_, err = p.Break(uintptr(sleepyaddr))
	if err != nil {
		t.Fatal("Break():", err)
	}

	err = p.Continue()
	if err != nil {
		t.Fatal("Continue():", err)
	}

	regs, err := p.Registers()
	if err != nil {
		t.Fatal("Registers():", err)
	}

	pc := regs.PC()
	if pc != sleepyaddr+1 {
		t.Fatalf("Break not respected:\nPC:%d\nFN:%d\n", pc, sleepyaddr)
	}

	err = p.Step()
	if err != nil {
		t.Fatal(err)
	}

	regs, err = p.Registers()
	if err != nil {
		t.Fatal("Registers():", err)
	}

	pc = regs.PC()
	if pc == sleepyaddr {
		t.Fatalf("Step not respected:\nPC:%d\nFN:%d\n", pc, sleepyaddr)
	}

	cmd.Process.Kill()
}

func TestBreakPointWithNonExistantFunction(t *testing.T) {
	cmd, err := StartTestProcess("testprog")
	if err != nil {
		t.Fatal("Starting test process:", err)
	}

	pid := cmd.Process.Pid
	p, err := NewDebugProcess(pid)
	if err != nil {
		t.Fatal("NewDebugProcess():", err)
	}

	_, err = p.Break(uintptr(0))
	if err == nil {
		t.Fatal("Should not be able to break at non existant function")
	}
}

func TestClearBreakPoint(t *testing.T) {
	cmd, err := StartTestProcess("testprog")
	if err != nil {
		t.Fatal("Starting test process:", err)
	}

	pid := cmd.Process.Pid
	p, err := NewDebugProcess(pid)
	if err != nil {
		t.Fatal("NewDebugProcess():", err)
	}

	fn := p.GoSymTable.LookupFunc("main.sleepytime")
	bp, err := p.Break(uintptr(fn.Entry))
	if err != nil {
		t.Fatal("Break():", err)
	}

	int3, err := dataAtAddr(pid, bp.Addr)
	if err != nil {
		t.Fatal(err)
	}

	bp, err = p.Clear(fn.Entry)
	if err != nil {
		t.Fatal("Break():", err)
	}

	data, err := dataAtAddr(pid, bp.Addr)
	if err != nil {
		t.Fatal(err)
	}

	if bytes.Equal(data, int3) {
		t.Fatalf("Breakpoint was not cleared data: %#v, int3: %#v", data, int3)
	}

	if len(p.BreakPoints) != 0 {
		t.Fatal("Breakpoint not removed internally")
	}
}
<commit_msg>Ensure test program is killed after spec<commit_after>package proctl

import (
	"bytes"
	"os/exec"
	"syscall"
	"testing"
)

func dataAtAddr(pid int, addr uint64) ([]byte, error) {
	data := make([]byte, 1)
	_, err := syscall.PtracePeekData(pid, uintptr(addr), data)
	if err != nil {
		return nil, err
	}

	return data, nil
}

func StartTestProcess(name string) (*exec.Cmd, error) {
	cmd := exec.Command("../fixtures/" + name)

	err := cmd.Start()
	if err != nil {
		return nil, err
	}

	return cmd, nil
}

func TestAttachProcess(t *testing.T) {
	cmd, err := StartTestProcess("testprog")
	if err != nil {
		t.Fatal("Starting test process:", err)
	}

	pid := cmd.Process.Pid
	p, err := NewDebugProcess(pid)
	if err != nil {
		t.Fatal("NewDebugProcess():", err)
	}

	if !p.ProcessState.Sys().(syscall.WaitStatus).Stopped() {
		t.Errorf("Process was not stopped correctly")
	}

	cmd.Process.Kill()
}

func TestStep(t *testing.T) {
	cmd, err := StartTestProcess("testprog")
	if err != nil {
		t.Fatal("Starting test process:", err)
	}

	pid := cmd.Process.Pid
	p, err := NewDebugProcess(pid)
	if err != nil {
		t.Fatal("NewDebugProcess():", err)
	}

	regs, err := p.Registers()
	if err != nil {
		t.Fatal("Registers():", err, pid)
	}

	rip := regs.PC()

	err = p.Step()
	if err != nil {
		t.Fatal("Step():", err)
	}

	regs, err = p.Registers()
	if err != nil {
		t.Fatal("Registers():", err)
	}

	if rip >= regs.PC() {
		t.Errorf("Expected %#v to be greater than %#v", regs.PC(), rip)
	}

	cmd.Process.Kill()
}

func TestContinue(t *testing.T) {
	cmd, err := StartTestProcess("continuetestprog")
	if err != nil {
		t.Fatal("Starting test process:", err)
	}

	pid := cmd.Process.Pid
	p, err := NewDebugProcess(pid)
	if err != nil {
		t.Fatal("NewDebugProcess():", err)
	}

	if p.ProcessState.Exited() {
		t.Fatal("Process already exited")
	}

	err = p.Continue()
	if err != nil {
		t.Fatal("Continue():", err)
	}

	if !p.ProcessState.Success() {
		t.Fatal("Process did not exit successfully")
	}
}

func TestBreakPoint(t *testing.T) {
	cmd, err := StartTestProcess("testprog")
	if err != nil {
		t.Fatal("Starting test process:", err)
	}

	pid := cmd.Process.Pid
	p, err := NewDebugProcess(pid)
	if err != nil {
		t.Fatal("NewDebugProcess():", err)
	}

	sleepytimefunc := p.GoSymTable.LookupFunc("main.sleepytime")
	sleepyaddr := sleepytimefunc.Entry

	_, err = p.Break(uintptr(sleepyaddr))
	if err != nil {
		t.Fatal("Break():", err)
	}

	err = p.Continue()
	if err != nil {
		t.Fatal("Continue():", err)
	}

	regs, err := p.Registers()
	if err != nil {
		t.Fatal("Registers():", err)
	}

	pc := regs.PC()
	if pc != sleepyaddr+1 {
		t.Fatalf("Break not respected:\nPC:%d\nFN:%d\n", pc, sleepyaddr)
	}

	err = p.Step()
	if err != nil {
		t.Fatal(err)
	}

	regs, err = p.Registers()
	if err != nil {
		t.Fatal("Registers():", err)
	}

	pc = regs.PC()
	if pc == sleepyaddr {
		t.Fatalf("Step not respected:\nPC:%d\nFN:%d\n", pc, sleepyaddr)
	}

	cmd.Process.Kill()
}

func TestBreakPointWithNonExistantFunction(t *testing.T) {
	cmd, err := StartTestProcess("testprog")
	if err != nil {
		t.Fatal("Starting test process:", err)
	}

	pid := cmd.Process.Pid
	p, err := NewDebugProcess(pid)
	if err != nil {
		t.Fatal("NewDebugProcess():", err)
	}

	_, err = p.Break(uintptr(0))
	if err == nil {
		t.Fatal("Should not be able to break at non existant function")
	}

	cmd.Process.Kill()
}

func TestClearBreakPoint(t *testing.T) {
	cmd, err := StartTestProcess("testprog")
	if err != nil {
		t.Fatal("Starting test process:", err)
	}

	pid := cmd.Process.Pid
	p, err := NewDebugProcess(pid)
	if err != nil {
		t.Fatal("NewDebugProcess():", err)
	}

	fn := p.GoSymTable.LookupFunc("main.sleepytime")
	bp, err := p.Break(uintptr(fn.Entry))
	if err != nil {
		t.Fatal("Break():", err)
	}

	int3, err := dataAtAddr(pid, bp.Addr)
	if err != nil {
		t.Fatal(err)
	}

	bp, err = p.Clear(fn.Entry)
	if err != nil {
		t.Fatal("Break():", err)
	}

	data, err := dataAtAddr(pid, bp.Addr)
	if err != nil {
		t.Fatal(err)
	}

	if bytes.Equal(data, int3) {
		t.Fatalf("Breakpoint was not cleared data: %#v, int3: %#v", data, int3)
	}

	if len(p.BreakPoints) != 0 {
		t.Fatal("Breakpoint not removed internally")
	}

	cmd.Process.Kill()
}
<|endoftext|>


<commit_before>package post

import (
    "appengine"
    "appengine/datastore"
    "appengine/blobstore"
    "io/ioutil"
    "encoding/json"
    "time"
    "strings"
    "sort"
    "errors"
)

type Post struct {
  Title       string
  Content     appengine.BlobKey
  Postdate    time.Time
  StickyUrl   string
}

type Tag struct {
  Name        string
  Postdate    time.Time
  PostKey     *datastore.Key
}

type Tags []Tag

func (s Tags) Less(i, j int) bool { return s[i].Postdate.UnixNano() > s[j].Postdate.UnixNano() }
func (s Tags) Len() int { return len(s) }
func (s Tags) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func conv_title_to_url(title string) string{
  lc := strings.ToLower(title)

  strip := func(r rune) rune{
    switch {
      case 'a' <= r && r <= 'z':
        return r
      case '0' <= r && r <= '9':
        return r
      case r == ' ', r == '-', r == '_':
        return r
    }
    return ' '
  }

  return strings.Replace(strings.Map(strip, lc), " ", "-", -1)
}

func SavePost(context appengine.Context, title string, content appengine.BlobKey, tags []string, postdate time.Time) (*datastore.Key, error){
  p1 := Post{
      Title:    title,
      Content:  content,
      Postdate: postdate,
      StickyUrl: conv_title_to_url(title),
  }

  temppostkey := datastore.NewIncompleteKey(context, "post", nil)
  postkey,err := datastore.Put(context, temppostkey, &p1)
  if err != nil {
    return nil, err
  }

  t1 := Tag{
    Name:     "all posts",
    Postdate: postdate,
    PostKey:  postkey,
  }
  tagkey := datastore.NewIncompleteKey(context, "tag", nil)
  _,err = datastore.Put(context, tagkey, &t1)
  if err != nil {
    return nil, err
  }

  for _,t := range tags{
    t1 := Tag{
      Name:     t,
      Postdate: postdate,
      PostKey:  postkey,
    }
    tagkey := datastore.NewIncompleteKey(context, "tag", nil)
    _,err = datastore.Put(context, tagkey, &t1)
    if err != nil {
      return nil, err
    }
  }

  return postkey, nil
}

func GetTagSlice(context appengine.Context, key *datastore.Key) ([]string, error){
  var tagstructs []Tag
  _,err := (GetTagsAssociatedWithPost(key).GetAll(context, &tagstructs))
  if err != nil { return nil, err }

  tags := make([]string, len(tagstructs))
  for i,ts := range tagstructs{
    tags[i] = ts.Name
  }

  return tags, nil
}

func GetPostContent(context appengine.Context, p Post)(string, error){

  data, err := ioutil.ReadAll(blobstore.NewReader(context, p.Content))
  if err != nil {
    context.Errorf("ioutil.ReadAll: %v", err)
    return "", err
  }
  if len(data) <= 0{
    context.Errorf("len(data): %v", len(data))
    return "", errors.New("len(data) < 1")
  }

  var decoded interface{}
  err = json.Unmarshal(data, &decoded)
  if err != nil {
    context.Errorf("json.Unmarshal: %v", err)
    return "", err
  }

  q := decoded.(map[string]interface{})
  content,ok := q["data"].(string)
  if !ok{
    context.Errorf("post content has no 'data' field internally")
    return "", errors.New("post has no 'data' field")
  }

  return content, nil
}

func GetPost(context appengine.Context, key *datastore.Key) (Post, string, []string, error){
  var p2 Post
  err := datastore.Get(context, key, &p2)
  if err != nil { return p2, "", nil, err }
  tags, err := GetTagSlice(context, key)
  if err != nil { return p2, "", nil, err }
  content, err := GetPostContent(context, p2)
  if err != nil { return p2, "", nil, err }

  return p2, content, tags, err
}

func UniquePosts(context appengine.Context, queries []*datastore.Query) ([]*datastore.Key, error){
  seen := map[string]*datastore.Key {}

  for _,query := range queries{
    var rawtags Tags
    _,err := query.GetAll(context, &rawtags)
    if err != nil { return nil, err }

    for _,t := range rawtags{
      if _, ok := seen[t.PostKey.String()]; !ok{
        seen[t.PostKey.String()] = t.PostKey
      }
    }
  }

  keys := make([]*datastore.Key, len(seen))

  i := 0
  for _,v := range seen{
    keys[i] = v
    i += 1
  }

  return keys, nil
}

type FullPost struct {
  PostStruct Post
  Tags []string
  Content string
}

func GetPosts(c appengine.Context, keys []*datastore.Key, start int, limit int, out chan<- FullPost, errout chan<- error){

  defer close(out)
  defer close(errout)

  if start > len(keys){ start = len(keys) }
  if start+limit > len(keys){ limit = len(keys) - start }

  for _,t := range keys[start:start+limit]{
    post, content, tags, err := GetPost(c, t)

    if err != nil{
      errout <- err
      return
    }

    p1 := FullPost{
      PostStruct: post,
      Tags: tags,
      Content: content,
    }

    out <- p1
  }
}

func ExecuteQuery(c appengine.Context, q *datastore.Query, start int, limit int, filter func(Post) bool, out chan<- Post, errout chan<- error){

  defer close(out)
  defer close(errout)

  for t,i := q.Run(c), 0;  ; i++ {
    if ((start < 0) || (limit < 0)) || (i < (start + limit)){
      var x Post
      // key, err := t.Next(&x)
      _, err := t.Next(&x)

      if err == datastore.Done {
        return
      }
      if err != nil {
        errout <- err
        return
      }

      if !filter(x) {
        i--
        continue
      }

      if i < start {
        continue
      }

      out <- x
    } else {
      break
    }
  }
}

func GetCount(c appengine.Context, q *datastore.Query) (int, error){
  return q.Count(c)
}

func GetPostsNotMatchingTag(tag string) ([]*datastore.Query){
  queries := []*datastore.Query { datastore.NewQuery("tag").Filter("Name <", tag),
                                  datastore.NewQuery("tag").Filter("Name >", tag),
                                }
  return queries
}

func GetPostsMatchingTag(tag string) ([]*datastore.Query){
  return []*datastore.Query {datastore.NewQuery("tag").Filter("Name =", tag)}
}

func GetPostsSortedByDate() ([]*datastore.Query){
  return []*datastore.Query {datastore.NewQuery("post").Order("-Postdate")}
}

func GetTagsAssociatedWithPost(postkey *datastore.Key) (*datastore.Query){
  return datastore.NewQuery("tag").Filter("PostKey =", postkey).Order("Name")
}

func GetPostsMatchingUrl(stickyurl string) (*datastore.Query){
  return datastore.NewQuery("post").Filter("StickyUrl =", stickyurl).Limit(1)
}

func GetAllPosts() (*datastore.Query){
  return datastore.NewQuery("post")
}

func GetLatestDate(context appengine.Context)(time.Time){
  q := datastore.NewQuery("post").Order("-Postdate")
  var mePosts []Post
  _,err := q.Limit(1).GetAll(context, &mePosts)
  if err != nil { return time.Now() }
  if len(mePosts) < 1{
    return time.Now()
  }
  return mePosts[0].Postdate
}

func GetAllTags(context appengine.Context) ([]string,[]int, error){
  seen := map[string]int {}

  query := datastore.NewQuery("tag")
  var rawtags Tags
  _,err := query.GetAll(context, &rawtags)
  if err != nil { return nil, nil, err }

  for _,t := range rawtags{
    if _,ok := seen[t.Name]; !ok {
      seen[t.Name] = 1
    } else {
      seen[t.Name] += 1
    }
  }

  delete(seen, "all posts")
  delete(seen, "static")

  tags := make([]string, len(seen))
  counts := make([]int, len(seen))

  i := 0
  for k := range seen {
    tags[i] = k
    i += 1
  }

  sort.Strings(tags)

  for i,v := range tags {
    counts[i] = seen[v]
  }

  return tags, counts, nil
}
<commit_msg>Fixed sorting issue.<commit_after>package post

import (
    "appengine"
    "appengine/datastore"
    "appengine/blobstore"
    "io/ioutil"
    "encoding/json"
    "time"
    "strings"
    "sort"
    "errors"
)

type Post struct {
  Title       string
  Content     appengine.BlobKey
  Postdate    time.Time
  StickyUrl   string
}

type Tag struct {
  Name        string
  Postdate    time.Time
  PostKey     *datastore.Key
}

type Tags []Tag

func (s Tags) Less(i, j int) bool { return s[i].Postdate.UnixNano() > s[j].Postdate.UnixNano() }
func (s Tags) Len() int { return len(s) }
func (s Tags) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func conv_title_to_url(title string) string{
  lc := strings.ToLower(title)

  strip := func(r rune) rune{
    switch {
      case 'a' <= r && r <= 'z':
        return r
      case '0' <= r && r <= '9':
        return r
      case r == ' ', r == '-', r == '_':
        return r
    }
    return ' '
  }

  return strings.Replace(strings.Map(strip, lc), " ", "-", -1)
}

func SavePost(context appengine.Context, title string, content appengine.BlobKey, tags []string, postdate time.Time) (*datastore.Key, error){
  p1 := Post{
      Title:    title,
      Content:  content,
      Postdate: postdate,
      StickyUrl: conv_title_to_url(title),
  }

  temppostkey := datastore.NewIncompleteKey(context, "post", nil)
  postkey,err := datastore.Put(context, temppostkey, &p1)
  if err != nil {
    return nil, err
  }

  t1 := Tag{
    Name:     "all posts",
    Postdate: postdate,
    PostKey:  postkey,
  }
  tagkey := datastore.NewIncompleteKey(context, "tag", nil)
  _,err = datastore.Put(context, tagkey, &t1)
  if err != nil {
    return nil, err
  }

  for _,t := range tags{
    t1 := Tag{
      Name:     t,
      Postdate: postdate,
      PostKey:  postkey,
    }
    tagkey := datastore.NewIncompleteKey(context, "tag", nil)
    _,err = datastore.Put(context, tagkey, &t1)
    if err != nil {
      return nil, err
    }
  }

  return postkey, nil
}

func GetTagSlice(context appengine.Context, key *datastore.Key) ([]string, error){
  var tagstructs []Tag
  _,err := (GetTagsAssociatedWithPost(key).GetAll(context, &tagstructs))
  if err != nil { return nil, err }

  tags := make([]string, len(tagstructs))
  for i,ts := range tagstructs{
    tags[i] = ts.Name
  }

  return tags, nil
}

func GetPostContent(context appengine.Context, p Post)(string, error){

  data, err := ioutil.ReadAll(blobstore.NewReader(context, p.Content))
  if err != nil {
    context.Errorf("ioutil.ReadAll: %v", err)
    return "", err
  }
  if len(data) <= 0{
    context.Errorf("len(data): %v", len(data))
    return "", errors.New("len(data) < 1")
  }

  var decoded interface{}
  err = json.Unmarshal(data, &decoded)
  if err != nil {
    context.Errorf("json.Unmarshal: %v", err)
    return "", err
  }

  q := decoded.(map[string]interface{})
  content,ok := q["data"].(string)
  if !ok{
    context.Errorf("post content has no 'data' field internally")
    return "", errors.New("post has no 'data' field")
  }

  return content, nil
}

func GetPost(context appengine.Context, key *datastore.Key) (Post, string, []string, error){
  var p2 Post
  err := datastore.Get(context, key, &p2)
  if err != nil { return p2, "", nil, err }
  tags, err := GetTagSlice(context, key)
  if err != nil { return p2, "", nil, err }
  content, err := GetPostContent(context, p2)
  if err != nil { return p2, "", nil, err }

  return p2, content, tags, err
}

func UniquePosts(context appengine.Context, queries []*datastore.Query) ([]*datastore.Key, error){
  seen := map[string]*datastore.Key {}

  alltags := make(Tags, 0)
  for _,query := range queries{
    var newtags Tags
    _,err := query.GetAll(context, &newtags)
    if err != nil { return nil, err }

    alltags = append(alltags, newtags...)
  }

  sort.Sort(alltags)

  keys := make([]*datastore.Key, 0)

  for _,t := range alltags{
    if _, ok := seen[t.PostKey.String()]; !ok{
      seen[t.PostKey.String()] = t.PostKey
      keys = append(keys, t.PostKey)
    }
  }

  return keys, nil
}

type FullPost struct {
  PostStruct Post
  Tags []string
  Content string
}

func GetPosts(c appengine.Context, keys []*datastore.Key, start int, limit int, out chan<- FullPost, errout chan<- error){

  defer close(out)
  defer close(errout)

  if start > len(keys){ start = len(keys) }
  if start+limit > len(keys){ limit = len(keys) - start }

  for _,t := range keys[start:start+limit]{
    post, content, tags, err := GetPost(c, t)

    if err != nil{
      errout <- err
      return
    }

    p1 := FullPost{
      PostStruct: post,
      Tags: tags,
      Content: content,
    }

    out <- p1
  }
}

func ExecuteQuery(c appengine.Context, q *datastore.Query, start int, limit int, filter func(Post) bool, out chan<- Post, errout chan<- error){

  defer close(out)
  defer close(errout)

  for t,i := q.Run(c), 0;  ; i++ {
    if ((start < 0) || (limit < 0)) || (i < (start + limit)){
      var x Post
      // key, err := t.Next(&x)
      _, err := t.Next(&x)

      if err == datastore.Done {
        return
      }
      if err != nil {
        errout <- err
        return
      }

      if !filter(x) {
        i--
        continue
      }

      if i < start {
        continue
      }

      out <- x
    } else {
      break
    }
  }
}

func GetCount(c appengine.Context, q *datastore.Query) (int, error){
  return q.Count(c)
}

func GetPostsNotMatchingTag(tag string) ([]*datastore.Query){
  queries := []*datastore.Query { datastore.NewQuery("tag").Filter("Name <", tag),
                                  datastore.NewQuery("tag").Filter("Name >", tag),
                                }
  return queries
}

func GetPostsMatchingTag(tag string) ([]*datastore.Query){
  return []*datastore.Query {datastore.NewQuery("tag").Filter("Name =", tag)}
}

func GetPostsSortedByDate() ([]*datastore.Query){
  return []*datastore.Query {datastore.NewQuery("post").Order("-Postdate")}
}

func GetTagsAssociatedWithPost(postkey *datastore.Key) (*datastore.Query){
  return datastore.NewQuery("tag").Filter("PostKey =", postkey).Order("Name")
}

func GetPostsMatchingUrl(stickyurl string) (*datastore.Query){
  return datastore.NewQuery("post").Filter("StickyUrl =", stickyurl).Limit(1)
}

func GetAllPosts() (*datastore.Query){
  return datastore.NewQuery("post")
}

func GetLatestDate(context appengine.Context)(time.Time){
  q := datastore.NewQuery("post").Order("-Postdate")
  var mePosts []Post
  _,err := q.Limit(1).GetAll(context, &mePosts)
  if err != nil { return time.Now() }
  if len(mePosts) < 1{
    return time.Now()
  }
  return mePosts[0].Postdate
}

func GetAllTags(context appengine.Context) ([]string,[]int, error){
  seen := map[string]int {}

  query := datastore.NewQuery("tag")
  var rawtags Tags
  _,err := query.GetAll(context, &rawtags)
  if err != nil { return nil, nil, err }

  for _,t := range rawtags{
    if _,ok := seen[t.Name]; !ok {
      seen[t.Name] = 1
    } else {
      seen[t.Name] += 1
    }
  }

  delete(seen, "all posts")
  delete(seen, "static")

  tags := make([]string, len(seen))
  counts := make([]int, len(seen))

  i := 0
  for k := range seen {
    tags[i] = k
    i += 1
  }

  sort.Strings(tags)

  for i,v := range tags {
    counts[i] = seen[v]
  }

  return tags, counts, nil
}
<|endoftext|>


<commit_before>package main

import (
        "./comms"
        "./EncryptionEngine"

        "flag"

        "net"
        "fmt"
        "io"

        "net/http"
        "net/url"
        "html"
        "log"
        "encoding/hex"
        "encoding/base64"
        "time"
       )

type State struct {
    Kc [16]byte
    clk uint32
    BD_ADDR [6]byte
    is_master bool
}

func server_main(s *State) net.Conn {
    ln, err := net.Listen("tcp", ":8080")

    if err != nil {
        fmt.Println("net.Listen failed:", err)
    }

    conn, err := ln.Accept()

    fmt.Printf("Accepted Connection\n")

    if err != nil {
        fmt.Println("ln.Accept failed:", err)
    }

    return conn
}

func client_main() net.Conn {
    conn, err := net.Dial("tcp", "127.0.0.1:8080")

    if err != nil {
        fmt.Println("net.Dial failed:", err)
    }

    return conn
}

func is_bigger(ours, theirs [6]byte) bool{
    //TODO: This... Note the bit ordering..
    return ours[0] > theirs[0]
}

func receiver(conn io.ReadWriter, s *State) {
  LOOP:
  for {
        packet_type := comms.Recv_packet(conn)

        switch packet_type {
            case 0:
                OTHER_BD_ADDR := comms.Recv_neg(conn)
                if !is_bigger(s.BD_ADDR, OTHER_BD_ADDR) {
                    s.BD_ADDR = OTHER_BD_ADDR
                    s.is_master = true
                } else {
                    s.is_master = false
                }
            case 1:
                s.clk, _, s.Kc = comms.Recv_init(conn)
            case 2:
                var msg []byte
                s.clk, msg = comms.Recv_data(conn)

                fmt.Println("Recieved: ", string(msg))

                keyStream := EncryptionEngine.GetKeyStream(s.Kc, s.BD_ADDR, s.clk, len(msg))
                decrypted_msg := EncryptionEngine.Encrypt(msg, keyStream)

                fmt.Println("Decypted as: ", string(decrypted_msg))

                ciphertext_b64 := base64.StdEncoding.EncodeToString(msg)
                keystream_b64 := base64.StdEncoding.EncodeToString(keyStream)

                var role string

                if s.is_master {
                    role = "master"
                } else {
                    role = "slave"
                }

                _, err := http.PostForm("http://127.0.0.1:8000/log?role=" + role,
                        url.Values{
                        "CLK" : { string(s.clk) },
                        "is_receiving" : { "true" },
                        "keystream" : { keystream_b64 },
                        "ciphertext" : { ciphertext_b64 },
                        "plaintext" : { string(decrypted_msg) },
                        "timestamp" : { time.Now().Format("Jan _2 15:04:05") },
                        })

                if err != nil {
                    fmt.Println("There was an http error: ", err)
                }

            case 99: break LOOP
        }
    }
}

func main() {
    isServerPtr := flag.Bool("server", false, "Run in server mode?")
    flag.Parse()
    fmt.Println("Is Server: ", *isServerPtr)

    var conn net.Conn
    var p string

    var state State

    state.Kc = [16]byte{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
    state.clk = 0

    if *isServerPtr {
        state.BD_ADDR = [6]byte{255, 255, 255, 255, 255, 255}
        conn = server_main(&state)
        p = ":8888"
    } else {
        state.BD_ADDR = [6]byte{0, 0, 0, 0, 0, 0}
        conn = client_main()
        p = ":6666"
    }

    fmt.Println("Running on ", p)

    comms.Send_neg(conn, state.BD_ADDR)

    go receiver(conn, &state)

    http.HandleFunc("/Kc", func(w http.ResponseWriter, r *http.Request) {
        var Kc_str string
        if r.Method == "POST" {
            r.ParseForm()
            Kc_str = r.PostForm["Kc"][0]
            fmt.Println("Kc String: ", Kc_str)
        }

        Kc, err := hex.DecodeString(Kc_str)

        if err != nil || len(Kc) < 16 {
            fmt.Println("Invalid key!")
            return
        }

        fmt.Println("Kc: ", Kc)

        for i:= 0; i < 16; i++ {
            state.Kc[i] = Kc[i]
        }

    })

    http.HandleFunc("/isMaster", func(w http.ResponseWriter, r *http.Request) {
        if state.is_master {
            fmt.Fprintf(w, "true")
        } else {
            fmt.Fprintf(w, "false")
        }
    })

    http.HandleFunc("/message", func(w http.ResponseWriter, r *http.Request) {

        if r.Method == "POST" {
            state.clk++
            r.ParseForm()

            pt := []byte(r.PostForm["plaintext"][0])
            fmt.Println("Sending: ", string(pt))

            fmt.Fprintf(w, html.EscapeString("Sending packet"))

            keyStream := EncryptionEngine.GetKeyStream(
                state.Kc, state.BD_ADDR, state.clk, len(pt))
            msg := EncryptionEngine.Encrypt(pt, keyStream)

            comms.Send_data(conn, state.clk, msg)

            fmt.Println("Encrypted as: ", string(msg))

            keystream_b64 := base64.StdEncoding.EncodeToString(keyStream)
            ciphertext_b64 := base64.StdEncoding.EncodeToString(msg)

            var role string

            if state.is_master {
                role = "master"
            } else {
                role = "slave"
            }

            _, err := http.PostForm("http://127.0.0.1:8000/log?role=" + role,
                    url.Values{
                    "CLK" : { string(state.clk) },
                    "is_receiving" : { "false" },
                    "keystream" : { keystream_b64 },
                    "ciphertext" : { ciphertext_b64 },
                    "plaintext" : { string(pt) },
                    "timestamp" : { time.Now().Format("Jan _2 15:04:05") },
                    })

            if err != nil {
                    fmt.Println("There was an http error: ", err)
            }
        }
    })

    log.Fatal(http.ListenAndServe(p, nil))

    conn.Close()
}
<commit_msg>Send server BD_ADDR<commit_after>package main

import (
        "./comms"
        "./EncryptionEngine"

        "flag"

        "net"
        "fmt"
        "io"

        "net/http"
        "net/url"
        "html"
        "log"
        "encoding/hex"
        "encoding/base64"
        "time"
       )

type State struct {
    Kc [16]byte
    clk uint32
    BD_ADDR [6]byte
    MASTER_BD_ADDR [6]byte
    is_master bool
}

func server_main(s *State) net.Conn {
    ln, err := net.Listen("tcp", ":8080")

    if err != nil {
        fmt.Println("net.Listen failed:", err)
    }

    conn, err := ln.Accept()

    fmt.Printf("Accepted Connection\n")

    if err != nil {
        fmt.Println("ln.Accept failed:", err)
    }

    return conn
}

func client_main() net.Conn {
    conn, err := net.Dial("tcp", "127.0.0.1:8080")

    if err != nil {
        fmt.Println("net.Dial failed:", err)
    }

    return conn
}

func is_bigger(ours, theirs [6]byte) bool{
    //TODO: This... Note the bit ordering..
    return ours[0] > theirs[0]
}

func receiver(conn io.ReadWriter, s *State) {
  LOOP:
  for {
        packet_type := comms.Recv_packet(conn)

        switch packet_type {
            case 0:
                OTHER_BD_ADDR := comms.Recv_neg(conn)
                if is_bigger(s.BD_ADDR, OTHER_BD_ADDR) {
                    s.MASTER_BD_ADDR = s.BD_ADDR
                    s.is_master = true
                } else {
                    s.MASTER_BD_ADDR = OTHER_BD_ADDR
                    s.is_master = false
                }
            case 1:
                s.clk, _, s.Kc = comms.Recv_init(conn)
            case 2:
                var msg []byte
                s.clk, msg = comms.Recv_data(conn)

                fmt.Println("Recieved: ", string(msg))

                keyStream := EncryptionEngine.GetKeyStream(s.Kc, s.MASTER_BD_ADDR, s.clk, len(msg))
                decrypted_msg := EncryptionEngine.Encrypt(msg, keyStream)

                fmt.Println("Decypted as: ", string(decrypted_msg))

                ciphertext_b64 := base64.StdEncoding.EncodeToString(msg)
                keystream_b64 := base64.StdEncoding.EncodeToString(keyStream)

                var role string

                if s.is_master {
                    role = "master"
                } else {
                    role = "slave"
                }

                _, err := http.PostForm("http://127.0.0.1:8000/log?role=" + role,
                        url.Values{
                        "CLK" : { string(s.clk) },
                        "is_receiving" : { "true" },
                        "keystream" : { keystream_b64 },
                        "ciphertext" : { ciphertext_b64 },
                        "plaintext" : { string(decrypted_msg) },
                        "timestamp" : { time.Now().Format("Jan _2 15:04:05") },
                        })

                if err != nil {
                    fmt.Println("There was an http error: ", err)
                }

            case 99: break LOOP
        }
    }
}

func main() {
    isServerPtr := flag.Bool("server", false, "Run in server mode?")
    flag.Parse()
    fmt.Println("Is Server: ", *isServerPtr)

    var conn net.Conn
    var p string

    var state State

    state.Kc = [16]byte{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
    state.clk = 0

    if *isServerPtr {
        state.BD_ADDR = [6]byte{255, 255, 255, 255, 255, 255}
        conn = server_main(&state)
        p = ":8888"
    } else {
        state.BD_ADDR = [6]byte{0, 0, 0, 0, 0, 0}
        conn = client_main()
        p = ":6666"
    }

    fmt.Println("Running on ", p)

    comms.Send_neg(conn, state.BD_ADDR)

    go receiver(conn, &state)

    http.HandleFunc("/Kc", func(w http.ResponseWriter, r *http.Request) {
        var Kc_str string
        if r.Method == "POST" {
            r.ParseForm()
            Kc_str = r.PostForm["Kc"][0]
            fmt.Println("Kc String: ", Kc_str)
        }

        Kc, err := hex.DecodeString(Kc_str)

        if err != nil || len(Kc) < 16 {
            fmt.Println("Invalid key!")
            return
        }

        fmt.Println("Kc: ", Kc)

        for i:= 0; i < 16; i++ {
            state.Kc[i] = Kc[i]
        }

    })

    http.HandleFunc("/isMaster", func(w http.ResponseWriter, r *http.Request) {
        if state.is_master {
            fmt.Fprintf(w, "true")
        } else {
            fmt.Fprintf(w, "false")
        }
    })

    http.HandleFunc("/message", func(w http.ResponseWriter, r *http.Request) {

        if r.Method == "POST" {
            state.clk++
            r.ParseForm()

            pt := []byte(r.PostForm["plaintext"][0])
            fmt.Println("Sending: ", string(pt))

            fmt.Fprintf(w, html.EscapeString("Sending packet"))

            keyStream := EncryptionEngine.GetKeyStream(
                state.Kc, state.MASTER_BD_ADDR, state.clk, len(pt))
            msg := EncryptionEngine.Encrypt(pt, keyStream)

            comms.Send_data(conn, state.clk, msg)

            fmt.Println("Encrypted as: ", string(msg))

            keystream_b64 := base64.StdEncoding.EncodeToString(keyStream)
            ciphertext_b64 := base64.StdEncoding.EncodeToString(msg)

            BD_ADDR_hex := hex.EncodeToString(state.BD_ADDR[:])

            var role string

            if state.is_master {
                role = "master"
            } else {
                role = "slave"
            }

            _, err := http.PostForm("http://127.0.0.1:8000/log?role=" + role,
                    url.Values{
                    "CLK" : { string(state.clk) },
                    "BD_ADDR" : { BD_ADDR_hex },
                    "is_receiving" : { "false" },
                    "keystream" : { keystream_b64 },
                    "ciphertext" : { ciphertext_b64 },
                    "plaintext" : { string(pt) },
                    "timestamp" : { time.Now().Format("Jan _2 15:04:05") },
                    })

            if err != nil {
                    fmt.Println("There was an http error: ", err)
            }
        }
    })

    log.Fatal(http.ListenAndServe(p, nil))

    conn.Close()
}
<|endoftext|>


<commit_before>// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package binding

import (
	"encoding/json"
	"encoding/xml"
	"errors"
	"net/http"
	"reflect"
	"strconv"
	"strings"
)

type (
	Binding interface {
		Bind(*http.Request, interface{}) error
	}

	// JSON binding
	jsonBinding struct{}

	// XML binding
	xmlBinding struct{}

	// // form binding
	formBinding struct{}
)

var (
	JSON = jsonBinding{}
	XML  = xmlBinding{}
	Form = formBinding{} // todo
)

func (_ jsonBinding) Bind(req *http.Request, obj interface{}) error {
	decoder := json.NewDecoder(req.Body)
	if err := decoder.Decode(obj); err == nil {
		return Validate(obj)
	} else {
		return err
	}
}

func (_ xmlBinding) Bind(req *http.Request, obj interface{}) error {
	decoder := xml.NewDecoder(req.Body)
	if err := decoder.Decode(obj); err == nil {
		return Validate(obj)
	} else {
		return err
	}
}

func (_ formBinding) Bind(req *http.Request, obj interface{}) error {
	if err := req.ParseForm(); err != nil {
		return err
	}
	if err := mapForm(obj, req.Form); err != nil {
		return err
	}
	return Validate(obj)
}

func mapForm(ptr interface{}, form map[string][]string) error {
	typ := reflect.TypeOf(ptr).Elem()
	formStruct := reflect.ValueOf(ptr).Elem()
	for i := 0; i < typ.NumField(); i++ {
		typeField := typ.Field(i)
		if inputFieldName := typeField.Tag.Get("form"); inputFieldName != "" {
			structField := formStruct.Field(i)
			if !structField.CanSet() {
				continue
			}

			inputValue, exists := form[inputFieldName]
			if !exists {
				continue
			}
			numElems := len(inputValue)
			if structField.Kind() == reflect.Slice && numElems > 0 {
				sliceOf := structField.Type().Elem().Kind()
				slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
				for i := 0; i < numElems; i++ {
					if err := setWithProperType(sliceOf, inputValue[i], slice.Index(i)); err != nil {
						return err
					}
				}
				formStruct.Elem().Field(i).Set(slice)
			} else {
				if err := setWithProperType(typeField.Type.Kind(), inputValue[0], structField); err != nil {
					return err
				}
			}
		}
	}
	return nil
}

func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value) error {
	switch valueKind {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if val == "" {
			val = "0"
		}
		intVal, err := strconv.Atoi(val)
		if err != nil {
			return err
		} else {
			structField.SetInt(int64(intVal))
		}
	case reflect.Bool:
		if val == "" {
			val = "false"
		}
		boolVal, err := strconv.ParseBool(val)
		if err != nil {
			return err
		} else {
			structField.SetBool(boolVal)
		}
	case reflect.Float32:
		if val == "" {
			val = "0.0"
		}
		floatVal, err := strconv.ParseFloat(val, 32)
		if err != nil {
			return err
		} else {
			structField.SetFloat(floatVal)
		}
	case reflect.Float64:
		if val == "" {
			val = "0.0"
		}
		floatVal, err := strconv.ParseFloat(val, 64)
		if err != nil {
			return err
		} else {
			structField.SetFloat(floatVal)
		}
	case reflect.String:
		structField.SetString(val)
	}
	return nil
}

// Don't pass in pointers to bind to. Can lead to bugs. See:
// https://github.com/codegangsta/martini-contrib/issues/40
// https://github.com/codegangsta/martini-contrib/pull/34#issuecomment-29683659
func ensureNotPointer(obj interface{}) {
	if reflect.TypeOf(obj).Kind() == reflect.Ptr {
		panic("Pointers are not accepted as binding models")
	}
}

func Validate(obj interface{}) error {
	typ := reflect.TypeOf(obj)
	val := reflect.ValueOf(obj)

	if typ.Kind() == reflect.Ptr {
		typ = typ.Elem()
		val = val.Elem()
	}

	switch typ.Kind() {
	case reflect.Struct:
		for i := 0; i < typ.NumField(); i++ {
			field := typ.Field(i)

			// Allow ignored fields in the struct
			if field.Tag.Get("form") == "-" {
				continue
			}

			fieldValue := val.Field(i).Interface()
			zero := reflect.Zero(field.Type).Interface()

			if strings.Index(field.Tag.Get("binding"), "required") > -1 {
				fieldType := field.Type.Kind()
				if fieldType == reflect.Struct {
					err := Validate(fieldValue)
					if err != nil {
						return err
					}
				} else if reflect.DeepEqual(zero, fieldValue) {
					return errors.New("Required " + field.Name)
				} else if fieldType == reflect.Slice && field.Type.Elem().Kind() == reflect.Struct {
					err := Validate(fieldValue)
					if err != nil {
						return err
					}
				}
			}
		}
	case reflect.Slice:
		for i := 0; i < val.Len(); i++ {
			fieldValue := val.Index(i).Interface()
			err := Validate(fieldValue)
			if err != nil {
				return err
			}
		}
	default:
		return nil
	}
	return nil
}
<commit_msg>Validate should ignore unexported struct fields.<commit_after>// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package binding

import (
	"encoding/json"
	"encoding/xml"
	"errors"
	"net/http"
	"reflect"
	"strconv"
	"strings"
)

type (
	Binding interface {
		Bind(*http.Request, interface{}) error
	}

	// JSON binding
	jsonBinding struct{}

	// XML binding
	xmlBinding struct{}

	// // form binding
	formBinding struct{}
)

var (
	JSON = jsonBinding{}
	XML  = xmlBinding{}
	Form = formBinding{} // todo
)

func (_ jsonBinding) Bind(req *http.Request, obj interface{}) error {
	decoder := json.NewDecoder(req.Body)
	if err := decoder.Decode(obj); err == nil {
		return Validate(obj)
	} else {
		return err
	}
}

func (_ xmlBinding) Bind(req *http.Request, obj interface{}) error {
	decoder := xml.NewDecoder(req.Body)
	if err := decoder.Decode(obj); err == nil {
		return Validate(obj)
	} else {
		return err
	}
}

func (_ formBinding) Bind(req *http.Request, obj interface{}) error {
	if err := req.ParseForm(); err != nil {
		return err
	}
	if err := mapForm(obj, req.Form); err != nil {
		return err
	}
	return Validate(obj)
}

func mapForm(ptr interface{}, form map[string][]string) error {
	typ := reflect.TypeOf(ptr).Elem()
	formStruct := reflect.ValueOf(ptr).Elem()
	for i := 0; i < typ.NumField(); i++ {
		typeField := typ.Field(i)
		if inputFieldName := typeField.Tag.Get("form"); inputFieldName != "" {
			structField := formStruct.Field(i)
			if !structField.CanSet() {
				continue
			}

			inputValue, exists := form[inputFieldName]
			if !exists {
				continue
			}
			numElems := len(inputValue)
			if structField.Kind() == reflect.Slice && numElems > 0 {
				sliceOf := structField.Type().Elem().Kind()
				slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
				for i := 0; i < numElems; i++ {
					if err := setWithProperType(sliceOf, inputValue[i], slice.Index(i)); err != nil {
						return err
					}
				}
				formStruct.Elem().Field(i).Set(slice)
			} else {
				if err := setWithProperType(typeField.Type.Kind(), inputValue[0], structField); err != nil {
					return err
				}
			}
		}
	}
	return nil
}

func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value) error {
	switch valueKind {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if val == "" {
			val = "0"
		}
		intVal, err := strconv.Atoi(val)
		if err != nil {
			return err
		} else {
			structField.SetInt(int64(intVal))
		}
	case reflect.Bool:
		if val == "" {
			val = "false"
		}
		boolVal, err := strconv.ParseBool(val)
		if err != nil {
			return err
		} else {
			structField.SetBool(boolVal)
		}
	case reflect.Float32:
		if val == "" {
			val = "0.0"
		}
		floatVal, err := strconv.ParseFloat(val, 32)
		if err != nil {
			return err
		} else {
			structField.SetFloat(floatVal)
		}
	case reflect.Float64:
		if val == "" {
			val = "0.0"
		}
		floatVal, err := strconv.ParseFloat(val, 64)
		if err != nil {
			return err
		} else {
			structField.SetFloat(floatVal)
		}
	case reflect.String:
		structField.SetString(val)
	}
	return nil
}

// Don't pass in pointers to bind to. Can lead to bugs. See:
// https://github.com/codegangsta/martini-contrib/issues/40
// https://github.com/codegangsta/martini-contrib/pull/34#issuecomment-29683659
func ensureNotPointer(obj interface{}) {
	if reflect.TypeOf(obj).Kind() == reflect.Ptr {
		panic("Pointers are not accepted as binding models")
	}
}

func Validate(obj interface{}) error {
	typ := reflect.TypeOf(obj)
	val := reflect.ValueOf(obj)

	if typ.Kind() == reflect.Ptr {
		typ = typ.Elem()
		val = val.Elem()
	}

	switch typ.Kind() {
	case reflect.Struct:
		for i := 0; i < typ.NumField(); i++ {
			field := typ.Field(i)

			// Allow ignored and unexported fields in the struct
			if field.Tag.Get("form") == "-" || field.PkgPath != "" {
				continue
			}

			fieldValue := val.Field(i).Interface()
			zero := reflect.Zero(field.Type).Interface()

			if strings.Index(field.Tag.Get("binding"), "required") > -1 {
				fieldType := field.Type.Kind()
				if fieldType == reflect.Struct {
					err := Validate(fieldValue)
					if err != nil {
						return err
					}
				} else if reflect.DeepEqual(zero, fieldValue) {
					return errors.New("Required " + field.Name)
				} else if fieldType == reflect.Slice && field.Type.Elem().Kind() == reflect.Struct {
					err := Validate(fieldValue)
					if err != nil {
						return err
					}
				}
			}
		}
	case reflect.Slice:
		for i := 0; i < val.Len(); i++ {
			fieldValue := val.Index(i).Interface()
			err := Validate(fieldValue)
			if err != nil {
				return err
			}
		}
	default:
		return nil
	}
	return nil
}
<|endoftext|>


<commit_before>package bitswap

import (
	"errors"
	"time"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/datastore.go"

	bsmsg "github.com/jbenet/go-ipfs/bitswap/message"
	bsnet "github.com/jbenet/go-ipfs/bitswap/network"
	notifications "github.com/jbenet/go-ipfs/bitswap/notifications"
	strategy "github.com/jbenet/go-ipfs/bitswap/strategy"
	blocks "github.com/jbenet/go-ipfs/blocks"
	blockstore "github.com/jbenet/go-ipfs/blockstore"
	peer "github.com/jbenet/go-ipfs/peer"
	u "github.com/jbenet/go-ipfs/util"
)

// TODO(brian): ensure messages are being received

// PartnerWantListMax is the bound for the number of keys we'll store per
// partner. These are usually taken from the top of the Partner's WantList
// advertisements. WantLists are sorted in terms of priority.
const PartnerWantListMax = 10

// KeySet is just a convenient alias for maps of keys, where we only care
// access/lookups.
type KeySet map[u.Key]struct{}

// bitswap instances implement the bitswap protocol.
type bitswap struct {
	// peer is the identity of this (local) node.
	peer *peer.Peer

	// sender delivers messages on behalf of the session
	sender bsnet.NetworkAdapter

	// blockstore is the local database
	// NB: ensure threadsafety
	blockstore blockstore.Blockstore

	// routing interface for communication
	routing Directory

	notifications notifications.PubSub

	// strategist listens to network traffic and makes decisions about how to
	// interact with partners.
	// TODO(brian): save the strategist's state to the datastore
	strategist strategy.Strategist

	partners ledgerMap

	// haveList is the set of keys we have values for. a map for fast lookups.
	// haveList KeySet -- not needed. all values in datastore?

	strategy strategyFunc

	haltChan chan struct{}
}

// NewSession initializes a bitswap session.
func NewSession(parent context.Context, s bsnet.NetworkService, p *peer.Peer, d ds.Datastore, directory Directory) Exchange {

	// FIXME(brian): instantiate a concrete Strategist
	receiver := bsnet.Forwarder{}
	bs := &bitswap{
		peer:          p,
		blockstore:    blockstore.NewBlockstore(d),
		partners:      ledgerMap{},
		routing:       directory,
		sender:        bsnet.NewNetworkAdapter(s, &receiver),
		haltChan:      make(chan struct{}),
		notifications: notifications.New(),
		strategy:      yesManStrategy,
	}
	receiver.Delegate(bs)

	return bs
}

// GetBlock attempts to retrieve a particular block from peers, within timeout.
func (bs *bitswap) Block(k u.Key, timeout time.Duration) (
	*blocks.Block, error) {
	begin := time.Now()
	tleft := timeout - time.Now().Sub(begin)
	provs_ch := bs.routing.FindProvidersAsync(k, 20, timeout)

	blockChannel := make(chan blocks.Block)
	after := time.After(tleft)

	// TODO: when the data is received, shut down this for loop ASAP
	go func() {
		for p := range provs_ch {
			go func(pr *peer.Peer) {
				blk, err := bs.getBlock(k, pr, tleft)
				if err != nil {
					return
				}
				select {
				case blockChannel <- *blk:
				default:
				}
			}(p)
		}
	}()

	select {
	case block := <-blockChannel:
		close(blockChannel)
		return &block, nil
	case <-after:
		return nil, u.ErrTimeout
	}
}

func (bs *bitswap) getBlock(k u.Key, p *peer.Peer, timeout time.Duration) (*blocks.Block, error) {

	ctx, _ := context.WithTimeout(context.Background(), timeout)
	blockChannel := bs.notifications.Subscribe(ctx, k)

	message := bsmsg.New()
	message.AppendWanted(k)

	// FIXME(brian): register the accountant on the service wrapper to ensure
	// that accounting is _always_ performed when SendMessage and
	// ReceiveMessage are called
	bs.sender.SendMessage(ctx, p, message)
	bs.strategist.MessageSent(p, message)

	block, ok := <-blockChannel
	if !ok {
		return nil, u.ErrTimeout
	}
	return &block, nil
}

func (bs *bitswap) sendToPeersThatWant(block blocks.Block) {
	for _, p := range bs.strategist.Peers() {
		if bs.strategist.IsWantedByPeer(block.Key(), p) {
			if bs.strategist.ShouldSendToPeer(block.Key(), p) {
				go bs.send(p, block)
			}
		}
	}
}

// HasBlock announces the existance of a block to bitswap, potentially sending
// it to peers (Partners) whose WantLists include it.
func (bs *bitswap) HasBlock(blk blocks.Block) error {
	go bs.sendToPeersThatWant(blk)
	return bs.routing.Provide(blk.Key())
}

// TODO(brian): get a return value
func (bs *bitswap) send(p *peer.Peer, b blocks.Block) {
	message := bsmsg.New()
	message.AppendBlock(b)
	// FIXME(brian): pass ctx
	bs.sender.SendMessage(context.Background(), p, message)
	bs.strategist.MessageSent(p, message)
}

func (bs *bitswap) Halt() {
	bs.haltChan <- struct{}{}
}

// TODO(brian): handle errors
func (bs *bitswap) ReceiveMessage(
	ctx context.Context, sender *peer.Peer, incoming bsmsg.BitSwapMessage) (
	*peer.Peer, bsmsg.BitSwapMessage, error) {

	bs.strategist.MessageReceived(sender, incoming)

	if incoming.Blocks() != nil {
		for _, block := range incoming.Blocks() {
			go bs.blockstore.Put(block) // FIXME(brian): err ignored
			go bs.notifications.Publish(block)
		}
	}

	if incoming.Wantlist() != nil {
		for _, key := range incoming.Wantlist() {
			if bs.strategist.ShouldSendToPeer(key, sender) {
				block, errBlockNotFound := bs.blockstore.Get(key)
				if errBlockNotFound != nil {
					// TODO(brian): log/return the error
					continue
				}
				go bs.send(sender, *block)
			}
		}
	}
	return nil, nil, errors.New("TODO implement")
}

func numBytes(b blocks.Block) int {
	return len(b.Data)
}
<commit_msg>chore(bitswap) rm vestigial fields<commit_after>package bitswap

import (
	"errors"
	"time"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/datastore.go"

	bsmsg "github.com/jbenet/go-ipfs/bitswap/message"
	bsnet "github.com/jbenet/go-ipfs/bitswap/network"
	notifications "github.com/jbenet/go-ipfs/bitswap/notifications"
	strategy "github.com/jbenet/go-ipfs/bitswap/strategy"
	blocks "github.com/jbenet/go-ipfs/blocks"
	blockstore "github.com/jbenet/go-ipfs/blockstore"
	peer "github.com/jbenet/go-ipfs/peer"
	u "github.com/jbenet/go-ipfs/util"
)

// TODO(brian): ensure messages are being received

// PartnerWantListMax is the bound for the number of keys we'll store per
// partner. These are usually taken from the top of the Partner's WantList
// advertisements. WantLists are sorted in terms of priority.
const PartnerWantListMax = 10

// KeySet is just a convenient alias for maps of keys, where we only care
// access/lookups.
type KeySet map[u.Key]struct{}

// bitswap instances implement the bitswap protocol.
type bitswap struct {
	// peer is the identity of this (local) node.
	peer *peer.Peer

	// sender delivers messages on behalf of the session
	sender bsnet.NetworkAdapter

	// blockstore is the local database
	// NB: ensure threadsafety
	blockstore blockstore.Blockstore

	// routing interface for communication
	routing Directory

	notifications notifications.PubSub

	// strategist listens to network traffic and makes decisions about how to
	// interact with partners.
	// TODO(brian): save the strategist's state to the datastore
	strategist strategy.Strategist

	// haveList is the set of keys we have values for. a map for fast lookups.
	// haveList KeySet -- not needed. all values in datastore?

	haltChan chan struct{}
}

// NewSession initializes a bitswap session.
func NewSession(parent context.Context, s bsnet.NetworkService, p *peer.Peer, d ds.Datastore, directory Directory) Exchange {

	// FIXME(brian): instantiate a concrete Strategist
	receiver := bsnet.Forwarder{}
	bs := &bitswap{
		peer:          p,
		blockstore:    blockstore.NewBlockstore(d),
		routing:       directory,
		sender:        bsnet.NewNetworkAdapter(s, &receiver),
		haltChan:      make(chan struct{}),
		notifications: notifications.New(),
	}
	receiver.Delegate(bs)

	return bs
}

// GetBlock attempts to retrieve a particular block from peers, within timeout.
func (bs *bitswap) Block(k u.Key, timeout time.Duration) (
	*blocks.Block, error) {
	begin := time.Now()
	tleft := timeout - time.Now().Sub(begin)
	provs_ch := bs.routing.FindProvidersAsync(k, 20, timeout)

	blockChannel := make(chan blocks.Block)
	after := time.After(tleft)

	// TODO: when the data is received, shut down this for loop ASAP
	go func() {
		for p := range provs_ch {
			go func(pr *peer.Peer) {
				blk, err := bs.getBlock(k, pr, tleft)
				if err != nil {
					return
				}
				select {
				case blockChannel <- *blk:
				default:
				}
			}(p)
		}
	}()

	select {
	case block := <-blockChannel:
		close(blockChannel)
		return &block, nil
	case <-after:
		return nil, u.ErrTimeout
	}
}

func (bs *bitswap) getBlock(k u.Key, p *peer.Peer, timeout time.Duration) (*blocks.Block, error) {

	ctx, _ := context.WithTimeout(context.Background(), timeout)
	blockChannel := bs.notifications.Subscribe(ctx, k)

	message := bsmsg.New()
	message.AppendWanted(k)

	// FIXME(brian): register the accountant on the service wrapper to ensure
	// that accounting is _always_ performed when SendMessage and
	// ReceiveMessage are called
	bs.sender.SendMessage(ctx, p, message)
	bs.strategist.MessageSent(p, message)

	block, ok := <-blockChannel
	if !ok {
		return nil, u.ErrTimeout
	}
	return &block, nil
}

func (bs *bitswap) sendToPeersThatWant(block blocks.Block) {
	for _, p := range bs.strategist.Peers() {
		if bs.strategist.IsWantedByPeer(block.Key(), p) {
			if bs.strategist.ShouldSendToPeer(block.Key(), p) {
				go bs.send(p, block)
			}
		}
	}
}

// HasBlock announces the existance of a block to bitswap, potentially sending
// it to peers (Partners) whose WantLists include it.
func (bs *bitswap) HasBlock(blk blocks.Block) error {
	go bs.sendToPeersThatWant(blk)
	return bs.routing.Provide(blk.Key())
}

// TODO(brian): get a return value
func (bs *bitswap) send(p *peer.Peer, b blocks.Block) {
	message := bsmsg.New()
	message.AppendBlock(b)
	// FIXME(brian): pass ctx
	bs.sender.SendMessage(context.Background(), p, message)
	bs.strategist.MessageSent(p, message)
}

func (bs *bitswap) Halt() {
	bs.haltChan <- struct{}{}
}

// TODO(brian): handle errors
func (bs *bitswap) ReceiveMessage(
	ctx context.Context, sender *peer.Peer, incoming bsmsg.BitSwapMessage) (
	*peer.Peer, bsmsg.BitSwapMessage, error) {

	bs.strategist.MessageReceived(sender, incoming)

	if incoming.Blocks() != nil {
		for _, block := range incoming.Blocks() {
			go bs.blockstore.Put(block) // FIXME(brian): err ignored
			go bs.notifications.Publish(block)
		}
	}

	if incoming.Wantlist() != nil {
		for _, key := range incoming.Wantlist() {
			if bs.strategist.ShouldSendToPeer(key, sender) {
				block, errBlockNotFound := bs.blockstore.Get(key)
				if errBlockNotFound != nil {
					// TODO(brian): log/return the error
					continue
				}
				go bs.send(sender, *block)
			}
		}
	}
	return nil, nil, errors.New("TODO implement")
}

func numBytes(b blocks.Block) int {
	return len(b.Data)
}
<|endoftext|>


<commit_before>// Http image server
package http

import (
	"fmt"
	"github.com/pierrre/imageserver"
	"log"
	"net/http"
	"regexp"
	"strconv"
	"time"
)

var inmHeaderRegexp, _ = regexp.Compile("^\"(.+)\"$")

var expiresHeaderLocation, _ = time.LoadLocation("GMT")

var msgInternalError = "Internal error"

// Http image server
//
// Only GET method is supported.
//
// Supports ETag/If-None-Match (status code 304).
// It doesn't check if the image really exists.
//
// Status codes: 200 (everything is ok), 400 (user error), 500 (internal error).
//
// If Expire is defined, the "Expires" header is set.
//
// The HeaderFunc function allows to set custom headers.
type Server struct {
	Parser      Parser
	ImageServer *imageserver.Server

	Expire time.Duration // optional

	Logger *log.Logger // optional

	HeaderFunc func(http.Header, *http.Request, imageserver.Parameters) // optional
}

func (server *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
	if request.Method != "GET" {
		server.sendError(writer, fmt.Errorf("Invalid request method"))
		return
	}

	parameters := make(imageserver.Parameters)
	if err := server.Parser.Parse(request, parameters); err != nil {
		server.sendError(writer, err)
		return
	}

	if server.checkNotModified(writer, request, parameters) {
		return
	}

	image, err := server.ImageServer.Get(parameters)
	if err != nil {
		server.sendError(writer, err)
		return
	}

	if err := server.sendImage(writer, request, parameters, image); err != nil {
		server.logError(err)
		return
	}
}

func (server *Server) checkNotModified(writer http.ResponseWriter, request *http.Request, parameters imageserver.Parameters) bool {
	inmHeader := request.Header.Get("If-None-Match")
	if len(inmHeader) > 0 {
		matches := inmHeaderRegexp.FindStringSubmatch(inmHeader)
		if matches != nil && len(matches) == 2 {
			inm := matches[1]
			if inm == parameters.Hash() {
				server.sendHeader(writer, request, parameters)
				writer.WriteHeader(http.StatusNotModified)
				return true
			}
		}
	}
	return false
}

func (server *Server) sendImage(writer http.ResponseWriter, request *http.Request, parameters imageserver.Parameters, image *imageserver.Image) error {
	server.sendHeader(writer, request, parameters)

	if len(image.Type) > 0 {
		writer.Header().Set("Content-Type", "image/"+image.Type)
	}

	writer.Header().Set("Content-Length", strconv.Itoa(len(image.Data)))

	if _, err := writer.Write(image.Data); err != nil {
		return err
	}

	return nil
}

func (server *Server) sendHeader(writer http.ResponseWriter, request *http.Request, parameters imageserver.Parameters) {
	header := writer.Header()
	if server.HeaderFunc != nil {
		server.HeaderFunc(header, request, parameters)
	}
	server.sendHeaderCache(header, parameters)
}

func (server *Server) sendHeaderCache(header http.Header, parameters imageserver.Parameters) {
	header.Set("Cache-Control", "public")

	header.Set("ETag", fmt.Sprintf("\"%s\"", parameters.Hash()))

	if server.Expire != 0 {
		t := time.Now()
		t = t.Add(server.Expire)
		t = t.In(expiresHeaderLocation)
		header.Set("Expires", t.Format(time.RFC1123))
	}
}

func (server *Server) sendError(writer http.ResponseWriter, err error) {
	if _, ok := err.(*imageserver.Error); ok {
		http.Error(writer, err.Error(), http.StatusBadRequest)
	} else {
		http.Error(writer, msgInternalError, http.StatusInternalServerError)

		server.logError(err)
	}
}

func (server *Server) logError(err error) {
	if server.Logger != nil {
		server.Logger.Println(err)
	}
}
<commit_msg>Log "previous error" in http server<commit_after>// Http image server
package http

import (
	"fmt"
	"github.com/pierrre/imageserver"
	"log"
	"net/http"
	"regexp"
	"strconv"
	"time"
)

var inmHeaderRegexp, _ = regexp.Compile("^\"(.+)\"$")

var expiresHeaderLocation, _ = time.LoadLocation("GMT")

var msgInternalError = "Internal error"

// Http image server
//
// Only GET method is supported.
//
// Supports ETag/If-None-Match (status code 304).
// It doesn't check if the image really exists.
//
// Status codes: 200 (everything is ok), 400 (user error), 500 (internal error).
//
// If Expire is defined, the "Expires" header is set.
//
// The HeaderFunc function allows to set custom headers.
type Server struct {
	Parser      Parser
	ImageServer *imageserver.Server

	Expire time.Duration // optional

	Logger *log.Logger // optional

	HeaderFunc func(http.Header, *http.Request, imageserver.Parameters) // optional
}

func (server *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
	if request.Method != "GET" {
		server.sendError(writer, fmt.Errorf("Invalid request method"))
		return
	}

	parameters := make(imageserver.Parameters)
	if err := server.Parser.Parse(request, parameters); err != nil {
		server.sendError(writer, err)
		return
	}

	if server.checkNotModified(writer, request, parameters) {
		return
	}

	image, err := server.ImageServer.Get(parameters)
	if err != nil {
		server.sendError(writer, err)
		return
	}

	if err := server.sendImage(writer, request, parameters, image); err != nil {
		server.logError(err)
		return
	}
}

func (server *Server) checkNotModified(writer http.ResponseWriter, request *http.Request, parameters imageserver.Parameters) bool {
	inmHeader := request.Header.Get("If-None-Match")
	if len(inmHeader) > 0 {
		matches := inmHeaderRegexp.FindStringSubmatch(inmHeader)
		if matches != nil && len(matches) == 2 {
			inm := matches[1]
			if inm == parameters.Hash() {
				server.sendHeader(writer, request, parameters)
				writer.WriteHeader(http.StatusNotModified)
				return true
			}
		}
	}
	return false
}

func (server *Server) sendImage(writer http.ResponseWriter, request *http.Request, parameters imageserver.Parameters, image *imageserver.Image) error {
	server.sendHeader(writer, request, parameters)

	if len(image.Type) > 0 {
		writer.Header().Set("Content-Type", "image/"+image.Type)
	}

	writer.Header().Set("Content-Length", strconv.Itoa(len(image.Data)))

	if _, err := writer.Write(image.Data); err != nil {
		return err
	}

	return nil
}

func (server *Server) sendHeader(writer http.ResponseWriter, request *http.Request, parameters imageserver.Parameters) {
	header := writer.Header()
	if server.HeaderFunc != nil {
		server.HeaderFunc(header, request, parameters)
	}
	server.sendHeaderCache(header, parameters)
}

func (server *Server) sendHeaderCache(header http.Header, parameters imageserver.Parameters) {
	header.Set("Cache-Control", "public")

	header.Set("ETag", fmt.Sprintf("\"%s\"", parameters.Hash()))

	if server.Expire != 0 {
		t := time.Now()
		t = t.Add(server.Expire)
		t = t.In(expiresHeaderLocation)
		header.Set("Expires", t.Format(time.RFC1123))
	}
}

func (server *Server) sendError(writer http.ResponseWriter, err error) {
	var internalErr error
	if err, ok := err.(*imageserver.Error); ok {
		http.Error(writer, err.Error(), http.StatusBadRequest)
		internalErr = err.Previous
	} else {
		http.Error(writer, msgInternalError, http.StatusInternalServerError)
		internalErr = err
	}
	if internalErr != nil {
		server.logError(internalErr)
	}
}

func (server *Server) logError(err error) {
	if server.Logger != nil {
		server.Logger.Println(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/gin-gonic/gin"
)

func pmdaServer() (result string) {
	result = os.Getenv("PMDA")
	if result == "" {
		result = "www.pmda.go.jp"
	}
	return
}

func pmdaPath(yjcode string) (path string, err error) {
	f := fmt.Sprintf("/asset/bin/yj/%s", yjcode)
	if _, err = os.Stat(f); err != nil {
		return
	}
	r, err := os.OpenFile(f, os.O_RDONLY, 0666)
	if err != nil {
		return
	}
	buf := bytes.NewBuffer([]byte{})
	_, err = io.Copy(buf, r)
	if err != nil {
		return
	}
	line := buf.String()
	path = strings.Trim(line, "\r\n ")
	return
}

func redirectToPMDA(c *gin.Context) {
	yjcode := c.Param("yjcode")
	path, err := pmdaPath(yjcode)
	if err != nil {
		message := fmt.Sprintf("NOT FOUND: %s \n error:%s", yjcode, err)
		fmt.Println(message)
		c.String(http.StatusNotFound, message)
		return
	}
	var pmda = pmdaServer()
	var url = fmt.Sprintf("//%s/PmdaSearch/iyakuDetail/%s", pmda, path)

	c.Redirect(http.StatusTemporaryRedirect, url)
}

func guessPmdaPath(yjcode string) (path_list []string, err error) {
	pattern := fmt.Sprintf("/asset/bin/html/??????_%s*_?_??.html", yjcode)
	path_list, err = filepath.Glob(pattern)
	return
}

//TODO 実装中
func guessRedirectToPMDA(c *gin.Context) {
	yjcode := c.Param("yjcode")
	path_list, err := guessPmdaPath(yjcode)
	if err != nil {
		message := fmt.Sprintf(
			"pattern search error: yj:%s \nerror:%s\n", yjcode, err)
		fmt.Println(message)
		c.String(http.StatusNotFound, message)
		return
	}

	var url = ""
	c.Redirect(http.StatusTemporaryRedirect, url)
}

func main() {
	r := gin.Default()
	r.GET("/", func(c *gin.Context) {
		c.String(200, "Converter(YJcode to PMDA path) works.")
	})

	//redirect to PMDA
	r.GET("/redirect/:yjcode/", redirectToPMDA)
	r.GET("/redirect_guess/:yjcode/", guessRedirectToPMDA)

	fmt.Println("listen: 80")
	r.Run(":80")
}
<commit_msg>go build error fix<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/gin-gonic/gin"
)

func pmdaServer() (result string) {
	result = os.Getenv("PMDA")
	if result == "" {
		result = "www.pmda.go.jp"
	}
	return
}

func pmdaPath(yjcode string) (path string, err error) {
	f := fmt.Sprintf("/asset/bin/yj/%s", yjcode)
	if _, err = os.Stat(f); err != nil {
		return
	}
	r, err := os.OpenFile(f, os.O_RDONLY, 0666)
	if err != nil {
		return
	}
	buf := bytes.NewBuffer([]byte{})
	_, err = io.Copy(buf, r)
	if err != nil {
		return
	}
	line := buf.String()
	path = strings.Trim(line, "\r\n ")
	return
}

func redirectToPMDA(c *gin.Context) {
	yjcode := c.Param("yjcode")
	path, err := pmdaPath(yjcode)
	if err != nil {
		message := fmt.Sprintf("NOT FOUND: %s \n error:%s", yjcode, err)
		fmt.Println(message)
		c.String(http.StatusNotFound, message)
		return
	}
	var pmda = pmdaServer()
	var url = fmt.Sprintf("//%s/PmdaSearch/iyakuDetail/%s", pmda, path)

	c.Redirect(http.StatusTemporaryRedirect, url)
}

func guessPmdaPath(yjcode string) (path_list []string, err error) {
	pattern := fmt.Sprintf("/asset/bin/html/??????_%s*_?_??.html", yjcode)
	path_list, err = filepath.Glob(pattern)
	return
}

//TODO 実装中
func guessRedirectToPMDA(c *gin.Context) {
	yjcode := c.Param("yjcode")
	path_list, err := guessPmdaPath(yjcode)
	fmt.Printf("path_list:%s\n", path_list)
	if err != nil {
		message := fmt.Sprintf(
			"pattern search error: yj:%s \nerror:%s\n", yjcode, err)
		fmt.Println(message)
		c.String(http.StatusNotFound, message)
		return
	}

	var url = ""
	c.Redirect(http.StatusTemporaryRedirect, url)
}

func main() {
	r := gin.Default()
	r.GET("/", func(c *gin.Context) {
		c.String(200, "Converter(YJcode to PMDA path) works.")
	})

	//redirect to PMDA
	r.GET("/redirect/:yjcode/", redirectToPMDA)
	r.GET("/redirect_guess/:yjcode/", guessRedirectToPMDA)

	fmt.Println("listen: 80")
	r.Run(":80")
}
<|endoftext|>


<commit_before>/*
Package dronenotify is an executeable that reads the environment variables
and sends an HTTP POST with a JSON payload to a cinotify server.

This variable is required for the bot to connect to an endpoint and must be set.
DRONE_NOTIFY_ADDRESS - eg localhost:3333

The variables it reads and json-ify's are as follows:
DRONE_REPO_SLUG
DRONE_BUILD_URL
DRONE_BUILD_DIR
DRONE_BUILD_NUMBER
DRONE_COMMIT
DRONE_BRANCH
*/
package main

import (
	"bytes"
	"encoding/json"
	"github.com/aarondl/cinotify"
	"log"
	"net/http"
	"os"
)

func main() {
	dr := cinotify.DroneRequest{
		RepoSlug:    os.Getenv("DRONE_REPO_SLUG"),
		BuildUrl:    os.Getenv("DRONE_BUILD_URL"),
		BuildDir:    os.Getenv("DRONE_BUILD_DIR"),
		BuildNumber: os.Getenv("DRONE_BUILD_NUMBER"),
		Commit:      os.Getenv("DRONE_COMMIT"),
		Branch:      os.Getenv("DRONE_BRANCH"),
	}

	buffer := &bytes.Buffer{}
	encoder := json.NewEncoder(buffer)
	err := encoder.Encode(dr)

	if err != nil {
		log.Fatalf("dronenotify: Failed to encode json %v", err)
	}

	addr := "http://" + os.Getenv("DRONE_NOTIFY_ADDRESS") + "/"
	req, err := http.NewRequest("POST", addr, buffer)
	req.Header.Add("Content-Type", "application/json")
	if err != nil {
		log.Fatalf("dronenotify: Failed to create request %v", err)
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatalf("dronenotify: Failed to send request %v", err)
	}

	log.Printf("dronenotify: Server responded with HTTP %v", resp.Status)
}
<commit_msg>Add silently fail feature.<commit_after>/*
Package dronenotify is an executeable that reads the environment variables
and sends an HTTP POST with a JSON payload to a cinotify server.

This variable is required for the bot to connect to an endpoint and must be set.
DRONE_NOTIFY_ADDRESS - eg localhost:3333

The variables it reads and json-ify's are as follows:
DRONE_REPO_SLUG
DRONE_BUILD_URL
DRONE_BUILD_DIR
DRONE_BUILD_NUMBER
DRONE_COMMIT
DRONE_BRANCH
*/
package main

import (
	"bytes"
	"encoding/json"
	"github.com/aarondl/cinotify"
	"log"
	"net/http"
	"os"
)

func main() {
	addr := os.Getenv("DRONE_NOTIFY_ADDRESS")

	if len(addr) == 0 {
		log.Printf("DRONE_NOTIFY_ADDRESS not set, silently failing.")
		return
	}

	dr := cinotify.DroneRequest{
		RepoSlug:    os.Getenv("DRONE_REPO_SLUG"),
		BuildUrl:    os.Getenv("DRONE_BUILD_URL"),
		BuildDir:    os.Getenv("DRONE_BUILD_DIR"),
		BuildNumber: os.Getenv("DRONE_BUILD_NUMBER"),
		Commit:      os.Getenv("DRONE_COMMIT"),
		Branch:      os.Getenv("DRONE_BRANCH"),
	}

	buffer := &bytes.Buffer{}
	encoder := json.NewEncoder(buffer)
	err := encoder.Encode(dr)

	if err != nil {
		log.Fatalf("dronenotify: Failed to encode json %v", err)
	}

	addr := "http://" + addr + "/"
	req, err := http.NewRequest("POST", addr, buffer)
	req.Header.Add("Content-Type", "application/json")
	if err != nil {
		log.Fatalf("dronenotify: Failed to create request %v", err)
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatalf("dronenotify: Failed to send request %v", err)
	}

	log.Printf("dronenotify: Server responded with HTTP %v", resp.Status)
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package dsputils

import (
	"math"
)

const (
	closeFactor = 1e-8
)

// PrettyClose returns true if the slices a and b are very close, else false.
func PrettyClose(a, b []float64) bool {
	if len(a) != len(b) {
		return false
	}

	for i, c := range a {
		if !Float64Equal(c, b[i]) {
			return false
		}
	}
	return true
}

// PrettyCloseC returns true if the slices a and b are very close, else false.
func PrettyCloseC(a, b []complex128) bool {
	if len(a) != len(b) {
		return false
	}

	for i, c := range a {
		if !ComplexEqual(c, b[i]) {
			return false
		}
	}
	return true
}

// PrettyClose returns true if the matrixes a and b are very close, else false.
func PrettyClose2(a, b [][]complex128) bool {
	if len(a) != len(b) {
		return false
	}

	for i, c := range a {
		if !PrettyCloseC(c, b[i]) {
			return false
		}
	}
	return true
}

// ComplexEqual returns true if a and b are very close, else false.
func ComplexEqual(a, b complex128) bool {
	r_a := real(a)
	r_b := real(b)
	i_a := imag(a)
	i_b := imag(b)

	return Float64Equal(r_a, r_b) && Float64Equal(i_a, i_b)
}

// Float64Equal returns true if a and b are very close, else false.
func Float64Equal(a, b float64) bool {
	return math.Abs(a-b) <= closeFactor || math.Abs(1-a/b) <= closeFactor
}
<commit_msg>Fix documented function name<commit_after>/*
 * Copyright (c) 2011 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package dsputils

import (
	"math"
)

const (
	closeFactor = 1e-8
)

// PrettyClose returns true if the slices a and b are very close, else false.
func PrettyClose(a, b []float64) bool {
	if len(a) != len(b) {
		return false
	}

	for i, c := range a {
		if !Float64Equal(c, b[i]) {
			return false
		}
	}
	return true
}

// PrettyCloseC returns true if the slices a and b are very close, else false.
func PrettyCloseC(a, b []complex128) bool {
	if len(a) != len(b) {
		return false
	}

	for i, c := range a {
		if !ComplexEqual(c, b[i]) {
			return false
		}
	}
	return true
}

// PrettyClose2 returns true if the matrixes a and b are very close, else false.
func PrettyClose2(a, b [][]complex128) bool {
	if len(a) != len(b) {
		return false
	}

	for i, c := range a {
		if !PrettyCloseC(c, b[i]) {
			return false
		}
	}
	return true
}

// ComplexEqual returns true if a and b are very close, else false.
func ComplexEqual(a, b complex128) bool {
	r_a := real(a)
	r_b := real(b)
	i_a := imag(a)
	i_b := imag(b)

	return Float64Equal(r_a, r_b) && Float64Equal(i_a, i_b)
}

// Float64Equal returns true if a and b are very close, else false.
func Float64Equal(a, b float64) bool {
	return math.Abs(a-b) <= closeFactor || math.Abs(1-a/b) <= closeFactor
}
<|endoftext|>


<commit_before>package blob

import (
	"crypto/sha1"
	"database/sql"
	"encoding/hex"
	"fmt"
	_ "github.com/herenow/go-crate"
	"io"
	"net/http"
	"time"
)

type Driver struct {
	url string
	db  *sql.DB
}

type Table struct {
	Name string
	drv  *Driver
	c    *http.Client
}

// New creates a new connection with crate server
func New(crate_url string) (*Driver, error) {
	db, err := sql.Open("crate", crate_url)
	if err != nil {
		return nil, err
	}
	return &Driver{
		url: crate_url,
		db:  db,
	}, nil
}

// NewTable create new blob table with name and extra int to specify
// shards(the second argument) and
// replicas(by the third int argument)
func (d *Driver) NewTable(name string, shards ...int) (*Table, error) {
	sql := fmt.Sprintf(
		"create blob table %s",
		name,
	)
	if len(shards) == 1 {
		sql = fmt.Sprintf(
			"create blob table %s clustered into %d shards",
			name, shards[0],
		)
	}
	if len(shards) >= 2 {
		sql = fmt.Sprintf(
			"create blob table %s clustered into %d shards with (number_of_replicas=%d)",
			name, shards[0], shards[1],
		)
	}
	_, err := d.db.Exec(sql)
	if err != nil {
		return nil, err
	}
	return &Table{
		Name: name,
		drv:  d,
		c:    new(http.Client),
	}, nil
}

// Get an existing table from the crate server
// or error when this table does not exist
func (d *Driver) GetTable(name string) (*Table, error) {
	row := d.db.QueryRow(
		"select table_name from information_schema.tables where table_name = ? and schema_name = 'blob'",
		name,
	)
	if err := row.Scan(&name); err != nil {
		return nil, err
	}
	return &Table{
		Name: name,
		drv:  d,
		c:    new(http.Client),
	}, nil
}

type Record struct {
	Digest       string
	LastModified time.Time
}

// Sha1Digest calculates the sha1 digest for the io.Reader
func Sha1Digest(r io.Reader) string {
	h := sha1.New()
	io.Copy(h, r)
	return hex.EncodeToString(h.Sum(nil))
}

func (t *Table) url(digest string) string {
	return fmt.Sprintf("%s/_blobs/%s/%s", t.drv.url, t.Name, digest)
}

// Upload upload the blob(r) with sha1 hash(digest)
func (t *Table) Upload(digest string, r io.Reader) (*Record, error) {
	req, err := http.NewRequest("PUT", t.url(digest), r)
	if err != nil {
		return nil, err
	}
	_, err = t.c.Do(req)
	if err != nil {
		return nil, err
	}
	return &Record{
		Digest: digest,
	}, nil
}

// UploadEx upload a io.ReadSeeker, and computes the sha1 hash automatically
func (t *Table) UploadEx(r io.ReadSeeker) (*Record, error) {
	digest := Sha1Digest(r)
	_, err := r.Seek(0, 0)
	if err != nil {
		return nil, err
	}
	req, err := http.NewRequest("PUT", t.url(digest), r)
	if err != nil {
		return nil, err
	}
	_, err = t.c.Do(req)
	if err != nil {
		return nil, err
	}
	return &Record{
		Digest: digest,
	}, nil
}

// List all blobs inside a blob table
func (t *Table) List() (*sql.Rows, error) {
	query := fmt.Sprintf("select digest, last_modified from blob.%s", t.Name)
	rows, err := t.drv.db.Query(query)
	if err != nil {
		return nil, err
	}
	return rows, err
}

// Is the blob specified by the digest exist in the table
func (t *Table) Has(digest string) (bool, error) {
	req, err := http.NewRequest("HEAD", t.url(digest), nil)
	if err != nil {
		return false, err
	}
	resp, err := t.c.Do(req)
	if err != nil {
		return false, err
	}
	if resp.StatusCode == http.StatusOK {
		return true, nil
	}
	return false, nil
}

// Download a blob in a blob table with the specific digest
func (t *Table) Download(digest string) (io.ReadCloser, error) {
	req, err := http.NewRequest("GET", t.url(digest), nil)
	if err != nil {
		return nil, err
	}
	resp, err := t.c.Do(req)
	if err != nil {
		return nil, err
	}
	return resp.Body, nil
}

// Delete a blob in a blob table with the specific digest
func (t *Table) Delete(digest string) error {
	req, err := http.NewRequest("DELETE", t.url(digest), nil)
	if err != nil {
		return err
	}
	resp, err := t.c.Do(req)
	if err != nil {
		return err
	}
	if resp.StatusCode == http.StatusNoContent {
		return nil
	}
	return fmt.Errorf("%s", resp.Status)
}

// Drop the blob table
func (t *Table) Drop() error {
	sql := fmt.Sprintf("drop blob table %s", t.Name)
	_, err := t.drv.db.Exec(sql)
	return err
}
<commit_msg>Return an error if upload was not successful.<commit_after>package blob

import (
	"crypto/sha1"
	"database/sql"
	"encoding/hex"
	"fmt"
	_ "github.com/herenow/go-crate"
	"io"
	"net/http"
	"time"
)

type Driver struct {
	url string
	db  *sql.DB
}

type Table struct {
	Name string
	drv  *Driver
	c    *http.Client
}

// New creates a new connection with crate server
func New(crate_url string) (*Driver, error) {
	db, err := sql.Open("crate", crate_url)
	if err != nil {
		return nil, err
	}
	return &Driver{
		url: crate_url,
		db:  db,
	}, nil
}

// NewTable create new blob table with name and extra int to specify
// shards(the second argument) and
// replicas(by the third int argument)
func (d *Driver) NewTable(name string, shards ...int) (*Table, error) {
	sql := fmt.Sprintf(
		"create blob table %s",
		name,
	)
	if len(shards) == 1 {
		sql = fmt.Sprintf(
			"create blob table %s clustered into %d shards",
			name, shards[0],
		)
	}
	if len(shards) >= 2 {
		sql = fmt.Sprintf(
			"create blob table %s clustered into %d shards with (number_of_replicas=%d)",
			name, shards[0], shards[1],
		)
	}
	_, err := d.db.Exec(sql)
	if err != nil {
		return nil, err
	}
	return &Table{
		Name: name,
		drv:  d,
		c:    new(http.Client),
	}, nil
}

// Get an existing table from the crate server
// or error when this table does not exist
func (d *Driver) GetTable(name string) (*Table, error) {
	row := d.db.QueryRow(
		"select table_name from information_schema.tables where table_name = ? and schema_name = 'blob'",
		name,
	)
	if err := row.Scan(&name); err != nil {
		return nil, err
	}
	return &Table{
		Name: name,
		drv:  d,
		c:    new(http.Client),
	}, nil
}

type Record struct {
	Digest       string
	LastModified time.Time
}

// Sha1Digest calculates the sha1 digest for the io.Reader
func Sha1Digest(r io.Reader) string {
	h := sha1.New()
	io.Copy(h, r)
	return hex.EncodeToString(h.Sum(nil))
}

func (t *Table) url(digest string) string {
	return fmt.Sprintf("%s/_blobs/%s/%s", t.drv.url, t.Name, digest)
}

// Upload upload the blob(r) with sha1 hash(digest)
func (t *Table) Upload(digest string, r io.Reader) (*Record, error) {
	req, err := http.NewRequest("PUT", t.url(digest), r)
	if err != nil {
		return nil, err
	}
	resp, err := t.c.Do(req)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 201 {
		return nil, fmt.Errorf("Upload failed: %s", resp.Status)
	}
	return &Record{
		Digest: digest,
	}, nil
}

// UploadEx upload a io.ReadSeeker, and computes the sha1 hash automatically
func (t *Table) UploadEx(r io.ReadSeeker) (*Record, error) {
	digest := Sha1Digest(r)
	_, err := r.Seek(0, 0)
	if err != nil {
		return nil, err
	}
	req, err := http.NewRequest("PUT", t.url(digest), r)
	if err != nil {
		return nil, err
	}
	_, err = t.c.Do(req)
	if err != nil {
		return nil, err
	}
	return &Record{
		Digest: digest,
	}, nil
}

// List all blobs inside a blob table
func (t *Table) List() (*sql.Rows, error) {
	query := fmt.Sprintf("select digest, last_modified from blob.%s", t.Name)
	rows, err := t.drv.db.Query(query)
	if err != nil {
		return nil, err
	}
	return rows, err
}

// Is the blob specified by the digest exist in the table
func (t *Table) Has(digest string) (bool, error) {
	req, err := http.NewRequest("HEAD", t.url(digest), nil)
	if err != nil {
		return false, err
	}
	resp, err := t.c.Do(req)
	if err != nil {
		return false, err
	}
	if resp.StatusCode == http.StatusOK {
		return true, nil
	}
	return false, nil
}

// Download a blob in a blob table with the specific digest
func (t *Table) Download(digest string) (io.ReadCloser, error) {
	req, err := http.NewRequest("GET", t.url(digest), nil)
	if err != nil {
		return nil, err
	}
	resp, err := t.c.Do(req)
	if err != nil {
		return nil, err
	}
	return resp.Body, nil
}

// Delete a blob in a blob table with the specific digest
func (t *Table) Delete(digest string) error {
	req, err := http.NewRequest("DELETE", t.url(digest), nil)
	if err != nil {
		return err
	}
	resp, err := t.c.Do(req)
	if err != nil {
		return err
	}
	if resp.StatusCode == http.StatusNoContent {
		return nil
	}
	return fmt.Errorf("%s", resp.Status)
}

// Drop the blob table
func (t *Table) Drop() error {
	sql := fmt.Sprintf("drop blob table %s", t.Name)
	_, err := t.drv.db.Exec(sql)
	return err
}
<|endoftext|>


<commit_before>package iamy

import (
	"encoding/json"
	"log"
	"net/url"
	"reflect"
	"sort"
)

func NewPolicyDocumentFromJson(jsonString string) (*PolicyDocument, error) {
	var doc PolicyDocument
	if err := json.Unmarshal([]byte(jsonString), &doc); err != nil {
		log.Printf("Error unmarshalling JSON %s %s", err, jsonString)
		return nil, err
	}
	//log.Printf("Doc %s\nJSON: %s", doc, jsonString)

	return &doc, nil
}

func NewPolicyDocumentFromEncodedJson(encoded string) (*PolicyDocument, error) {
	jsonString, err := url.QueryUnescape(encoded)
	if err != nil {
		return nil, err
	}
	var doc PolicyDocument
	if err := json.Unmarshal([]byte(jsonString), &doc); err != nil {
		log.Printf("Error unmarshalling JSON %s %s", err, jsonString)
		return nil, err
	}
	//log.Printf("Doc %s\nJSON: %s", doc, jsonString)

	return &doc, nil
}

// PolicyDocument represents an AWS policy document.
// It normalises the data when Marshaling and Unmarshaling JSON
// the same way AWS does to avoid conflicts when diffing
type PolicyDocument struct {
	data interface{}
}

func (p *PolicyDocument) JsonString() string {
	jsonBytes, err := json.MarshalIndent(p, "", "  ")
	if err != nil {
		log.Fatal(err)
	}

	return string(jsonBytes)
}

func (p PolicyDocument) MarshalJSON() ([]byte, error) {
	return json.Marshal(recursivelyNormaliseAwsPolicy(p.data))
}

func (p *PolicyDocument) UnmarshalJSON(jsonData []byte) error {
	err := json.Unmarshal(jsonData, &p.data)
	p.data = recursivelyNormaliseAwsPolicy(p.data)
	return err
}

// RecursivelyNormaliseAwsPolicy recursively searches i for slices
// and normalises
//  1. slices of length 1 become single strings
//  2. slices of length > 1 are sorted
func recursivelyNormaliseAwsPolicy(i interface{}) interface{} {

	switch reflect.TypeOf(i).Kind() {

	case reflect.Map:
		origMap := reflect.ValueOf(i)
		newMap := reflect.MakeMap(origMap.Type())
		for _, key := range origMap.MapKeys() {
			originalValue := origMap.MapIndex(key).Interface()
			newValue := recursivelyNormaliseAwsPolicy(originalValue)
			newMap.SetMapIndex(key, reflect.ValueOf(newValue))
		}
		return newMap.Interface()

	case reflect.Slice:
		if ss, ok := i.([]string); ok {
			if len(ss) == 1 {
				return ss[0]
			}
			sort.Strings(ss)
			return ss
		}

		if ii, ok := i.([]interface{}); ok {
			if len(ii) > 0 {
				// if it's actually a string slice
				if _, ok := ii[0].(string); ok {
					if len(ii) == 1 {
						return ii[0]
					}
					ss := interfaceSliceToStringSlice(ii)
					sort.Strings(ss)
					return stringSliceToInterfaceSlice(ss)
				} else {
					origSlice := reflect.ValueOf(ii)
					newSlice := reflect.MakeSlice(origSlice.Type(), 0, origSlice.Cap())
					for _, originalValue := range ii {
						newValue := recursivelyNormaliseAwsPolicy(originalValue)
						newSlice = reflect.Append(newSlice, reflect.ValueOf(newValue))
					}
					return newSlice.Interface()
				}
			}
		}
	}

	return i
}

func interfaceSliceToStringSlice(a []interface{}) []string {
	b := make([]string, len(a))
	for i := range a {
		b[i] = a[i].(string)
	}
	return b
}

func stringSliceToInterfaceSlice(a []string) []interface{} {
	b := make([]interface{}, len(a))
	for i := range a {
		b[i] = a[i]
	}
	return b
}
<commit_msg>DRY up function<commit_after>package iamy

import (
	"encoding/json"
	"log"
	"net/url"
	"reflect"
	"sort"
)

func NewPolicyDocumentFromJson(jsonString string) (*PolicyDocument, error) {
	var doc PolicyDocument
	if err := json.Unmarshal([]byte(jsonString), &doc); err != nil {
		log.Printf("Error unmarshalling JSON %s %s", err, jsonString)
		return nil, err
	}

	return &doc, nil
}

func NewPolicyDocumentFromEncodedJson(encoded string) (*PolicyDocument, error) {
	jsonString, err := url.QueryUnescape(encoded)
	if err != nil {
		return nil, err
	}

	return NewPolicyDocumentFromJson(jsonString)
}

// PolicyDocument represents an AWS policy document.
// It normalises the data when Marshaling and Unmarshaling JSON
// the same way AWS does to avoid conflicts when diffing
type PolicyDocument struct {
	data interface{}
}

func (p *PolicyDocument) JsonString() string {
	jsonBytes, err := json.MarshalIndent(p, "", "  ")
	if err != nil {
		log.Fatal(err)
	}

	return string(jsonBytes)
}

func (p PolicyDocument) MarshalJSON() ([]byte, error) {
	return json.Marshal(recursivelyNormaliseAwsPolicy(p.data))
}

func (p *PolicyDocument) UnmarshalJSON(jsonData []byte) error {
	err := json.Unmarshal(jsonData, &p.data)
	p.data = recursivelyNormaliseAwsPolicy(p.data)
	return err
}

// RecursivelyNormaliseAwsPolicy recursively searches i for slices
// and normalises
//  1. slices of length 1 become single strings
//  2. slices of length > 1 are sorted
func recursivelyNormaliseAwsPolicy(i interface{}) interface{} {

	switch reflect.TypeOf(i).Kind() {

	case reflect.Map:
		origMap := reflect.ValueOf(i)
		newMap := reflect.MakeMap(origMap.Type())
		for _, key := range origMap.MapKeys() {
			originalValue := origMap.MapIndex(key).Interface()
			newValue := recursivelyNormaliseAwsPolicy(originalValue)
			newMap.SetMapIndex(key, reflect.ValueOf(newValue))
		}
		return newMap.Interface()

	case reflect.Slice:
		if ss, ok := i.([]string); ok {
			if len(ss) == 1 {
				return ss[0]
			}
			sort.Strings(ss)
			return ss
		}

		if ii, ok := i.([]interface{}); ok {
			if len(ii) > 0 {
				// if it's actually a string slice
				if _, ok := ii[0].(string); ok {
					if len(ii) == 1 {
						return ii[0]
					}
					ss := interfaceSliceToStringSlice(ii)
					sort.Strings(ss)
					return stringSliceToInterfaceSlice(ss)
				} else {
					origSlice := reflect.ValueOf(ii)
					newSlice := reflect.MakeSlice(origSlice.Type(), 0, origSlice.Cap())
					for _, originalValue := range ii {
						newValue := recursivelyNormaliseAwsPolicy(originalValue)
						newSlice = reflect.Append(newSlice, reflect.ValueOf(newValue))
					}
					return newSlice.Interface()
				}
			}
		}
	}

	return i
}

func interfaceSliceToStringSlice(a []interface{}) []string {
	b := make([]string, len(a))
	for i := range a {
		b[i] = a[i].(string)
	}
	return b
}

func stringSliceToInterfaceSlice(a []string) []interface{} {
	b := make([]interface{}, len(a))
	for i := range a {
		b[i] = a[i]
	}
	return b
}
<|endoftext|>


<commit_before>package rocserv

import (
	"context"
	"fmt"
	"time"

	"gitlab.pri.ibanyu.com/middleware/seaweed/xlog"

	etcd "github.com/coreos/etcd/client"
)

// RegisterCrossDCService, the path and value is the same as RegisterService, but different register center
func (m *ServBaseV2) RegisterCrossDCService(servs map[string]*ServInfo) error {
	fun := "ServBaseV2.RegisterService -->"
	ctx := context.Background()
	err := m.RegisterServiceV2(servs, BASE_LOC_REG_SERV, true)
	if err != nil {
		xlog.Errorf(ctx, "%s register server v2 failed, err: %v", fun, err)
		return err
	}

	err = m.RegisterServiceV1(servs, true)
	if err != nil {
		xlog.Errorf(ctx, "%s register server v1 failed, err: %v", fun, err)
		return err
	}

	xlog.Infof(ctx, "%s register cross dc server ok", fun)

	return nil
}

func (m *ServBaseV2) doCrossDCRegister(path, js string, refresh bool) error {
	fun := "ServBaseV2.doCrossDCRegister -->"
	ctx := context.Background()
	for addr, _ := range m.crossRegisterClients {
		// 创建完成标志
		var isCreated bool

		go func() {

			for j := 0; ; j++ {
				updateEtcd := func() {
					var err error
					var r *etcd.Response
					if !isCreated {
						xlog.Warnf(ctx, "%s create idx:%d server_info: %s", fun, j, js)
						r, err = m.crossRegisterClients[addr].Set(context.Background(), path, js, &etcd.SetOptions{
							TTL: time.Second * 60,
						})
					} else {
						if refresh {
							// 在刷新ttl时候，不允许变更value
							r, err = m.crossRegisterClients[addr].Set(context.Background(), path, "", &etcd.SetOptions{
								PrevExist: etcd.PrevExist,
								TTL:       time.Second * 60,
								Refresh:   true,
							})
						} else {
							r, err = m.crossRegisterClients[addr].Set(context.Background(), path, js, &etcd.SetOptions{
								TTL: time.Second * 60,
							})
						}

					}

					if err != nil {
						isCreated = false
						xlog.Errorf(ctx, "%s reg idx: %d, resp: %v, err: %v", fun, j, r, err)

					} else {
						isCreated = true
					}
				}

				withRegLockRunClosureBeforeStop(m, ctx, fun, updateEtcd)

				time.Sleep(time.Second * 20)

				if m.isStop() {
					xlog.Infof(ctx, "%s server stop, register info [%s] clear", fun, path)
					return
				}
			}

		}()
	}

	return nil
}

func (m *ServBaseV2) clearCrossDCRegisterInfos() {
	fun := "ServBaseV2.clearCrossDCRegisterInfos -->"
	ctx := context.Background()
	//延迟清理注册信息,防止新实例还没有完成注册
	time.Sleep(time.Second * 2)

	m.muReg.Lock()
	defer m.muReg.Unlock()

	for addr, _ := range m.crossRegisterClients {
		for path, _ := range m.regInfos {
			_, err := m.crossRegisterClients[addr].Delete(context.Background(), path, &etcd.DeleteOptions{
				Recursive: true,
			})
			if err != nil {
				xlog.Warnf(ctx, "%s path: %s, err: %v", fun, path, err)
			}
		}
	}
}

// 初始化跨机房etcd客户端
func initCrossRegisterCenter(sb *ServBaseV2) error {
	var baseConfig BaseConfig
	err := sb.ServConfig(&baseConfig)
	if err != nil {
		return err
	}
	for _, addr := range baseConfig.Base.CrossRegisterCenters {
		baseCfg := etcd.Config{
			Endpoints: []string{addr},
			Transport: etcd.DefaultTransport,
		}
		baseClient, err := etcd.New(baseCfg)
		if err != nil {
			return fmt.Errorf("create etcd client failed, config: %v", baseCfg)
		}
		baseKeysAPI := etcd.NewKeysAPI(baseClient)
		if baseClient == nil {
			return fmt.Errorf("create etchd api error")
		}
		sb.crossRegisterClients[addr] = baseKeysAPI
	}
	return nil
}
<commit_msg>refactor: initCrossRegisterCenterOrigin<commit_after>package rocserv

import (
	"context"
	"fmt"
	"time"

	"gitlab.pri.ibanyu.com/middleware/seaweed/xlog"

	etcd "github.com/coreos/etcd/client"
)

// RegisterCrossDCService, the path and value is the same as RegisterService, but different register center
func (m *ServBaseV2) RegisterCrossDCService(servs map[string]*ServInfo) error {
	fun := "ServBaseV2.RegisterService -->"
	ctx := context.Background()
	err := m.RegisterServiceV2(servs, BASE_LOC_REG_SERV, true)
	if err != nil {
		xlog.Errorf(ctx, "%s register server v2 failed, err: %v", fun, err)
		return err
	}

	err = m.RegisterServiceV1(servs, true)
	if err != nil {
		xlog.Errorf(ctx, "%s register server v1 failed, err: %v", fun, err)
		return err
	}

	xlog.Infof(ctx, "%s register cross dc server ok", fun)

	return nil
}

func (m *ServBaseV2) doCrossDCRegister(path, js string, refresh bool) error {
	fun := "ServBaseV2.doCrossDCRegister -->"
	ctx := context.Background()
	for addr, _ := range m.crossRegisterClients {
		// 创建完成标志
		var isCreated bool

		go func() {

			for j := 0; ; j++ {
				updateEtcd := func() {
					var err error
					var r *etcd.Response
					if !isCreated {
						xlog.Warnf(ctx, "%s create idx:%d server_info: %s", fun, j, js)
						r, err = m.crossRegisterClients[addr].Set(context.Background(), path, js, &etcd.SetOptions{
							TTL: time.Second * 60,
						})
					} else {
						if refresh {
							// 在刷新ttl时候，不允许变更value
							r, err = m.crossRegisterClients[addr].Set(context.Background(), path, "", &etcd.SetOptions{
								PrevExist: etcd.PrevExist,
								TTL:       time.Second * 60,
								Refresh:   true,
							})
						} else {
							r, err = m.crossRegisterClients[addr].Set(context.Background(), path, js, &etcd.SetOptions{
								TTL: time.Second * 60,
							})
						}

					}

					if err != nil {
						isCreated = false
						xlog.Errorf(ctx, "%s reg idx: %d, resp: %v, err: %v", fun, j, r, err)

					} else {
						isCreated = true
					}
				}

				withRegLockRunClosureBeforeStop(m, ctx, fun, updateEtcd)

				time.Sleep(time.Second * 20)

				if m.isStop() {
					xlog.Infof(ctx, "%s server stop, register info [%s] clear", fun, path)
					return
				}
			}

		}()
	}

	return nil
}

func (m *ServBaseV2) clearCrossDCRegisterInfos() {
	fun := "ServBaseV2.clearCrossDCRegisterInfos -->"
	ctx := context.Background()
	//延迟清理注册信息,防止新实例还没有完成注册
	time.Sleep(time.Second * 2)

	m.muReg.Lock()
	defer m.muReg.Unlock()

	for addr, _ := range m.crossRegisterClients {
		for path, _ := range m.regInfos {
			_, err := m.crossRegisterClients[addr].Delete(context.Background(), path, &etcd.DeleteOptions{
				Recursive: true,
			})
			if err != nil {
				xlog.Warnf(ctx, "%s path: %s, err: %v", fun, path, err)
			}
		}
	}
}

// 初始化跨机房etcd客户端
func initCrossRegisterCenter(sb *ServBaseV2) error {
	return initCrossRegisterCenterOrigin(sb)
}

// 旧版本初始化跨机房注册etcd客户端, 使用服务内静态配置
func initCrossRegisterCenterOrigin(sb *ServBaseV2) error {
	var baseConfig BaseConfig
	err := sb.ServConfig(&baseConfig)
	if err != nil {
		return err
	}
	for _, addr := range baseConfig.Base.CrossRegisterCenters {
		baseCfg := etcd.Config{
			Endpoints: []string{addr},
			Transport: etcd.DefaultTransport,
		}
		baseClient, err := etcd.New(baseCfg)
		if err != nil {
			return fmt.Errorf("create etcd client failed, config: %v", baseCfg)
		}
		baseKeysAPI := etcd.NewKeysAPI(baseClient)
		if baseClient == nil {
			return fmt.Errorf("create etchd api error")
		}
		sb.crossRegisterClients[addr] = baseKeysAPI
	}
	return nil
}
<|endoftext|>