func LoadAppendOnlyFile(comChan chan com.Command) { f, err := os.Open("./db/store.oaf") if err != nil { return } b := bufio.NewReader(f) c := parser.CommandParser{} c.Reset() c.Restart() reply := make(chan string) line := make([]byte, 1024) var done bool var n int var commands []com.Command for { n, err = b.Read(line[:]) if err != nil { break } done, commands, err = c.ParseBytes(line[:n]) if err != nil { fmt.Println(err) break } if done { for _, command := range commands { command.ReplyChan = reply comChan <- command <-reply } c.Reset() } } persistDisabled = false }
func handleConn(client net.Conn, comChan chan com.Command) { // Buffer the current client b := bufio.NewReader(client) // Set up and initialize the command parser for this connection c := parser.CommandParser{} c.Reset() c.Restart() // Initialize varrious channels, buffers, and state variables reply := make(chan string) line := make([]byte, 1024) checkSync := true // Define variables we're going to set on every single loop var err error var done bool var n int var commands []com.Command for { // wait for commands to come down the pipe n, err = b.Read(line[:]) if err != nil { fmt.Println("Connection closed") break } // process bytes received from the client done, commands, err = c.ParseBytes(line[:n]) if err != nil { break } // if we've processed any commands, run them if done { for _, command := range commands { // If the first command we ever see is a "SYNC" command, bypass // the command processor and set this connection up as a replica if checkSync { command_key := strings.ToLower(command.Args[0]) switch command_key { case "sync": persist.StartSync(client) return } checkSync = false } // make sure we get replies for all commands we send to the db command.ReplyChan = reply //send our command and wait for a repsonse comChan <- command client.Write([]byte(<-reply)) } c.Reset() } } }
func init() { slaveChan := make(chan string) var slaveConn net.Conn go func() { c := parser.CommandParser{} c.Reset() c.Restart() replyChan := make(chan string) line := make([]byte, 1024) var done bool var err error var commands []com.Command comChan := store.DefaultDBManager.ComChan for { master := <-slaveChan if slaveConn != nil { slaveConn.Close() slaveConn = nil } if master != "NO:ONE" { slaveConn, err = net.Dial("tcp", master) if err == nil { slaveConn.Write([]byte("*1\r\n$4\r\nSYNC\r\n")) go func() { db_dec := gob.NewDecoder(slaveConn) store.DefaultDBManager.LoadFromGobDecoder(db_dec) for { n, err := slaveConn.Read(line[:]) if err != nil { return } done, commands, err = c.ParseBytes(line[:n]) if err != nil { break } // if we've processed any commands, run them if done { for _, command := range commands { command.ReplyChan = replyChan comChan <- command <-replyChan } c.Reset() } } }() } else { slaveChan <- reply.ErrorReply(fmt.Sprintf("Unable to connect to server at %s", master)) continue } } slaveChan <- reply.OKReply } }() store.DefaultDBManager.AddFunc("slaveof", func(db *store.DB, args []string) string { ip := args[0] port := args[1] slaveChan <- fmt.Sprintf("%s:%s", ip, port) return <-slaveChan }) store.DefaultDBManager.AddFunc("movebucket", func(db *store.DB, args []string) string { ip := args[0] port := args[1] bucket, err := strconv.Atoi(args[2]) if err != nil { return reply.ErrorReply("Invalid bucket") } slaveChan <- fmt.Sprintf("%s:%s", ip, port) return <-slaveChan }) }