From 68e8d3528e774acaa922f09fce3e7ba80ce30001 Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Sun, 13 Jul 2014 11:30:40 -0400 Subject: [PATCH] oh hai --- rsload.go | 83 +++++++++++++++++++++++++++++++++++++++ split.go | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 rsload.go create mode 100644 split.go diff --git a/rsload.go b/rsload.go new file mode 100644 index 0000000..876f8f1 --- /dev/null +++ b/rsload.go @@ -0,0 +1,83 @@ +package main + +import ( + "bufio" + "flag" + "fmt" + "io" + "math/rand" + "net" + "os" + "strings" +) + +var ( + host = "localhost" + port = 6379 +) + +func usage(status int) { + fmt.Println("usage: rsload [filename]") + os.Exit(status) +} + +func randomString(n int) string { + var alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + buf := make([]byte, n) + for i := 0; i < len(buf); i++ { + buf[i] = alpha[rand.Intn(len(alpha)-1)] + } + return string(buf) +} + +func main() { + flag.Parse() + args := flag.Args() + if len(args) < 1 { + usage(1) + } + fname := args[0] + + conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", host, port)) + if err != nil { + fmt.Printf("unable to connect to redis: %v\n", err) + os.Exit(1) + } + defer conn.Close() + + f, err := os.Open(fname) + if err != nil { + fmt.Printf("unable to open file %s: %v\n", fname, err) + os.Exit(1) + } + defer f.Close() + + c := make(chan statement) + go split(f, c) + + s := randomString(32) + go func() { + for s := range c { + if err := s.write(conn); err != nil { + fmt.Println(err) + break + } + } + fmt.Fprintf(conn, "*2\r\n$4\r\necho\r\n$32\r\n%s\r\n", s) + }() + + r := bufio.NewReader(conn) + for { + line, err := r.ReadString('\n') + switch err { + case nil: + if strings.TrimSpace(line) == s { + return + } + case io.EOF: + return + default: + fmt.Println(err) + } + } +} diff --git a/split.go b/split.go new file mode 100644 index 0000000..b12fa81 --- /dev/null +++ b/split.go @@ -0,0 +1,114 @@ +package main + +import ( + "bufio" + "bytes" + "fmt" + "io" +) + +type statement struct { + head *node + tail *node +} + +func (s statement) String() string { + var buf bytes.Buffer + s.each(func(n *node) error { + _, err := fmt.Fprint(&buf, n) + return err + }) + return buf.String() +} + +func (s *statement) each(fn func(*node) error) error { + curr := s.head + for curr != nil { + err := fn(curr) + if err != nil { + return err + } + curr = curr.next + } + return nil +} + +func (s *statement) write(w io.Writer) error { + return s.each(func(n *node) error { + _, err := w.Write(n.line) + return err + }) +} + +type node struct { + line []byte + next *node +} + +func (n node) String() string { + return fmt.Sprintf("%s", n.line) +} + +func (s *statement) add(line []byte) { + n := &node{line, nil} + if s.head == nil { + s.head = n + } else if s.head.next == nil { + s.head.next = n + } + if s.tail != nil { + s.tail.next = n + } + s.tail = n +} + +func whitespace(buf []byte) bool { + for i, _ := range buf { + switch buf[i] { + case '\r', '\n': + default: + return false + } + } + return true +} + +func split(r io.Reader, c chan statement) { + defer close(c) + br := bufio.NewReader(r) + var s *statement + for { + line, err := br.ReadBytes('\n') + switch err { + case nil: + case io.EOF: + if s != nil { + c <- *s + } + return + default: + fmt.Printf("error on read: %v\n", err) + return + } + if whitespace(line) { + continue + } + if line[len(line)-2] != '\r' { + fmt.Printf("bad line terminator") + break + } + if line[0] == '*' { + if s != nil { + c <- *s + } + s = new(statement) + s.add(line) + } else { + if s == nil { + fmt.Println("ummm wut") + return + } + s.add(line) + } + } +}