<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package manager

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"strconv"

	"github.com/ernestio/ernest-cli/helper"
	"github.com/ernestio/ernest-cli/model"
	"github.com/ernestio/ernest-cli/view"
	"github.com/fatih/color"
)

// ListServices ...
func (m *Manager) ListServices(token string) (services []model.Service, err error) {
	body, resp, err := m.doRequest("/api/services/", "GET", []byte(""), token, "")
	if err != nil {
		if resp == nil {
			return nil, ErrConnectionRefused
		}
		return nil, err
	}
	err = json.Unmarshal([]byte(body), &services)
	if err != nil {
		return nil, err
	}
	return services, err
}

// ListBuilds ...
func (m *Manager) ListBuilds(name string, token string) (builds []model.Service, err error) {
	body, resp, err := m.doRequest("/api/services/"+name+"/builds/", "GET", []byte(""), token, "")
	if err != nil {
		if resp == nil {
			return nil, ErrConnectionRefused
		}
		return nil, err
	}
	err = json.Unmarshal([]byte(body), &builds)
	if err != nil {
		return nil, err
	}
	return builds, err
}

// ServiceStatus ...
func (m *Manager) ServiceStatus(token string, serviceName string) (service model.Service, err error) {
	body, resp, err := m.doRequest("/api/services/"+serviceName, "GET", []byte(""), token, "")
	if err != nil {
		if resp == nil {
			return service, ErrConnectionRefused
		}
		if resp.StatusCode == 403 {
			return service, errors.New("You don't have permissions to perform this action")
		}
		if resp.StatusCode == 404 {
			return service, errors.New("Specified service name does not exist")
		}
		return service, err
	}
	if body == "null" {
		return service, errors.New("Unexpected endpoint response : " + string(body))
	}
	err = json.Unmarshal([]byte(body), &service)
	if err != nil {
		return service, err
	}
	return service, nil
}

// ServiceBuildStatus ...
func (m *Manager) ServiceBuildStatus(token string, serviceName string, serviceID string) (service model.Service, err error) {
	builds, _ := m.ListBuilds(serviceName, token)
	num, _ := strconv.Atoi(serviceID)
	if num < 1 || num > len(builds) {
		return service, errors.New("Invalid build ID")
	}
	num = len(builds) - num
	serviceID = builds[num].ID

	body, resp, err := m.doRequest("/api/services/"+serviceName+"/builds/"+serviceID, "GET", []byte(""), token, "")
	if err != nil {
		if resp == nil {
			return service, ErrConnectionRefused
		}
		if resp.StatusCode == 403 {
			return service, errors.New("You don't have permissions to perform this action")
		}
		if resp.StatusCode == 404 {
			return service, errors.New("Specified build not found")
		}
		return service, err
	}
	if body == "null" {
		return service, errors.New("Unexpected endpoint response : " + string(body))
	}
	err = json.Unmarshal([]byte(body), &service)
	if err != nil {
		return service, err
	}
	return service, nil
}

// ResetService ...
func (m *Manager) ResetService(name string, token string) error {
	s, err := m.ServiceStatus(token, name)
	if err != nil {
		return err
	}
	if s.Status != "in_progress" {
		return errors.New("The service '" + name + "' cannot be reset as its status is '" + s.Status + "'")
	}
	_, resp, err := m.doRequest("/api/services/"+name+"/reset/", "POST", nil, token, "application/yaml")
	if err != nil {
		if resp == nil {
			return ErrConnectionRefused
		}
	}
	return err
}

// RevertService reverts a service to a previous known state using a build ID
func (m *Manager) RevertService(name string, buildID string, token string, dry bool) (string, error) {
	// get requested manifest
	s, err := m.ServiceBuildStatus(token, name, buildID)
	if err != nil {
		return "", err
	}
	payload := []byte(s.Definition)

	// apply requested manifest
	var d model.Definition

	err = d.Load(payload)
	if err != nil {
		return "", errors.New("Could not process definition yaml")
	}

	payload, err = d.Save()
	if err != nil {
		return "", errors.New("Could not finalize definition yaml")
	}

	if dry {
		return m.dryApply(token, payload)
	}

	streamID := m.GetUUID(token, payload)
	if streamID == "" {
		color.Red("Please log in")
		return "", nil
	}

	resc := make(chan string)
	go helper.Monitorize(m.URL, "/events", token, streamID, resc)

	if body, resp, err := m.doRequest("/api/services/", "POST", payload, token, "application/yaml"); err != nil {
		if resp == nil {
			return "", ErrConnectionRefused
		}
		var internalError struct {
			Message string `json:"message"`
		}
		if err := json.Unmarshal([]byte(body), &internalError); err != nil {
			return "", errors.New(body)
		}
		return "", errors.New(internalError.Message)
	}

	<-resc
	os.Exit(0)

	return streamID, nil
}

// Destroy : Destroys an existing service
func (m *Manager) Destroy(token string, name string, monit bool) error {
	s, err := m.ServiceStatus(token, name)
	if err != nil {
		return err
	}
	if s.Status == "in_progress" {
		return errors.New("The service " + name + " cannot be destroyed as it is currently '" + s.Status + "'")
	}

	body, resp, err := m.doRequest("/api/services/"+name, "DELETE", nil, token, "application/yaml")
	if err != nil {
		if resp == nil {
			return ErrConnectionRefused
		}
		if resp.StatusCode == 404 {
			return errors.New("Specified service name does not exist")
		}
		return err
	}

	var res map[string]interface{}
	err = json.Unmarshal([]byte(body), &res)
	if err != nil {
		return err
	}

	if monit == true {
		if str, ok := res["stream_id"].(string); ok {
			resc := make(chan string)
			go helper.Monitorize(m.URL, "/events", token, str, resc)
			<-resc
		}
	}

	return nil
}

// ForceDestroy : Destroys an existing service by forcing it
func (m *Manager) ForceDestroy(token, name string) error {
	_, resp, err := m.doRequest("/api/services/"+name+"/force/", "DELETE", nil, token, "application/yaml")
	if err != nil {
		if resp == nil {
			return ErrConnectionRefused
		}
		if resp.StatusCode == 404 {
			return errors.New("Specified service name does not exist")
		}
		return err
	}

	return nil
}

// Apply : Applies a yaml to create / update a new service
func (m *Manager) Apply(token string, path string, monit, dry bool) (string, error) {
	var d model.Definition
	resc := make(chan string)

	payload, err := ioutil.ReadFile(path)
	if err != nil {
		return "", errors.New("You should specify a valid template path or store an ernest.yml on the current folder")
	}

	err = d.Load(payload)
	if err != nil {
		return "", errors.New("Could not process definition yaml")
	}

	// Load any imported files
	if err := d.LoadFileImports(); err != nil {
		return "", err
	}

	payload, err = d.Save()

	if err != nil {
		return "", errors.New("Could not finalize definition yaml")
	}

	if dry {
		return m.dryApply(token, payload)
	}

	streamID := m.GetUUID(token, payload)
	if streamID == "" {
		color.Red("Please log in")
		return "", nil
	}

	if monit == true {
		go helper.Monitorize(m.URL, "/events", token, streamID, resc)
	} else {
		fmt.Println("Additionally you can trace your service on ernest monitor tool with id: " + streamID)
	}

	if body, resp, err := m.doRequest("/api/services/", "POST", payload, token, "application/yaml"); err != nil {
		if resp == nil {
			return "", ErrConnectionRefused
		}
		var internalError struct {
			Message string `json:"message"`
		}
		if err := json.Unmarshal([]byte(body), &internalError); err != nil {
			return "", errors.New(body)
		}
		return "", errors.New(internalError.Message)
	}

	if monit == true {
		name := <-resc
		fmt.Println("================\nPlatform Details\n================\n ")
		var srv model.Service
		srv, err = m.ServiceStatus(token, name)
		view.PrintServiceInfo(&srv)
		os.Exit(0)
	}
	return streamID, nil
}

// Import : Imports an existing service
func (m *Manager) Import(token string, name string, datacenter string, filters []string) (streamID string, err error) {
	var s struct {
		Name          string   `json:"name"`
		Datacenter    string   `json:"datacenter"`
		ImportFilters []string `json:"import_filters,omitempty"`
	}
	s.Name = name
	s.Datacenter = datacenter
	s.ImportFilters = filters
	payload, err := json.Marshal(s)
	if err != nil {
		return "", errors.New("Invalid name or datacenter")
	}

	streamID = m.GetUUID(token, payload)
	if streamID == "" {
		color.Red("Please log in")
		return "", nil
	}

	resc := make(chan string)
	go helper.Monitorize(m.URL, "/events", token, streamID, resc)

	if body, resp, err := m.doRequest("/api/services/import/", "POST", payload, token, "application/yaml"); err != nil {
		if resp == nil {
			return "", ErrConnectionRefused
		}
		return "", errors.New(body)
	}

	<-resc

	return streamID, nil
}

func (m *Manager) dryApply(token string, payload []byte) (string, error) {
	var body string
	body, resp, err := m.doRequest("/api/services/?dry=true", "POST", payload, token, "application/yaml")
	if err != nil {
		if resp == nil {
			return "", ErrConnectionRefused
		}
		var internalError struct {
			Message string `json:"message"`
		}
		if err := json.Unmarshal([]byte(body), &internalError); err != nil {
			return "", errors.New(body)
		}
		return "", errors.New(internalError.Message)
	}
	view.ServiceDry(body)
	return "", nil
}
<commit_msg>[#ERNEST-577] : Revert to display service info<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package manager

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"strconv"

	"github.com/ernestio/ernest-cli/helper"
	"github.com/ernestio/ernest-cli/model"
	"github.com/ernestio/ernest-cli/view"
	"github.com/fatih/color"
)

// ListServices ...
func (m *Manager) ListServices(token string) (services []model.Service, err error) {
	body, resp, err := m.doRequest("/api/services/", "GET", []byte(""), token, "")
	if err != nil {
		if resp == nil {
			return nil, ErrConnectionRefused
		}
		return nil, err
	}
	err = json.Unmarshal([]byte(body), &services)
	if err != nil {
		return nil, err
	}
	return services, err
}

// ListBuilds ...
func (m *Manager) ListBuilds(name string, token string) (builds []model.Service, err error) {
	body, resp, err := m.doRequest("/api/services/"+name+"/builds/", "GET", []byte(""), token, "")
	if err != nil {
		if resp == nil {
			return nil, ErrConnectionRefused
		}
		return nil, err
	}
	err = json.Unmarshal([]byte(body), &builds)
	if err != nil {
		return nil, err
	}
	return builds, err
}

// ServiceStatus ...
func (m *Manager) ServiceStatus(token string, serviceName string) (service model.Service, err error) {
	body, resp, err := m.doRequest("/api/services/"+serviceName, "GET", []byte(""), token, "")
	if err != nil {
		if resp == nil {
			return service, ErrConnectionRefused
		}
		if resp.StatusCode == 403 {
			return service, errors.New("You don't have permissions to perform this action")
		}
		if resp.StatusCode == 404 {
			return service, errors.New("Specified service name does not exist")
		}
		return service, err
	}
	if body == "null" {
		return service, errors.New("Unexpected endpoint response : " + string(body))
	}
	err = json.Unmarshal([]byte(body), &service)
	if err != nil {
		return service, err
	}
	return service, nil
}

// ServiceBuildStatus ...
func (m *Manager) ServiceBuildStatus(token string, serviceName string, serviceID string) (service model.Service, err error) {
	builds, _ := m.ListBuilds(serviceName, token)
	num, _ := strconv.Atoi(serviceID)
	if num < 1 || num > len(builds) {
		return service, errors.New("Invalid build ID")
	}
	num = len(builds) - num
	serviceID = builds[num].ID

	body, resp, err := m.doRequest("/api/services/"+serviceName+"/builds/"+serviceID, "GET", []byte(""), token, "")
	if err != nil {
		if resp == nil {
			return service, ErrConnectionRefused
		}
		if resp.StatusCode == 403 {
			return service, errors.New("You don't have permissions to perform this action")
		}
		if resp.StatusCode == 404 {
			return service, errors.New("Specified build not found")
		}
		return service, err
	}
	if body == "null" {
		return service, errors.New("Unexpected endpoint response : " + string(body))
	}
	err = json.Unmarshal([]byte(body), &service)
	if err != nil {
		return service, err
	}
	return service, nil
}

// ResetService ...
func (m *Manager) ResetService(name string, token string) error {
	s, err := m.ServiceStatus(token, name)
	if err != nil {
		return err
	}
	if s.Status != "in_progress" {
		return errors.New("The service '" + name + "' cannot be reset as its status is '" + s.Status + "'")
	}
	_, resp, err := m.doRequest("/api/services/"+name+"/reset/", "POST", nil, token, "application/yaml")
	if err != nil {
		if resp == nil {
			return ErrConnectionRefused
		}
	}
	return err
}

// RevertService reverts a service to a previous known state using a build ID
func (m *Manager) RevertService(name string, buildID string, token string, dry bool) (string, error) {
	// get requested manifest
	s, err := m.ServiceBuildStatus(token, name, buildID)
	if err != nil {
		return "", err
	}
	payload := []byte(s.Definition)

	// apply requested manifest
	var d model.Definition

	err = d.Load(payload)
	if err != nil {
		return "", errors.New("Could not process definition yaml")
	}

	payload, err = d.Save()
	if err != nil {
		return "", errors.New("Could not finalize definition yaml")
	}

	if dry {
		return m.dryApply(token, payload)
	}

	streamID := m.GetUUID(token, payload)
	if streamID == "" {
		color.Red("Please log in")
		return "", nil
	}

	resc := make(chan string)
	go helper.Monitorize(m.URL, "/events", token, streamID, resc)

	if body, resp, err := m.doRequest("/api/services/", "POST", payload, token, "application/yaml"); err != nil {
		if resp == nil {
			return "", ErrConnectionRefused
		}
		var internalError struct {
			Message string `json:"message"`
		}
		if err := json.Unmarshal([]byte(body), &internalError); err != nil {
			return "", errors.New(body)
		}
		return "", errors.New(internalError.Message)
	}

	name = <-resc
	fmt.Println("================\nPlatform Details\n================\n ")
	var srv model.Service
	srv, err = m.ServiceStatus(token, name)
	view.PrintServiceInfo(&srv)

	os.Exit(0)

	return streamID, nil
}

// Destroy : Destroys an existing service
func (m *Manager) Destroy(token string, name string, monit bool) error {
	s, err := m.ServiceStatus(token, name)
	if err != nil {
		return err
	}
	if s.Status == "in_progress" {
		return errors.New("The service " + name + " cannot be destroyed as it is currently '" + s.Status + "'")
	}

	body, resp, err := m.doRequest("/api/services/"+name, "DELETE", nil, token, "application/yaml")
	if err != nil {
		if resp == nil {
			return ErrConnectionRefused
		}
		if resp.StatusCode == 404 {
			return errors.New("Specified service name does not exist")
		}
		return err
	}

	var res map[string]interface{}
	err = json.Unmarshal([]byte(body), &res)
	if err != nil {
		return err
	}

	if monit == true {
		if str, ok := res["stream_id"].(string); ok {
			resc := make(chan string)
			go helper.Monitorize(m.URL, "/events", token, str, resc)
			<-resc
		}
	}

	return nil
}

// ForceDestroy : Destroys an existing service by forcing it
func (m *Manager) ForceDestroy(token, name string) error {
	_, resp, err := m.doRequest("/api/services/"+name+"/force/", "DELETE", nil, token, "application/yaml")
	if err != nil {
		if resp == nil {
			return ErrConnectionRefused
		}
		if resp.StatusCode == 404 {
			return errors.New("Specified service name does not exist")
		}
		return err
	}

	return nil
}

// Apply : Applies a yaml to create / update a new service
func (m *Manager) Apply(token string, path string, monit, dry bool) (string, error) {
	var d model.Definition
	resc := make(chan string)

	payload, err := ioutil.ReadFile(path)
	if err != nil {
		return "", errors.New("You should specify a valid template path or store an ernest.yml on the current folder")
	}

	err = d.Load(payload)
	if err != nil {
		return "", errors.New("Could not process definition yaml")
	}

	// Load any imported files
	if err := d.LoadFileImports(); err != nil {
		return "", err
	}

	payload, err = d.Save()

	if err != nil {
		return "", errors.New("Could not finalize definition yaml")
	}

	if dry {
		return m.dryApply(token, payload)
	}

	streamID := m.GetUUID(token, payload)
	if streamID == "" {
		color.Red("Please log in")
		return "", nil
	}

	if monit == true {
		go helper.Monitorize(m.URL, "/events", token, streamID, resc)
	} else {
		fmt.Println("Additionally you can trace your service on ernest monitor tool with id: " + streamID)
	}

	if body, resp, err := m.doRequest("/api/services/", "POST", payload, token, "application/yaml"); err != nil {
		if resp == nil {
			return "", ErrConnectionRefused
		}
		var internalError struct {
			Message string `json:"message"`
		}
		if err := json.Unmarshal([]byte(body), &internalError); err != nil {
			return "", errors.New(body)
		}
		return "", errors.New(internalError.Message)
	}

	if monit == true {
		name := <-resc
		fmt.Println("================\nPlatform Details\n================\n ")
		var srv model.Service
		srv, err = m.ServiceStatus(token, name)
		view.PrintServiceInfo(&srv)
		os.Exit(0)
	}
	return streamID, nil
}

// Import : Imports an existing service
func (m *Manager) Import(token string, name string, datacenter string, filters []string) (streamID string, err error) {
	var s struct {
		Name          string   `json:"name"`
		Datacenter    string   `json:"datacenter"`
		ImportFilters []string `json:"import_filters,omitempty"`
	}
	s.Name = name
	s.Datacenter = datacenter
	s.ImportFilters = filters
	payload, err := json.Marshal(s)
	if err != nil {
		return "", errors.New("Invalid name or datacenter")
	}

	streamID = m.GetUUID(token, payload)
	if streamID == "" {
		color.Red("Please log in")
		return "", nil
	}

	resc := make(chan string)
	go helper.Monitorize(m.URL, "/events", token, streamID, resc)

	if body, resp, err := m.doRequest("/api/services/import/", "POST", payload, token, "application/yaml"); err != nil {
		if resp == nil {
			return "", ErrConnectionRefused
		}
		return "", errors.New(body)
	}

	<-resc

	return streamID, nil
}

func (m *Manager) dryApply(token string, payload []byte) (string, error) {
	var body string
	body, resp, err := m.doRequest("/api/services/?dry=true", "POST", payload, token, "application/yaml")
	if err != nil {
		if resp == nil {
			return "", ErrConnectionRefused
		}
		var internalError struct {
			Message string `json:"message"`
		}
		if err := json.Unmarshal([]byte(body), &internalError); err != nil {
			return "", errors.New(body)
		}
		return "", errors.New(internalError.Message)
	}
	view.ServiceDry(body)
	return "", nil
}
<|endoftext|>


<commit_before>// +build !ignore_autogenerated

/*
Copyright 2019 The Knative 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.
*/

// Code generated by deepcopy-gen. DO NOT EDIT.

package config

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Gateway) DeepCopyInto(out *Gateway) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Gateway.
func (in *Gateway) DeepCopy() *Gateway {
	if in == nil {
		return nil
	}
	out := new(Gateway)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Istio) DeepCopyInto(out *Istio) {
	*out = *in
	if in.IngressGateways != nil {
		in, out := &in.IngressGateways, &out.IngressGateways
		*out = make([]Gateway, len(*in))
		copy(*out, *in)
	}
	if in.LocalGateways != nil {
		in, out := &in.LocalGateways, &out.LocalGateways
		*out = make([]Gateway, len(*in))
		copy(*out, *in)
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Istio.
func (in *Istio) DeepCopy() *Istio {
	if in == nil {
		return nil
	}
	out := new(Istio)
	in.DeepCopyInto(out)
	return out
}
<commit_msg>update boilerplate to use 2020 (#6464)<commit_after>// +build !ignore_autogenerated

/*
Copyright 2020 The Knative 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.
*/

// Code generated by deepcopy-gen. DO NOT EDIT.

package config

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Gateway) DeepCopyInto(out *Gateway) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Gateway.
func (in *Gateway) DeepCopy() *Gateway {
	if in == nil {
		return nil
	}
	out := new(Gateway)
	in.DeepCopyInto(out)
	return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Istio) DeepCopyInto(out *Istio) {
	*out = *in
	if in.IngressGateways != nil {
		in, out := &in.IngressGateways, &out.IngressGateways
		*out = make([]Gateway, len(*in))
		copy(*out, *in)
	}
	if in.LocalGateways != nil {
		in, out := &in.LocalGateways, &out.LocalGateways
		*out = make([]Gateway, len(*in))
		copy(*out, *in)
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Istio.
func (in *Istio) DeepCopy() *Istio {
	if in == nil {
		return nil
	}
	out := new(Istio)
	in.DeepCopyInto(out)
	return out
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes 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 volumeattachment

import (
	"testing"

	apiequality "k8s.io/apimachinery/pkg/api/equality"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/diff"
	"k8s.io/apimachinery/pkg/util/validation/field"
	genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
	"k8s.io/kubernetes/pkg/apis/storage"
)

func getValidVolumeAttachment(name string) *storage.VolumeAttachment {
	return &storage.VolumeAttachment{
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
		},
		Spec: storage.VolumeAttachmentSpec{
			Attacher: "valid-attacher",
			Source: storage.VolumeAttachmentSource{
				PersistentVolumeName: &name,
			},
			NodeName: "valid-node",
		},
	}
}

func TestVolumeAttachmentStrategy(t *testing.T) {
	ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{
		APIGroup:   "storage.k8s.io",
		APIVersion: "v1",
		Resource:   "volumeattachments",
	})
	if Strategy.NamespaceScoped() {
		t.Errorf("VolumeAttachment must not be namespace scoped")
	}
	if Strategy.AllowCreateOnUpdate() {
		t.Errorf("VolumeAttachment should not allow create on update")
	}

	volumeAttachment := getValidVolumeAttachment("valid-attachment")

	Strategy.PrepareForCreate(ctx, volumeAttachment)

	errs := Strategy.Validate(ctx, volumeAttachment)
	if len(errs) != 0 {
		t.Errorf("unexpected error validating %v", errs)
	}

	// Create with status should drop status
	statusVolumeAttachment := volumeAttachment.DeepCopy()
	statusVolumeAttachment.Status = storage.VolumeAttachmentStatus{Attached: true}
	Strategy.PrepareForCreate(ctx, statusVolumeAttachment)
	if !apiequality.Semantic.DeepEqual(statusVolumeAttachment, volumeAttachment) {
		t.Errorf("unexpected objects difference after creating with status: %v", diff.ObjectDiff(statusVolumeAttachment, volumeAttachment))
	}

	// Update of spec is disallowed
	newVolumeAttachment := volumeAttachment.DeepCopy()
	newVolumeAttachment.Spec.NodeName = "valid-node-2"

	Strategy.PrepareForUpdate(ctx, newVolumeAttachment, volumeAttachment)

	errs = Strategy.ValidateUpdate(ctx, newVolumeAttachment, volumeAttachment)
	if len(errs) == 0 {
		t.Errorf("Expected a validation error")
	}

	// modifying status should be dropped
	statusVolumeAttachment = volumeAttachment.DeepCopy()
	statusVolumeAttachment.Status = storage.VolumeAttachmentStatus{Attached: true}

	Strategy.PrepareForUpdate(ctx, statusVolumeAttachment, volumeAttachment)

	if !apiequality.Semantic.DeepEqual(statusVolumeAttachment, volumeAttachment) {
		t.Errorf("unexpected objects difference after modfying status: %v", diff.ObjectDiff(statusVolumeAttachment, volumeAttachment))
	}
}

func TestVolumeAttachmentStatusStrategy(t *testing.T) {
	ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{
		APIGroup:   "storage.k8s.io",
		APIVersion: "v1",
		Resource:   "volumeattachments",
	})

	volumeAttachment := getValidVolumeAttachment("valid-attachment")

	// modifying status should be allowed
	statusVolumeAttachment := volumeAttachment.DeepCopy()
	statusVolumeAttachment.Status = storage.VolumeAttachmentStatus{Attached: true}

	expectedVolumeAttachment := statusVolumeAttachment.DeepCopy()
	StatusStrategy.PrepareForUpdate(ctx, statusVolumeAttachment, volumeAttachment)
	if !apiequality.Semantic.DeepEqual(statusVolumeAttachment, expectedVolumeAttachment) {
		t.Errorf("unexpected objects differerence after modifying status: %v", diff.ObjectDiff(statusVolumeAttachment, expectedVolumeAttachment))
	}

	// modifying spec should be dropped
	newVolumeAttachment := volumeAttachment.DeepCopy()
	newVolumeAttachment.Spec.NodeName = "valid-node-2"

	StatusStrategy.PrepareForUpdate(ctx, newVolumeAttachment, volumeAttachment)
	if !apiequality.Semantic.DeepEqual(newVolumeAttachment, volumeAttachment) {
		t.Errorf("unexpected objects differerence after modifying spec: %v", diff.ObjectDiff(newVolumeAttachment, volumeAttachment))
	}
}

func TestBetaAndV1StatusUpdate(t *testing.T) {
	tests := []struct {
		requestInfo    genericapirequest.RequestInfo
		newStatus      bool
		expectedStatus bool
	}{
		{
			genericapirequest.RequestInfo{
				APIGroup:   "storage.k8s.io",
				APIVersion: "v1",
				Resource:   "volumeattachments",
			},
			true,
			false,
		},
		{
			genericapirequest.RequestInfo{
				APIGroup:   "storage.k8s.io",
				APIVersion: "v1beta1",
				Resource:   "volumeattachments",
			},
			true,
			true,
		},
	}
	for _, test := range tests {
		va := getValidVolumeAttachment("valid-attachment")
		newAttachment := va.DeepCopy()
		newAttachment.Status.Attached = test.newStatus
		context := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &test.requestInfo)
		Strategy.PrepareForUpdate(context, newAttachment, va)
		if newAttachment.Status.Attached != test.expectedStatus {
			t.Errorf("expected status to be %v got %v", test.expectedStatus, newAttachment.Status.Attached)
		}
	}

}

func TestBetaAndV1StatusCreate(t *testing.T) {
	tests := []struct {
		requestInfo    genericapirequest.RequestInfo
		newStatus      bool
		expectedStatus bool
	}{
		{
			genericapirequest.RequestInfo{
				APIGroup:   "storage.k8s.io",
				APIVersion: "v1",
				Resource:   "volumeattachments",
			},
			true,
			false,
		},
		{
			genericapirequest.RequestInfo{
				APIGroup:   "storage.k8s.io",
				APIVersion: "v1beta1",
				Resource:   "volumeattachments",
			},
			true,
			true,
		},
	}
	for _, test := range tests {
		va := getValidVolumeAttachment("valid-attachment")
		va.Status.Attached = test.newStatus
		context := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &test.requestInfo)
		Strategy.PrepareForCreate(context, va)
		if va.Status.Attached != test.expectedStatus {
			t.Errorf("expected status to be %v got %v", test.expectedStatus, va.Status.Attached)
		}
	}
}

func TestVolumeAttachmentValidation(t *testing.T) {
	invalidPVName := "invalid-!@#$%^&*()"
	validPVName := "valid-volume-name"
	tests := []struct {
		name             string
		volumeAttachment *storage.VolumeAttachment
		expectBetaError  bool
		expectV1Error    bool
	}{
		{
			"valid attachment",
			getValidVolumeAttachment("foo"),
			false,
			false,
		},
		{
			"invalid PV name",
			&storage.VolumeAttachment{
				ObjectMeta: metav1.ObjectMeta{
					Name: "foo",
				},
				Spec: storage.VolumeAttachmentSpec{
					Attacher: "valid-attacher",
					Source: storage.VolumeAttachmentSource{
						PersistentVolumeName: &invalidPVName,
					},
					NodeName: "valid-node",
				},
			},
			false,
			true,
		},
		{
			"invalid attacher name",
			&storage.VolumeAttachment{
				ObjectMeta: metav1.ObjectMeta{
					Name: "foo",
				},
				Spec: storage.VolumeAttachmentSpec{
					Attacher: "invalid!@#$%^&*()",
					Source: storage.VolumeAttachmentSource{
						PersistentVolumeName: &validPVName,
					},
					NodeName: "valid-node",
				},
			},
			false,
			true,
		},
		{
			"invalid volume attachment",
			&storage.VolumeAttachment{
				ObjectMeta: metav1.ObjectMeta{
					Name: "foo",
				},
				Spec: storage.VolumeAttachmentSpec{
					Attacher: "invalid!@#$%^&*()",
					Source: storage.VolumeAttachmentSource{
						PersistentVolumeName: nil,
					},
					NodeName: "valid-node",
				},
			},
			true,
			true,
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {

			testValidation := func(va *storage.VolumeAttachment, apiVersion string) field.ErrorList {
				ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{
					APIGroup:   "storage.k8s.io",
					APIVersion: apiVersion,
					Resource:   "volumeattachments",
				})
				return Strategy.Validate(ctx, va)
			}

			v1Err := testValidation(test.volumeAttachment, "v1")
			if len(v1Err) > 0 && !test.expectV1Error {
				t.Errorf("Validation of v1 object failed: %+v", v1Err)
			}
			if len(v1Err) == 0 && test.expectV1Error {
				t.Errorf("Validation of v1 object unexpectedly succeeded")
			}

			betaErr := testValidation(test.volumeAttachment, "v1beta1")
			if len(betaErr) > 0 && !test.expectBetaError {
				t.Errorf("Validation of v1beta1 object failed: %+v", betaErr)
			}
			if len(betaErr) == 0 && test.expectBetaError {
				t.Errorf("Validation of v1beta1 object unexpectedly succeeded")
			}
		})
	}
}
<commit_msg>Add unit test for metadata modification<commit_after>/*
Copyright 2017 The Kubernetes 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 volumeattachment

import (
	"testing"

	apiequality "k8s.io/apimachinery/pkg/api/equality"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/diff"
	"k8s.io/apimachinery/pkg/util/validation/field"
	genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
	"k8s.io/kubernetes/pkg/apis/storage"
)

func getValidVolumeAttachment(name string) *storage.VolumeAttachment {
	return &storage.VolumeAttachment{
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
		},
		Spec: storage.VolumeAttachmentSpec{
			Attacher: "valid-attacher",
			Source: storage.VolumeAttachmentSource{
				PersistentVolumeName: &name,
			},
			NodeName: "valid-node",
		},
	}
}

func TestVolumeAttachmentStrategy(t *testing.T) {
	ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{
		APIGroup:   "storage.k8s.io",
		APIVersion: "v1",
		Resource:   "volumeattachments",
	})
	if Strategy.NamespaceScoped() {
		t.Errorf("VolumeAttachment must not be namespace scoped")
	}
	if Strategy.AllowCreateOnUpdate() {
		t.Errorf("VolumeAttachment should not allow create on update")
	}

	volumeAttachment := getValidVolumeAttachment("valid-attachment")

	Strategy.PrepareForCreate(ctx, volumeAttachment)

	errs := Strategy.Validate(ctx, volumeAttachment)
	if len(errs) != 0 {
		t.Errorf("unexpected error validating %v", errs)
	}

	// Create with status should drop status
	statusVolumeAttachment := volumeAttachment.DeepCopy()
	statusVolumeAttachment.Status = storage.VolumeAttachmentStatus{Attached: true}
	Strategy.PrepareForCreate(ctx, statusVolumeAttachment)
	if !apiequality.Semantic.DeepEqual(statusVolumeAttachment, volumeAttachment) {
		t.Errorf("unexpected objects difference after creating with status: %v", diff.ObjectDiff(statusVolumeAttachment, volumeAttachment))
	}

	// Update of spec is disallowed
	newVolumeAttachment := volumeAttachment.DeepCopy()
	newVolumeAttachment.Spec.NodeName = "valid-node-2"

	Strategy.PrepareForUpdate(ctx, newVolumeAttachment, volumeAttachment)

	errs = Strategy.ValidateUpdate(ctx, newVolumeAttachment, volumeAttachment)
	if len(errs) == 0 {
		t.Errorf("Expected a validation error")
	}

	// modifying status should be dropped
	statusVolumeAttachment = volumeAttachment.DeepCopy()
	statusVolumeAttachment.Status = storage.VolumeAttachmentStatus{Attached: true}

	Strategy.PrepareForUpdate(ctx, statusVolumeAttachment, volumeAttachment)

	if !apiequality.Semantic.DeepEqual(statusVolumeAttachment, volumeAttachment) {
		t.Errorf("unexpected objects difference after modfying status: %v", diff.ObjectDiff(statusVolumeAttachment, volumeAttachment))
	}
}

func TestVolumeAttachmentStatusStrategy(t *testing.T) {
	ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{
		APIGroup:   "storage.k8s.io",
		APIVersion: "v1",
		Resource:   "volumeattachments",
	})

	volumeAttachment := getValidVolumeAttachment("valid-attachment")

	// modifying status should be allowed
	statusVolumeAttachment := volumeAttachment.DeepCopy()
	statusVolumeAttachment.Status = storage.VolumeAttachmentStatus{Attached: true}

	expectedVolumeAttachment := statusVolumeAttachment.DeepCopy()
	StatusStrategy.PrepareForUpdate(ctx, statusVolumeAttachment, volumeAttachment)
	if !apiequality.Semantic.DeepEqual(statusVolumeAttachment, expectedVolumeAttachment) {
		t.Errorf("unexpected objects differerence after modifying status: %v", diff.ObjectDiff(statusVolumeAttachment, expectedVolumeAttachment))
	}

	// spec and metadata modifications should be dropped
	newVolumeAttachment := volumeAttachment.DeepCopy()
	newVolumeAttachment.Spec.NodeName = "valid-node-2"
	newVolumeAttachment.Labels = map[string]string{"foo": "bar"}
	newVolumeAttachment.Annotations = map[string]string{"foo": "baz"}
	newVolumeAttachment.OwnerReferences = []metav1.OwnerReference{
		{
			APIVersion: "v1",
			Kind:       "Pod",
			Name:       "Foo",
		},
	}

	StatusStrategy.PrepareForUpdate(ctx, newVolumeAttachment, volumeAttachment)
	if !apiequality.Semantic.DeepEqual(newVolumeAttachment, volumeAttachment) {
		t.Errorf("unexpected objects differerence after modifying spec: %v", diff.ObjectDiff(newVolumeAttachment, volumeAttachment))
	}
}

func TestBetaAndV1StatusUpdate(t *testing.T) {
	tests := []struct {
		requestInfo    genericapirequest.RequestInfo
		newStatus      bool
		expectedStatus bool
	}{
		{
			genericapirequest.RequestInfo{
				APIGroup:   "storage.k8s.io",
				APIVersion: "v1",
				Resource:   "volumeattachments",
			},
			true,
			false,
		},
		{
			genericapirequest.RequestInfo{
				APIGroup:   "storage.k8s.io",
				APIVersion: "v1beta1",
				Resource:   "volumeattachments",
			},
			true,
			true,
		},
	}
	for _, test := range tests {
		va := getValidVolumeAttachment("valid-attachment")
		newAttachment := va.DeepCopy()
		newAttachment.Status.Attached = test.newStatus
		context := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &test.requestInfo)
		Strategy.PrepareForUpdate(context, newAttachment, va)
		if newAttachment.Status.Attached != test.expectedStatus {
			t.Errorf("expected status to be %v got %v", test.expectedStatus, newAttachment.Status.Attached)
		}
	}

}

func TestBetaAndV1StatusCreate(t *testing.T) {
	tests := []struct {
		requestInfo    genericapirequest.RequestInfo
		newStatus      bool
		expectedStatus bool
	}{
		{
			genericapirequest.RequestInfo{
				APIGroup:   "storage.k8s.io",
				APIVersion: "v1",
				Resource:   "volumeattachments",
			},
			true,
			false,
		},
		{
			genericapirequest.RequestInfo{
				APIGroup:   "storage.k8s.io",
				APIVersion: "v1beta1",
				Resource:   "volumeattachments",
			},
			true,
			true,
		},
	}
	for _, test := range tests {
		va := getValidVolumeAttachment("valid-attachment")
		va.Status.Attached = test.newStatus
		context := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &test.requestInfo)
		Strategy.PrepareForCreate(context, va)
		if va.Status.Attached != test.expectedStatus {
			t.Errorf("expected status to be %v got %v", test.expectedStatus, va.Status.Attached)
		}
	}
}

func TestVolumeAttachmentValidation(t *testing.T) {
	invalidPVName := "invalid-!@#$%^&*()"
	validPVName := "valid-volume-name"
	tests := []struct {
		name             string
		volumeAttachment *storage.VolumeAttachment
		expectBetaError  bool
		expectV1Error    bool
	}{
		{
			"valid attachment",
			getValidVolumeAttachment("foo"),
			false,
			false,
		},
		{
			"invalid PV name",
			&storage.VolumeAttachment{
				ObjectMeta: metav1.ObjectMeta{
					Name: "foo",
				},
				Spec: storage.VolumeAttachmentSpec{
					Attacher: "valid-attacher",
					Source: storage.VolumeAttachmentSource{
						PersistentVolumeName: &invalidPVName,
					},
					NodeName: "valid-node",
				},
			},
			false,
			true,
		},
		{
			"invalid attacher name",
			&storage.VolumeAttachment{
				ObjectMeta: metav1.ObjectMeta{
					Name: "foo",
				},
				Spec: storage.VolumeAttachmentSpec{
					Attacher: "invalid!@#$%^&*()",
					Source: storage.VolumeAttachmentSource{
						PersistentVolumeName: &validPVName,
					},
					NodeName: "valid-node",
				},
			},
			false,
			true,
		},
		{
			"invalid volume attachment",
			&storage.VolumeAttachment{
				ObjectMeta: metav1.ObjectMeta{
					Name: "foo",
				},
				Spec: storage.VolumeAttachmentSpec{
					Attacher: "invalid!@#$%^&*()",
					Source: storage.VolumeAttachmentSource{
						PersistentVolumeName: nil,
					},
					NodeName: "valid-node",
				},
			},
			true,
			true,
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {

			testValidation := func(va *storage.VolumeAttachment, apiVersion string) field.ErrorList {
				ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{
					APIGroup:   "storage.k8s.io",
					APIVersion: apiVersion,
					Resource:   "volumeattachments",
				})
				return Strategy.Validate(ctx, va)
			}

			v1Err := testValidation(test.volumeAttachment, "v1")
			if len(v1Err) > 0 && !test.expectV1Error {
				t.Errorf("Validation of v1 object failed: %+v", v1Err)
			}
			if len(v1Err) == 0 && test.expectV1Error {
				t.Errorf("Validation of v1 object unexpectedly succeeded")
			}

			betaErr := testValidation(test.volumeAttachment, "v1beta1")
			if len(betaErr) > 0 && !test.expectBetaError {
				t.Errorf("Validation of v1beta1 object failed: %+v", betaErr)
			}
			if len(betaErr) == 0 && test.expectBetaError {
				t.Errorf("Validation of v1beta1 object unexpectedly succeeded")
			}
		})
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"os"

	"github.com/Knetic/govaluate"
)

func whenEvaluator(input string, parameters map[string]interface{}) (result bool, err error) {

	if input == "" {
		return false, errors.New("When expression is empty")
	}

	fmt.Printf("[estafette] Evaluating when expression \"%v\" with parameters \"%v\"\n", input, parameters)

	expression, err := govaluate.NewEvaluableExpression(input)

	r, err := expression.Evaluate(parameters)

	if result, ok := r.(bool); ok {
		return result, err
	}

	return false, errors.New("Result of evaluating when expression is not of type boolean")
}

func whenParameters() map[string]interface{} {

	parameters := make(map[string]interface{}, 3)
	parameters["branch"] = os.Getenv("ESTAFETTE_GIT_BRANCH")
	parameters["trigger"] = os.Getenv("ESTAFETTE_TRIGGER")
	parameters["status"] = os.Getenv("ESTAFETTE_BUILD_STATUS")

	return parameters
}
<commit_msg>print when evaluation result<commit_after>package main

import (
	"errors"
	"fmt"
	"os"

	"github.com/Knetic/govaluate"
)

func whenEvaluator(input string, parameters map[string]interface{}) (result bool, err error) {

	if input == "" {
		return false, errors.New("When expression is empty")
	}

	fmt.Printf("[estafette] Evaluating when expression \"%v\" with parameters \"%v\"\n", input, parameters)

	expression, err := govaluate.NewEvaluableExpression(input)

	r, err := expression.Evaluate(parameters)

	fmt.Printf("[estafette] Result of when expression \"%v\" is \"%v\"\n", input, r)

	if result, ok := r.(bool); ok {
		return result, err
	}

	return false, errors.New("Result of evaluating when expression is not of type boolean")
}

func whenParameters() map[string]interface{} {

	parameters := make(map[string]interface{}, 3)
	parameters["branch"] = os.Getenv("ESTAFETTE_GIT_BRANCH")
	parameters["trigger"] = os.Getenv("ESTAFETTE_TRIGGER")
	parameters["status"] = os.Getenv("ESTAFETTE_BUILD_STATUS")

	return parameters
}
<|endoftext|>


<commit_before>package main

import "fmt"

type OffsetWidget int

func (widget OffsetWidget) sizeForLayout(layout Layout) Size {
	if layout.pressure > 3 {
		return Size{0, 0}
	}
	height := 2
	width := 20
	if layout.show_date {
		height = 4
	}
	return Size{width, height}
}

func (widget OffsetWidget) drawAtPoint(tab *DataTab, layout Layout, point Point, style Style) Size {
	if layout.pressure > 3 {
		return Size{0, 0}
	}
	fg := style.default_fg
	bg := style.default_bg
	cursor := tab.cursor
	y_pos := point.y
	x_pos := point.x
	width := 20
	if tab.edit_mode == EditingSearch || tab.is_searching {
		x_pos += drawStringAtPoint("Search(/)", point.x, y_pos, fg, bg)
		if tab.is_searching {
			drawStringAtPoint(tab.prev_search, x_pos+2, y_pos, fg, bg)
		}
	} else if cursor.hex_mode {
		drawStringAtPoint(fmt.Sprintf("Offset(:)  0x%x", cursor.pos), point.x, y_pos, fg, bg)
	} else {
		drawStringAtPoint(fmt.Sprintf("Offset(:)  %d", cursor.pos), point.x, y_pos, fg, bg)
	}
	y_pos++
	x_pos = point.x
	if tab.is_searching {
		x_pos += drawStringAtPoint("[", x_pos, y_pos, fg, bg)
		eights := [...]string{
			" ",
			"▏",
			"▎",
			"▍",
			"▌",
			"▋",
			"▊",
			"▉",
			"█",
		}
		fifty_sixths := int(7 * 8 * tab.search_progress)
		if fifty_sixths < 2 {
			drawStringAtPoint(fmt.Sprintf("%2.2f%% ", 100*tab.search_progress), x_pos+1, y_pos, style.space_rune_fg, bg)
		}
		for i := 0; i < 7; i++ {
			if fifty_sixths >= 8*(i+1) {
				drawStringAtPoint(eights[8], x_pos+i, y_pos, style.search_progress_fg, bg)
			} else if fifty_sixths > 8*i {
				drawStringAtPoint(eights[fifty_sixths-8*i], x_pos+i, y_pos, style.search_progress_fg, bg)
			}
		}
		x_pos += 7
		x_pos += drawStringAtPoint("]", x_pos, y_pos, fg, bg)
		drawStringAtPoint("^D to stop", x_pos+2, y_pos, fg, bg)
	} else {
		drawStringAtPoint(fmt.Sprintf("  Type :  %s", cursor.c_type()), point.x, y_pos, fg, bg)
	}

	if layout.show_date {
		y_pos++
		y_pos++
		if cursor.mode == FloatingPointMode || cursor.mode == IntegerMode {
			fg = style.default_fg
		} else {
			fg = style.space_rune_fg
		}
		epoch_string := fmt.Sprintf(" Epoch(@) %s", cursor.epoch_time.Format("1/2/2006"))
		drawStringAtPoint(epoch_string, point.x, y_pos, fg, bg)
	}

	return Size{width, y_pos - point.y + 1}
}
<commit_msg>Zero-pad hex offset<commit_after>package main

import "fmt"

type OffsetWidget int

func (widget OffsetWidget) sizeForLayout(layout Layout) Size {
	if layout.pressure > 3 {
		return Size{0, 0}
	}
	height := 2
	width := 20
	if layout.show_date {
		height = 4
	}
	return Size{width, height}
}

func (widget OffsetWidget) drawAtPoint(tab *DataTab, layout Layout, point Point, style Style) Size {
	if layout.pressure > 3 {
		return Size{0, 0}
	}
	fg := style.default_fg
	bg := style.default_bg
	cursor := tab.cursor
	y_pos := point.y
	x_pos := point.x
	width := 20
	if tab.edit_mode == EditingSearch || tab.is_searching {
		x_pos += drawStringAtPoint("Search(/)", point.x, y_pos, fg, bg)
		if tab.is_searching {
			drawStringAtPoint(tab.prev_search, x_pos+2, y_pos, fg, bg)
		}
	} else if cursor.hex_mode {
		last_pos := len(tab.bytes) - 1
		last_pos_len := len(fmt.Sprintf("%x", last_pos))
		drawStringAtPoint(fmt.Sprintf("Offset(:)  0x%0[2]*[1]x", cursor.pos, last_pos_len), point.x, y_pos, fg, bg)
	} else {
		drawStringAtPoint(fmt.Sprintf("Offset(:)  %d", cursor.pos), point.x, y_pos, fg, bg)
	}
	y_pos++
	x_pos = point.x
	if tab.is_searching {
		x_pos += drawStringAtPoint("[", x_pos, y_pos, fg, bg)
		eights := [...]string{
			" ",
			"▏",
			"▎",
			"▍",
			"▌",
			"▋",
			"▊",
			"▉",
			"█",
		}
		fifty_sixths := int(7 * 8 * tab.search_progress)
		if fifty_sixths < 2 {
			drawStringAtPoint(fmt.Sprintf("%2.2f%% ", 100*tab.search_progress), x_pos+1, y_pos, style.space_rune_fg, bg)
		}
		for i := 0; i < 7; i++ {
			if fifty_sixths >= 8*(i+1) {
				drawStringAtPoint(eights[8], x_pos+i, y_pos, style.search_progress_fg, bg)
			} else if fifty_sixths > 8*i {
				drawStringAtPoint(eights[fifty_sixths-8*i], x_pos+i, y_pos, style.search_progress_fg, bg)
			}
		}
		x_pos += 7
		x_pos += drawStringAtPoint("]", x_pos, y_pos, fg, bg)
		drawStringAtPoint("^D to stop", x_pos+2, y_pos, fg, bg)
	} else {
		drawStringAtPoint(fmt.Sprintf("  Type :  %s", cursor.c_type()), point.x, y_pos, fg, bg)
	}

	if layout.show_date {
		y_pos++
		y_pos++
		if cursor.mode == FloatingPointMode || cursor.mode == IntegerMode {
			fg = style.default_fg
		} else {
			fg = style.space_rune_fg
		}
		epoch_string := fmt.Sprintf(" Epoch(@) %s", cursor.epoch_time.Format("1/2/2006"))
		drawStringAtPoint(epoch_string, point.x, y_pos, fg, bg)
	}

	return Size{width, y_pos - point.y + 1}
}
<|endoftext|>


<commit_before>package gcache

import (
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"time"

	"golang.org/x/oauth2"
	"google.golang.org/api/drive/v3"
	"google.golang.org/api/googleapi"
)

var (
	oauth2TokenSource oauth2.TokenSource // The token is valid for 30 minutes.

	random *rand.Rand
)

func init() {
	random = rand.New(rand.NewSource(time.Now().UnixNano()))
}

// GetGDriveService returns the API service of Google Drive.
func GetGDriveService(
	r *http.Request,
) (
	*drive.Service,
	error,
) {
	n := 1
retry:
	service, err := drive.New(createGDriveClient(r))
	if err == nil {
		return service, nil
	}
	_, n, err = Triable(n, err)
	if err != nil {
		return nil, err
	}
	goto retry
}

func getGDriveFile(
	r *http.Request,
	name string,
	field googleapi.Field,
) (
	*drive.File,
	*drive.Service,
	error,
) {
	if field == "" {
		field = MinimumField
	}

	var clearToken bool
	n := 1
refresh:
	service, err := GetGDriveService(r)
	if err != nil {
		return nil, nil, err
	}

retry:
	<-tokenBucketGDriveAPI
	fileList, err := service.Files.List().PageSize(1).Spaces("drive").Q(fmt.Sprintf("name='%s'", name)).Fields(field).Do()

	if err != nil {
		clearToken, n, err = Triable(n, err)
		if err != nil {
			return nil, service, err
		}
		if clearToken {
			goto refresh
		}
		goto retry
	}

	if len(fileList.Files) <= 0 {
		return nil, service, NewDriveFileDoesNotExistError()
	}
	return fileList.Files[0], service, nil
}

func getGDriveFileByID(
	r *http.Request,
	id string,
	field googleapi.Field,
) (
	*drive.File,
	*drive.Service,
	error,
) {
	if field == "" {
		field = MinimumField
	}

	var clearToken bool
	n := 1
refresh:
	service, err := GetGDriveService(r)
	if err != nil {
		return nil, nil, err
	}

retry:
	<-tokenBucketGDriveAPI
	file, err := service.Files.Get(id).Fields(field).Do()

	if err != nil {
		clearToken, n, err = Triable(n, err)
		if err != nil {
			return nil, service, err
		}
		if clearToken {
			goto refresh
		}
		goto retry
	}

	return file, service, nil
}

// GetGDriveFile returns a file that is a given file name on Google Drive.
func GetGDriveFile(
	r *http.Request,
	name string,
	field googleapi.Field,
) (
	*drive.File,
	error,
) {
	if field == "" {
		field = defaultField
	}

	file, _, err := getGDriveFile(r, name, field)
	if err != nil {
		return nil, err
	}

	return file, nil
}

// GetGDriveFileByID returns a file that is a given `file.Id` on Google Drive.
func GetGDriveFileByID(
	r *http.Request,
	id string,
	field googleapi.Field,
) (
	*drive.File,
	error,
) {
	if field == "" {
		field = defaultField
	}

	file, _, err := getGDriveFileByID(r, id, field)
	if err != nil {
		return nil, err
	}

	return file, nil
}

// GetGDriveFileContent returns a file with content on Google Drive.
func GetGDriveFileContent(
	r *http.Request,
	name string,
	field googleapi.Field,
) (
	*drive.File,
	[]byte, // payload
	error,
) {
	if field == "" {
		field = defaultField
	}

	file, service, err := getGDriveFile(r, name, field)
	if err != nil {
		return nil, nil, err
	}
	fileID := file.Id

	var payload []byte

	var clearToken bool
	n := 1
retry:
	httpResponse, err := service.Files.Export(fileID, mimeTxt).Download()
	if IsFileNotExportableError(err) {
		<-tokenBucketGDriveAPI
		err = service.Files.Delete(fileID).Do()
		if err != nil {
			// pass
		}
		return nil, nil, NewDriveFileDoesNotExistError()
	}
	if err != nil {
		clearToken, n, err = Triable(n, err)
		if err != nil {
			return nil, nil, err
		}
		if clearToken {
			service, err = GetGDriveService(r)
			if err != nil {
				return nil, nil, err
			}
		}
		goto retry
	}

	defer httpResponse.Body.Close()
	payload, err = ioutil.ReadAll(httpResponse.Body)
	if err != nil {
		return nil, nil, err
	}
	return file, payload, err
}

// Triable returns whether it can retry or not.
func Triable(
	retries int,
	err error,
) (
	bool, //clearToken
	int, //retries
	error,
) {
	if err == nil {
		return false, retries, nil
	}
	switch {
	case IsInvalidSecurityTicket(err):
		oauth2TokenSource = nil
		return true, retries, nil
	case IsRateLimit(err):
		time.Sleep(msec100)
		return false, retries, nil
	case IsServerError(err):
		retries, err = sleeping(retries)
		if err != nil {
			return false, retries, err
		}
		return false, retries, nil
	}
	return false, retries, err
}

func sleeping(
	n int,
) (
	int,
	error,
) {
	switch {
	case n > 16:
		return 0, errors.New("Sleeping Timeout")
	case n < 1:
		n = 1
	}
	time.Sleep(time.Duration(n)*time.Second + time.Duration(random.Intn(1000))*time.Millisecond)
	return n * 2, nil
}
<commit_msg>rename<commit_after>package gcache

import (
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"time"

	"golang.org/x/oauth2"
	"google.golang.org/api/drive/v3"
	"google.golang.org/api/googleapi"
)

var (
	oauth2TokenSource oauth2.TokenSource // The token is valid for 30 minutes.

	random *rand.Rand
)

func init() {
	random = rand.New(rand.NewSource(time.Now().UnixNano()))
}

// GetGDriveService returns the API service of Google Drive.
func GetGDriveService(
	r *http.Request,
) (
	*drive.Service,
	error,
) {
	n := 1
retry:
	service, err := drive.New(createGDriveClient(r))
	if err == nil {
		return service, nil
	}
	_, n, err = Triable(n, err)
	if err != nil {
		return nil, err
	}
	goto retry
}

func getGDriveFile(
	r *http.Request,
	name string,
	field googleapi.Field,
) (
	*drive.File,
	*drive.Service,
	error,
) {
	if field == "" {
		field = MinimumField
	}

	var refresh bool
	n := 1
refresh:
	service, err := GetGDriveService(r)
	if err != nil {
		return nil, nil, err
	}

retry:
	<-tokenBucketGDriveAPI
	fileList, err := service.Files.List().PageSize(1).Spaces("drive").Q(fmt.Sprintf("name='%s'", name)).Fields(field).Do()

	if err != nil {
		refresh, n, err = Triable(n, err)
		if err != nil {
			return nil, service, err
		}
		if refresh {
			goto refresh
		}
		goto retry
	}

	if len(fileList.Files) <= 0 {
		return nil, service, NewDriveFileDoesNotExistError()
	}
	return fileList.Files[0], service, nil
}

func getGDriveFileByID(
	r *http.Request,
	id string,
	field googleapi.Field,
) (
	*drive.File,
	*drive.Service,
	error,
) {
	if field == "" {
		field = MinimumField
	}

	var refresh bool
	n := 1
refresh:
	service, err := GetGDriveService(r)
	if err != nil {
		return nil, nil, err
	}

retry:
	<-tokenBucketGDriveAPI
	file, err := service.Files.Get(id).Fields(field).Do()

	if err != nil {
		refresh, n, err = Triable(n, err)
		if err != nil {
			return nil, service, err
		}
		if refresh {
			goto refresh
		}
		goto retry
	}

	return file, service, nil
}

// GetGDriveFile returns a file that is a given file name on Google Drive.
func GetGDriveFile(
	r *http.Request,
	name string,
	field googleapi.Field,
) (
	*drive.File,
	error,
) {
	if field == "" {
		field = defaultField
	}

	file, _, err := getGDriveFile(r, name, field)
	if err != nil {
		return nil, err
	}

	return file, nil
}

// GetGDriveFileByID returns a file that is a given `file.Id` on Google Drive.
func GetGDriveFileByID(
	r *http.Request,
	id string,
	field googleapi.Field,
) (
	*drive.File,
	error,
) {
	if field == "" {
		field = defaultField
	}

	file, _, err := getGDriveFileByID(r, id, field)
	if err != nil {
		return nil, err
	}

	return file, nil
}

// GetGDriveFileContent returns a file with content on Google Drive.
func GetGDriveFileContent(
	r *http.Request,
	name string,
	field googleapi.Field,
) (
	*drive.File,
	[]byte, // payload
	error,
) {
	if field == "" {
		field = defaultField
	}

	file, service, err := getGDriveFile(r, name, field)
	if err != nil {
		return nil, nil, err
	}
	fileID := file.Id

	var payload []byte

	var refresh bool
	n := 1
retry:
	httpResponse, err := service.Files.Export(fileID, mimeTxt).Download()
	if IsFileNotExportableError(err) {
		<-tokenBucketGDriveAPI
		err = service.Files.Delete(fileID).Do()
		if err != nil {
			// pass
		}
		return nil, nil, NewDriveFileDoesNotExistError()
	}
	if err != nil {
		refresh, n, err = Triable(n, err)
		if err != nil {
			return nil, nil, err
		}
		if refresh {
			service, err = GetGDriveService(r)
			if err != nil {
				return nil, nil, err
			}
		}
		goto retry
	}

	defer httpResponse.Body.Close()
	payload, err = ioutil.ReadAll(httpResponse.Body)
	if err != nil {
		return nil, nil, err
	}
	return file, payload, err
}

// Triable returns whether it can retry or not.
func Triable(
	retries int,
	err error,
) (
	bool, //refresh
	int, //retries
	error,
) {
	if err == nil {
		return false, retries, nil
	}
	switch {
	case IsInvalidSecurityTicket(err):
		oauth2TokenSource = nil
		return true, retries, nil
	case IsRateLimit(err):
		time.Sleep(msec100)
		return false, retries, nil
	case IsServerError(err):
		retries, err = sleeping(retries)
		if err != nil {
			return false, retries, err
		}
		return false, retries, nil
	}
	return false, retries, err
}

func sleeping(
	n int,
) (
	int,
	error,
) {
	switch {
	case n > 16:
		return 0, errors.New("Sleeping Timeout")
	case n < 1:
		n = 1
	}
	time.Sleep(time.Duration(n)*time.Second + time.Duration(random.Intn(1000))*time.Millisecond)
	return n * 2, nil
}
<|endoftext|>


<commit_before>// Copyright 2015 The Go 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 big

import "testing"

func TestDecimalString(t *testing.T) {
	for _, test := range []struct {
		x    decimal
		want string
	}{
		{want: "0"},
		{decimal{nil, 1000}, "0"}, // exponent of 0 is ignored
		{decimal{[]byte("12345"), 0}, "0.12345"},
		{decimal{[]byte("12345"), -3}, "0.00012345"},
		{decimal{[]byte("12345"), +3}, "123.45"},
		{decimal{[]byte("12345"), +10}, "1234500000"},
	} {
		if got := test.x.String(); got != test.want {
			t.Errorf("%v == %s; want %s", test.x, got, test.want)
		}
	}
}

func TestDecimalInit(t *testing.T) {
	for _, test := range []struct {
		x     Word
		shift int
		want  string
	}{
		{0, 0, "0"},
		{0, -100, "0"},
		{0, 100, "0"},
		{1, 0, "1"},
		{1, 10, "1024"},
		{1, 100, "1267650600228229401496703205376"},
		{1, -100, "0.0000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625"},
		{12345678, 8, "3160493568"},
		{12345678, -8, "48225.3046875"},
		{195312, 9, "99999744"},
		{1953125, 9, "1000000000"},
	} {
		var d decimal
		d.init(nat{test.x}.norm(), test.shift)
		if got := d.String(); got != test.want {
			t.Errorf("%d << %d == %s; want %s", test.x, test.shift, got, test.want)
		}
	}
}

func TestDecimalRounding(t *testing.T) {
	for _, test := range []struct {
		x              uint64
		n              int
		down, even, up string
	}{
		{0, 0, "0", "0", "0"},
		{0, 1, "0", "0", "0"},

		{1, 0, "0", "0", "10"},
		{5, 0, "0", "0", "10"},
		{9, 0, "0", "10", "10"},

		{15, 1, "10", "20", "20"},
		{45, 1, "40", "40", "50"},
		{95, 1, "90", "100", "100"},

		{12344999, 4, "12340000", "12340000", "12350000"},
		{12345000, 4, "12340000", "12340000", "12350000"},
		{12345001, 4, "12340000", "12350000", "12350000"},
		{23454999, 4, "23450000", "23450000", "23460000"},
		{23455000, 4, "23450000", "23460000", "23460000"},
		{23455001, 4, "23450000", "23460000", "23460000"},

		{99994999, 4, "99990000", "99990000", "100000000"},
		{99995000, 4, "99990000", "100000000", "100000000"},
		{99999999, 4, "99990000", "100000000", "100000000"},

		{12994999, 4, "12990000", "12990000", "13000000"},
		{12995000, 4, "12990000", "13000000", "13000000"},
		{12999999, 4, "12990000", "13000000", "13000000"},
	} {
		x := nat(nil).setUint64(test.x)

		var d decimal
		d.init(x, 0)
		d.roundDown(test.n)
		if got := d.String(); got != test.down {
			t.Errorf("roundDown(%d, %d) = %s; want %s", test.x, test.n, got, test.down)
		}

		d.init(x, 0)
		d.round(test.n)
		if got := d.String(); got != test.even {
			t.Errorf("round(%d, %d) = %s; want %s", test.x, test.n, got, test.even)
		}

		d.init(x, 0)
		d.roundUp(test.n)
		if got := d.String(); got != test.up {
			t.Errorf("roundUp(%d, %d) = %s; want %s", test.x, test.n, got, test.up)
		}
	}
}

var sink string

func BenchmarkDecimalConversion(b *testing.B) {
	for i := 0; i < b.N; i++ {
		for shift := -100; shift <= +100; shift++ {
			var d decimal
			d.init(natOne, shift)
			sink = d.String()
		}
	}
}
<commit_msg>math/big: add benchmarks for big.Float String<commit_after>// Copyright 2015 The Go 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 big

import (
	"fmt"
	"testing"
)

func TestDecimalString(t *testing.T) {
	for _, test := range []struct {
		x    decimal
		want string
	}{
		{want: "0"},
		{decimal{nil, 1000}, "0"}, // exponent of 0 is ignored
		{decimal{[]byte("12345"), 0}, "0.12345"},
		{decimal{[]byte("12345"), -3}, "0.00012345"},
		{decimal{[]byte("12345"), +3}, "123.45"},
		{decimal{[]byte("12345"), +10}, "1234500000"},
	} {
		if got := test.x.String(); got != test.want {
			t.Errorf("%v == %s; want %s", test.x, got, test.want)
		}
	}
}

func TestDecimalInit(t *testing.T) {
	for _, test := range []struct {
		x     Word
		shift int
		want  string
	}{
		{0, 0, "0"},
		{0, -100, "0"},
		{0, 100, "0"},
		{1, 0, "1"},
		{1, 10, "1024"},
		{1, 100, "1267650600228229401496703205376"},
		{1, -100, "0.0000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625"},
		{12345678, 8, "3160493568"},
		{12345678, -8, "48225.3046875"},
		{195312, 9, "99999744"},
		{1953125, 9, "1000000000"},
	} {
		var d decimal
		d.init(nat{test.x}.norm(), test.shift)
		if got := d.String(); got != test.want {
			t.Errorf("%d << %d == %s; want %s", test.x, test.shift, got, test.want)
		}
	}
}

func TestDecimalRounding(t *testing.T) {
	for _, test := range []struct {
		x              uint64
		n              int
		down, even, up string
	}{
		{0, 0, "0", "0", "0"},
		{0, 1, "0", "0", "0"},

		{1, 0, "0", "0", "10"},
		{5, 0, "0", "0", "10"},
		{9, 0, "0", "10", "10"},

		{15, 1, "10", "20", "20"},
		{45, 1, "40", "40", "50"},
		{95, 1, "90", "100", "100"},

		{12344999, 4, "12340000", "12340000", "12350000"},
		{12345000, 4, "12340000", "12340000", "12350000"},
		{12345001, 4, "12340000", "12350000", "12350000"},
		{23454999, 4, "23450000", "23450000", "23460000"},
		{23455000, 4, "23450000", "23460000", "23460000"},
		{23455001, 4, "23450000", "23460000", "23460000"},

		{99994999, 4, "99990000", "99990000", "100000000"},
		{99995000, 4, "99990000", "100000000", "100000000"},
		{99999999, 4, "99990000", "100000000", "100000000"},

		{12994999, 4, "12990000", "12990000", "13000000"},
		{12995000, 4, "12990000", "13000000", "13000000"},
		{12999999, 4, "12990000", "13000000", "13000000"},
	} {
		x := nat(nil).setUint64(test.x)

		var d decimal
		d.init(x, 0)
		d.roundDown(test.n)
		if got := d.String(); got != test.down {
			t.Errorf("roundDown(%d, %d) = %s; want %s", test.x, test.n, got, test.down)
		}

		d.init(x, 0)
		d.round(test.n)
		if got := d.String(); got != test.even {
			t.Errorf("round(%d, %d) = %s; want %s", test.x, test.n, got, test.even)
		}

		d.init(x, 0)
		d.roundUp(test.n)
		if got := d.String(); got != test.up {
			t.Errorf("roundUp(%d, %d) = %s; want %s", test.x, test.n, got, test.up)
		}
	}
}

var sink string

func BenchmarkDecimalConversion(b *testing.B) {
	for i := 0; i < b.N; i++ {
		for shift := -100; shift <= +100; shift++ {
			var d decimal
			d.init(natOne, shift)
			sink = d.String()
		}
	}
}

func BenchmarkFloatString(b *testing.B) {
	x := new(Float)
	for _, prec := range []uint{1e2, 1e3, 1e4, 1e5} {
		x.SetPrec(prec).SetRat(NewRat(1, 3))
		b.Run(fmt.Sprintf("%v", prec), func(b *testing.B) {
			b.ReportAllocs()
			for i := 0; i < b.N; i++ {
				sink = x.String()
			}
		})
	}
}
<|endoftext|>


<commit_before>// @author Couchbase <info@couchbase.com>
// @copyright 2014 Couchbase, Inc.
//
// 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 repository

import (
	"github.com/couchbase/gometa/common"
	"github.com/couchbase/gometa/log"
	// fdb "github.com/couchbase/goforestdb"
	"errors"
	fdb "github.com/couchbase/indexing/secondary/fdb"
	"math"
	"sync"
)

/////////////////////////////////////////////////////////////////////////////
// Repository
/////////////////////////////////////////////////////////////////////////////

type RepoKind int

const (
	MAIN RepoKind = iota
	COMMIT_LOG
	SERVER_CONFIG
	LOCAL
)

type Repository struct {
	dbfile    *fdb.File
	stores    map[RepoKind]*fdb.KVStore
	snapshots map[RepoKind][]*Snapshot
	mutex     sync.Mutex
}

type RepoIterator struct {
	iter  *fdb.Iterator
	store *fdb.KVStore
}

type Snapshot struct {
	snapshot *fdb.KVStore
	count    int
	txnid    common.Txnid
	mutex    sync.Mutex
}

/////////////////////////////////////////////////////////////////////////////
// Repository Public Function
/////////////////////////////////////////////////////////////////////////////

//
// Open a repository
//
func OpenRepository() (*Repository, error) {
	return OpenRepositoryWithName(common.REPOSITORY_NAME, uint64(0))
}

func OpenRepositoryWithName(name string, memory_quota uint64) (repo *Repository, err error) {
	return OpenRepositoryWithName2(name, memory_quota, uint64(600), uint8(30), uint64(0))
}

func OpenRepositoryWithName2(name string, memory_quota uint64, sleepDur uint64, threshold uint8, minFileSize uint64) (repo *Repository, err error) {

	if memory_quota < common.MIN_FOREST_DB_CACHE_SIZE {
		memory_quota = common.MIN_FOREST_DB_CACHE_SIZE
	}

	log.Current.Debugf("Repo.OpenRepositoryWithName(): open repo with name %s, buffer cache size %d", name, memory_quota)

	config := fdb.DefaultConfig()
	config.SetBufferCacheSize(memory_quota)

	config.SetCompactionMode(fdb.COMPACT_AUTO)
	config.SetBlockReuseThreshold(uint8(0))

	config.SetCompactorSleepDuration(sleepDur)
	config.SetCompactionThreshold(threshold)

	if minFileSize != 0 {
		config.SetCompactionMinimumFilesize(minFileSize)
	}

	dbfile, err := fdb.Open(name, config)
	if err != nil {
		return nil, err
	}

	cleanup := common.NewCleanup(func() {
		dbfile.Close()
	})
	defer cleanup.Run()

	stores := make(map[RepoKind]*fdb.KVStore)

	if stores[MAIN], err = dbfile.OpenKVStore("MAIN", nil); err != nil {
		return nil, err
	}
	if stores[COMMIT_LOG], err = dbfile.OpenKVStore("COMMIT_LOG", nil); err != nil {
		return nil, err
	}
	if stores[SERVER_CONFIG], err = dbfile.OpenKVStore("SERVER_CONFIG", nil); err != nil {
		return nil, err
	}
	if stores[LOCAL], err = dbfile.OpenKVStore("LOCAL", nil); err != nil {
		return nil, err
	}
	cleanup.Cancel()

	snapshots := make(map[RepoKind][]*Snapshot)
	snapshots[MAIN] = nil
	snapshots[COMMIT_LOG] = nil
	snapshots[SERVER_CONFIG] = nil
	snapshots[LOCAL] = nil

	repo = &Repository{dbfile: dbfile,
		stores:    stores,
		snapshots: snapshots}

	return repo, nil
}

//
// Update/Insert into the repository
//
func (r *Repository) Set(kind RepoKind, key string, content []byte) error {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return errors.New("repo closed")
	}

	log.Current.Debugf("Repo.Set(): key %s, len(content) %d", key, len(content))

	//convert key to its collatejson encoded byte representation
	k, err := CollateString(key)
	if err != nil {
		return err
	}

	// set value
	err = r.stores[kind].SetKV(k, content)
	if err != nil {
		return err
	}

	return r.dbfile.Commit(fdb.COMMIT_NORMAL)
}

func (r *Repository) CreateSnapshot(kind RepoKind, txnid common.Txnid) error {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return errors.New("repo closed")
	}

	info, err := r.stores[kind].Info()
	if err != nil {
		return err
	}

	fdbSnapshot, err := r.stores[kind].SnapshotOpen(info.LastSeqNum())
	if err != nil {
		return err
	}

	snapshot := &Snapshot{snapshot: fdbSnapshot,
		txnid: txnid,
		count: 0}

	r.pruneSnapshotNoLock(kind)

	r.snapshots[kind] = append(r.snapshots[kind], snapshot)

	log.Current.Debugf("Repo.CreateSnapshot(): txnid %v, forestdb seqnum %v", txnid, info.LastSeqNum())
	return nil
}

func (r *Repository) AcquireSnapshot(kind RepoKind) (common.Txnid, *RepoIterator, error) {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return common.Txnid(0), nil, errors.New("repo closed")
	}

	if len(r.snapshots[kind]) == 0 {
		return common.Txnid(0), nil, nil
	}

	snapshot := r.snapshots[kind][len(r.snapshots[kind])-1]
	snapshot.count++

	// Create a snaphsot for iteration
	var FORESTDB_INMEMSEQ = fdb.SeqNum(math.MaxUint64)
	kvstore, err := snapshot.snapshot.SnapshotOpen(FORESTDB_INMEMSEQ)

	iter, err := kvstore.IteratorInit(nil, nil, fdb.ITR_NO_DELETES)
	if err != nil {
		return common.Txnid(0), nil, err
	}
	return snapshot.txnid, &RepoIterator{iter: iter, store: kvstore}, nil
}

func (r *Repository) ReleaseSnapshot(kind RepoKind, txnid common.Txnid) {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	for _, snapshot := range r.snapshots[kind] {
		if snapshot.txnid == txnid && snapshot.count > 0 {
			snapshot.count--
		}
	}
}

func (r *Repository) pruneSnapshotNoLock(kind RepoKind) {

	var newList []*Snapshot = nil
	for _, snapshot := range r.snapshots[kind] {
		if snapshot.count > 0 {
			newList = append(newList, snapshot)
		} else {
			// closing snapshot
			snapshot.snapshot.Close()
		}
	}

	r.snapshots[kind] = newList
}

//
// Update/Insert into the repository
//
func (r *Repository) SetNoCommit(kind RepoKind, key string, content []byte) error {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return errors.New("repo closed")
	}

	log.Current.Debugf("Repo.SetNoCommit(): key %s, len(content) %d", key, len(content))

	//convert key to its collatejson encoded byte representation
	k, err := CollateString(key)
	if err != nil {
		return err
	}

	// set value
	return r.stores[kind].SetKV(k, content)
}

//
// Retrieve from repository
//
func (r *Repository) Get(kind RepoKind, key string) ([]byte, error) {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return nil, errors.New("repo closed")
	}

	//convert key to its collatejson encoded byte representation
	k, err := CollateString(key)
	if err != nil {
		return nil, err
	}

	value, err := r.stores[kind].GetKV(k)
	log.Current.Tracef("Repo.Get(): key %s, found=%v", key, err == nil)
	return value, err
}

//
// Delete from repository
//
func (r *Repository) Delete(kind RepoKind, key string) error {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return errors.New("repo closed")
	}

	//convert key to its collatejson encoded byte representation
	k, err := CollateString(key)
	if err != nil {
		return err
	}

	err = r.stores[kind].DeleteKV(k)
	if err != nil {
		return err
	}

	return r.dbfile.Commit(fdb.COMMIT_NORMAL)
}

//
// Delete from repository
//
func (r *Repository) DeleteNoCommit(kind RepoKind, key string) error {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return errors.New("repo closed")
	}

	//convert key to its collatejson encoded byte representation
	k, err := CollateString(key)
	if err != nil {
		return err
	}

	return r.stores[kind].DeleteKV(k)
}

//
// Delete from repository
//
func (r *Repository) Commit() error {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return errors.New("repo closed")
	}

	return r.dbfile.Commit(fdb.COMMIT_NORMAL)
}

//
// Close repository.
//
func (r *Repository) Close() {
	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile != nil {
		for _, snapshot := range r.snapshots[MAIN] {
			snapshot.snapshot.Close()
		}
		for _, snapshot := range r.snapshots[COMMIT_LOG] {
			snapshot.snapshot.Close()
		}
		for _, snapshot := range r.snapshots[SERVER_CONFIG] {
			snapshot.snapshot.Close()
		}
		for _, snapshot := range r.snapshots[LOCAL] {
			snapshot.snapshot.Close()
		}
		r.snapshots = nil

		for _, store := range r.stores {
			store.Close()
		}
		r.stores = nil

		r.dbfile.Close()
		r.dbfile = nil
	}
}

/////////////////////////////////////////////////////////////////////////////
// RepoIterator Public Function
/////////////////////////////////////////////////////////////////////////////

//
// Create a new iterator.  EndKey is inclusive.
//
func (r *Repository) NewIterator(kind RepoKind, startKey, endKey string) (*RepoIterator, error) {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return nil, errors.New("repo closed")
	}

	k1, err := CollateString(startKey)
	if err != nil {
		return nil, err
	}

	k2, err := CollateString(endKey)
	if err != nil {
		return nil, err
	}

	// Create a snaphsot for iteration
	var FORESTDB_INMEMSEQ = fdb.SeqNum(math.MaxUint64)
	snapshot, err := r.stores[kind].SnapshotOpen(FORESTDB_INMEMSEQ)

	iter, err := snapshot.IteratorInit(k1, k2, fdb.ITR_NO_DELETES)
	if err != nil {
		return nil, err
	}
	result := &RepoIterator{iter: iter, store: snapshot}
	return result, nil
}

// Get value from iterator
func (i *RepoIterator) Next() (key string, content []byte, err error) {

	if i.iter == nil {
		return "", nil, fdb.RESULT_ITERATOR_FAIL
	}

	doc, err := i.iter.Get()
	if err != nil {
		return "", nil, err
	}

	err = i.iter.Next()
	if err != nil && err != fdb.RESULT_ITERATOR_FAIL {
		return "", nil, err
	}

	//i.db.Get(doc)
	key = DecodeString(doc.Key())
	body := doc.Body()

	if err == fdb.RESULT_ITERATOR_FAIL {
		i.iter = nil
	}

	return key, body, nil
}

// close iterator
func (i *RepoIterator) Close() {
	// TODO: Check if fdb iterator is closed
	if i.iter != nil {
		i.iter.Close()
		i.iter = nil
	}

	if i.store != nil {
		i.store.Close()
		i.store = nil
	}
}

// This only support ascii.
func CollateString(key string) ([]byte, error) {
	if key == "" {
		return nil, nil
	}

	return ([]byte)(key), nil
}

func DecodeString(data []byte) string {
	return string(data)
}
<commit_msg>MB-32192: comment out auto compaction<commit_after>// @author Couchbase <info@couchbase.com>
// @copyright 2014 Couchbase, Inc.
//
// 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 repository

import (
	"github.com/couchbase/gometa/common"
	"github.com/couchbase/gometa/log"
	// fdb "github.com/couchbase/goforestdb"
	"errors"
	fdb "github.com/couchbase/indexing/secondary/fdb"
	"math"
	"sync"
)

/////////////////////////////////////////////////////////////////////////////
// Repository
/////////////////////////////////////////////////////////////////////////////

type RepoKind int

const (
	MAIN RepoKind = iota
	COMMIT_LOG
	SERVER_CONFIG
	LOCAL
)

type Repository struct {
	dbfile    *fdb.File
	stores    map[RepoKind]*fdb.KVStore
	snapshots map[RepoKind][]*Snapshot
	mutex     sync.Mutex
}

type RepoIterator struct {
	iter  *fdb.Iterator
	store *fdb.KVStore
}

type Snapshot struct {
	snapshot *fdb.KVStore
	count    int
	txnid    common.Txnid
	mutex    sync.Mutex
}

/////////////////////////////////////////////////////////////////////////////
// Repository Public Function
/////////////////////////////////////////////////////////////////////////////

//
// Open a repository
//
func OpenRepository() (*Repository, error) {
	return OpenRepositoryWithName(common.REPOSITORY_NAME, uint64(0))
}

func OpenRepositoryWithName(name string, memory_quota uint64) (repo *Repository, err error) {
	return OpenRepositoryWithName2(name, memory_quota, uint64(600), uint8(30), uint64(0))
}

func OpenRepositoryWithName2(name string, memory_quota uint64, sleepDur uint64, threshold uint8, minFileSize uint64) (repo *Repository, err error) {

	if memory_quota < common.MIN_FOREST_DB_CACHE_SIZE {
		memory_quota = common.MIN_FOREST_DB_CACHE_SIZE
	}

	log.Current.Debugf("Repo.OpenRepositoryWithName(): open repo with name %s, buffer cache size %d", name, memory_quota)

	config := fdb.DefaultConfig()
	config.SetBufferCacheSize(memory_quota)

	/*
		config.SetCompactionMode(fdb.COMPACT_AUTO)
		config.SetBlockReuseThreshold(uint8(0))

		config.SetCompactorSleepDuration(sleepDur)
		config.SetCompactionThreshold(threshold)

		if minFileSize != 0 {
			config.SetCompactionMinimumFilesize(minFileSize)
		}
	*/

	dbfile, err := fdb.Open(name, config)
	if err != nil {
		return nil, err
	}

	cleanup := common.NewCleanup(func() {
		dbfile.Close()
	})
	defer cleanup.Run()

	stores := make(map[RepoKind]*fdb.KVStore)

	if stores[MAIN], err = dbfile.OpenKVStore("MAIN", nil); err != nil {
		return nil, err
	}
	if stores[COMMIT_LOG], err = dbfile.OpenKVStore("COMMIT_LOG", nil); err != nil {
		return nil, err
	}
	if stores[SERVER_CONFIG], err = dbfile.OpenKVStore("SERVER_CONFIG", nil); err != nil {
		return nil, err
	}
	if stores[LOCAL], err = dbfile.OpenKVStore("LOCAL", nil); err != nil {
		return nil, err
	}
	cleanup.Cancel()

	snapshots := make(map[RepoKind][]*Snapshot)
	snapshots[MAIN] = nil
	snapshots[COMMIT_LOG] = nil
	snapshots[SERVER_CONFIG] = nil
	snapshots[LOCAL] = nil

	repo = &Repository{dbfile: dbfile,
		stores:    stores,
		snapshots: snapshots}

	return repo, nil
}

//
// Update/Insert into the repository
//
func (r *Repository) Set(kind RepoKind, key string, content []byte) error {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return errors.New("repo closed")
	}

	log.Current.Debugf("Repo.Set(): key %s, len(content) %d", key, len(content))

	//convert key to its collatejson encoded byte representation
	k, err := CollateString(key)
	if err != nil {
		return err
	}

	// set value
	err = r.stores[kind].SetKV(k, content)
	if err != nil {
		return err
	}

	return r.dbfile.Commit(fdb.COMMIT_NORMAL)
}

func (r *Repository) CreateSnapshot(kind RepoKind, txnid common.Txnid) error {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return errors.New("repo closed")
	}

	info, err := r.stores[kind].Info()
	if err != nil {
		return err
	}

	fdbSnapshot, err := r.stores[kind].SnapshotOpen(info.LastSeqNum())
	if err != nil {
		return err
	}

	snapshot := &Snapshot{snapshot: fdbSnapshot,
		txnid: txnid,
		count: 0}

	r.pruneSnapshotNoLock(kind)

	r.snapshots[kind] = append(r.snapshots[kind], snapshot)

	log.Current.Debugf("Repo.CreateSnapshot(): txnid %v, forestdb seqnum %v", txnid, info.LastSeqNum())
	return nil
}

func (r *Repository) AcquireSnapshot(kind RepoKind) (common.Txnid, *RepoIterator, error) {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return common.Txnid(0), nil, errors.New("repo closed")
	}

	if len(r.snapshots[kind]) == 0 {
		return common.Txnid(0), nil, nil
	}

	snapshot := r.snapshots[kind][len(r.snapshots[kind])-1]
	snapshot.count++

	// Create a snaphsot for iteration
	var FORESTDB_INMEMSEQ = fdb.SeqNum(math.MaxUint64)
	kvstore, err := snapshot.snapshot.SnapshotOpen(FORESTDB_INMEMSEQ)

	iter, err := kvstore.IteratorInit(nil, nil, fdb.ITR_NO_DELETES)
	if err != nil {
		return common.Txnid(0), nil, err
	}
	return snapshot.txnid, &RepoIterator{iter: iter, store: kvstore}, nil
}

func (r *Repository) ReleaseSnapshot(kind RepoKind, txnid common.Txnid) {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	for _, snapshot := range r.snapshots[kind] {
		if snapshot.txnid == txnid && snapshot.count > 0 {
			snapshot.count--
		}
	}
}

func (r *Repository) pruneSnapshotNoLock(kind RepoKind) {

	var newList []*Snapshot = nil
	for _, snapshot := range r.snapshots[kind] {
		if snapshot.count > 0 {
			newList = append(newList, snapshot)
		} else {
			// closing snapshot
			snapshot.snapshot.Close()
		}
	}

	r.snapshots[kind] = newList
}

//
// Update/Insert into the repository
//
func (r *Repository) SetNoCommit(kind RepoKind, key string, content []byte) error {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return errors.New("repo closed")
	}

	log.Current.Debugf("Repo.SetNoCommit(): key %s, len(content) %d", key, len(content))

	//convert key to its collatejson encoded byte representation
	k, err := CollateString(key)
	if err != nil {
		return err
	}

	// set value
	return r.stores[kind].SetKV(k, content)
}

//
// Retrieve from repository
//
func (r *Repository) Get(kind RepoKind, key string) ([]byte, error) {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return nil, errors.New("repo closed")
	}

	//convert key to its collatejson encoded byte representation
	k, err := CollateString(key)
	if err != nil {
		return nil, err
	}

	value, err := r.stores[kind].GetKV(k)
	log.Current.Tracef("Repo.Get(): key %s, found=%v", key, err == nil)
	return value, err
}

//
// Delete from repository
//
func (r *Repository) Delete(kind RepoKind, key string) error {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return errors.New("repo closed")
	}

	//convert key to its collatejson encoded byte representation
	k, err := CollateString(key)
	if err != nil {
		return err
	}

	err = r.stores[kind].DeleteKV(k)
	if err != nil {
		return err
	}

	return r.dbfile.Commit(fdb.COMMIT_NORMAL)
}

//
// Delete from repository
//
func (r *Repository) DeleteNoCommit(kind RepoKind, key string) error {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return errors.New("repo closed")
	}

	//convert key to its collatejson encoded byte representation
	k, err := CollateString(key)
	if err != nil {
		return err
	}

	return r.stores[kind].DeleteKV(k)
}

//
// Delete from repository
//
func (r *Repository) Commit() error {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return errors.New("repo closed")
	}

	return r.dbfile.Commit(fdb.COMMIT_NORMAL)
}

//
// Close repository.
//
func (r *Repository) Close() {
	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile != nil {
		for _, snapshot := range r.snapshots[MAIN] {
			snapshot.snapshot.Close()
		}
		for _, snapshot := range r.snapshots[COMMIT_LOG] {
			snapshot.snapshot.Close()
		}
		for _, snapshot := range r.snapshots[SERVER_CONFIG] {
			snapshot.snapshot.Close()
		}
		for _, snapshot := range r.snapshots[LOCAL] {
			snapshot.snapshot.Close()
		}
		r.snapshots = nil

		for _, store := range r.stores {
			store.Close()
		}
		r.stores = nil

		r.dbfile.Close()
		r.dbfile = nil
	}
}

/////////////////////////////////////////////////////////////////////////////
// RepoIterator Public Function
/////////////////////////////////////////////////////////////////////////////

//
// Create a new iterator.  EndKey is inclusive.
//
func (r *Repository) NewIterator(kind RepoKind, startKey, endKey string) (*RepoIterator, error) {

	r.mutex.Lock()
	defer r.mutex.Unlock()

	if r.dbfile == nil {
		return nil, errors.New("repo closed")
	}

	k1, err := CollateString(startKey)
	if err != nil {
		return nil, err
	}

	k2, err := CollateString(endKey)
	if err != nil {
		return nil, err
	}

	// Create a snaphsot for iteration
	var FORESTDB_INMEMSEQ = fdb.SeqNum(math.MaxUint64)
	snapshot, err := r.stores[kind].SnapshotOpen(FORESTDB_INMEMSEQ)

	iter, err := snapshot.IteratorInit(k1, k2, fdb.ITR_NO_DELETES)
	if err != nil {
		return nil, err
	}
	result := &RepoIterator{iter: iter, store: snapshot}
	return result, nil
}

// Get value from iterator
func (i *RepoIterator) Next() (key string, content []byte, err error) {

	if i.iter == nil {
		return "", nil, fdb.RESULT_ITERATOR_FAIL
	}

	doc, err := i.iter.Get()
	if err != nil {
		return "", nil, err
	}

	err = i.iter.Next()
	if err != nil && err != fdb.RESULT_ITERATOR_FAIL {
		return "", nil, err
	}

	//i.db.Get(doc)
	key = DecodeString(doc.Key())
	body := doc.Body()

	if err == fdb.RESULT_ITERATOR_FAIL {
		i.iter = nil
	}

	return key, body, nil
}

// close iterator
func (i *RepoIterator) Close() {
	// TODO: Check if fdb iterator is closed
	if i.iter != nil {
		i.iter.Close()
		i.iter = nil
	}

	if i.store != nil {
		i.store.Close()
		i.store = nil
	}
}

// This only support ascii.
func CollateString(key string) ([]byte, error) {
	if key == "" {
		return nil, nil
	}

	return ([]byte)(key), nil
}

func DecodeString(data []byte) string {
	return string(data)
}
<|endoftext|>


<commit_before>// +build linux

// Copyright 2020 Google Inc. All Rights Reserved.
//
// 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.

// Manager of resctrl for containers.
package resctrl

import (
	"github.com/google/cadvisor/stats"

	"github.com/opencontainers/runc/libcontainer/intelrdt"
)

type manager struct {
	id string
	stats.NoopDestroy
}

func (m manager) GetCollector(resctrlPath string) (stats.Collector, error) {
	collector := newCollector(m.id, resctrlPath)
	return collector, nil
}

func NewManager(id string) (stats.Manager, error) {

	if intelrdt.IsMBMEnabled() || intelrdt.IsCMTEnabled() {
		return &manager{id: id}, nil
	}

	return &stats.NoopManager{}, nil
}
<commit_msg>Add checking if resctrl path exists<commit_after>// +build linux

// Copyright 2020 Google Inc. All Rights Reserved.
//
// 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.

// Manager of resctrl for containers.
package resctrl

import (
	"os"

	"github.com/google/cadvisor/stats"

	"github.com/opencontainers/runc/libcontainer/intelrdt"
)

type manager struct {
	id string
	stats.NoopDestroy
}

func (m manager) GetCollector(resctrlPath string) (stats.Collector, error) {
	if _, err := os.Stat(resctrlPath); err != nil {
		return &stats.NoopCollector{}, err
	}
	collector := newCollector(m.id, resctrlPath)
	return collector, nil
}

func NewManager(id string) (stats.Manager, error) {

	if intelrdt.IsMBMEnabled() || intelrdt.IsCMTEnabled() {
		return &manager{id: id}, nil
	}

	return &stats.NoopManager{}, nil
}
<|endoftext|>