예제 #1
0
파일: persist.go 프로젝트: brianbrunner/omg
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

}
예제 #2
0
파일: omg.go 프로젝트: brianbrunner/omg
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()

		}
	}
}
예제 #3
0
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
	})

}