Esempio n. 1
0
// serveShardMapping maps the requested shard and streams data back to the client.
func (h *Handler) serveShardMapping(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("content-type", "application/json")
	var err error

	// Pull out shard ID, query statement, and chunking size.
	q := r.URL.Query()
	pretty := q.Get("pretty") == "true"
	id, s, cs := q.Get("shard"), q.Get("q"), q.Get("chunksize")

	var chunkSize int
	if id == "" {
		httpError(w, `no shard ID specified`, pretty, http.StatusBadRequest)
		return
	}
	shardID, err := strconv.Atoi(id)
	if err != nil {
		httpError(w, `shard ID is not valid`, pretty, http.StatusBadRequest)
		return
	}
	if s == "" {
		httpError(w, `no query specified`, pretty, http.StatusBadRequest)
		return
	}
	if cs == "" {
		chunkSize = 0
	} else {
		chunkSize, err = strconv.Atoi(cs)
		if err != nil {
			httpError(w, `chunk size is not valid`, pretty, http.StatusBadRequest)
			return
		}
	}

	mapper, err := h.TSDBStore.CreateMapper(uint64(shardID), s, chunkSize)
	if err != nil {
		httpError(w, fmt.Sprintf("mapper create: %s", err), pretty, http.StatusInternalServerError)
	}
	if mapper == nil {
		b := MarshalJSON(&tsdb.MapperResponse{}, pretty)
		w.Write(b)
		w.(http.Flusher).Flush()
		return
	}

	if err := mapper.Open(); err != nil {
		httpError(w, fmt.Sprintf("mapper open: %s", err), pretty, http.StatusInternalServerError)
	}
	defer mapper.Close()

	var tagSetsSent bool
	for {
		var r tsdb.MapperResponse

		if !tagSetsSent {
			r.TagSets = mapper.TagSets()
			tagSetsSent = true
		}

		chunk, err := mapper.NextChunk()
		if err != nil {
			httpError(w, fmt.Sprintf("next chunk: %s", err), pretty, http.StatusInternalServerError)
			return
		}
		if chunk != nil {
			data := MarshalJSON(&chunk, pretty)
			r.Data = data
		}

		b := MarshalJSON(&r, pretty)
		w.Write(b)
		w.(http.Flusher).Flush()

		if chunk == nil {
			return
		}
	}
}