Example #1
0
func (s *DefaultServer) Loop() {
	defer func() {
		if r := recover(); r != nil {
			if r != io.EOF {
				log.Println("Recovered from runtime panic:", r)
				log.Println("Panic location: ", identifyPanic())
			}
		}
	}()

	for {
		start := time.Now()

		request, reqType, err := s.rp.Parse()
		if err != nil {
			if err == common.ErrBadRequest ||
				err == common.ErrBadLength ||
				err == common.ErrBadFlags ||
				err == common.ErrBadExptime {
				s.orca.Error(nil, common.RequestUnknown, err)
				continue
			} else {
				// Otherwise IO error. Abort!
				abort(s.conns, err)
				return
			}
		}

		metrics.IncCounter(MetricCmdTotal)

		// TODO: handle nil
		switch reqType {
		case common.RequestSet:
			err = s.orca.Set(request.(common.SetRequest))
		case common.RequestAdd:
			err = s.orca.Add(request.(common.SetRequest))
		case common.RequestReplace:
			err = s.orca.Replace(request.(common.SetRequest))
		case common.RequestDelete:
			err = s.orca.Delete(request.(common.DeleteRequest))
		case common.RequestTouch:
			err = s.orca.Touch(request.(common.TouchRequest))
		case common.RequestGet:
			err = s.orca.Get(request.(common.GetRequest))
		case common.RequestGetE:
			err = s.orca.GetE(request.(common.GetRequest))
		case common.RequestGat:
			err = s.orca.Gat(request.(common.GATRequest))
		case common.RequestNoop:
			err = s.orca.Noop(request.(common.NoopRequest))
		case common.RequestQuit:
			s.orca.Quit(request.(common.QuitRequest))
			abort(s.conns, err)
			return
		case common.RequestVersion:
			err = s.orca.Version(request.(common.VersionRequest))
		case common.RequestUnknown:
			err = s.orca.Unknown(request)
		}

		if err != nil {
			if common.IsAppError(err) {
				if err != common.ErrKeyNotFound {
					metrics.IncCounter(MetricErrAppError)
				}
				s.orca.Error(request, reqType, err)
			} else {
				metrics.IncCounter(MetricErrUnrecoverable)
				abort(s.conns, err)
				return
			}
		}

		dur := uint64(time.Since(start))
		switch reqType {
		case common.RequestSet:
			metrics.ObserveHist(HistSet, dur)
		case common.RequestAdd:
			metrics.ObserveHist(HistAdd, dur)
		case common.RequestReplace:
			metrics.ObserveHist(HistReplace, dur)
		case common.RequestDelete:
			metrics.ObserveHist(HistDelete, dur)
		case common.RequestTouch:
			metrics.ObserveHist(HistTouch, dur)
		case common.RequestGet:
			metrics.ObserveHist(HistGet, dur)
		case common.RequestGetE:
			metrics.ObserveHist(HistGetE, dur)
		case common.RequestGat:
			metrics.ObserveHist(HistGat, dur)
		}
	}
}
Example #2
0
func handleConnectionReal(remoteConn net.Conn, l1, l2 handlers.Handler) {
	remoteReader := bufio.NewReader(remoteConn)
	remoteWriter := bufio.NewWriter(remoteConn)

	var reqParser common.RequestParser
	var responder common.Responder
	var reqType common.RequestType
	var request interface{}

	binaryParser := binprot.NewBinaryParser(remoteReader)
	binaryResponder := binprot.NewBinaryResponder(remoteWriter)
	textParser := textprot.NewTextParser(remoteReader)
	textResponder := textprot.NewTextResponder(remoteWriter)

	for {
		binary, err := isBinaryRequest(remoteReader)

		if err != nil {
			abort([]io.Closer{remoteConn, l1, l2}, err, binary)
			return
		}

		if binary {
			reqParser = binaryParser
			responder = binaryResponder
		} else {
			reqParser = textParser
			responder = textResponder
		}

		request, reqType, err = reqParser.Parse()

		if err != nil {
			abort([]io.Closer{remoteConn, l1, l2}, err, binary)
			return
		}

		// TODO: handle nil
		switch reqType {
		case common.RequestSet:
			req := request.(common.SetRequest)
			//fmt.Println("set", string(req.Key))
			err = l1.Set(req, remoteReader)

			if err == nil {
				responder.Set()
			}

		case common.RequestDelete:
			req := request.(common.DeleteRequest)
			//fmt.Println("delete", string(req.Key))
			err = l1.Delete(req)

			if err == nil {
				responder.Delete()
			}

		case common.RequestTouch:
			req := request.(common.TouchRequest)
			//fmt.Println("touch", string(req.Key))
			err = l1.Touch(req)

			if err == nil {
				responder.Touch()
			}

		case common.RequestGet:
			req := request.(common.GetRequest)
			//debugString := "get"
			//for _, k := range req.Keys {
			//	debugString += " "
			//	debugString += string(k)
			//}
			//println(debugString)
			resChan, errChan := l1.Get(req)

			for {
				select {
				case res, ok := <-resChan:
					if !ok {
						resChan = nil
					} else {
						if res.Miss {
							responder.GetMiss(res)
						} else {
							responder.Get(res)
						}
					}

				case getErr, ok := <-errChan:
					if !ok {
						errChan = nil
					} else {
						err = getErr
					}
				}

				if resChan == nil && errChan == nil {
					break
				}
			}

			if err == nil {
				responder.GetEnd(req.NoopEnd)
			}

		case common.RequestGat:
			req := request.(common.GATRequest)
			//fmt.Println("gat", string(req.Key))
			res, err := l1.GAT(req)

			if err == nil {
				if res.Miss {
					responder.GATMiss(res)
				} else {
					responder.GAT(res)
					responder.GetEnd(false)
				}
			}

		case common.RequestUnknown:
			err = common.ErrUnknownCmd
		}

		// TODO: distinguish fatal errors from non-fatal
		if err != nil {
			if common.IsAppError(err) {
				responder.Error(err)
			} else {
				abort([]io.Closer{remoteConn, l1, l2}, err, binary)
				return
			}
		}
	}
}