<commit_before>// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package prometheusexporter

import (
	"context"
	"errors"
	"net"
	"net/http"
	"strings"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/config/configtelemetry"
	"go.opentelemetry.io/collector/model/pdata"
	"go.opentelemetry.io/collector/obsreport"
)

type prometheusExporter struct {
	name         string
	endpoint     string
	shutdownFunc func() error
	handler      http.Handler
	collector    *collector
	registry     *prometheus.Registry
	obsrep       *obsreport.Exporter
}

var errBlankPrometheusAddress = errors.New("expecting a non-blank address to run the Prometheus metrics handler")

func newPrometheusExporter(config *Config, set component.ExporterCreateSettings) (*prometheusExporter, error) {
	addr := strings.TrimSpace(config.Endpoint)
	if strings.TrimSpace(config.Endpoint) == "" {
		return nil, errBlankPrometheusAddress
	}

	obsrep := obsreport.NewExporter(obsreport.ExporterSettings{
		Level:                  configtelemetry.GetMetricsLevelFlagValue(),
		ExporterID:             config.ID(),
		ExporterCreateSettings: set,
	})

	collector := newCollector(config, set.Logger)
	registry := prometheus.NewRegistry()
	_ = registry.Register(collector)

	return &prometheusExporter{
		name:         config.ID().String(),
		endpoint:     addr,
		collector:    collector,
		registry:     registry,
		shutdownFunc: func() error { return nil },
		obsrep:       obsrep,
		handler: promhttp.HandlerFor(
			registry,
			promhttp.HandlerOpts{
				ErrorHandling: promhttp.ContinueOnError,
			},
		),
	}, nil
}

func (pe *prometheusExporter) Start(_ context.Context, _ component.Host) error {
	ln, err := net.Listen("tcp", pe.endpoint)
	if err != nil {
		return err
	}

	pe.shutdownFunc = ln.Close

	mux := http.NewServeMux()
	mux.Handle("/metrics", pe.handler)
	srv := &http.Server{Handler: mux}
	go func() {
		_ = srv.Serve(ln)
	}()

	return nil
}

func (pe *prometheusExporter) ConsumeMetrics(ctx context.Context, md pdata.Metrics) error {
	pe.obsrep.StartMetricsOp(ctx)
	n := 0
	rmetrics := md.ResourceMetrics()
	for i := 0; i < rmetrics.Len(); i++ {
		n += pe.collector.processMetrics(rmetrics.At(i))
	}
	pe.obsrep.EndMetricsOp(ctx, n, nil)

	return nil
}

func (pe *prometheusExporter) Shutdown(context.Context) error {
	return pe.shutdownFunc()
}
<commit_msg>Do not record obsreport calls in prom exporter, exporter helper does it already (#5438)<commit_after>// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package prometheusexporter

import (
	"context"
	"errors"
	"net"
	"net/http"
	"strings"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/model/pdata"
)

type prometheusExporter struct {
	name         string
	endpoint     string
	shutdownFunc func() error
	handler      http.Handler
	collector    *collector
	registry     *prometheus.Registry
}

var errBlankPrometheusAddress = errors.New("expecting a non-blank address to run the Prometheus metrics handler")

func newPrometheusExporter(config *Config, set component.ExporterCreateSettings) (*prometheusExporter, error) {
	addr := strings.TrimSpace(config.Endpoint)
	if strings.TrimSpace(config.Endpoint) == "" {
		return nil, errBlankPrometheusAddress
	}

	collector := newCollector(config, set.Logger)
	registry := prometheus.NewRegistry()
	_ = registry.Register(collector)

	return &prometheusExporter{
		name:         config.ID().String(),
		endpoint:     addr,
		collector:    collector,
		registry:     registry,
		shutdownFunc: func() error { return nil },
		handler: promhttp.HandlerFor(
			registry,
			promhttp.HandlerOpts{
				ErrorHandling: promhttp.ContinueOnError,
			},
		),
	}, nil
}

func (pe *prometheusExporter) Start(_ context.Context, _ component.Host) error {
	ln, err := net.Listen("tcp", pe.endpoint)
	if err != nil {
		return err
	}

	pe.shutdownFunc = ln.Close

	mux := http.NewServeMux()
	mux.Handle("/metrics", pe.handler)
	srv := &http.Server{Handler: mux}
	go func() {
		_ = srv.Serve(ln)
	}()

	return nil
}

func (pe *prometheusExporter) ConsumeMetrics(_ context.Context, md pdata.Metrics) error {
	n := 0
	rmetrics := md.ResourceMetrics()
	for i := 0; i < rmetrics.Len(); i++ {
		n += pe.collector.processMetrics(rmetrics.At(i))
	}

	return nil
}

func (pe *prometheusExporter) Shutdown(context.Context) error {
	return pe.shutdownFunc()
}
<|endoftext|>


<commit_before>package lib

import "time"

func F한국증시_폐장_시간임() bool {
	return f한국증시_거래시간_도우미(0, 0, 8, 30) ||
		f한국증시_거래시간_도우미(18, 0, 23, 59)
}

func F한국증시_정규_거래_시간임() bool {
	return f한국증시_거래시간_도우미(9, 0, 15, 20)
}

func F한국증시_ETF_LP_의무_호가제출_시간임() bool {
	// 규정상 9시 5분부터 LP 호가 제출이 시작되지만,
	// 9시 10분까지 가격이 NAV에서 벗어나 심하게 출렁이는 과거 사례가 많이 있으므로,
	// 안전하게 9시 10분부터 시작하는 것으로 설정함.
	return f한국증시_거래시간_도우미(9, 10, 15, 20)
}

func F한국증시_동시호가_시간임() bool {
	return f한국증시_거래시간_도우미(8, 30, 9, 0) ||
		f한국증시_거래시간_도우미(15, 20, 15, 30)
}

func F한국증시_장전_시간외_종가매매_시간임() bool {
	return f한국증시_거래시간_도우미(8, 30, 8, 40)
}

func F한국증시_장후_시간외_종가매매_시간임() bool {
	return f한국증시_거래시간_도우미(15, 40, 16, 0)
}

func F한국증시_시간외_단일가매매_시간임() bool {
	return f한국증시_거래시간_도우미(16, 0, 18, 0)
}

func F한국증시_정규경쟁대량매매_거래시간임() bool {
	return f한국증시_거래시간_도우미(9, 0, 15, 00)
}

func F한국증시_시간외_대량바스켓매매_거래시간임() bool {
	return f한국증시_거래시간_도우미(15, 40, 18, 0)
}

func f한국증시_거래시간_도우미(시작_시간, 시작_분, 종료_시간, 종료_분 int) bool {
	값 := F금일()
	지금 := time.Now()
	로케일 := 지금.Location()

	시작_시각 := time.Date(값.Year(), 값.Month(), 값.Day(), 시작_시간, 시작_분, 0, 0, 로케일)
	종료_시각 := time.Date(값.Year(), 값.Month(), 값.Day(), 종료_시간, 종료_분, 0, 0, 로케일)

	if 지금.After(시작_시각) && 지금.Before(종료_시각) {
		return true
	}

	return false
}
<commit_msg>동시호가 시작 시간 수정.<commit_after>package lib

import "time"

func F한국증시_폐장_시간임() bool {
	return f한국증시_거래시간_도우미(0, 0, 8, 30) ||
		f한국증시_거래시간_도우미(18, 0, 23, 59)
}

func F한국증시_정규_거래_시간임() bool {
	return f한국증시_거래시간_도우미(9, 0, 15, 20)
}

func F한국증시_ETF_LP_의무_호가제출_시간임() bool {
	// 규정상 9시 5분부터 LP 호가 제출이 시작되지만,
	// 9시 10분까지 가격이 NAV에서 벗어나 심하게 출렁이는 과거 사례가 많이 있으므로,
	// 안전하게 9시 10분부터 시작하는 것으로 설정함.
	return f한국증시_거래시간_도우미(9, 10, 15, 20)
}

func F한국증시_동시호가_시간임() bool {
	return f한국증시_거래시간_도우미(8, 40, 9, 0) ||
		f한국증시_거래시간_도우미(15, 20, 15, 30)
}

func F한국증시_장전_시간외_종가매매_시간임() bool {
	return f한국증시_거래시간_도우미(8, 30, 8, 40)
}

func F한국증시_장후_시간외_종가매매_시간임() bool {
	return f한국증시_거래시간_도우미(15, 40, 16, 0)
}

func F한국증시_시간외_단일가매매_시간임() bool {
	return f한국증시_거래시간_도우미(16, 0, 18, 0)
}

func F한국증시_정규경쟁대량매매_거래시간임() bool {
	return f한국증시_거래시간_도우미(9, 0, 15, 00)
}

func F한국증시_시간외_대량바스켓매매_거래시간임() bool {
	return f한국증시_거래시간_도우미(15, 40, 18, 0)
}

func f한국증시_거래시간_도우미(시작_시간, 시작_분, 종료_시간, 종료_분 int) bool {
	값 := F금일()
	지금 := time.Now()
	로케일 := 지금.Location()

	시작_시각 := time.Date(값.Year(), 값.Month(), 값.Day(), 시작_시간, 시작_분, 0, 0, 로케일)
	종료_시각 := time.Date(값.Year(), 값.Month(), 값.Day(), 종료_시간, 종료_분, 0, 0, 로케일)

	if 지금.After(시작_시각) && 지금.Before(종료_시각) {
		return true
	}

	return false
}
<|endoftext|>


<commit_before>// Loading PNGs with SDL_image
// Adapted from http://lazyfoo.net/tutorials/SDL/06_extension_libraries_and_loading_other_image_formats/index2.php

package main

import (
	"log"

	"github.com/veandco/go-sdl2/sdl"
	"github.com/veandco/go-sdl2/sdl_image"
)

const (
	screenWidth  = 640
	screenHeight = 480
)

var (
	err              error
	window           *sdl.Window
	renderer         *sdl.Renderer
	texture          *sdl.Texture
	screenSurface    *sdl.Surface
	stretchedSurface *sdl.Surface
	quit             bool
	event            sdl.Event
)

func initSDL() error {
	err = sdl.Init(sdl.INIT_VIDEO)

	if err != nil {
		return err
	}

	window, err = sdl.CreateWindow("SDL Tutorial", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, screenWidth, screenHeight, sdl.WINDOW_SHOWN)
	if err != nil {
		return err
	}

	renderer, err = sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
	if err != nil {
		return err
	}

	renderer.SetDrawColor(0xFF, 0xFF, 0xFF, 0xFF)

	imgFlags := img.INIT_PNG
	imgInitResult := img.Init(imgFlags)
	if (imgInitResult & imgFlags) != imgFlags {
		return img.GetError()
	}

	screenSurface, err = window.GetSurface()
	if err != nil {
		return err
	}

	return nil
}

func loadTexture(path string) (*sdl.Texture, error) {
	var newTexture *sdl.Texture

	loadedSurface, err := img.Load(path)
	if err != nil {
		return nil, err
	}

	newTexture, err = renderer.CreateTextureFromSurface(loadedSurface)
	if err != nil {
		return nil, err
	}

	loadedSurface.Free()

	return newTexture, nil
}

func loadSurface(path string) (*sdl.Surface, error) {

	loadedSurface, err := img.Load(path)
	if err != nil {
		return nil, err
	}

	optimizedSurface, err := loadedSurface.Convert(screenSurface.Format, 0)
	if err != nil {
		return nil, err
	}

	// Get rid of old loaded surface
	loadedSurface.Free()

	return optimizedSurface, nil
}

func loadMedia() error {
	texture, err = loadTexture("texture.png")
	if err != nil {
		return err
	}

	return nil
}

func close() {
	texture.Destroy()
	renderer.Destroy()
	window.Destroy()
	img.Quit()
	sdl.Quit()
}

func main() {
	err = initSDL()
	if err != nil {
		log.Fatal("Error initializing SDL:", err)
	}

	err = loadMedia()
	if err != nil {
		log.Fatal("Error loading Media:", err)
	}

	quit = false
	for !quit {
		for event = sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
			switch event.(type) {
			case *sdl.QuitEvent:
				quit = true
			}
		}

		renderer.Clear()
		renderer.Copy(texture, nil, nil)
		renderer.Present()
	}

	close()
}
<commit_msg>Fix title and link<commit_after>// Texture Loading and Rendering
// Adapted from http://lazyfoo.net/tutorials/SDL/07_texture_loading_and_rendering/index.php

package main

import (
	"log"

	"github.com/veandco/go-sdl2/sdl"
	"github.com/veandco/go-sdl2/sdl_image"
)

const (
	screenWidth  = 640
	screenHeight = 480
)

var (
	err              error
	window           *sdl.Window
	renderer         *sdl.Renderer
	texture          *sdl.Texture
	screenSurface    *sdl.Surface
	stretchedSurface *sdl.Surface
	quit             bool
	event            sdl.Event
)

func initSDL() error {
	err = sdl.Init(sdl.INIT_VIDEO)

	if err != nil {
		return err
	}

	window, err = sdl.CreateWindow("SDL Tutorial", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, screenWidth, screenHeight, sdl.WINDOW_SHOWN)
	if err != nil {
		return err
	}

	renderer, err = sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
	if err != nil {
		return err
	}

	renderer.SetDrawColor(0xFF, 0xFF, 0xFF, 0xFF)

	imgFlags := img.INIT_PNG
	imgInitResult := img.Init(imgFlags)
	if (imgInitResult & imgFlags) != imgFlags {
		return img.GetError()
	}

	screenSurface, err = window.GetSurface()
	if err != nil {
		return err
	}

	return nil
}

func loadTexture(path string) (*sdl.Texture, error) {
	var newTexture *sdl.Texture

	loadedSurface, err := img.Load(path)
	if err != nil {
		return nil, err
	}

	newTexture, err = renderer.CreateTextureFromSurface(loadedSurface)
	if err != nil {
		return nil, err
	}

	loadedSurface.Free()

	return newTexture, nil
}

func loadSurface(path string) (*sdl.Surface, error) {

	loadedSurface, err := img.Load(path)
	if err != nil {
		return nil, err
	}

	optimizedSurface, err := loadedSurface.Convert(screenSurface.Format, 0)
	if err != nil {
		return nil, err
	}

	// Get rid of old loaded surface
	loadedSurface.Free()

	return optimizedSurface, nil
}

func loadMedia() error {
	texture, err = loadTexture("texture.png")
	if err != nil {
		return err
	}

	return nil
}

func close() {
	texture.Destroy()
	renderer.Destroy()
	window.Destroy()
	img.Quit()
	sdl.Quit()
}

func main() {
	err = initSDL()
	if err != nil {
		log.Fatal("Error initializing SDL:", err)
	}

	err = loadMedia()
	if err != nil {
		log.Fatal("Error loading Media:", err)
	}

	quit = false
	for !quit {
		for event = sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
			switch event.(type) {
			case *sdl.QuitEvent:
				quit = true
			}
		}

		renderer.Clear()
		renderer.Copy(texture, nil, nil)
		renderer.Present()
	}

	close()
}
<|endoftext|>


<commit_before>// Server application serves index engine via rest API.
// TODO :
//  - Create a goroutine that will pull mutations from UPR and update the
//    index.

package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/couchbaselabs/indexing/api"
	"github.com/couchbaselabs/indexing/catalog"
	"github.com/couchbaselabs/indexing/engine/leveldb"
	"log"
	"net/http"
	"sync"
)

var c catalog.IndexCatalog
var ddlLock sync.Mutex
var chnotify chan ddlNotification

func main() {
	var err error

	// Create index catalog
	if c, err = catalog.NewIndexCatalog("./"); err != nil {
		log.Fatalf("Fatal error opening catalog: %v", err)
	}

	openIndexEngine()

	addr := ":8095"
	// Subscribe to HTTP server handlers
	http.HandleFunc("/create", handleCreate)
	http.HandleFunc("/drop", handleDrop)
	http.HandleFunc("/scan", handleScan)
	http.HandleFunc("/stats", handleStats)

	//FIXME add error handing to this

	if chnotify, err = StartMutationManager(); err != nil {
		log.Printf("Error Starting Mutation Manager %v", err)
		return
	}

	//FIXME This doesn't work on Ctrl-C
	defer freeResourcesOnExit()
	log.Println("Indexer Listening on", addr)
	if err := http.ListenAndServe(addr, nil); err != nil {
		log.Fatalf("Fatal: %v", err)
	}

}

// /create
func handleCreate(w http.ResponseWriter, r *http.Request) {
	var res api.IndexMetaResponse
	var err error

	indexinfo := indexRequest(r).Index // Get IndexInfo

	ddlLock.Lock()
	defer ddlLock.Unlock()

	if err = assignIndexEngine(&indexinfo); err == nil {
		if _, err = c.Create(indexinfo); err == nil {
			//notify mutation manager about the new index
			notification := ddlNotification{
				ddltype:   api.CREATE,
				indexinfo: indexinfo,
			}
			chnotify <- notification

			res = api.IndexMetaResponse{
				Status: api.SUCCESS,
			}
			log.Printf("Created index(%v) %v", indexinfo.Uuid, indexinfo.Name)
		}
	}
	if err != nil {
		res = createMetaResponseFromError(err)
		log.Println("ERROR: Failed to create index", err)
	}
	sendResponse(w, res)
}

// /drop
func handleDrop(w http.ResponseWriter, r *http.Request) {
	var res api.IndexMetaResponse
	var err error

	indexinfo := indexRequest(r).Index

	ddlLock.Lock()
	defer ddlLock.Unlock()

	if indexinfo, err = c.Index(indexinfo.Uuid); err == nil {
		//Notify mutation manager before destroying the engine
		notification := ddlNotification{
			ddltype:   api.DROP,
			indexinfo: indexinfo,
		}
		chnotify <- notification

		if err = indexinfo.Engine.Destroy(); err == nil {
			if _, err = c.Drop(indexinfo.Uuid); err == nil {
				res = api.IndexMetaResponse{
					Status: api.SUCCESS,
				}
				log.Printf("Dropped index(%v) %v", indexinfo.Uuid, indexinfo.Name)
			}
		}

		if err != nil {
			//FIXME need to renotify the mutation manager??
		}
	}

	if err != nil {
		res = createMetaResponseFromError(err)
		log.Println("ERROR: Failed to drop index", err)
	}
	sendResponse(w, res)
}

// /scan
func handleScan(w http.ResponseWriter, r *http.Request) {
	var err error

	indexreq := indexRequest(r) // Gather request
	uuid := indexreq.Index.Uuid
	q := indexreq.Params

	log.Printf("Received Scan Index %v Params %v %v", uuid, q.Low, q.High)

	// Scan
	rows := make([]api.IndexRow, 0)
	var totalRows uint64
	var lowkey, highkey api.Key

	if lowkey, err = api.NewKey(q.Low, ""); err != nil {
		sendScanResponse(w, nil, 0, err)
		return
	}

	if highkey, err = api.NewKey(q.High, ""); err != nil {
		sendScanResponse(w, nil, 0, err)
		return
	}

	var indexinfo api.IndexInfo
	if indexinfo, err = c.Index(uuid); err == nil {
		switch q.ScanType {

		case api.COUNT:
			totalRows, err = countQuery(&indexinfo, q.Limit)

		case api.EXISTS:
			var exists bool
			exists, err = existsQuery(&indexinfo, lowkey)
			if exists {
				totalRows = 1
			}

		case api.LOOKUP:

			rows, err = lookupQuery(&indexinfo, lowkey, q.Limit)
			totalRows = uint64(len(rows))

		case api.RANGESCAN:

			rows, err = rangeQuery(&indexinfo, lowkey, highkey, q.Inclusion, q.Limit)
			totalRows = uint64(len(rows))

		case api.FULLSCAN:
			rows, err = scanQuery(&indexinfo, q.Limit)
			totalRows = uint64(len(rows))

		case api.RANGECOUNT:
			totalRows, err = rangeCountQuery(&indexinfo, lowkey, highkey, q.Inclusion, q.Limit)
		}
	}
	// send back the response
	sendScanResponse(w, rows, totalRows, err)
}

// /stats.
func handleStats(w http.ResponseWriter, r *http.Request) {
	panic("Not yet impleted")
}

//---- helper functions

func countQuery(indexinfo *api.IndexInfo, limit int64) (
	uint64, error) {

	if counter, ok := indexinfo.Engine.(api.Counter); ok {
		count, err := counter.CountTotal()
		return count, err
	}
	err := errors.New("Index does not support Looker interface")
	return uint64(0), err
}

func existsQuery(indexinfo *api.IndexInfo, key api.Key) (bool, error) {

	if exister, ok := indexinfo.Engine.(api.Exister); ok {
		exists := exister.Exists(key)
		return exists, nil
	}
	err := errors.New("Index does not support Exister interface")
	return false, err
}

func scanQuery(indexinfo *api.IndexInfo, limit int64) (
	[]api.IndexRow, error) {

	if looker, ok := indexinfo.Engine.(api.Looker); ok {
		ch, cherr := looker.ValueSet()
		return receiveValue(ch, cherr, limit)
	}
	err := errors.New("Index does not support Looker interface")
	return nil, err
}

func rangeQuery(
	indexinfo *api.IndexInfo, low, high api.Key, incl api.Inclusion,
	limit int64) ([]api.IndexRow, error) {

	if ranger, ok := indexinfo.Engine.(api.Ranger); ok {
		ch, cherr, _ := ranger.ValueRange(low, high, incl)
		return receiveValue(ch, cherr, limit)
	}
	err := errors.New("Index does not support ranger interface")
	return nil, err
}

func lookupQuery(indexinfo *api.IndexInfo, key api.Key, limit int64) (
	[]api.IndexRow, error) {

	if looker, ok := indexinfo.Engine.(api.Looker); ok {
		log.Printf("Looking up key %s", key.String())
		ch, cherr := looker.Lookup(key)
		return receiveValue(ch, cherr, limit)
	}
	err := errors.New("Index does not support looker interface")
	return nil, err
}

func rangeCountQuery(
	indexinfo *api.IndexInfo, low, high api.Key, incl api.Inclusion,
	limit int64) (uint64, error) {

	if rangeCounter, ok := indexinfo.Engine.(api.RangeCounter); ok {
		totalRows, err := rangeCounter.CountRange(low, high, incl)
		return totalRows, err
	}
	err := errors.New("Index does not support RangeCounter interface")
	return 0, err
}
func sendResponse(w http.ResponseWriter, res interface{}) {
	var buf []byte
	var err error
	header := w.Header()
	header["Content-Type"] = []string{"application/json"}

	if buf, err = json.Marshal(&res); err != nil {
		log.Println("Unable to marshal response", res)
	}
	w.Write(buf)
}

func sendScanResponse(w http.ResponseWriter, rows []api.IndexRow, totalRows uint64, err error) {
	var res api.IndexScanResponse

	if err == nil {
		res = api.IndexScanResponse{
			Status:    api.SUCCESS,
			TotalRows: totalRows,
			Rows:      rows,
			Errors:    nil,
		}
	} else {
		indexerr := api.IndexError{Code: string(api.ERROR), Msg: err.Error()}
		res = api.IndexScanResponse{
			Status:    api.ERROR,
			TotalRows: uint64(0),
			Rows:      nil,
			Errors:    []api.IndexError{indexerr},
		}
	}
	sendResponse(w, res)
}

func receiveValue(ch chan api.Value, cherr chan error, limit int64) (
	[]api.IndexRow, error) {

	//FIXME limit should be sent to the engine and only limit response be sent on the
	//channel
	rows := make([]api.IndexRow, 0)
	var nolimit = false
	if limit == 0 {
		nolimit = true
	}
	ok := true
	var value api.Value
	var err error
	for ok && (limit > 0 || nolimit) {
		select {
		case value, ok = <-ch:
			if ok {
				log.Printf("Indexer Received Value %s", value.String())
				row := api.IndexRow{
					Key:   value.KeyBytes(),
					Value: value.Docid(),
				}
				rows = append(rows, row)
				limit--
			}
		case err, ok = <-cherr:
			if err != nil {
				return rows, err
			}
		}
	}
	return rows, nil
}

// Parse HTTP Request to get IndexInfo.
func indexRequest(r *http.Request) *api.IndexRequest {
	indexreq := api.IndexRequest{}
	buf := make([]byte, r.ContentLength, r.ContentLength)
	r.Body.Read(buf)
	json.Unmarshal(buf, &indexreq)
	return &indexreq
}

func createMetaResponseFromError(err error) api.IndexMetaResponse {

	indexerr := api.IndexError{Code: string(api.ERROR), Msg: err.Error()}
	res := api.IndexMetaResponse{
		Status: api.ERROR,
		Errors: []api.IndexError{indexerr},
	}
	return res
}

// Instantiate index engine
func assignIndexEngine(indexinfo *api.IndexInfo) error {
	var err error
	indexinfo.Engine = nil
	switch indexinfo.Using {
	case api.LevelDB:
		indexinfo.Engine = leveldb.NewIndexEngine(indexinfo.Uuid)
	default:
		err = errors.New(fmt.Sprintf("Invalid index-type, `%v`", indexinfo.Using))
	}
	return err
}

func openIndexEngine() error {

	var err error
	var indexinfos []api.IndexInfo
	//For the existing indexes, open the existing engine
	if _, indexinfos, err = c.List(""); err != nil {
		log.Printf("Error while retrieving index list %v", err)
		return err
	}

	for _, indexinfo := range indexinfos {
		log.Printf("Try Finding Existing Engine for Index %v", indexinfo)
		switch indexinfo.Using {
		case api.LevelDB:
			indexinfo.Engine = leveldb.OpenIndexEngine(indexinfo.Uuid)
			log.Printf("Got Existing Engine for Index %v", indexinfo.Uuid)
		default:
			err = errors.New(fmt.Sprintf("Unknown Index Type. Skipping Opening Engine"))
		}
	}

	return err

}

func freeResourcesOnExit() {

	//purge the catalog
	if err := c.Purge(); err != nil {
		log.Printf("Error Purging Catalog %v", err)
	}

	//close the index engines
	if err := closeIndexEngines(); err != nil {
		log.Printf("Error Closing Index Engine %v", err)
	}

	//FIXME close the mutation manager?

}

func closeIndexEngines() error {

	if _, indexinfos, err := c.List(""); err == nil {

		for _, indexinfo := range indexinfos {
			if err := indexinfo.Engine.Close(); err != nil {
				return err
			}
		}
	} else {
		return err
	}

	return nil
}
<commit_msg>Restartability support for indexer<commit_after>// Server application serves index engine via rest API.
// TODO :
//  - Create a goroutine that will pull mutations from UPR and update the
//    index.

package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/couchbaselabs/indexing/api"
	"github.com/couchbaselabs/indexing/catalog"
	"github.com/couchbaselabs/indexing/engine/leveldb"
	"log"
	"net/http"
	"sync"
)

var c catalog.IndexCatalog
var ddlLock sync.Mutex
var chnotify chan ddlNotification
var engineMap map[string]api.Finder

func main() {
	var err error

	// Create index catalog
	if c, err = catalog.NewIndexCatalog("./"); err != nil {
		log.Fatalf("Fatal error opening catalog: %v", err)
	}

	engineMap = make(map[string]api.Finder)
	//open engine for existing indexes and assign to engineMap
	openIndexEngine()

	//FIXME add error handing to this
	if chnotify, err = StartMutationManager(engineMap); err != nil {
		log.Printf("Error Starting Mutation Manager %v", err)
		return
	}

	addr := ":8095"
	// Subscribe to HTTP server handlers
	http.HandleFunc("/create", handleCreate)
	http.HandleFunc("/drop", handleDrop)
	http.HandleFunc("/scan", handleScan)
	http.HandleFunc("/stats", handleStats)

	//FIXME This doesn't work on Ctrl-C
	defer freeResourcesOnExit()
	log.Println("Indexer Listening on", addr)
	if err := http.ListenAndServe(addr, nil); err != nil {
		log.Fatalf("Fatal: %v", err)
	}

}

// /create
func handleCreate(w http.ResponseWriter, r *http.Request) {
	var res api.IndexMetaResponse
	var err error

	indexinfo := indexRequest(r).Index // Get IndexInfo

	ddlLock.Lock()
	defer ddlLock.Unlock()

	if err = assignIndexEngine(&indexinfo); err == nil {
		if _, err = c.Create(indexinfo); err == nil {
			//notify mutation manager about the new index
			notification := ddlNotification{
				ddltype:   api.CREATE,
				engine:    engineMap[indexinfo.Uuid],
				indexinfo: indexinfo,
			}
			chnotify <- notification

			res = api.IndexMetaResponse{
				Status: api.SUCCESS,
			}
			log.Printf("Created index(%v) %v", indexinfo.Uuid, indexinfo.Name)
		}
	}
	if err != nil {
		res = createMetaResponseFromError(err)
		log.Println("ERROR: Failed to create index", err)
	}
	sendResponse(w, res)
}

// /drop
func handleDrop(w http.ResponseWriter, r *http.Request) {
	var res api.IndexMetaResponse
	var err error

	indexinfo := indexRequest(r).Index

	ddlLock.Lock()
	defer ddlLock.Unlock()

	if indexinfo, err = c.Index(indexinfo.Uuid); err == nil {
		//Notify mutation manager before destroying the engine
		notification := ddlNotification{
			ddltype:   api.DROP,
			engine:    engineMap[indexinfo.Uuid],
			indexinfo: indexinfo,
		}
		chnotify <- notification

		if err = engineMap[indexinfo.Uuid].Destroy(); err == nil {
			if _, err = c.Drop(indexinfo.Uuid); err == nil {
				res = api.IndexMetaResponse{
					Status: api.SUCCESS,
				}
				log.Printf("Dropped index(%v) %v", indexinfo.Uuid, indexinfo.Name)
			}
		}

		if err != nil {
			//FIXME need to renotify the mutation manager??
		}
	}

	if err != nil {
		res = createMetaResponseFromError(err)
		log.Println("ERROR: Failed to drop index", err)
	}
	sendResponse(w, res)
}

// /scan
func handleScan(w http.ResponseWriter, r *http.Request) {
	var err error

	indexreq := indexRequest(r) // Gather request
	uuid := indexreq.Index.Uuid
	q := indexreq.Params

	log.Printf("Received Scan Index %v Params %v %v", uuid, q.Low, q.High)

	// Scan
	rows := make([]api.IndexRow, 0)
	var totalRows uint64
	var lowkey, highkey api.Key

	if lowkey, err = api.NewKey(q.Low, ""); err != nil {
		sendScanResponse(w, nil, 0, err)
		return
	}

	if highkey, err = api.NewKey(q.High, ""); err != nil {
		sendScanResponse(w, nil, 0, err)
		return
	}

	var indexinfo api.IndexInfo
	if indexinfo, err = c.Index(uuid); err == nil {
		switch q.ScanType {

		case api.COUNT:
			totalRows, err = countQuery(&indexinfo, q.Limit)

		case api.EXISTS:
			var exists bool
			exists, err = existsQuery(&indexinfo, lowkey)
			if exists {
				totalRows = 1
			}

		case api.LOOKUP:

			rows, err = lookupQuery(&indexinfo, lowkey, q.Limit)
			totalRows = uint64(len(rows))

		case api.RANGESCAN:

			rows, err = rangeQuery(&indexinfo, lowkey, highkey, q.Inclusion, q.Limit)
			totalRows = uint64(len(rows))

		case api.FULLSCAN:
			rows, err = scanQuery(&indexinfo, q.Limit)
			totalRows = uint64(len(rows))

		case api.RANGECOUNT:
			totalRows, err = rangeCountQuery(&indexinfo, lowkey, highkey, q.Inclusion, q.Limit)
		}
	}
	// send back the response
	sendScanResponse(w, rows, totalRows, err)
}

// /stats.
func handleStats(w http.ResponseWriter, r *http.Request) {
	panic("Not yet implemented")
}

//---- helper functions

func countQuery(indexinfo *api.IndexInfo, limit int64) (
	uint64, error) {

	if counter, ok := engineMap[indexinfo.Uuid].(api.Counter); ok {
		count, err := counter.CountTotal()
		return count, err
	}
	err := errors.New("Index does not support Looker interface")
	return uint64(0), err
}

func existsQuery(indexinfo *api.IndexInfo, key api.Key) (bool, error) {

	if exister, ok := engineMap[indexinfo.Uuid].(api.Exister); ok {
		exists := exister.Exists(key)
		return exists, nil
	}
	err := errors.New("Index does not support Exister interface")
	return false, err
}

func scanQuery(indexinfo *api.IndexInfo, limit int64) (
	[]api.IndexRow, error) {

	if looker, ok := engineMap[indexinfo.Uuid].(api.Looker); ok {
		ch, cherr := looker.ValueSet()
		return receiveValue(ch, cherr, limit)
	}
	err := errors.New("Index does not support Looker interface")
	return nil, err
}

func rangeQuery(
	indexinfo *api.IndexInfo, low, high api.Key, incl api.Inclusion,
	limit int64) ([]api.IndexRow, error) {

	if ranger, ok := engineMap[indexinfo.Uuid].(api.Ranger); ok {
		ch, cherr, _ := ranger.ValueRange(low, high, incl)
		return receiveValue(ch, cherr, limit)
	}
	err := errors.New("Index does not support ranger interface")
	return nil, err
}

func lookupQuery(indexinfo *api.IndexInfo, key api.Key, limit int64) (
	[]api.IndexRow, error) {

	if looker, ok := engineMap[indexinfo.Uuid].(api.Looker); ok {
		log.Printf("Looking up key %s", key.String())
		ch, cherr := looker.Lookup(key)
		return receiveValue(ch, cherr, limit)
	}
	err := errors.New("Index does not support looker interface")
	return nil, err
}

func rangeCountQuery(
	indexinfo *api.IndexInfo, low, high api.Key, incl api.Inclusion,
	limit int64) (uint64, error) {

	if rangeCounter, ok := engineMap[indexinfo.Uuid].(api.RangeCounter); ok {
		totalRows, err := rangeCounter.CountRange(low, high, incl)
		return totalRows, err
	}
	err := errors.New("Index does not support RangeCounter interface")
	return 0, err
}
func sendResponse(w http.ResponseWriter, res interface{}) {
	var buf []byte
	var err error
	header := w.Header()
	header["Content-Type"] = []string{"application/json"}

	if buf, err = json.Marshal(&res); err != nil {
		log.Println("Unable to marshal response", res)
	}
	w.Write(buf)
}

func sendScanResponse(w http.ResponseWriter, rows []api.IndexRow, totalRows uint64, err error) {
	var res api.IndexScanResponse

	if err == nil {
		res = api.IndexScanResponse{
			Status:    api.SUCCESS,
			TotalRows: totalRows,
			Rows:      rows,
			Errors:    nil,
		}
	} else {
		indexerr := api.IndexError{Code: string(api.ERROR), Msg: err.Error()}
		res = api.IndexScanResponse{
			Status:    api.ERROR,
			TotalRows: uint64(0),
			Rows:      nil,
			Errors:    []api.IndexError{indexerr},
		}
	}
	sendResponse(w, res)
}

func receiveValue(ch chan api.Value, cherr chan error, limit int64) (
	[]api.IndexRow, error) {

	//FIXME limit should be sent to the engine and only limit response be sent on the
	//channel
	rows := make([]api.IndexRow, 0)
	var nolimit = false
	if limit == 0 {
		nolimit = true
	}
	ok := true
	var value api.Value
	var err error
	for ok && (limit > 0 || nolimit) {
		select {
		case value, ok = <-ch:
			if ok {
				log.Printf("Indexer Received Value %s", value.String())
				row := api.IndexRow{
					Key:   value.KeyBytes(),
					Value: value.Docid(),
				}
				rows = append(rows, row)
				limit--
			}
		case err, ok = <-cherr:
			if err != nil {
				return rows, err
			}
		}
	}
	return rows, nil
}

// Parse HTTP Request to get IndexInfo.
func indexRequest(r *http.Request) *api.IndexRequest {
	indexreq := api.IndexRequest{}
	buf := make([]byte, r.ContentLength, r.ContentLength)
	r.Body.Read(buf)
	json.Unmarshal(buf, &indexreq)
	return &indexreq
}

func createMetaResponseFromError(err error) api.IndexMetaResponse {

	indexerr := api.IndexError{Code: string(api.ERROR), Msg: err.Error()}
	res := api.IndexMetaResponse{
		Status: api.ERROR,
		Errors: []api.IndexError{indexerr},
	}
	return res
}

// Instantiate index engine
func assignIndexEngine(indexinfo *api.IndexInfo) error {
	var err error
	switch indexinfo.Using {
	case api.LevelDB:
		engineMap[indexinfo.Uuid] = leveldb.NewIndexEngine(indexinfo.Uuid)
	default:
		err = errors.New(fmt.Sprintf("Invalid index-type, `%v`", indexinfo.Using))
	}
	return err
}

func openIndexEngine() error {

	var err error
	var indexinfos []api.IndexInfo
	//For the existing indexes, open the existing engine
	if _, indexinfos, err = c.List(""); err != nil {
		log.Printf("Error while retrieving index list %v", err)
		return err
	}

	for _, indexinfo := range indexinfos {
		log.Printf("Try Finding Existing Engine for Index %v", indexinfo)
		switch indexinfo.Using {
		case api.LevelDB:
			engineMap[indexinfo.Uuid] = leveldb.OpenIndexEngine(indexinfo.Uuid)
			log.Printf("Got Existing Engine for Index %v", indexinfo.Uuid)
		default:
			err = errors.New(fmt.Sprintf("Unknown Index Type. Skipping Opening Engine"))
		}
	}

	return err

}

func freeResourcesOnExit() {

	//purge the catalog
	if err := c.Purge(); err != nil {
		log.Printf("Error Purging Catalog %v", err)
	}

	//close the index engines
	if err := closeIndexEngines(); err != nil {
		log.Printf("Error Closing Index Engine %v", err)
	}

	//FIXME close the mutation manager?

}

func closeIndexEngines() error {

	if _, indexinfos, err := c.List(""); err == nil {

		for _, indexinfo := range indexinfos {
			if err := engineMap[indexinfo.Uuid].Close(); err != nil {
				return err
			}
		}
	} else {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2017 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package integration

import (
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"math/rand"
	"os"
	"time"

	"google.golang.org/api/container/v1"
	"google.golang.org/api/option"

	"golang.org/x/net/context"
)

const gceClusterStatusRunning = "RUNNING"

var zone = os.Getenv("GCE_ZONE")
var projectID = os.Getenv("GCE_PROJECT_ID")
var serviceAccount = os.Getenv("GCE_SERVICE_ACCOUNT")

// GceClusterManager represents a Google Compute Engine cluster (Container Engine)
type GceClusterManager struct {
	env         *Environment
	client      *gceClient
	clusterName string
	cluster     *container.Cluster
}

func newClusterName() string {
	return fmt.Sprintf("integration-test-%d", randInt())
}

func randInt() int {
	rand.Seed(time.Now().UnixNano())
	return rand.Int()
}

func createTempFile(data []byte, prefix string) (string, error) {
	tmpfile, err := ioutil.TempFile("", prefix)
	if err != nil {
		return "", err
	}
	if _, err := tmpfile.Write(data); err != nil {
		return "", err
	}
	if err := tmpfile.Close(); err != nil {
		return "", err
	}
	return tmpfile.Name(), nil
}

func (g *GceClusterManager) Name() string {
	return "gce"
}

func (g *GceClusterManager) Provisioner() string {
	return "kubernetes"
}

func (g *GceClusterManager) IP() string {
	g.fetchClusterData()
	if g.cluster != nil {
		return g.cluster.Endpoint
	}
	return ""
}

func (g *GceClusterManager) Start() *Result {
	ctx := context.Background()
	serviceAccountFile, err := createTempFile([]byte(serviceAccount), "gce-sa-")
	if err != nil {
		return &Result{ExitCode: 1, Error: fmt.Errorf("[gce] error creating service account file: %s", err)}
	}
	client, err := newClient(ctx, projectID, option.WithServiceAccountFile(serviceAccountFile))
	if err != nil {
		return &Result{ExitCode: 1, Error: fmt.Errorf("[gce] error creating client: %s", err)}
	}
	g.client = client
	g.clusterName = g.env.Get("clustername")
	if g.clusterName == "" {
		g.clusterName = newClusterName()
		g.env.Set("clustername", g.clusterName)
		if g.env.VerboseLevel() > 0 {
			fmt.Fprintf(safeStdout, "[gce] starting cluster %s in zone %s\n", g.clusterName, zone)
		}
		g.client.createCluster(g.clusterName, zone, 1)
	} else {
		g.fetchClusterData()
		if g.cluster == nil || g.cluster.Status != gceClusterStatusRunning {
			return &Result{ExitCode: 1, Error: fmt.Errorf("[gce] cluster %s is not running", g.clusterName)}
		}
	}
	return &Result{ExitCode: 0}
}

func (g *GceClusterManager) Delete() *Result {
	if g.clusterName == "" {
		return &Result{ExitCode: 1, Error: fmt.Errorf("[gce] cluster name undefined")}
	}
	if g.env.VerboseLevel() > 0 {
		fmt.Fprintf(safeStdout, "[gce] deleting cluster %s in zone %s\n", g.clusterName, zone)
	}
	g.client.deleteCluster(g.cluster.Name, zone)
	return &Result{ExitCode: 0}
}

func (g *GceClusterManager) fetchClusterData() {
	if g.cluster != nil && g.cluster.Status == gceClusterStatusRunning {
		return
	}
	retries := 20
	sleepTime := 20 * time.Second
	for i := 0; i < retries; i++ {
		cluster, err := g.client.describeCluster(g.clusterName, zone)
		if err != nil {
			if g.env.VerboseLevel() > 0 {
				fmt.Fprintf(safeStdout, "[gce] error fetching cluster %s: %s\n", g.clusterName, err)
			}
			return
		}
		if cluster.Status == gceClusterStatusRunning {
			g.cluster = cluster
			if g.env.VerboseLevel() > 0 {
				fmt.Fprintf(safeStdout, "[gce] cluster %s is running. Endpoint: %s\n", g.clusterName, cluster.Endpoint)
			}
			return
		}
		if g.env.VerboseLevel() > 0 {
			fmt.Fprintf(safeStdout, "[gce] cluster %s status: %s\n", g.clusterName, cluster.Status)
		}
		time.Sleep(sleepTime)
	}
}

func (g *GceClusterManager) credentials() (map[string]string, error) {
	g.fetchClusterData()
	if g.cluster == nil {
		return nil, fmt.Errorf("cluster unavailable")
	}
	credentials := make(map[string]string)
	credentials["username"] = g.cluster.MasterAuth.Username
	credentials["password"] = g.cluster.MasterAuth.Password
	contents, err := base64.StdEncoding.DecodeString(g.cluster.MasterAuth.ClusterCaCertificate)
	if err != nil {
		return credentials, err
	}
	filename, err := createTempFile(contents, "gce-ca-")
	if err != nil {
		return credentials, err
	}
	credentials["certificateFilename"] = filename
	return credentials, nil
}

func (g *GceClusterManager) UpdateParams() []string {
	address := fmt.Sprintf("https://%s", g.IP())
	credentials, err := g.credentials()
	if err != nil {
		return []string{}
	}
	return []string{
		"--addr", address,
		"--custom", "username=" + credentials["username"],
		"--custom", "password=" + credentials["password"],
		"--cacert", credentials["certificateFilename"],
	}
}
<commit_msg>integration: keep cluster if it already existed before<commit_after>// Copyright 2017 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package integration

import (
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"math/rand"
	"os"
	"time"

	"google.golang.org/api/container/v1"
	"google.golang.org/api/option"

	"golang.org/x/net/context"
)

const gceClusterStatusRunning = "RUNNING"

var zone = os.Getenv("GCE_ZONE")
var projectID = os.Getenv("GCE_PROJECT_ID")
var serviceAccount = os.Getenv("GCE_SERVICE_ACCOUNT")

// GceClusterManager represents a Google Compute Engine cluster (Container Engine)
type GceClusterManager struct {
	env         *Environment
	client      *gceClient
	clusterName string
	cluster     *container.Cluster
}

func newClusterName() string {
	return fmt.Sprintf("integration-test-%d", randInt())
}

func randInt() int {
	rand.Seed(time.Now().UnixNano())
	return rand.Int()
}

func createTempFile(data []byte, prefix string) (string, error) {
	tmpfile, err := ioutil.TempFile("", prefix)
	if err != nil {
		return "", err
	}
	if _, err := tmpfile.Write(data); err != nil {
		return "", err
	}
	if err := tmpfile.Close(); err != nil {
		return "", err
	}
	return tmpfile.Name(), nil
}

func (g *GceClusterManager) Name() string {
	return "gce"
}

func (g *GceClusterManager) Provisioner() string {
	return "kubernetes"
}

func (g *GceClusterManager) IP() string {
	g.fetchClusterData()
	if g.cluster != nil {
		return g.cluster.Endpoint
	}
	return ""
}

func (g *GceClusterManager) Start() *Result {
	ctx := context.Background()
	serviceAccountFile, err := createTempFile([]byte(serviceAccount), "gce-sa-")
	if err != nil {
		return &Result{ExitCode: 1, Error: fmt.Errorf("[gce] error creating service account file: %s", err)}
	}
	client, err := newClient(ctx, projectID, option.WithServiceAccountFile(serviceAccountFile))
	if err != nil {
		return &Result{ExitCode: 1, Error: fmt.Errorf("[gce] error creating client: %s", err)}
	}
	g.client = client
	g.clusterName = g.env.Get("clustername")
	if g.clusterName == "" {
		g.clusterName = newClusterName()
		if g.env.VerboseLevel() > 0 {
			fmt.Fprintf(safeStdout, "[gce] starting cluster %s in zone %s\n", g.clusterName, zone)
		}
		g.client.createCluster(g.clusterName, zone, 1)
	} else {
		g.fetchClusterData()
		if g.cluster == nil || g.cluster.Status != gceClusterStatusRunning {
			return &Result{ExitCode: 1, Error: fmt.Errorf("[gce] cluster %s is not running", g.clusterName)}
		}
	}
	return &Result{ExitCode: 0}
}

func (g *GceClusterManager) Delete() *Result {
	if g.env.Get("clustername") == "" {
		return &Result{ExitCode: 0}
	}
	if g.env.VerboseLevel() > 0 {
		fmt.Fprintf(safeStdout, "[gce] deleting cluster %s in zone %s\n", g.clusterName, zone)
	}
	g.client.deleteCluster(g.cluster.Name, zone)
	return &Result{ExitCode: 0}
}

func (g *GceClusterManager) fetchClusterData() {
	if g.cluster != nil && g.cluster.Status == gceClusterStatusRunning {
		return
	}
	retries := 20
	sleepTime := 20 * time.Second
	for i := 0; i < retries; i++ {
		cluster, err := g.client.describeCluster(g.clusterName, zone)
		if err != nil {
			if g.env.VerboseLevel() > 0 {
				fmt.Fprintf(safeStdout, "[gce] error fetching cluster %s: %s\n", g.clusterName, err)
			}
			return
		}
		if cluster.Status == gceClusterStatusRunning {
			g.cluster = cluster
			if g.env.VerboseLevel() > 0 {
				fmt.Fprintf(safeStdout, "[gce] cluster %s is running. Endpoint: %s\n", g.clusterName, cluster.Endpoint)
			}
			return
		}
		if g.env.VerboseLevel() > 0 {
			fmt.Fprintf(safeStdout, "[gce] cluster %s status: %s\n", g.clusterName, cluster.Status)
		}
		time.Sleep(sleepTime)
	}
}

func (g *GceClusterManager) credentials() (map[string]string, error) {
	g.fetchClusterData()
	if g.cluster == nil {
		return nil, fmt.Errorf("cluster unavailable")
	}
	credentials := make(map[string]string)
	credentials["username"] = g.cluster.MasterAuth.Username
	credentials["password"] = g.cluster.MasterAuth.Password
	contents, err := base64.StdEncoding.DecodeString(g.cluster.MasterAuth.ClusterCaCertificate)
	if err != nil {
		return credentials, err
	}
	filename, err := createTempFile(contents, "gce-ca-")
	if err != nil {
		return credentials, err
	}
	credentials["certificateFilename"] = filename
	return credentials, nil
}

func (g *GceClusterManager) UpdateParams() []string {
	address := fmt.Sprintf("https://%s", g.IP())
	credentials, err := g.credentials()
	if err != nil {
		return []string{}
	}
	return []string{
		"--addr", address,
		"--custom", "username=" + credentials["username"],
		"--custom", "password=" + credentials["password"],
		"--cacert", credentials["certificateFilename"],
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.

package v4

import (
	"fmt"
	"net/http"
	"net/url"

	"gopkg.in/juju/charm.v2"
	"labix.org/v2/mgo/bson"

	"github.com/juju/charmstore/internal/charmstore"
	"github.com/juju/charmstore/internal/mongodoc"
	"github.com/juju/charmstore/internal/router"
	"github.com/juju/charmstore/params"
)

type handler struct {
	*router.Router
	store *charmstore.Store
}

// New returns a new instance of the v4 API handler.
func New(store *charmstore.Store) http.Handler {
	h := &handler{
		store: store,
	}
	h.Router = router.New(&router.Handlers{
		Global: map[string]http.Handler{
			"stats/counter":      http.HandlerFunc(h.serveStatsCounter),
			"search":             http.HandlerFunc(h.serveSearch),
			"search/interesting": http.HandlerFunc(h.serveSearchInteresting),
			"debug":              http.HandlerFunc(h.serveDebug),
		},
		Id: map[string]router.IdHandler{
			"resources": h.serveResources,
			"archive":   h.serveArchive,
			"archive/":  h.serveArchiveFile,
			"expand-id": h.serveExpandId,
		},
		Meta: map[string]router.BulkIncludeHandler{
			"charm-metadata":  h.entityHandler(h.metaCharmMetadata, "charmmeta"),
			"bundle-metadata": h.entityHandler(h.metaBundleMetadata, "bundledata"),
			"charm-config":    h.entityHandler(h.metaCharmConfig, "charmconfig"),

			// endpoints not yet implemented - use SingleIncludeHandler for the time being.
			"manifest":            router.SingleIncludeHandler(h.metaManifest),
			"charm-actions":       router.SingleIncludeHandler(h.metaCharmActions),
			"color":               router.SingleIncludeHandler(h.metaColor),
			"archive-size":        router.SingleIncludeHandler(h.metaArchiveSize),
			"bundles-containing":  router.SingleIncludeHandler(h.metaBundlesContaining),
			"extra-info":          router.SingleIncludeHandler(h.metaExtraInfo),
			"extra-info/":         router.SingleIncludeHandler(h.metaExtraInfoWithKey),
			"charm-related":       router.SingleIncludeHandler(h.metaCharmRelated),
			"archive-upload-time": router.SingleIncludeHandler(h.metaArchiveUploadTime),
		},
	}, h.resolveURL)
	return h
}

// ResolveURL resolves the series and revision of the given URL
// if either is unspecified by filling them out with information retrieved
// from the store.
func ResolveURL(store *charmstore.Store, url *charm.URL) error {
	if url.Series != "" && url.Revision != -1 {
		return nil
	}
	urls, err := store.ExpandURL(url)
	if err != nil {
		return err
	}
	if len(urls) == 0 {
		return fmt.Errorf("no matching charm or bundle for %q", url)
	}
	*url = *selectPreferredURL(urls)
	return nil
}

func (h *handler) resolveURL(url *charm.URL) error {
	return ResolveURL(h.store, url)
}

type entityHandlerFunc func(entity *mongodoc.Entity, id *charm.URL, path string, flags url.Values) (interface{}, error)

// entityHandler returns a handler that calls f with a *mongodoc.Entity that
// contains at least the given fields.
func (h *handler) entityHandler(f entityHandlerFunc, fields ...string) router.BulkIncludeHandler {
	handle := func(doc interface{}, id *charm.URL, path string, flags url.Values) (interface{}, error) {
		edoc := doc.(*mongodoc.Entity)
		return f(edoc, id, path, flags)
	}
	type entityHandlerKey struct{}
	return router.FieldIncludeHandler(
		entityHandlerKey{},
		h.entityQuery,
		fields,
		handle,
	)
}

func (h *handler) entityQuery(id *charm.URL, selector map[string]int) (interface{}, error) {
	var val mongodoc.Entity
	err := h.store.DB.Entities().
		Find(bson.D{{"_id", id}}).
		Select(selector).
		One(&val)
	if err != nil {
		return nil, err
	}
	return &val, nil
}

var ltsReleases = map[string]bool{
	"lucid":   true,
	"precise": true,
	"trusty":  true,
}

func selectPreferredURL(urls []*charm.URL) *charm.URL {
	best := urls[0]
	for _, url := range urls {
		if preferredURL(url, best) {
			best = url
		}
	}
	return best
}

// preferredURL reports whether url0 is preferred over url1.
func preferredURL(url0, url1 *charm.URL) bool {
	if url0.Series == url1.Series {
		return url0.Revision > url1.Revision
	}
	if url0.Series == "bundle" || url1.Series == "bundle" {
		// One of the URLs refers to a bundle. Choose
		// a charm by preference.
		return url0.Series != "bundle"
	}
	if ltsReleases[url0.Series] == ltsReleases[url1.Series] {
		return url0.Series > url1.Series
	}
	return ltsReleases[url0.Series]
}

var ErrMetadataNotRelevant = fmt.Errorf("metadata not relevant for the given entity")

var errNotImplemented = fmt.Errorf("method not implemented")

// GET stats/counter/key[:key]...?[by=unit]&start=date][&stop=date][&list=1]
// http://tinyurl.com/nkdovcf
func (h *handler) serveStatsCounter(w http.ResponseWriter, req *http.Request) {
	router.WriteError(w, errNotImplemented)
}

// GET search[?text=text][&autocomplete=1][&filter=value…][&limit=limit][&include=meta]
// http://tinyurl.com/qzobc69
func (h *handler) serveSearch(w http.ResponseWriter, req *http.Request) {
	router.WriteError(w, errNotImplemented)
}

// GET search/interesting[?limit=limit][&include=meta]
// http://tinyurl.com/ntmdrg8
func (h *handler) serveSearchInteresting(w http.ResponseWriter, req *http.Request) {
	router.WriteError(w, errNotImplemented)
}

// GET /debug
// http://tinyurl.com/m63xhz8
func (h *handler) serveDebug(w http.ResponseWriter, req *http.Request) {
	router.WriteError(w, errNotImplemented)
}

// POST id/resources/name.stream
// http://tinyurl.com/pnmwvy4
//
// GET  id/resources/name.stream[-revision]/arch/filename
// http://tinyurl.com/pydbn3u
//
// PUT id/resources/[~user/]series/name.stream-revision/arch?sha256=hash
// http://tinyurl.com/k8l8kdg
func (h *handler) serveResources(charmId *charm.URL, w http.ResponseWriter, req *http.Request) error {
	return errNotImplemented
}

// GET id/expand-id
// https://docs.google.com/a/canonical.com/document/d/1TgRA7jW_mmXoKH3JiwBbtPvQu7WiM6XMrz1wSrhTMXw/edit#bookmark=id.4xdnvxphb2si
func (h *handler) serveExpandId(charmId *charm.URL, w http.ResponseWriter, req *http.Request) error {
	return errNotImplemented
}

// GET id/archive
// http://tinyurl.com/qjrwq53
//
// POST id/archive?sha256=hash
// http://tinyurl.com/lzrzrgb
func (h *handler) serveArchive(charmId *charm.URL, w http.ResponseWriter, req *http.Request) error {
	return errNotImplemented
}

// GET id/archive/…
// http://tinyurl.com/lampm24
func (h *handler) serveArchiveFile(charmId *charm.URL, w http.ResponseWriter, req *http.Request) error {
	return errNotImplemented
}

// GET id/meta/charm-metadata
// http://tinyurl.com/poeoulw
func (h *handler) metaCharmMetadata(entity *mongodoc.Entity, id *charm.URL, path string, flags url.Values) (interface{}, error) {
	if params.IsBundle(id) {
		return nil, ErrMetadataNotRelevant
	}
	return entity.CharmMeta, nil
}

// GET id/meta/bundle-metadata
// http://tinyurl.com/ozshbtb
func (h *handler) metaBundleMetadata(entity *mongodoc.Entity, id *charm.URL, path string, flags url.Values) (interface{}, error) {
	if !params.IsBundle(id) {
		return nil, ErrMetadataNotRelevant
	}
	return entity.BundleData, nil
}

// GET id/meta/manifest
// http://tinyurl.com/p3xdcto
func (h *handler) metaManifest(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/charm-actions
// http://tinyurl.com/kfd2h34
func (h *handler) metaCharmActions(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/charm-config
// http://tinyurl.com/oxxyujx
func (h *handler) metaCharmConfig(entity *mongodoc.Entity, id *charm.URL, path string, flags url.Values) (interface{}, error) {
	if params.IsBundle(id) {
		return nil, ErrMetadataNotRelevant
	}
	return entity.CharmConfig, nil
}

// GET id/meta/color
// http://tinyurl.com/o2t3j4p
func (h *handler) metaColor(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/archive-size
// http://tinyurl.com/m8b9geq
func (h *handler) metaArchiveSize(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/stats/
// http://tinyurl.com/lvyp2l5
func (h *handler) metaStats(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/bundles-containing[?include=meta[&include=meta…]]
// http://tinyurl.com/oqc386r
func (h *handler) metaBundlesContaining(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/extra-info
// http://tinyurl.com/keos7wd
func (h *handler) metaExtraInfo(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/extra-info/key
// http://tinyurl.com/polrbn7
func (h *handler) metaExtraInfoWithKey(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/charm-related[?include=meta[&include=meta…]]
// http://tinyurl.com/q7vdmzl
func (h *handler) metaCharmRelated(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/archive-upload-time
// http://tinyurl.com/nmujuqk
func (h *handler) metaArchiveUploadTime(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}
<commit_msg>* new version of charm actions implementation<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.

package v4

import (
	"fmt"
	"net/http"
	"net/url"

	"gopkg.in/juju/charm.v2"
	"labix.org/v2/mgo/bson"

	"github.com/juju/charmstore/internal/charmstore"
	"github.com/juju/charmstore/internal/mongodoc"
	"github.com/juju/charmstore/internal/router"
	"github.com/juju/charmstore/params"
)

type handler struct {
	*router.Router
	store *charmstore.Store
}

// New returns a new instance of the v4 API handler.
func New(store *charmstore.Store) http.Handler {
	h := &handler{
		store: store,
	}
	h.Router = router.New(&router.Handlers{
		Global: map[string]http.Handler{
			"stats/counter":      http.HandlerFunc(h.serveStatsCounter),
			"search":             http.HandlerFunc(h.serveSearch),
			"search/interesting": http.HandlerFunc(h.serveSearchInteresting),
			"debug":              http.HandlerFunc(h.serveDebug),
		},
		Id: map[string]router.IdHandler{
			"resources": h.serveResources,
			"archive":   h.serveArchive,
			"archive/":  h.serveArchiveFile,
			"expand-id": h.serveExpandId,
		},
		Meta: map[string]router.BulkIncludeHandler{
			"charm-metadata":  h.entityHandler(h.metaCharmMetadata, "charmmeta"),
			"bundle-metadata": h.entityHandler(h.metaBundleMetadata, "bundledata"),
			"charm-config":    h.entityHandler(h.metaCharmConfig, "charmconfig"),
			"charm-actions":   h.entityHandler(h.metaCharmActions, "charmactions"),

			// endpoints not yet implemented - use SingleIncludeHandler for the time being.
			"manifest":            router.SingleIncludeHandler(h.metaManifest),
			"color":               router.SingleIncludeHandler(h.metaColor),
			"archive-size":        router.SingleIncludeHandler(h.metaArchiveSize),
			"bundles-containing":  router.SingleIncludeHandler(h.metaBundlesContaining),
			"extra-info":          router.SingleIncludeHandler(h.metaExtraInfo),
			"extra-info/":         router.SingleIncludeHandler(h.metaExtraInfoWithKey),
			"charm-related":       router.SingleIncludeHandler(h.metaCharmRelated),
			"archive-upload-time": router.SingleIncludeHandler(h.metaArchiveUploadTime),
		},
	}, h.resolveURL)
	return h
}

// ResolveURL resolves the series and revision of the given URL
// if either is unspecified by filling them out with information retrieved
// from the store.
func ResolveURL(store *charmstore.Store, url *charm.URL) error {
	if url.Series != "" && url.Revision != -1 {
		return nil
	}
	urls, err := store.ExpandURL(url)
	if err != nil {
		return err
	}
	if len(urls) == 0 {
		return fmt.Errorf("no matching charm or bundle for %q", url)
	}
	*url = *selectPreferredURL(urls)
	return nil
}

func (h *handler) resolveURL(url *charm.URL) error {
	return ResolveURL(h.store, url)
}

type entityHandlerFunc func(entity *mongodoc.Entity, id *charm.URL, path string, flags url.Values) (interface{}, error)

// entityHandler returns a handler that calls f with a *mongodoc.Entity that
// contains at least the given fields.
func (h *handler) entityHandler(f entityHandlerFunc, fields ...string) router.BulkIncludeHandler {
	handle := func(doc interface{}, id *charm.URL, path string, flags url.Values) (interface{}, error) {
		edoc := doc.(*mongodoc.Entity)
		return f(edoc, id, path, flags)
	}
	type entityHandlerKey struct{}
	return router.FieldIncludeHandler(
		entityHandlerKey{},
		h.entityQuery,
		fields,
		handle,
	)
}

func (h *handler) entityQuery(id *charm.URL, selector map[string]int) (interface{}, error) {
	var val mongodoc.Entity
	err := h.store.DB.Entities().
		Find(bson.D{{"_id", id}}).
		Select(selector).
		One(&val)
	if err != nil {
		return nil, err
	}
	return &val, nil
}

var ltsReleases = map[string]bool{
	"lucid":   true,
	"precise": true,
	"trusty":  true,
}

func selectPreferredURL(urls []*charm.URL) *charm.URL {
	best := urls[0]
	for _, url := range urls {
		if preferredURL(url, best) {
			best = url
		}
	}
	return best
}

// preferredURL reports whether url0 is preferred over url1.
func preferredURL(url0, url1 *charm.URL) bool {
	if url0.Series == url1.Series {
		return url0.Revision > url1.Revision
	}
	if url0.Series == "bundle" || url1.Series == "bundle" {
		// One of the URLs refers to a bundle. Choose
		// a charm by preference.
		return url0.Series != "bundle"
	}
	if ltsReleases[url0.Series] == ltsReleases[url1.Series] {
		return url0.Series > url1.Series
	}
	return ltsReleases[url0.Series]
}

var ErrMetadataNotRelevant = fmt.Errorf("metadata not relevant for the given entity")

var errNotImplemented = fmt.Errorf("method not implemented")

// GET stats/counter/key[:key]...?[by=unit]&start=date][&stop=date][&list=1]
// http://tinyurl.com/nkdovcf
func (h *handler) serveStatsCounter(w http.ResponseWriter, req *http.Request) {
	router.WriteError(w, errNotImplemented)
}

// GET search[?text=text][&autocomplete=1][&filter=value…][&limit=limit][&include=meta]
// http://tinyurl.com/qzobc69
func (h *handler) serveSearch(w http.ResponseWriter, req *http.Request) {
	router.WriteError(w, errNotImplemented)
}

// GET search/interesting[?limit=limit][&include=meta]
// http://tinyurl.com/ntmdrg8
func (h *handler) serveSearchInteresting(w http.ResponseWriter, req *http.Request) {
	router.WriteError(w, errNotImplemented)
}

// GET /debug
// http://tinyurl.com/m63xhz8
func (h *handler) serveDebug(w http.ResponseWriter, req *http.Request) {
	router.WriteError(w, errNotImplemented)
}

// POST id/resources/name.stream
// http://tinyurl.com/pnmwvy4
//
// GET  id/resources/name.stream[-revision]/arch/filename
// http://tinyurl.com/pydbn3u
//
// PUT id/resources/[~user/]series/name.stream-revision/arch?sha256=hash
// http://tinyurl.com/k8l8kdg
func (h *handler) serveResources(charmId *charm.URL, w http.ResponseWriter, req *http.Request) error {
	return errNotImplemented
}

// GET id/expand-id
// https://docs.google.com/a/canonical.com/document/d/1TgRA7jW_mmXoKH3JiwBbtPvQu7WiM6XMrz1wSrhTMXw/edit#bookmark=id.4xdnvxphb2si
func (h *handler) serveExpandId(charmId *charm.URL, w http.ResponseWriter, req *http.Request) error {
	return errNotImplemented
}

// GET id/archive
// http://tinyurl.com/qjrwq53
//
// POST id/archive?sha256=hash
// http://tinyurl.com/lzrzrgb
func (h *handler) serveArchive(charmId *charm.URL, w http.ResponseWriter, req *http.Request) error {
	return errNotImplemented
}

// GET id/archive/…
// http://tinyurl.com/lampm24
func (h *handler) serveArchiveFile(charmId *charm.URL, w http.ResponseWriter, req *http.Request) error {
	return errNotImplemented
}

// GET id/meta/charm-metadata
// http://tinyurl.com/poeoulw
func (h *handler) metaCharmMetadata(entity *mongodoc.Entity, id *charm.URL, path string, flags url.Values) (interface{}, error) {
	if params.IsBundle(id) {
		return nil, ErrMetadataNotRelevant
	}
	return entity.CharmMeta, nil
}

// GET id/meta/bundle-metadata
// http://tinyurl.com/ozshbtb
func (h *handler) metaBundleMetadata(entity *mongodoc.Entity, id *charm.URL, path string, flags url.Values) (interface{}, error) {
	if !params.IsBundle(id) {
		return nil, ErrMetadataNotRelevant
	}
	return entity.BundleData, nil
}

// GET id/meta/manifest
// http://tinyurl.com/p3xdcto
func (h *handler) metaManifest(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/charm-actions
// http://tinyurl.com/kfd2h34
func (h *handler) metaCharmActions(entity *mongodoc.Entity, id *charm.URL, path string, flags url.Values) (interface{}, error) {
	if params.IsBundle(id) {
		return nil, ErrMetadataNotRelevant
	}
	return entity.CharmActions, nil
}

// GET id/meta/charm-config
// http://tinyurl.com/oxxyujx
func (h *handler) metaCharmConfig(entity *mongodoc.Entity, id *charm.URL, path string, flags url.Values) (interface{}, error) {
	if params.IsBundle(id) {
		return nil, ErrMetadataNotRelevant
	}
	return entity.CharmConfig, nil
}

// GET id/meta/color
// http://tinyurl.com/o2t3j4p
func (h *handler) metaColor(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/archive-size
// http://tinyurl.com/m8b9geq
func (h *handler) metaArchiveSize(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/stats/
// http://tinyurl.com/lvyp2l5
func (h *handler) metaStats(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/bundles-containing[?include=meta[&include=meta…]]
// http://tinyurl.com/oqc386r
func (h *handler) metaBundlesContaining(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/extra-info
// http://tinyurl.com/keos7wd
func (h *handler) metaExtraInfo(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/extra-info/key
// http://tinyurl.com/polrbn7
func (h *handler) metaExtraInfoWithKey(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/charm-related[?include=meta[&include=meta…]]
// http://tinyurl.com/q7vdmzl
func (h *handler) metaCharmRelated(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}

// GET id/meta/archive-upload-time
// http://tinyurl.com/nmujuqk
func (h *handler) metaArchiveUploadTime(id *charm.URL, path string, flags url.Values) (interface{}, error) {
	return nil, errNotImplemented
}
<|endoftext|>


<commit_before>// Copyright © 2016 Roberto De Sousa (https://github.com/rodesousa) / Patrick Tavares (https://github.com/ptavares)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package shard provides ...
package shard

import (
	"os/exec"
)

func getExpected(shard *Shard) bool {
	if val, ok := shard.Args["expected"]; ok {
		return val.(bool)
	}
	return true
}

func (s *Shard) Cmd() bool {
	status, error := exeCmd(s.Command, s.Args["name"].(string))
	if getExpected(s) != status {
		s.Status.Err = error
		s.Status.Check = false
	}
	return s.Status.Check
}

type FnEmpty func() string

func (shard *Shard) Do(fn FnEmpty) string {
	return fn()
}

func exeCmd(cmd string, arg string) (bool, error) {
	var out []byte
	var err error

	// One args or more
	out, err = exec.Command(cmd, arg).Output()

	if out != nil { //TODO
	}

	if err != nil {
		return false, err
	} else {
		return true, err
	}
}
<commit_msg>change class method<commit_after>// Copyright © 2016 Roberto De Sousa (https://github.com/rodesousa) / Patrick Tavares (https://github.com/ptavares)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package shard provides ...
package shard

import (
	"os/exec"
)

func getExpected(shard *Shard) bool {
	if val, ok := shard.Args["expected"]; ok {
		return val.(bool)
	}
	return true
}

func (s *Shard) Cmd() bool {
	status, error := s.exeCmd()
	if getExpected(s) != status {
		s.Status.Err = error
		s.Status.Check = false
	}
	return s.Status.Check
}

type FnEmpty func() string

func (shard *Shard) Do(fn FnEmpty) string {
	return fn()
}

func (s Shard) exeCmd() (bool, error) {
	var out []byte
	var err error

	// One args or more
	out, err = exec.Command(s.Command, s.CommandArguments).Output()

	if out != nil { //TODO
	}

	if err != nil {
		return false, err
	} else {
		return true, err
	}
}
<|endoftext|>


<commit_before>package kloud

import (
	"fmt"
	"strconv"
)

const (
	ErrAlreadyInitialized  = 101
	ErrNotInitialized      = 102
	ErrUnknownState        = 103
	ErrBuilding            = 104
	ErrMachineIdMissing    = 107
	ErrProviderNotFound    = 108
	ErrNoKiteConnection    = 109
	ErrMachineTerminating  = 110
	ErrMachinePendingEvent = 111

	ErrEventNotFound    = 201
	ErrEventIdMissing   = 202
	ErrEventTypeMissing = 203
	ErrEventArgsEmpty   = 204

	ErrSignUsernameEmpty   = 301
	ErrSignKontrolURLEmpty = 302
	ErrSignPrivateKeyEmpty = 303
	ErrSignPublicKeyEmpty  = 304
	ErrSignGenerateToken   = 305
)

var errors = map[int]string{
	ErrAlreadyInitialized:  "Machine is already initialized and prepared.",
	ErrNotInitialized:      "Machine is not initialized.",
	ErrUnknownState:        "Machine is in unknown state. Please contact support.",
	ErrBuilding:            "Machine is being build. Hold on.",
	ErrMachineIdMissing:    "Machine id is missing.",
	ErrProviderNotFound:    "Provider is not found",
	ErrNoKiteConnection:    "Couldn't connect to remote klient kite",
	ErrMachineTerminating:  "Machine is terminated.",
	ErrMachinePendingEvent: "MachineId has a pending event going on",

	// Event errors
	ErrEventIdMissing:   "Event id is missing.",
	ErrEventTypeMissing: "Event type is missing.",
	ErrEventNotFound:    "Event not found.",
	ErrEventArgsEmpty:   "Event arguments is empty, expecting an array.",

	// Signer errors
	ErrSignUsernameEmpty:   "Username is empty",
	ErrSignKontrolURLEmpty: "Kontrol URL is empty",
	ErrSignPrivateKeyEmpty: "Private key is empty",
	ErrSignPublicKeyEmpty:  "Public key is empty",
	ErrSignGenerateToken:   "Cannot generate token",
}

type Error struct {
	Message string `json:"message"`
	Code    int    `json:"code"`
}

func (e Error) Error() string {
	return e.Message + " (error code: " + strconv.Itoa(e.Code) + ")"
}

func NewError(errorCode int) *Error {
	errMsg, ok := errors[errorCode]
	if !ok {
		panic(fmt.Sprintf("no message is defined for error code %s", errorCode))
	}

	return &Error{
		Message: errMsg,
		Code:    errorCode,
	}
}
<commit_msg>kloud: improve errors and use kite.Error to send better error messages to client<commit_after>package kloud

import (
	"fmt"
	"strconv"

	"github.com/koding/kite"
)

const (
	ErrAlreadyInitialized  = 101
	ErrNotInitialized      = 102
	ErrUnknownState        = 103
	ErrBuilding            = 104
	ErrMachineIdMissing    = 107
	ErrProviderNotFound    = 108
	ErrNoKiteConnection    = 109
	ErrMachineTerminating  = 110
	ErrMachinePendingEvent = 111

	ErrEventNotFound    = 201
	ErrEventIdMissing   = 202
	ErrEventTypeMissing = 203
	ErrEventArgsEmpty   = 204

	ErrSignUsernameEmpty   = 301
	ErrSignKontrolURLEmpty = 302
	ErrSignPrivateKeyEmpty = 303
	ErrSignPublicKeyEmpty  = 304
	ErrSignGenerateToken   = 305
)

var errors = map[int]string{
	ErrAlreadyInitialized:  "Machine is already initialized and prepared.",
	ErrNotInitialized:      "Machine is not initialized.",
	ErrUnknownState:        "Machine is in unknown state. Please contact support.",
	ErrBuilding:            "Machine is being build. Hold on.",
	ErrMachineIdMissing:    "Machine id is missing.",
	ErrProviderNotFound:    "Provider is not found",
	ErrNoKiteConnection:    "Couldn't connect to remote klient kite",
	ErrMachineTerminating:  "Machine is terminated.",
	ErrMachinePendingEvent: "MachineId has a pending event going on",

	// Event errors
	ErrEventIdMissing:   "Event id is missing.",
	ErrEventTypeMissing: "Event type is missing.",
	ErrEventNotFound:    "Event not found.",
	ErrEventArgsEmpty:   "Event arguments is empty, expecting an array.",

	// Signer errors
	ErrSignUsernameEmpty:   "Username is empty",
	ErrSignKontrolURLEmpty: "Kontrol URL is empty",
	ErrSignPrivateKeyEmpty: "Private key is empty",
	ErrSignPublicKeyEmpty:  "Public key is empty",
	ErrSignGenerateToken:   "Cannot generate token",
}

func NewError(errorCode int) *kite.Error {
	errMsg, ok := errors[errorCode]
	if !ok {
		panic(fmt.Sprintf("no message is defined for error code %s", errorCode))
	}

	code := strconv.Itoa(errorCode)

	return &kite.Error{
		Type:    "kloudError",
		Message: errMsg + " (error code: " + code + ")",
		CodeVal: code,
	}
}
<|endoftext|>


<commit_before>package models

import (
	"errors"
	"fmt"
	"socialapi/config"
	"time"

	"github.com/koding/bongo"
)

type ChannelMessage struct {
	// unique identifier of the channel message
	Id int64 `json:"id"`

	// Body of the mesage
	Body string `json:"body"`

	// Generated Slug for body
	Slug string `json:"slug"                        sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// type of the message
	TypeConstant string `json:"typeConstant"        sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// Creator of the channel message
	AccountId int64 `json:"accountId"               sql:"NOT NULL"`

	// in which channel this message is created
	InitialChannelId int64 `json:"initialChannelId" sql:"NOT NULL"`

	// Creation date of the message
	CreatedAt time.Time `json:"createdAt"           sql:"DEFAULT:CURRENT_TIMESTAMP"`

	// Modification date of the message
	UpdatedAt time.Time `json:"updatedAt"           sql:"DEFAULT:CURRENT_TIMESTAMP"`
}

func (c *ChannelMessage) AfterCreate() {
	bongo.B.AfterCreate(c)
}

func (c *ChannelMessage) AfterUpdate() {
	bongo.B.AfterUpdate(c)
}

func (c *ChannelMessage) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *ChannelMessage) GetId() int64 {
	return c.Id
}

func (c ChannelMessage) TableName() string {
	return "api.channel_message"
}

const (
	ChannelMessage_TYPE_POST  = "post"
	ChannelMessage_TYPE_REPLY = "reply"
	ChannelMessage_TYPE_JOIN  = "join"
	ChannelMessage_TYPE_LEAVE = "leave"
	ChannelMessage_TYPE_CHAT  = "chat"
)

func NewChannelMessage() *ChannelMessage {
	return &ChannelMessage{}
}

func (c *ChannelMessage) Fetch() error {
	return bongo.B.Fetch(c)
}

func (c *ChannelMessage) One(q *bongo.Query) error {
	return bongo.B.One(c, c, q)
}

func bodyLenCheck(body string) error {
	if len(body) < config.Get().Limits.MessageBodyMinLen {
		return fmt.Errorf("Message Body Length should be greater than %d, yours is %d ", config.Get().Limits.MessageBodyMinLen, len(body))
	}
	return nil
}

func (c *ChannelMessage) Update() error {
	if err := bodyLenCheck(c.Body); err != nil {
		return err
	}
	// only update body
	err := bongo.B.UpdatePartial(c,
		map[string]interface{}{
			"body": c.Body,
		},
	)
	return err
}

func (c *ChannelMessage) Create() error {
	if err := bodyLenCheck(c.Body); err != nil {
		return err
	}

	var err error
	c, err = Slugify(c)
	if err != nil {
		return err
	}

	return bongo.B.Create(c)
}

func (c *ChannelMessage) Delete() error {
	return bongo.B.Delete(c)
}

func (c *ChannelMessage) FetchByIds(ids []int64) ([]ChannelMessage, error) {
	var messages []ChannelMessage

	if len(ids) == 0 {
		return messages, nil
	}

	if err := bongo.B.FetchByIds(c, &messages, ids); err != nil {
		return nil, err
	}
	return messages, nil
}

func (c *ChannelMessage) FetchRelatives() (*ChannelMessageContainer, error) {
	if c.Id == 0 {
		return nil, errors.New("Channel message id is not set")
	}
	container := NewChannelMessageContainer()
	container.Message = c

	i := NewInteraction()
	i.MessageId = c.Id

	oldId, err := FetchMongoIdByAccountId(c.AccountId)
	if err != nil {
		return nil, err
	}

	container.AccountOldId = oldId

	interactorIds, err := i.List("like")
	if err != nil {
		return nil, err
	}

	oldIds, err := FetchMongoIdsByAccountIds(interactorIds)
	if err != nil {
		return nil, err
	}

	interactionContainer := NewInteractionContainer()
	interactionContainer.Actors = oldIds
	// check this from database
	interactionContainer.IsInteracted = true

	if container.Interactions == nil {
		container.Interactions = make(map[string]*InteractionContainer)
	}
	if _, ok := container.Interactions["like"]; !ok {
		container.Interactions["like"] = NewInteractionContainer()
	}
	container.Interactions["like"] = interactionContainer
	return container, nil
}
<commit_msg>Social: check is interacted from database<commit_after>package models

import (
	"errors"
	"fmt"
	"socialapi/config"
	"time"

	"github.com/koding/bongo"
)

type ChannelMessage struct {
	// unique identifier of the channel message
	Id int64 `json:"id"`

	// Body of the mesage
	Body string `json:"body"`

	// Generated Slug for body
	Slug string `json:"slug"                        sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// type of the message
	TypeConstant string `json:"typeConstant"        sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// Creator of the channel message
	AccountId int64 `json:"accountId"               sql:"NOT NULL"`

	// in which channel this message is created
	InitialChannelId int64 `json:"initialChannelId" sql:"NOT NULL"`

	// Creation date of the message
	CreatedAt time.Time `json:"createdAt"           sql:"DEFAULT:CURRENT_TIMESTAMP"`

	// Modification date of the message
	UpdatedAt time.Time `json:"updatedAt"           sql:"DEFAULT:CURRENT_TIMESTAMP"`
}

func (c *ChannelMessage) AfterCreate() {
	bongo.B.AfterCreate(c)
}

func (c *ChannelMessage) AfterUpdate() {
	bongo.B.AfterUpdate(c)
}

func (c *ChannelMessage) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *ChannelMessage) GetId() int64 {
	return c.Id
}

func (c ChannelMessage) TableName() string {
	return "api.channel_message"
}

const (
	ChannelMessage_TYPE_POST  = "post"
	ChannelMessage_TYPE_REPLY = "reply"
	ChannelMessage_TYPE_JOIN  = "join"
	ChannelMessage_TYPE_LEAVE = "leave"
	ChannelMessage_TYPE_CHAT  = "chat"
)

func NewChannelMessage() *ChannelMessage {
	return &ChannelMessage{}
}

func (c *ChannelMessage) Fetch() error {
	return bongo.B.Fetch(c)
}

func (c *ChannelMessage) One(q *bongo.Query) error {
	return bongo.B.One(c, c, q)
}

func bodyLenCheck(body string) error {
	if len(body) < config.Get().Limits.MessageBodyMinLen {
		return fmt.Errorf("Message Body Length should be greater than %d, yours is %d ", config.Get().Limits.MessageBodyMinLen, len(body))
	}
	return nil
}

func (c *ChannelMessage) Update() error {
	if err := bodyLenCheck(c.Body); err != nil {
		return err
	}
	// only update body
	err := bongo.B.UpdatePartial(c,
		map[string]interface{}{
			"body": c.Body,
		},
	)
	return err
}

func (c *ChannelMessage) Create() error {
	if err := bodyLenCheck(c.Body); err != nil {
		return err
	}

	var err error
	c, err = Slugify(c)
	if err != nil {
		return err
	}

	return bongo.B.Create(c)
}

func (c *ChannelMessage) Delete() error {
	return bongo.B.Delete(c)
}

func (c *ChannelMessage) FetchByIds(ids []int64) ([]ChannelMessage, error) {
	var messages []ChannelMessage

	if len(ids) == 0 {
		return messages, nil
	}

	if err := bongo.B.FetchByIds(c, &messages, ids); err != nil {
		return nil, err
	}
	return messages, nil
}

func (c *ChannelMessage) FetchRelatives() (*ChannelMessageContainer, error) {
	if c.Id == 0 {
		return nil, errors.New("Channel message id is not set")
	}
	container := NewChannelMessageContainer()
	container.Message = c

	i := NewInteraction()
	i.MessageId = c.Id

	oldId, err := FetchMongoIdByAccountId(c.AccountId)
	if err != nil {
		return nil, err
	}

	container.AccountOldId = oldId

	interactorIds, err := i.List("like")
	if err != nil {
		return nil, err
	}

	oldIds, err := FetchMongoIdsByAccountIds(interactorIds)
	if err != nil {
		return nil, err
	}

	interactionContainer := NewInteractionContainer()
	interactionContainer.Actors = oldIds

	isInteracted, err := i.IsInteracted(c.AccountId)
	if err != nil {
		return nil, err
	}

	interactionContainer.IsInteracted = isInteracted

	if container.Interactions == nil {
		container.Interactions = make(map[string]*InteractionContainer)
	}
	if _, ok := container.Interactions["like"]; !ok {
		container.Interactions["like"] = NewInteractionContainer()
	}
	container.Interactions["like"] = interactionContainer
	return container, nil
}
<|endoftext|>


<commit_before>// Copyright 2014 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// Author: Peter Mattis (peter@cockroachlabs.com)

package engine

import (
	"github.com/cockroachdb/cockroach/util/hlc"
)

const (
	batchTypeDeletion byte = 0x0
	batchTypeValue         = 0x1
	batchTypeMerge         = 0x2

	// The batch header is composed of an 8-byte sequence number (all zeroes) and
	// 4-byte count of the number of entries in the batch.
	headerSize       int = 12
	initialBatchSize     = 1 << 10
	maxVarintLen32       = 5
)

// A rocksDBBatchBuilder constructs a RocksDB batch representation. From the
// RocksDB code, the representation of a batch is:
//
//   WriteBatch::rep_ :=
//      sequence: fixed64
//      count: fixed32
//      data: record[count]
//   record :=
//      kTypeValue varstring varstring
//      kTypeDeletion varstring
//      kTypeSingleDeletion varstring
//      kTypeMerge varstring varstring
//      kTypeColumnFamilyValue varint32 varstring varstring
//      kTypeColumnFamilyDeletion varint32 varstring varstring
//      kTypeColumnFamilySingleDeletion varint32 varstring varstring
//      kTypeColumnFamilyMerge varint32 varstring varstring
//   varstring :=
//      len: varint32
//      data: uint8[len]
//
// The rocksDBBatchBuilder code currently only supports kTypeValue
// (batchTypeValue), kTypeDeletion (batchTypeDeletion)and kTypeMerge
// (batchTypeMerge) operations. Before a batch is written to the RocksDB
// write-ahead-log, the sequence number is 0. The "fixed32" format is little
// endian.
//
// The keys encoded into the batch or MVCC keys: a string key with a timestamp
// suffix. MVCC keys are encoded as:
//
//   <key>[<wall_time>[<logical>]]<#timestamp-bytes>
//
// The <wall_time> and <logical> portions of the key are encoded as 64 and
// 32-bit big-endian integers. A custom RocksDB comparator is used to maintain
// the desired ordering as these keys do not sort lexicographically
// correctly. Note that the encoding of these keys needs to match up with the
// encoding in rocksdb/db.cc:EncodeKey().
type rocksDBBatchBuilder struct {
	repr  []byte
	count int
}

func (b *rocksDBBatchBuilder) maybeInit() {
	if b.repr == nil {
		b.repr = make([]byte, headerSize, initialBatchSize)
	}
}

// Finish returns the constructed batch representation. After calling Finish,
// the builder may be used to construct another batch, but the returned []byte
// is only valid until the next builder method is called.
func (b *rocksDBBatchBuilder) Finish() []byte {
	buf := b.repr[8:headerSize]
	v := uint32(b.count)
	buf[0] = byte(v)
	buf[1] = byte(v >> 8)
	buf[2] = byte(v >> 16)
	buf[3] = byte(v >> 24)
	repr := b.repr
	b.repr = b.repr[:headerSize]
	b.count = 0
	return repr
}

func (b *rocksDBBatchBuilder) grow(n int) {
	newSize := len(b.repr) + n
	if newSize > cap(b.repr) {
		newCap := 2 * cap(b.repr)
		for newCap < newSize {
			newCap *= 2
		}
		newRepr := make([]byte, len(b.repr), newCap)
		copy(newRepr, b.repr)
		b.repr = newRepr
	}
	b.repr = b.repr[:newSize]
}

func putUvarint32(buf []byte, x uint32) int {
	i := 0
	for x >= 0x80 {
		buf[i] = byte(x) | 0x80
		x >>= 7
		i++
	}
	buf[i] = byte(x)
	return i + 1
}

func putUint32(b []byte, v uint32) {
	b[0] = byte(v >> 24)
	b[1] = byte(v >> 16)
	b[2] = byte(v >> 8)
	b[3] = byte(v)
}

func putUint64(b []byte, v uint64) {
	b[0] = byte(v >> 56)
	b[1] = byte(v >> 48)
	b[2] = byte(v >> 40)
	b[3] = byte(v >> 32)
	b[4] = byte(v >> 24)
	b[5] = byte(v >> 16)
	b[6] = byte(v >> 8)
	b[7] = byte(v)
}

// encodeKey encodes an MVCC key into the batch, reserving extra bytes in
// b.repr for use in encoding a value as well. This encoding must match with
// the encoding in engine/db.cc:EncodeKey().
func (b *rocksDBBatchBuilder) encodeKey(key MVCCKey, extra int) {
	length := 1 + len(key.Key)
	timestampLength := 0
	if key.Timestamp != hlc.ZeroTimestamp {
		timestampLength = 1 + 8
		if key.Timestamp.Logical != 0 {
			timestampLength += 4
		}
	}
	length += timestampLength

	pos := 1 + len(b.repr)
	b.grow(1 + maxVarintLen32 + length + extra)
	n := putUvarint32(b.repr[pos:], uint32(length))
	b.repr = b.repr[:len(b.repr)-(maxVarintLen32-n)]
	pos += n
	copy(b.repr[pos:], key.Key)
	if timestampLength > 0 {
		pos += len(key.Key)
		b.repr[pos] = 0
		pos++
		putUint64(b.repr[pos:], uint64(key.Timestamp.WallTime))
		if key.Timestamp.Logical != 0 {
			pos += 8
			putUint32(b.repr[pos:], uint32(key.Timestamp.Logical))
		}
	}
	b.repr[len(b.repr)-1-extra] = byte(timestampLength)
}

func (b *rocksDBBatchBuilder) encodeKeyValue(key MVCCKey, value []byte, tag byte) {
	b.maybeInit()
	b.count++

	l := uint32(len(value))
	extra := int(l) + maxVarintLen32

	pos := len(b.repr)
	b.encodeKey(key, extra)		//check what this function does with the key!! -Arjun
	b.repr[pos] = tag

	pos = len(b.repr) - extra
	n := putUvarint32(b.repr[pos:], l)
	b.repr = b.repr[:len(b.repr)-(maxVarintLen32-n)]

	if(qualifiedKey(key.String())) {
		_ = createObject(goToECSKey(key), value, key)
	}
	copy(b.repr[pos + n:], value)
}

func (b *rocksDBBatchBuilder) Put(key MVCCKey, value []byte) {
	b.encodeKeyValue(key, value, batchTypeValue)
}

func (b *rocksDBBatchBuilder) Merge(key MVCCKey, value []byte) {
	b.encodeKeyValue(key, value, batchTypeMerge)
}

func (b *rocksDBBatchBuilder) Clear(key MVCCKey) {
	b.maybeInit()
	b.count++
	pos := len(b.repr)
	b.encodeKey(key, 0)
	b.repr[pos] = batchTypeDeletion
}
<commit_msg>removing intents from ECS too. Seek accuracy increased :)<commit_after>// Copyright 2014 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// Author: Peter Mattis (peter@cockroachlabs.com)

package engine

import (
	"github.com/cockroachdb/cockroach/util/hlc"
)

const (
	batchTypeDeletion byte = 0x0
	batchTypeValue         = 0x1
	batchTypeMerge         = 0x2

	// The batch header is composed of an 8-byte sequence number (all zeroes) and
	// 4-byte count of the number of entries in the batch.
	headerSize       int = 12
	initialBatchSize     = 1 << 10
	maxVarintLen32       = 5
)

// A rocksDBBatchBuilder constructs a RocksDB batch representation. From the
// RocksDB code, the representation of a batch is:
//
//   WriteBatch::rep_ :=
//      sequence: fixed64
//      count: fixed32
//      data: record[count]
//   record :=
//      kTypeValue varstring varstring
//      kTypeDeletion varstring
//      kTypeSingleDeletion varstring
//      kTypeMerge varstring varstring
//      kTypeColumnFamilyValue varint32 varstring varstring
//      kTypeColumnFamilyDeletion varint32 varstring varstring
//      kTypeColumnFamilySingleDeletion varint32 varstring varstring
//      kTypeColumnFamilyMerge varint32 varstring varstring
//   varstring :=
//      len: varint32
//      data: uint8[len]
//
// The rocksDBBatchBuilder code currently only supports kTypeValue
// (batchTypeValue), kTypeDeletion (batchTypeDeletion)and kTypeMerge
// (batchTypeMerge) operations. Before a batch is written to the RocksDB
// write-ahead-log, the sequence number is 0. The "fixed32" format is little
// endian.
//
// The keys encoded into the batch or MVCC keys: a string key with a timestamp
// suffix. MVCC keys are encoded as:
//
//   <key>[<wall_time>[<logical>]]<#timestamp-bytes>
//
// The <wall_time> and <logical> portions of the key are encoded as 64 and
// 32-bit big-endian integers. A custom RocksDB comparator is used to maintain
// the desired ordering as these keys do not sort lexicographically
// correctly. Note that the encoding of these keys needs to match up with the
// encoding in rocksdb/db.cc:EncodeKey().
type rocksDBBatchBuilder struct {
	repr  []byte
	count int
}

func (b *rocksDBBatchBuilder) maybeInit() {
	if b.repr == nil {
		b.repr = make([]byte, headerSize, initialBatchSize)
	}
}

// Finish returns the constructed batch representation. After calling Finish,
// the builder may be used to construct another batch, but the returned []byte
// is only valid until the next builder method is called.
func (b *rocksDBBatchBuilder) Finish() []byte {
	buf := b.repr[8:headerSize]
	v := uint32(b.count)
	buf[0] = byte(v)
	buf[1] = byte(v >> 8)
	buf[2] = byte(v >> 16)
	buf[3] = byte(v >> 24)
	repr := b.repr
	b.repr = b.repr[:headerSize]
	b.count = 0
	return repr
}

func (b *rocksDBBatchBuilder) grow(n int) {
	newSize := len(b.repr) + n
	if newSize > cap(b.repr) {
		newCap := 2 * cap(b.repr)
		for newCap < newSize {
			newCap *= 2
		}
		newRepr := make([]byte, len(b.repr), newCap)
		copy(newRepr, b.repr)
		b.repr = newRepr
	}
	b.repr = b.repr[:newSize]
}

func putUvarint32(buf []byte, x uint32) int {
	i := 0
	for x >= 0x80 {
		buf[i] = byte(x) | 0x80
		x >>= 7
		i++
	}
	buf[i] = byte(x)
	return i + 1
}

func putUint32(b []byte, v uint32) {
	b[0] = byte(v >> 24)
	b[1] = byte(v >> 16)
	b[2] = byte(v >> 8)
	b[3] = byte(v)
}

func putUint64(b []byte, v uint64) {
	b[0] = byte(v >> 56)
	b[1] = byte(v >> 48)
	b[2] = byte(v >> 40)
	b[3] = byte(v >> 32)
	b[4] = byte(v >> 24)
	b[5] = byte(v >> 16)
	b[6] = byte(v >> 8)
	b[7] = byte(v)
}

// encodeKey encodes an MVCC key into the batch, reserving extra bytes in
// b.repr for use in encoding a value as well. This encoding must match with
// the encoding in engine/db.cc:EncodeKey().
func (b *rocksDBBatchBuilder) encodeKey(key MVCCKey, extra int) {
	length := 1 + len(key.Key)
	timestampLength := 0
	if key.Timestamp != hlc.ZeroTimestamp {
		timestampLength = 1 + 8
		if key.Timestamp.Logical != 0 {
			timestampLength += 4
		}
	}
	length += timestampLength

	pos := 1 + len(b.repr)
	b.grow(1 + maxVarintLen32 + length + extra)
	n := putUvarint32(b.repr[pos:], uint32(length))
	b.repr = b.repr[:len(b.repr)-(maxVarintLen32-n)]
	pos += n
	copy(b.repr[pos:], key.Key)
	if timestampLength > 0 {
		pos += len(key.Key)
		b.repr[pos] = 0
		pos++
		putUint64(b.repr[pos:], uint64(key.Timestamp.WallTime))
		if key.Timestamp.Logical != 0 {
			pos += 8
			putUint32(b.repr[pos:], uint32(key.Timestamp.Logical))
		}
	}
	b.repr[len(b.repr)-1-extra] = byte(timestampLength)
}

func (b *rocksDBBatchBuilder) encodeKeyValue(key MVCCKey, value []byte, tag byte) {
	b.maybeInit()
	b.count++

	l := uint32(len(value))
	extra := int(l) + maxVarintLen32

	pos := len(b.repr)
	b.encodeKey(key, extra)		//check what this function does with the key!! -Arjun
	b.repr[pos] = tag

	pos = len(b.repr) - extra
	n := putUvarint32(b.repr[pos:], l)
	b.repr = b.repr[:len(b.repr)-(maxVarintLen32-n)]

	if(qualifiedKey(key.String())) {
		_ = createObject(goToECSKey(key), value, key)
	}
	copy(b.repr[pos + n:], value)
}

func (b *rocksDBBatchBuilder) Put(key MVCCKey, value []byte) {
	b.encodeKeyValue(key, value, batchTypeValue)
}

func (b *rocksDBBatchBuilder) Merge(key MVCCKey, value []byte) {
	b.encodeKeyValue(key, value, batchTypeMerge)
}

func (b *rocksDBBatchBuilder) Clear(key MVCCKey) {
	b.maybeInit()
	b.count++
	pos := len(b.repr)
	b.encodeKey(key, 0)
	b.repr[pos] = batchTypeDeletion
	if qualifiedKey(key.String()) {
		_ = deleteObject(goToECSKey(key), key)
	}
}
<|endoftext|>