<commit_before>package compact

import (
	"os"
	"sort"

	"github.com/kezhuw/leveldb/internal/configs"
	"github.com/kezhuw/leveldb/internal/errors"
	"github.com/kezhuw/leveldb/internal/file"
	"github.com/kezhuw/leveldb/internal/files"
	"github.com/kezhuw/leveldb/internal/keys"
	"github.com/kezhuw/leveldb/internal/options"
	"github.com/kezhuw/leveldb/internal/table"
	"github.com/kezhuw/leveldb/internal/version"
)

func NewLevelCompaction(dbname string, seq keys.Sequence, compaction *version.Compaction, s *version.State, opts *options.Options) Compactor {
	if compaction.IsTrivialMove() {
		return &moveCompaction{c: compaction}
	}
	c := &levelCompaction{
		dbname:           dbname,
		state:            s,
		options:          opts,
		fs:               opts.FileSystem,
		Compaction:       compaction,
		smallestSequence: seq,
	}
	return c
}

type moveCompaction struct {
	c *version.Compaction
}

type levelCompaction struct {
	*version.Compaction

	state   *version.State
	dbname  string
	options *options.Options
	fs      file.FileSystem

	smallestSequence keys.Sequence

	outputs []version.FileMeta

	tableName   string
	tableMeta   version.FileMeta
	tableFile   file.WriteCloser
	tableWriter table.Writer

	fileNumbers    []uint64
	fileNumbersOff int
	nextFileNumber uint64

	grandparentsIndex           int
	grandparentsSeenKey         bool
	grandparentsOverlappedBytes uint64

	levelFilePointers [configs.NumberLevels]int
}

func (c *moveCompaction) Level() int {
	return c.c.Level
}

func (c *moveCompaction) Rewind() {
}

func (c *moveCompaction) FileNumbers() []uint64 {
	return nil
}

func (c *moveCompaction) Compact(edit *version.Edit) error {
	f := c.c.Inputs[0][0]
	edit.AddedFiles = append(edit.AddedFiles[:0], version.LevelFileMeta{Level: c.c.Level + 1, FileMeta: f})
	edit.DeletedFiles = append(edit.DeletedFiles[:0], version.LevelFileNumber{Level: c.c.Level, Number: f.Number})
	return nil
}

var zeroLevelFilePointers [configs.NumberLevels]int

func (c *levelCompaction) Level() int {
	return c.Compaction.Level
}

func (c *levelCompaction) Rewind() {
	if c.tableFile != nil {
		c.tableFile.Close()
		c.tableFile = nil
	}
	c.outputs = c.outputs[:0]
	c.fileNumbersOff = 0
	c.grandparentsIndex = 0
	c.grandparentsSeenKey = false
	c.grandparentsOverlappedBytes = 0
	copy(c.levelFilePointers[:], zeroLevelFilePointers[:])
}

func (c *levelCompaction) FileNumbers() []uint64 {
	return c.fileNumbers
}

func (c *levelCompaction) closeCurrentTable() error {
	f := c.tableFile
	if f == nil {
		return nil
	}
	c.tableFile = nil
	defer f.Close()

	c.tableMeta.Largest = append(c.tableMeta.Largest[:0], c.tableWriter.LastKey()...)
	err := c.tableWriter.Finish()
	if err != nil {
		return err
	}
	err = f.Sync()
	if err != nil {
		return err
	}
	c.outputs = append(c.outputs, version.FileMeta{
		Number:   c.tableMeta.Number,
		Size:     uint64(c.tableWriter.FileSize()),
		Smallest: c.tableMeta.Smallest.Dup(),
		Largest:  c.tableMeta.Largest.Dup()})
	return nil
}

func (c *levelCompaction) newFileNumber() uint64 {
	if c.fileNumbersOff < len(c.fileNumbers) {
		x := c.fileNumbers[c.fileNumbersOff]
		c.fileNumbersOff++
		return x
	}
	var fileNumber uint64
	fileNumber, c.nextFileNumber = c.state.NewFileNumber()
	c.fileNumbers = append(c.fileNumbers, fileNumber)
	c.fileNumbersOff = len(c.fileNumbers)
	return fileNumber
}

func (c *levelCompaction) openTableFile() error {
	err := c.closeCurrentTable()
	if err != nil {
		return err
	}
	tableNumber := c.newFileNumber()
	tableName := files.TableFileName(c.dbname, tableNumber)
	f, err := c.fs.Open(tableName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC)
	if err != nil {
		return err
	}
	c.tableName = tableName
	c.tableFile = f
	c.tableMeta.Number = tableNumber
	c.tableWriter.Reset(f, c.options)
	return nil
}

func (c *levelCompaction) shouldStopBefore(ikey []byte) bool {
	icmp := c.options.Comparator
	for c.grandparentsIndex < len(c.Grandparents) && icmp.Compare(ikey, c.Grandparents[c.grandparentsIndex].Largest) > 0 {
		if c.grandparentsSeenKey {
			c.grandparentsOverlappedBytes += c.Grandparents[c.grandparentsIndex].Size
		}
		c.grandparentsIndex++
	}
	c.grandparentsSeenKey = true
	return c.grandparentsOverlappedBytes > configs.MaxGrandparentOverlappingBytes
}

func (c *levelCompaction) isBaseLevelForKey(ukey []byte) bool {
	ucmp := c.options.Comparator.UserKeyComparator
	v := c.Base
	for level := c.Level() + 2; level < configs.NumberLevels; level++ {
		k := c.levelFilePointers[level]
		files := v.Levels[level][k:]
		n := len(files)
		if n == 0 {
			continue
		}
		i := sort.Search(n, func(i int) bool { return ucmp.Compare(ukey, files[i].Largest.UserKey()) <= 0 })
		c.levelFilePointers[level] = k + i
		if i != n && ucmp.Compare(ukey, files[i].Smallest) >= 0 {
			return false
		}
	}
	return true
}

func (c *levelCompaction) add(key, value []byte, firstTime bool) error {
	// We save keys with same user key in same table, so tables in level+1
	// will not overlap with each other in user key space.
	switch {
	case c.tableFile == nil:
		fallthrough
	case firstTime && (c.tableWriter.FileSize() >= c.MaxOutputFileSize || c.shouldStopBefore(key)):
		err := c.openTableFile()
		if err != nil {
			return err
		}
	}
	if c.tableWriter.Empty() {
		c.tableMeta.Smallest = append(c.tableMeta.Smallest[:0], key...)
	}
	return c.tableWriter.Add(key, value)
}

func (c *levelCompaction) compact() error {
	it := c.NewIterator()
	defer it.Release()

	ucmp := c.options.Comparator.UserKeyComparator
	var lastKey keys.InternalKey
	var lastSequence keys.Sequence
	for it.Next() {
		ikey := it.Key()
		currentUserKey, currentSequence, kind, ok := keys.SplitInternalKey3(ikey)
		if !ok {
			return errors.ErrCorruptInternalKey
		}
		if len(lastKey) == 0 || ucmp.Compare(lastKey.UserKey(), currentUserKey) != 0 {
			lastKey = append(lastKey[:0], currentUserKey...)
			lastSequence = keys.MaxSequence
		}
		switch {
		case lastSequence <= c.smallestSequence:
		case kind == keys.Delete && currentSequence <= c.smallestSequence && c.isBaseLevelForKey(currentUserKey):
		default:
			err := c.add(ikey, it.Value(), lastSequence == keys.MaxSequence)
			if err != nil {
				return err
			}
		}
		lastSequence = currentSequence
	}

	if err := c.closeCurrentTable(); err != nil {
		return err
	}

	return it.Err()
}

func (c *levelCompaction) record(edit *version.Edit) {
	level := c.Level()
	for which := 0; which < 2; which++ {
		files := c.Inputs[which]
		for _, f := range files {
			edit.DeletedFiles = append(edit.DeletedFiles, version.LevelFileNumber{Level: level + which, Number: f.Number})
		}
	}
	for _, f := range c.outputs {
		edit.AddedFiles = append(edit.AddedFiles, version.LevelFileMeta{Level: level + 1, FileMeta: f})
	}
	edit.CompactPointers = append(edit.CompactPointers, version.LevelCompactPointer{Level: level, Largest: c.NextCompactPointer})
	if c.nextFileNumber > edit.NextFileNumber {
		edit.NextFileNumber = c.nextFileNumber
	}
}

func (c *levelCompaction) Compact(edit *version.Edit) error {
	err := c.compact()
	if err != nil {
		return err
	}
	c.record(edit)
	return nil
}
<commit_msg>Reset grandparents overlapped bytes for new table<commit_after>package compact

import (
	"os"
	"sort"

	"github.com/kezhuw/leveldb/internal/configs"
	"github.com/kezhuw/leveldb/internal/errors"
	"github.com/kezhuw/leveldb/internal/file"
	"github.com/kezhuw/leveldb/internal/files"
	"github.com/kezhuw/leveldb/internal/keys"
	"github.com/kezhuw/leveldb/internal/options"
	"github.com/kezhuw/leveldb/internal/table"
	"github.com/kezhuw/leveldb/internal/version"
)

func NewLevelCompaction(dbname string, seq keys.Sequence, compaction *version.Compaction, s *version.State, opts *options.Options) Compactor {
	if compaction.IsTrivialMove() {
		return &moveCompaction{c: compaction}
	}
	c := &levelCompaction{
		dbname:           dbname,
		state:            s,
		options:          opts,
		fs:               opts.FileSystem,
		Compaction:       compaction,
		smallestSequence: seq,
	}
	return c
}

type moveCompaction struct {
	c *version.Compaction
}

type levelCompaction struct {
	*version.Compaction

	state   *version.State
	dbname  string
	options *options.Options
	fs      file.FileSystem

	smallestSequence keys.Sequence

	outputs []version.FileMeta

	tableName   string
	tableMeta   version.FileMeta
	tableFile   file.WriteCloser
	tableWriter table.Writer

	fileNumbers    []uint64
	fileNumbersOff int
	nextFileNumber uint64

	grandparentsIndex           int
	grandparentsSeenKey         bool
	grandparentsOverlappedBytes uint64

	levelFilePointers [configs.NumberLevels]int
}

func (c *moveCompaction) Level() int {
	return c.c.Level
}

func (c *moveCompaction) Rewind() {
}

func (c *moveCompaction) FileNumbers() []uint64 {
	return nil
}

func (c *moveCompaction) Compact(edit *version.Edit) error {
	f := c.c.Inputs[0][0]
	edit.AddedFiles = append(edit.AddedFiles[:0], version.LevelFileMeta{Level: c.c.Level + 1, FileMeta: f})
	edit.DeletedFiles = append(edit.DeletedFiles[:0], version.LevelFileNumber{Level: c.c.Level, Number: f.Number})
	return nil
}

var zeroLevelFilePointers [configs.NumberLevels]int

func (c *levelCompaction) Level() int {
	return c.Compaction.Level
}

func (c *levelCompaction) Rewind() {
	if c.tableFile != nil {
		c.tableFile.Close()
		c.tableFile = nil
	}
	c.outputs = c.outputs[:0]
	c.fileNumbersOff = 0
	c.grandparentsIndex = 0
	c.grandparentsSeenKey = false
	c.grandparentsOverlappedBytes = 0
	copy(c.levelFilePointers[:], zeroLevelFilePointers[:])
}

func (c *levelCompaction) FileNumbers() []uint64 {
	return c.fileNumbers
}

func (c *levelCompaction) closeCurrentTable() error {
	f := c.tableFile
	if f == nil {
		return nil
	}
	c.tableFile = nil
	defer f.Close()

	c.tableMeta.Largest = append(c.tableMeta.Largest[:0], c.tableWriter.LastKey()...)
	err := c.tableWriter.Finish()
	if err != nil {
		return err
	}
	err = f.Sync()
	if err != nil {
		return err
	}
	c.outputs = append(c.outputs, version.FileMeta{
		Number:   c.tableMeta.Number,
		Size:     uint64(c.tableWriter.FileSize()),
		Smallest: c.tableMeta.Smallest.Dup(),
		Largest:  c.tableMeta.Largest.Dup()})
	return nil
}

func (c *levelCompaction) newFileNumber() uint64 {
	if c.fileNumbersOff < len(c.fileNumbers) {
		x := c.fileNumbers[c.fileNumbersOff]
		c.fileNumbersOff++
		return x
	}
	var fileNumber uint64
	fileNumber, c.nextFileNumber = c.state.NewFileNumber()
	c.fileNumbers = append(c.fileNumbers, fileNumber)
	c.fileNumbersOff = len(c.fileNumbers)
	return fileNumber
}

func (c *levelCompaction) openTableFile() error {
	err := c.closeCurrentTable()
	if err != nil {
		return err
	}
	tableNumber := c.newFileNumber()
	tableName := files.TableFileName(c.dbname, tableNumber)
	f, err := c.fs.Open(tableName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC)
	if err != nil {
		return err
	}
	c.tableName = tableName
	c.tableFile = f
	c.tableMeta.Number = tableNumber
	c.tableWriter.Reset(f, c.options)
	c.grandparentsOverlappedBytes = 0
	return nil
}

func (c *levelCompaction) shouldStopBefore(ikey []byte) bool {
	icmp := c.options.Comparator
	for c.grandparentsIndex < len(c.Grandparents) && icmp.Compare(ikey, c.Grandparents[c.grandparentsIndex].Largest) > 0 {
		if c.grandparentsSeenKey {
			c.grandparentsOverlappedBytes += c.Grandparents[c.grandparentsIndex].Size
		}
		c.grandparentsIndex++
	}
	c.grandparentsSeenKey = true
	return c.grandparentsOverlappedBytes > configs.MaxGrandparentOverlappingBytes
}

func (c *levelCompaction) isBaseLevelForKey(ukey []byte) bool {
	ucmp := c.options.Comparator.UserKeyComparator
	v := c.Base
	for level := c.Level() + 2; level < configs.NumberLevels; level++ {
		k := c.levelFilePointers[level]
		files := v.Levels[level][k:]
		n := len(files)
		if n == 0 {
			continue
		}
		i := sort.Search(n, func(i int) bool { return ucmp.Compare(ukey, files[i].Largest.UserKey()) <= 0 })
		c.levelFilePointers[level] = k + i
		if i != n && ucmp.Compare(ukey, files[i].Smallest) >= 0 {
			return false
		}
	}
	return true
}

func (c *levelCompaction) add(key, value []byte, firstTime bool) error {
	// We save keys with same user key in same table, so tables in level+1
	// will not overlap with each other in user key space.
	switch {
	case c.tableFile == nil:
		fallthrough
	case firstTime && (c.tableWriter.FileSize() >= c.MaxOutputFileSize || c.shouldStopBefore(key)):
		err := c.openTableFile()
		if err != nil {
			return err
		}
	}
	if c.tableWriter.Empty() {
		c.tableMeta.Smallest = append(c.tableMeta.Smallest[:0], key...)
	}
	return c.tableWriter.Add(key, value)
}

func (c *levelCompaction) compact() error {
	it := c.NewIterator()
	defer it.Release()

	ucmp := c.options.Comparator.UserKeyComparator
	var lastKey keys.InternalKey
	var lastSequence keys.Sequence
	for it.Next() {
		ikey := it.Key()
		currentUserKey, currentSequence, kind, ok := keys.SplitInternalKey3(ikey)
		if !ok {
			return errors.ErrCorruptInternalKey
		}
		if len(lastKey) == 0 || ucmp.Compare(lastKey.UserKey(), currentUserKey) != 0 {
			lastKey = append(lastKey[:0], currentUserKey...)
			lastSequence = keys.MaxSequence
		}
		switch {
		case lastSequence <= c.smallestSequence:
		case kind == keys.Delete && currentSequence <= c.smallestSequence && c.isBaseLevelForKey(currentUserKey):
		default:
			err := c.add(ikey, it.Value(), lastSequence == keys.MaxSequence)
			if err != nil {
				return err
			}
		}
		lastSequence = currentSequence
	}

	if err := c.closeCurrentTable(); err != nil {
		return err
	}

	return it.Err()
}

func (c *levelCompaction) record(edit *version.Edit) {
	level := c.Level()
	for which := 0; which < 2; which++ {
		files := c.Inputs[which]
		for _, f := range files {
			edit.DeletedFiles = append(edit.DeletedFiles, version.LevelFileNumber{Level: level + which, Number: f.Number})
		}
	}
	for _, f := range c.outputs {
		edit.AddedFiles = append(edit.AddedFiles, version.LevelFileMeta{Level: level + 1, FileMeta: f})
	}
	edit.CompactPointers = append(edit.CompactPointers, version.LevelCompactPointer{Level: level, Largest: c.NextCompactPointer})
	if c.nextFileNumber > edit.NextFileNumber {
		edit.NextFileNumber = c.nextFileNumber
	}
}

func (c *levelCompaction) Compact(edit *version.Edit) error {
	err := c.compact()
	if err != nil {
		return err
	}
	c.record(edit)
	return nil
}
<|endoftext|>


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

// Package config provides utilities for managing fake-gcs-server's
// configuration using command line flags.
package config

import (
	"flag"
	"fmt"
	"math"

	"github.com/fsouza/fake-gcs-server/fakestorage"
	"github.com/sirupsen/logrus"
)

const (
	filesystemBackend = "filesystem"
	memoryBackend     = "memory"
)

type Config struct {
	Seed        string
	publicHost  string
	externalURL string
	scheme      string
	host        string
	port        uint
	backend     string
	fsRoot      string
}

// Load parses the given arguments list and return a config object (and/or an
// error in case of failures).
func Load(args []string) (Config, error) {
	var cfg Config
	fs := flag.NewFlagSet("gcs-emulator", flag.ContinueOnError)
	fs.StringVar(&cfg.backend, "backend", filesystemBackend, "storage backend (memory or filesystem)")
	fs.StringVar(&cfg.fsRoot, "filesystem-root", "/storage", "filesystem root (required for the filesystem backend). folder will be created if it doesn't exist")
	fs.StringVar(&cfg.publicHost, "public-host", "storage.googleapis.com", "Optional URL for public host")
	fs.StringVar(&cfg.externalURL, "external-url", "", "optional external URL, returned in the Location header for uploads. Defaults to the address where the server is running")
	fs.StringVar(&cfg.scheme, "scheme", "https", "using http or https")
	fs.StringVar(&cfg.host, "host", "0.0.0.0", "host to bind to")
	fs.StringVar(&cfg.Seed, "data", "", "where to load data from (provided that the directory exists)")
	fs.UintVar(&cfg.port, "port", 4443, "port to bind to")
	err := fs.Parse(args)
	if err != nil {
		return cfg, err
	}
	return cfg, cfg.validate()
}

func (c *Config) validate() error {
	if c.backend != memoryBackend && c.backend != filesystemBackend {
		return fmt.Errorf(`invalid backend %q, must be either "memory" or "filesystem"`, c.backend)
	}
	if c.backend == filesystemBackend && c.fsRoot == "" {
		return fmt.Errorf("backend %q requires the filesystem-root to be defined", c.backend)
	}
	if c.scheme != "http" && c.scheme != "https" {
		return fmt.Errorf(`invalid scheme %s, must be either "http"" or "https"`, c.scheme)
	}
	if c.port > math.MaxUint16 {
		return fmt.Errorf("port %d is too high, maximum value is %d", c.port, math.MaxUint16)
	}
	return nil
}

func (c *Config) ToFakeGcsOptions() fakestorage.Options {
	storageRoot := c.fsRoot
	if c.backend == memoryBackend {
		storageRoot = ""
	}
	return fakestorage.Options{
		StorageRoot: storageRoot,
		Scheme:      c.scheme,
		Host:        c.host,
		Port:        uint16(c.port),
		PublicHost:  c.publicHost,
		ExternalURL: c.externalURL,
		Writer:      logrus.New().Writer(),
	}
}
<commit_msg>internal/config: fix flagset name<commit_after>// Copyright 2019 Francisco Souza. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package config provides utilities for managing fake-gcs-server's
// configuration using command line flags.
package config

import (
	"flag"
	"fmt"
	"math"

	"github.com/fsouza/fake-gcs-server/fakestorage"
	"github.com/sirupsen/logrus"
)

const (
	filesystemBackend = "filesystem"
	memoryBackend     = "memory"
)

type Config struct {
	Seed        string
	publicHost  string
	externalURL string
	scheme      string
	host        string
	port        uint
	backend     string
	fsRoot      string
}

// Load parses the given arguments list and return a config object (and/or an
// error in case of failures).
func Load(args []string) (Config, error) {
	var cfg Config
	fs := flag.NewFlagSet("fake-gcs-server", flag.ContinueOnError)
	fs.StringVar(&cfg.backend, "backend", filesystemBackend, "storage backend (memory or filesystem)")
	fs.StringVar(&cfg.fsRoot, "filesystem-root", "/storage", "filesystem root (required for the filesystem backend). folder will be created if it doesn't exist")
	fs.StringVar(&cfg.publicHost, "public-host", "storage.googleapis.com", "Optional URL for public host")
	fs.StringVar(&cfg.externalURL, "external-url", "", "optional external URL, returned in the Location header for uploads. Defaults to the address where the server is running")
	fs.StringVar(&cfg.scheme, "scheme", "https", "using http or https")
	fs.StringVar(&cfg.host, "host", "0.0.0.0", "host to bind to")
	fs.StringVar(&cfg.Seed, "data", "", "where to load data from (provided that the directory exists)")
	fs.UintVar(&cfg.port, "port", 4443, "port to bind to")
	err := fs.Parse(args)
	if err != nil {
		return cfg, err
	}
	return cfg, cfg.validate()
}

func (c *Config) validate() error {
	if c.backend != memoryBackend && c.backend != filesystemBackend {
		return fmt.Errorf(`invalid backend %q, must be either "memory" or "filesystem"`, c.backend)
	}
	if c.backend == filesystemBackend && c.fsRoot == "" {
		return fmt.Errorf("backend %q requires the filesystem-root to be defined", c.backend)
	}
	if c.scheme != "http" && c.scheme != "https" {
		return fmt.Errorf(`invalid scheme %s, must be either "http"" or "https"`, c.scheme)
	}
	if c.port > math.MaxUint16 {
		return fmt.Errorf("port %d is too high, maximum value is %d", c.port, math.MaxUint16)
	}
	return nil
}

func (c *Config) ToFakeGcsOptions() fakestorage.Options {
	storageRoot := c.fsRoot
	if c.backend == memoryBackend {
		storageRoot = ""
	}
	return fakestorage.Options{
		StorageRoot: storageRoot,
		Scheme:      c.scheme,
		Host:        c.host,
		Port:        uint16(c.port),
		PublicHost:  c.publicHost,
		ExternalURL: c.externalURL,
		Writer:      logrus.New().Writer(),
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 Hajime Hoshi
//
// 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 graphics

import (
	"errors"
	"fmt"
	"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
)

func glMatrix(m *[4][4]float64) []float32 {
	return []float32{
		float32(m[0][0]), float32(m[1][0]), float32(m[2][0]), float32(m[3][0]),
		float32(m[0][1]), float32(m[1][1]), float32(m[2][1]), float32(m[3][1]),
		float32(m[0][2]), float32(m[1][2]), float32(m[2][2]), float32(m[3][2]),
		float32(m[0][3]), float32(m[1][3]), float32(m[2][3]), float32(m[3][3]),
	}
}

type Matrix interface {
	Element(i, j int) float64
}

var vertices = make([]int16, 16*quadsMaxNum)

var shadersInitialized = false

func drawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4][4]float64, quads TextureQuads, geo Matrix, color Matrix) error {
	// NOTE: WebGL doesn't seem to have Check gl.MAX_ELEMENTS_VERTICES or gl.MAX_ELEMENTS_INDICES so far.
	// Let's use them to compare to len(quads) in the future.

	if !shadersInitialized {
		if err := initialize(c); err != nil {
			return err
		}
		shadersInitialized = true
	}

	if quads.Len() == 0 {
		return nil
	}
	if quadsMaxNum < quads.Len() {
		return errors.New(fmt.Sprintf("len(quads) must be equal to or less than %d", quadsMaxNum))
	}

	p := programContext{
		program:          programTexture,
		context:          c,
		projectionMatrix: glMatrix(projectionMatrix),
		texture:          texture,
		geoM:             geo,
		colorM:           color,
	}
	p.begin()
	defer p.end()
	n := quads.SetVertices(vertices)
	if n == 0 {
		return nil
	}
	c.BufferSubData(c.ArrayBuffer, vertices[:16*n])
	c.DrawElements(c.Triangles, 6*n)
	return nil
}
<commit_msg>graphics: Reduce calling TextureQuad.Len()<commit_after>// Copyright 2014 Hajime Hoshi
//
// 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 graphics

import (
	"errors"
	"fmt"
	"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
)

func glMatrix(m *[4][4]float64) []float32 {
	return []float32{
		float32(m[0][0]), float32(m[1][0]), float32(m[2][0]), float32(m[3][0]),
		float32(m[0][1]), float32(m[1][1]), float32(m[2][1]), float32(m[3][1]),
		float32(m[0][2]), float32(m[1][2]), float32(m[2][2]), float32(m[3][2]),
		float32(m[0][3]), float32(m[1][3]), float32(m[2][3]), float32(m[3][3]),
	}
}

type Matrix interface {
	Element(i, j int) float64
}

var vertices = make([]int16, 16*quadsMaxNum)

var shadersInitialized = false

func drawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4][4]float64, quads TextureQuads, geo Matrix, color Matrix) error {
	// NOTE: WebGL doesn't seem to have Check gl.MAX_ELEMENTS_VERTICES or gl.MAX_ELEMENTS_INDICES so far.
	// Let's use them to compare to len(quads) in the future.

	if !shadersInitialized {
		if err := initialize(c); err != nil {
			return err
		}
		shadersInitialized = true
	}

	l := quads.Len()
	if l == 0 {
		return nil
	}
	if quadsMaxNum < l {
		return errors.New(fmt.Sprintf("len(quads) must be equal to or less than %d", quadsMaxNum))
	}

	p := programContext{
		program:          programTexture,
		context:          c,
		projectionMatrix: glMatrix(projectionMatrix),
		texture:          texture,
		geoM:             geo,
		colorM:           color,
	}
	p.begin()
	defer p.end()
	n := quads.SetVertices(vertices)
	if n == 0 {
		return nil
	}
	c.BufferSubData(c.ArrayBuffer, vertices[:16*n])
	c.DrawElements(c.Triangles, 6*n)
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2015-2022 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package hash

import (
	"bytes"
	"crypto/sha1"
	"encoding/base64"
	"encoding/binary"
	"fmt"
	"hash"
	"hash/crc32"
	"net/http"
	"strings"

	"github.com/minio/minio/internal/hash/sha256"
	xhttp "github.com/minio/minio/internal/http"
)

// MinIOMultipartChecksum is as metadata on multipart uploads to indicate checksum type.
const MinIOMultipartChecksum = "x-minio-multipart-checksum"

// ChecksumType contains information about the checksum type.
type ChecksumType uint32

const (

	// ChecksumTrailing indicates the checksum will be sent in the trailing header.
	// Another checksum type will be set.
	ChecksumTrailing ChecksumType = 1 << iota

	// ChecksumSHA256 indicates a SHA256 checksum.
	ChecksumSHA256
	// ChecksumSHA1 indicates a SHA-1 checksum.
	ChecksumSHA1
	// ChecksumCRC32 indicates a CRC32 checksum with IEEE table.
	ChecksumCRC32
	// ChecksumCRC32C indicates a CRC32 checksum with Castagnoli table.
	ChecksumCRC32C
	// ChecksumInvalid indicates an invalid checksum.
	ChecksumInvalid

	// ChecksumNone indicates no checksum.
	ChecksumNone ChecksumType = 0
)

// Checksum is a type and base 64 encoded value.
type Checksum struct {
	Type    ChecksumType
	Encoded string
	Raw     []byte
}

// Is returns if c is all of t.
func (c ChecksumType) Is(t ChecksumType) bool {
	if t == ChecksumNone {
		return c == ChecksumNone
	}
	return c&t == t
}

// Key returns the header key.
// returns empty string if invalid or none.
func (c ChecksumType) Key() string {
	switch {
	case c.Is(ChecksumCRC32):
		return xhttp.AmzChecksumCRC32
	case c.Is(ChecksumCRC32C):
		return xhttp.AmzChecksumCRC32C
	case c.Is(ChecksumSHA1):
		return xhttp.AmzChecksumSHA1
	case c.Is(ChecksumSHA256):
		return xhttp.AmzChecksumSHA256
	}
	return ""
}

// RawByteLen returns the size of the un-encoded checksum.
func (c ChecksumType) RawByteLen() int {
	switch {
	case c.Is(ChecksumCRC32):
		return 4
	case c.Is(ChecksumCRC32C):
		return 4
	case c.Is(ChecksumSHA1):
		return sha1.Size
	case c.Is(ChecksumSHA256):
		return sha256.Size
	}
	return 0
}

// IsSet returns whether the type is valid and known.
func (c ChecksumType) IsSet() bool {
	return !c.Is(ChecksumInvalid) && !c.Is(ChecksumNone)
}

// NewChecksumType returns a checksum type based on the algorithm string.
func NewChecksumType(alg string) ChecksumType {
	switch strings.ToUpper(alg) {
	case "CRC32":
		return ChecksumCRC32
	case "CRC32C":
		return ChecksumCRC32C
	case "SHA1":
		return ChecksumSHA1
	case "SHA256":
		return ChecksumSHA256
	case "":
		return ChecksumNone
	}
	return ChecksumInvalid
}

// String returns the type as a string.
func (c ChecksumType) String() string {
	switch {
	case c.Is(ChecksumCRC32):
		return "CRC32"
	case c.Is(ChecksumCRC32C):
		return "CRC32C"
	case c.Is(ChecksumSHA1):
		return "SHA1"
	case c.Is(ChecksumSHA256):
		return "SHA256"
	case c.Is(ChecksumNone):
		return ""
	}
	return "invalid"
}

// Hasher returns a hasher corresponding to the checksum type.
// Returns nil if no checksum.
func (c ChecksumType) Hasher() hash.Hash {
	switch {
	case c.Is(ChecksumCRC32):
		return crc32.NewIEEE()
	case c.Is(ChecksumCRC32C):
		return crc32.New(crc32.MakeTable(crc32.Castagnoli))
	case c.Is(ChecksumSHA1):
		return sha1.New()
	case c.Is(ChecksumSHA256):
		return sha256.New()
	}
	return nil
}

// Trailing return whether the checksum is traling.
func (c ChecksumType) Trailing() bool {
	return c.Is(ChecksumTrailing)
}

// NewChecksumFromData returns a new checksum from specified algorithm and base64 encoded value.
func NewChecksumFromData(t ChecksumType, data []byte) *Checksum {
	if !t.IsSet() {
		return nil
	}
	h := t.Hasher()
	h.Write(data)
	raw := h.Sum(nil)
	c := Checksum{Type: t, Encoded: base64.StdEncoding.EncodeToString(raw), Raw: raw}
	if !c.Valid() {
		return nil
	}
	return &c
}

// ReadCheckSums will read checksums from b and return them.
func ReadCheckSums(b []byte) map[string]string {
	res := make(map[string]string, 1)
	for len(b) > 0 {
		t, n := binary.Uvarint(b)
		if n < 0 {
			break
		}
		b = b[n:]

		typ := ChecksumType(t)
		length := typ.RawByteLen()
		if length == 0 || len(b) < length {
			break
		}
		res[typ.String()] = base64.StdEncoding.EncodeToString(b[:length])
		b = b[length:]
	}
	if len(res) == 0 {
		res = nil
	}
	return res
}

// NewChecksumWithType is similar to NewChecksumString but expects input algo of ChecksumType.
func NewChecksumWithType(alg ChecksumType, value string) *Checksum {
	if !alg.IsSet() {
		return nil
	}
	bvalue, err := base64.StdEncoding.DecodeString(value)
	if err != nil {
		return nil
	}
	c := Checksum{Type: alg, Encoded: value, Raw: bvalue}
	if !c.Valid() {
		return nil
	}
	return &c
}

// NewChecksumString returns a new checksum from specified algorithm and base64 encoded value.
func NewChecksumString(alg, value string) *Checksum {
	return NewChecksumWithType(NewChecksumType(alg), value)
}

// AppendTo will append the checksum to b.
// ReadCheckSums reads the values back.
func (c *Checksum) AppendTo(b []byte) []byte {
	if c == nil {
		return nil
	}
	var tmp [binary.MaxVarintLen32]byte
	n := binary.PutUvarint(tmp[:], uint64(c.Type))
	crc := c.Raw
	if len(crc) != c.Type.RawByteLen() {
		return b
	}
	b = append(b, tmp[:n]...)
	b = append(b, crc...)
	return b
}

// Valid returns whether checksum is valid.
func (c Checksum) Valid() bool {
	if c.Type == ChecksumInvalid {
		return false
	}
	if len(c.Encoded) == 0 || c.Type.Is(ChecksumTrailing) {
		return c.Type.Is(ChecksumNone) || c.Type.Is(ChecksumTrailing)
	}
	raw := c.Raw
	return c.Type.RawByteLen() == len(raw)
}

// Matches returns whether given content matches c.
func (c Checksum) Matches(content []byte) error {
	if len(c.Encoded) == 0 {
		return nil
	}
	hasher := c.Type.Hasher()
	_, err := hasher.Write(content)
	if err != nil {
		return err
	}
	sum := hasher.Sum(nil)
	if !bytes.Equal(sum, c.Raw) {
		return ChecksumMismatch{
			Want: c.Encoded,
			Got:  base64.StdEncoding.EncodeToString(sum),
		}
	}
	return nil
}

// AsMap returns the
func (c *Checksum) AsMap() map[string]string {
	if c == nil || !c.Valid() {
		return nil
	}
	return map[string]string{c.Type.String(): c.Encoded}
}

// TransferChecksumHeader will transfer any checksum value that has been checked.
func TransferChecksumHeader(w http.ResponseWriter, r *http.Request) {
	t, s := getContentChecksum(r)
	if !t.IsSet() || t.Is(ChecksumTrailing) {
		// TODO: Add trailing when we can read it.
		return
	}
	w.Header().Set(t.Key(), s)
}

// AddChecksumHeader will transfer any checksum value that has been checked.
func AddChecksumHeader(w http.ResponseWriter, c map[string]string) {
	for k, v := range c {
		fmt.Println(c, v)
		cksum := NewChecksumString(k, v)
		if cksum == nil {
			continue
		}
		if cksum.Valid() {
			w.Header().Set(cksum.Type.Key(), v)
		}
	}
}

// GetContentChecksum returns content checksum.
// Returns ErrInvalidChecksum if so.
// Returns nil, nil if no checksum.
func GetContentChecksum(r *http.Request) (*Checksum, error) {
	t, s := getContentChecksum(r)
	if t == ChecksumNone {
		if s == "" {
			return nil, nil
		}
		return nil, ErrInvalidChecksum
	}
	cksum := NewChecksumWithType(t, s)
	if cksum == nil {
		return nil, ErrInvalidChecksum
	}
	return cksum, nil
}

// getContentChecksum returns content checksum type and value.
// Returns ChecksumInvalid if so.
func getContentChecksum(r *http.Request) (t ChecksumType, s string) {
	t = ChecksumNone
	alg := r.Header.Get(xhttp.AmzChecksumAlgo)
	if alg != "" {
		t |= NewChecksumType(alg)
		if t.IsSet() {
			hdr := t.Key()
			if s = r.Header.Get(hdr); s == "" {
				if strings.EqualFold(r.Header.Get(xhttp.AmzTrailer), hdr) {
					t |= ChecksumTrailing
				} else {
					t = ChecksumInvalid
				}
				return ChecksumNone, ""
			}
		}
		return t, s
	}
	checkType := func(c ChecksumType) {
		if got := r.Header.Get(c.Key()); got != "" {
			// If already set, invalid
			if t != ChecksumNone {
				t = ChecksumInvalid
				s = ""
			} else {
				t = c
				s = got
			}
		}
	}
	checkType(ChecksumCRC32)
	checkType(ChecksumCRC32C)
	checkType(ChecksumSHA1)
	checkType(ChecksumSHA256)
	return t, s
}
<commit_msg>remove printing map() checksums (#16028)<commit_after>// Copyright (c) 2015-2022 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package hash

import (
	"bytes"
	"crypto/sha1"
	"encoding/base64"
	"encoding/binary"
	"hash"
	"hash/crc32"
	"net/http"
	"strings"

	"github.com/minio/minio/internal/hash/sha256"
	xhttp "github.com/minio/minio/internal/http"
)

// MinIOMultipartChecksum is as metadata on multipart uploads to indicate checksum type.
const MinIOMultipartChecksum = "x-minio-multipart-checksum"

// ChecksumType contains information about the checksum type.
type ChecksumType uint32

const (

	// ChecksumTrailing indicates the checksum will be sent in the trailing header.
	// Another checksum type will be set.
	ChecksumTrailing ChecksumType = 1 << iota

	// ChecksumSHA256 indicates a SHA256 checksum.
	ChecksumSHA256
	// ChecksumSHA1 indicates a SHA-1 checksum.
	ChecksumSHA1
	// ChecksumCRC32 indicates a CRC32 checksum with IEEE table.
	ChecksumCRC32
	// ChecksumCRC32C indicates a CRC32 checksum with Castagnoli table.
	ChecksumCRC32C
	// ChecksumInvalid indicates an invalid checksum.
	ChecksumInvalid

	// ChecksumNone indicates no checksum.
	ChecksumNone ChecksumType = 0
)

// Checksum is a type and base 64 encoded value.
type Checksum struct {
	Type    ChecksumType
	Encoded string
	Raw     []byte
}

// Is returns if c is all of t.
func (c ChecksumType) Is(t ChecksumType) bool {
	if t == ChecksumNone {
		return c == ChecksumNone
	}
	return c&t == t
}

// Key returns the header key.
// returns empty string if invalid or none.
func (c ChecksumType) Key() string {
	switch {
	case c.Is(ChecksumCRC32):
		return xhttp.AmzChecksumCRC32
	case c.Is(ChecksumCRC32C):
		return xhttp.AmzChecksumCRC32C
	case c.Is(ChecksumSHA1):
		return xhttp.AmzChecksumSHA1
	case c.Is(ChecksumSHA256):
		return xhttp.AmzChecksumSHA256
	}
	return ""
}

// RawByteLen returns the size of the un-encoded checksum.
func (c ChecksumType) RawByteLen() int {
	switch {
	case c.Is(ChecksumCRC32):
		return 4
	case c.Is(ChecksumCRC32C):
		return 4
	case c.Is(ChecksumSHA1):
		return sha1.Size
	case c.Is(ChecksumSHA256):
		return sha256.Size
	}
	return 0
}

// IsSet returns whether the type is valid and known.
func (c ChecksumType) IsSet() bool {
	return !c.Is(ChecksumInvalid) && !c.Is(ChecksumNone)
}

// NewChecksumType returns a checksum type based on the algorithm string.
func NewChecksumType(alg string) ChecksumType {
	switch strings.ToUpper(alg) {
	case "CRC32":
		return ChecksumCRC32
	case "CRC32C":
		return ChecksumCRC32C
	case "SHA1":
		return ChecksumSHA1
	case "SHA256":
		return ChecksumSHA256
	case "":
		return ChecksumNone
	}
	return ChecksumInvalid
}

// String returns the type as a string.
func (c ChecksumType) String() string {
	switch {
	case c.Is(ChecksumCRC32):
		return "CRC32"
	case c.Is(ChecksumCRC32C):
		return "CRC32C"
	case c.Is(ChecksumSHA1):
		return "SHA1"
	case c.Is(ChecksumSHA256):
		return "SHA256"
	case c.Is(ChecksumNone):
		return ""
	}
	return "invalid"
}

// Hasher returns a hasher corresponding to the checksum type.
// Returns nil if no checksum.
func (c ChecksumType) Hasher() hash.Hash {
	switch {
	case c.Is(ChecksumCRC32):
		return crc32.NewIEEE()
	case c.Is(ChecksumCRC32C):
		return crc32.New(crc32.MakeTable(crc32.Castagnoli))
	case c.Is(ChecksumSHA1):
		return sha1.New()
	case c.Is(ChecksumSHA256):
		return sha256.New()
	}
	return nil
}

// Trailing return whether the checksum is traling.
func (c ChecksumType) Trailing() bool {
	return c.Is(ChecksumTrailing)
}

// NewChecksumFromData returns a new checksum from specified algorithm and base64 encoded value.
func NewChecksumFromData(t ChecksumType, data []byte) *Checksum {
	if !t.IsSet() {
		return nil
	}
	h := t.Hasher()
	h.Write(data)
	raw := h.Sum(nil)
	c := Checksum{Type: t, Encoded: base64.StdEncoding.EncodeToString(raw), Raw: raw}
	if !c.Valid() {
		return nil
	}
	return &c
}

// ReadCheckSums will read checksums from b and return them.
func ReadCheckSums(b []byte) map[string]string {
	res := make(map[string]string, 1)
	for len(b) > 0 {
		t, n := binary.Uvarint(b)
		if n < 0 {
			break
		}
		b = b[n:]

		typ := ChecksumType(t)
		length := typ.RawByteLen()
		if length == 0 || len(b) < length {
			break
		}
		res[typ.String()] = base64.StdEncoding.EncodeToString(b[:length])
		b = b[length:]
	}
	if len(res) == 0 {
		res = nil
	}
	return res
}

// NewChecksumWithType is similar to NewChecksumString but expects input algo of ChecksumType.
func NewChecksumWithType(alg ChecksumType, value string) *Checksum {
	if !alg.IsSet() {
		return nil
	}
	bvalue, err := base64.StdEncoding.DecodeString(value)
	if err != nil {
		return nil
	}
	c := Checksum{Type: alg, Encoded: value, Raw: bvalue}
	if !c.Valid() {
		return nil
	}
	return &c
}

// NewChecksumString returns a new checksum from specified algorithm and base64 encoded value.
func NewChecksumString(alg, value string) *Checksum {
	return NewChecksumWithType(NewChecksumType(alg), value)
}

// AppendTo will append the checksum to b.
// ReadCheckSums reads the values back.
func (c *Checksum) AppendTo(b []byte) []byte {
	if c == nil {
		return nil
	}
	var tmp [binary.MaxVarintLen32]byte
	n := binary.PutUvarint(tmp[:], uint64(c.Type))
	crc := c.Raw
	if len(crc) != c.Type.RawByteLen() {
		return b
	}
	b = append(b, tmp[:n]...)
	b = append(b, crc...)
	return b
}

// Valid returns whether checksum is valid.
func (c Checksum) Valid() bool {
	if c.Type == ChecksumInvalid {
		return false
	}
	if len(c.Encoded) == 0 || c.Type.Is(ChecksumTrailing) {
		return c.Type.Is(ChecksumNone) || c.Type.Is(ChecksumTrailing)
	}
	raw := c.Raw
	return c.Type.RawByteLen() == len(raw)
}

// Matches returns whether given content matches c.
func (c Checksum) Matches(content []byte) error {
	if len(c.Encoded) == 0 {
		return nil
	}
	hasher := c.Type.Hasher()
	_, err := hasher.Write(content)
	if err != nil {
		return err
	}
	sum := hasher.Sum(nil)
	if !bytes.Equal(sum, c.Raw) {
		return ChecksumMismatch{
			Want: c.Encoded,
			Got:  base64.StdEncoding.EncodeToString(sum),
		}
	}
	return nil
}

// AsMap returns the
func (c *Checksum) AsMap() map[string]string {
	if c == nil || !c.Valid() {
		return nil
	}
	return map[string]string{c.Type.String(): c.Encoded}
}

// TransferChecksumHeader will transfer any checksum value that has been checked.
func TransferChecksumHeader(w http.ResponseWriter, r *http.Request) {
	t, s := getContentChecksum(r)
	if !t.IsSet() || t.Is(ChecksumTrailing) {
		// TODO: Add trailing when we can read it.
		return
	}
	w.Header().Set(t.Key(), s)
}

// AddChecksumHeader will transfer any checksum value that has been checked.
func AddChecksumHeader(w http.ResponseWriter, c map[string]string) {
	for k, v := range c {
		cksum := NewChecksumString(k, v)
		if cksum == nil {
			continue
		}
		if cksum.Valid() {
			w.Header().Set(cksum.Type.Key(), v)
		}
	}
}

// GetContentChecksum returns content checksum.
// Returns ErrInvalidChecksum if so.
// Returns nil, nil if no checksum.
func GetContentChecksum(r *http.Request) (*Checksum, error) {
	t, s := getContentChecksum(r)
	if t == ChecksumNone {
		if s == "" {
			return nil, nil
		}
		return nil, ErrInvalidChecksum
	}
	cksum := NewChecksumWithType(t, s)
	if cksum == nil {
		return nil, ErrInvalidChecksum
	}
	return cksum, nil
}

// getContentChecksum returns content checksum type and value.
// Returns ChecksumInvalid if so.
func getContentChecksum(r *http.Request) (t ChecksumType, s string) {
	t = ChecksumNone
	alg := r.Header.Get(xhttp.AmzChecksumAlgo)
	if alg != "" {
		t |= NewChecksumType(alg)
		if t.IsSet() {
			hdr := t.Key()
			if s = r.Header.Get(hdr); s == "" {
				if strings.EqualFold(r.Header.Get(xhttp.AmzTrailer), hdr) {
					t |= ChecksumTrailing
				} else {
					t = ChecksumInvalid
				}
				return ChecksumNone, ""
			}
		}
		return t, s
	}
	checkType := func(c ChecksumType) {
		if got := r.Header.Get(c.Key()); got != "" {
			// If already set, invalid
			if t != ChecksumNone {
				t = ChecksumInvalid
				s = ""
			} else {
				t = c
				s = got
			}
		}
	}
	checkType(ChecksumCRC32)
	checkType(ChecksumCRC32C)
	checkType(ChecksumSHA1)
	checkType(ChecksumSHA256)
	return t, s
}
<|endoftext|>


<commit_before>// Package image consolidates knowledge about various container image formats
// (as opposed to image storage mechanisms, which are handled by types.ImageSource)
// and exposes all of them using an unified interface.
package image

import (
	"context"

	"github.com/containers/image/v5/types"
)

// FromReference returns a types.ImageCloser implementation for the default instance reading from reference.
// If reference poitns to a manifest list, .Manifest() still returns the manifest list,
// but other methods transparently return data from an appropriate image instance.
//
// The caller must call .Close() on the returned ImageCloser.
//
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage instead of calling this function.
func FromReference(ctx context.Context, sys *types.SystemContext, ref types.ImageReference) (types.ImageCloser, error) {
	src, err := ref.NewImageSource(ctx, sys)
	if err != nil {
		return nil, err
	}
	img, err := FromSource(ctx, sys, src)
	if err != nil {
		src.Close()
		return nil, err
	}
	return img, nil
}

// imageCloser implements types.ImageCloser, perhaps allowing simple users
// to use a single object without having keep a reference to a types.ImageSource
// only to call types.ImageSource.Close().
type imageCloser struct {
	types.Image
	src types.ImageSource
}

// FromSource returns a types.ImageCloser implementation for the default instance of source.
// If source is a manifest list, .Manifest() still returns the manifest list,
// but other methods transparently return data from an appropriate image instance.
//
// The caller must call .Close() on the returned ImageCloser.
//
// FromSource “takes ownership” of the input ImageSource and will call src.Close()
// when the image is closed.  (This does not prevent callers from using both the
// Image and ImageSource objects simultaneously, but it means that they only need to
// the Image.)
//
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage instead of calling this function.
//
// Most callers can use either FromUnparsedImage or FromReference instead.
//
// This is publicly visible as c/image/image.FromSource.
func FromSource(ctx context.Context, sys *types.SystemContext, src types.ImageSource) (types.ImageCloser, error) {
	img, err := FromUnparsedImage(ctx, sys, UnparsedInstance(src, nil))
	if err != nil {
		return nil, err
	}
	return &imageCloser{
		Image: img,
		src:   src,
	}, nil
}

func (ic *imageCloser) Close() error {
	return ic.src.Close()
}

// sourcedImage is a general set of utilities for working with container images,
// whatever is their underlying location (i.e. dockerImageSource-independent).
// Note the existence of skopeo/docker.Image: some instances of a `types.Image`
// may not be a `sourcedImage` directly. However, most users of `types.Image`
// do not care, and those who care about `skopeo/docker.Image` know they do.
type sourcedImage struct {
	*UnparsedImage
	manifestBlob     []byte
	manifestMIMEType string
	// genericManifest contains data corresponding to manifestBlob.
	// NOTE: The manifest may have been modified in the process; DO NOT reserialize and store genericManifest
	// if you want to preserve the original manifest; use manifestBlob directly.
	genericManifest
}

// FromUnparsedImage returns a types.Image implementation for unparsed.
// If unparsed represents a manifest list, .Manifest() still returns the manifest list,
// but other methods transparently return data from an appropriate single image.
//
// The Image must not be used after the underlying ImageSource is Close()d.
//
// This is publicly visible as c/image/image.FromUnparsedImage.
func FromUnparsedImage(ctx context.Context, sys *types.SystemContext, unparsed *UnparsedImage) (types.Image, error) {
	// Note that the input parameter above is specifically *image.UnparsedImage, not types.UnparsedImage:
	// we want to be able to use unparsed.src.  We could make that an explicit interface, but, well,
	// this is the only UnparsedImage implementation around, anyway.

	// NOTE: It is essential for signature verification that all parsing done in this object happens on the same manifest which is returned by unparsed.Manifest().
	manifestBlob, manifestMIMEType, err := unparsed.Manifest(ctx)
	if err != nil {
		return nil, err
	}

	parsedManifest, err := manifestInstanceFromBlob(ctx, sys, unparsed.src, manifestBlob, manifestMIMEType)
	if err != nil {
		return nil, err
	}

	return &sourcedImage{
		UnparsedImage:    unparsed,
		manifestBlob:     manifestBlob,
		manifestMIMEType: manifestMIMEType,
		genericManifest:  parsedManifest,
	}, nil
}

// Size returns the size of the image as stored, if it's known, or -1 if it isn't.
func (i *sourcedImage) Size() (int64, error) {
	return -1, nil
}

// Manifest overrides the UnparsedImage.Manifest to always use the fields which we have already fetched.
func (i *sourcedImage) Manifest(ctx context.Context) ([]byte, string, error) {
	return i.manifestBlob, i.manifestMIMEType, nil
}

func (i *sourcedImage) LayerInfosForCopy(ctx context.Context) ([]types.BlobInfo, error) {
	return i.UnparsedImage.src.LayerInfosForCopy(ctx, i.UnparsedImage.instanceDigest)
}
<commit_msg>Have image.FromUnparsedImage return a SourcedImage instead of types.Image<commit_after>// Package image consolidates knowledge about various container image formats
// (as opposed to image storage mechanisms, which are handled by types.ImageSource)
// and exposes all of them using an unified interface.
package image

import (
	"context"

	"github.com/containers/image/v5/types"
)

// FromReference returns a types.ImageCloser implementation for the default instance reading from reference.
// If reference poitns to a manifest list, .Manifest() still returns the manifest list,
// but other methods transparently return data from an appropriate image instance.
//
// The caller must call .Close() on the returned ImageCloser.
//
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage instead of calling this function.
func FromReference(ctx context.Context, sys *types.SystemContext, ref types.ImageReference) (types.ImageCloser, error) {
	src, err := ref.NewImageSource(ctx, sys)
	if err != nil {
		return nil, err
	}
	img, err := FromSource(ctx, sys, src)
	if err != nil {
		src.Close()
		return nil, err
	}
	return img, nil
}

// imageCloser implements types.ImageCloser, perhaps allowing simple users
// to use a single object without having keep a reference to a types.ImageSource
// only to call types.ImageSource.Close().
type imageCloser struct {
	types.Image
	src types.ImageSource
}

// FromSource returns a types.ImageCloser implementation for the default instance of source.
// If source is a manifest list, .Manifest() still returns the manifest list,
// but other methods transparently return data from an appropriate image instance.
//
// The caller must call .Close() on the returned ImageCloser.
//
// FromSource “takes ownership” of the input ImageSource and will call src.Close()
// when the image is closed.  (This does not prevent callers from using both the
// Image and ImageSource objects simultaneously, but it means that they only need to
// the Image.)
//
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage instead of calling this function.
//
// Most callers can use either FromUnparsedImage or FromReference instead.
//
// This is publicly visible as c/image/image.FromSource.
func FromSource(ctx context.Context, sys *types.SystemContext, src types.ImageSource) (types.ImageCloser, error) {
	img, err := FromUnparsedImage(ctx, sys, UnparsedInstance(src, nil))
	if err != nil {
		return nil, err
	}
	return &imageCloser{
		Image: img,
		src:   src,
	}, nil
}

func (ic *imageCloser) Close() error {
	return ic.src.Close()
}

// SourcedImage is a general set of utilities for working with container images,
// whatever is their underlying transport (i.e. ImageSource-independent).
// Note the existence of docker.Image and image.memoryImage: various instances
// of a types.Image may not be a SourcedImage directly.
//
// Most external users of `types.Image` do not care, and those who care about `docker.Image` know they do.
//
// Internal users may depend on methods available in SourcedImage but not (yet?) in types.Image.
type SourcedImage struct {
	*UnparsedImage
	manifestBlob     []byte
	manifestMIMEType string
	// genericManifest contains data corresponding to manifestBlob.
	// NOTE: The manifest may have been modified in the process; DO NOT reserialize and store genericManifest
	// if you want to preserve the original manifest; use manifestBlob directly.
	genericManifest
}

// FromUnparsedImage returns a types.Image implementation for unparsed.
// If unparsed represents a manifest list, .Manifest() still returns the manifest list,
// but other methods transparently return data from an appropriate single image.
//
// The Image must not be used after the underlying ImageSource is Close()d.
//
// This is publicly visible as c/image/image.FromUnparsedImage.
func FromUnparsedImage(ctx context.Context, sys *types.SystemContext, unparsed *UnparsedImage) (*SourcedImage, error) {
	// Note that the input parameter above is specifically *image.UnparsedImage, not types.UnparsedImage:
	// we want to be able to use unparsed.src.  We could make that an explicit interface, but, well,
	// this is the only UnparsedImage implementation around, anyway.

	// NOTE: It is essential for signature verification that all parsing done in this object happens on the same manifest which is returned by unparsed.Manifest().
	manifestBlob, manifestMIMEType, err := unparsed.Manifest(ctx)
	if err != nil {
		return nil, err
	}

	parsedManifest, err := manifestInstanceFromBlob(ctx, sys, unparsed.src, manifestBlob, manifestMIMEType)
	if err != nil {
		return nil, err
	}

	return &SourcedImage{
		UnparsedImage:    unparsed,
		manifestBlob:     manifestBlob,
		manifestMIMEType: manifestMIMEType,
		genericManifest:  parsedManifest,
	}, nil
}

// Size returns the size of the image as stored, if it's known, or -1 if it isn't.
func (i *SourcedImage) Size() (int64, error) {
	return -1, nil
}

// Manifest overrides the UnparsedImage.Manifest to always use the fields which we have already fetched.
func (i *SourcedImage) Manifest(ctx context.Context) ([]byte, string, error) {
	return i.manifestBlob, i.manifestMIMEType, nil
}

func (i *SourcedImage) LayerInfosForCopy(ctx context.Context) ([]types.BlobInfo, error) {
	return i.UnparsedImage.src.LayerInfosForCopy(ctx, i.UnparsedImage.instanceDigest)
}
<|endoftext|>


<commit_before>package logger

import (
	"io/ioutil"
	"log"
	"os"
)

func isEnabledLogger() bool {
	return len(os.Getenv("LOG_ENABLE")) > 0
}

// GetLogger return private logger instance.
func GetLogger() *log.Logger {
	instance := log.New(os.Stdout, "", log.LstdFlags|log.Lshortfile)

	if !isEnabledLogger() {
		instance.SetOutput(ioutil.Discard)
	}

	return instance
}
<commit_msg>Delete unused logger<commit_after><|endoftext|>


<commit_before>package mbhttp

import (
	"encoding/json"
	"io/ioutil"
	"net/http"

	"github.com/pkg/errors"
)

// Client makes requests and handles common Machine Box error cases.
type Client struct {
	boxname    string
	HTTPClient *http.Client
}

// New makes a new Client.
func New(boxname string, client *http.Client) *Client {
	return &Client{
		boxname:    boxname,
		HTTPClient: client,
	}
}

// Do makes the request and unmarshals the response into v.
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
	resp, err := c.HTTPClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, errors.Wrap(err, "read response data")
	}
	var o struct {
		Success bool
		Error   string
	}
	if err := json.Unmarshal(b, &o); err != nil {
		if resp.StatusCode < 200 || resp.StatusCode >= 400 {
			return nil, errors.Errorf("%s: %s", c.boxname, resp.Status)
		}
		return nil, errors.Wrap(err, "decode common response data")
	}
	if !o.Success {
		if o.Error == "" {
			o.Error = "an unknown error occurred in the box"
		}
		return nil, errors.Errorf("%s: %s", c.boxname, o.Error)
	}
	if err := json.Unmarshal(b, &v); err != nil {
		return nil, errors.Wrap(err, "decode response data")
	}
	return resp, nil
}
<commit_msg>added comment<commit_after>package mbhttp

import (
	"encoding/json"
	"io/ioutil"
	"net/http"

	"github.com/pkg/errors"
)

// Client makes requests and handles common Machine Box error cases.
type Client struct {
	boxname string

	// HTTPClient is the underlying http.Client that will be
	// used to make requests.
	HTTPClient *http.Client
}

// New makes a new Client.
func New(boxname string, client *http.Client) *Client {
	return &Client{
		boxname:    boxname,
		HTTPClient: client,
	}
}

// Do makes the request and unmarshals the response into v.
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
	resp, err := c.HTTPClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, errors.Wrap(err, "read response data")
	}
	var o struct {
		Success bool
		Error   string
	}
	if err := json.Unmarshal(b, &o); err != nil {
		if resp.StatusCode < 200 || resp.StatusCode >= 400 {
			return nil, errors.Errorf("%s: %s", c.boxname, resp.Status)
		}
		return nil, errors.Wrap(err, "decode common response data")
	}
	if !o.Success {
		if o.Error == "" {
			o.Error = "an unknown error occurred in the box"
		}
		return nil, errors.Errorf("%s: %s", c.boxname, o.Error)
	}
	if err := json.Unmarshal(b, &v); err != nil {
		return nil, errors.Wrap(err, "decode response data")
	}
	return resp, nil
}
<|endoftext|>


<commit_before>// Copyright 2019 Google Inc. All Rights Reserved.
// This file is available under the Apache license.
// +build integration

package mtail

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"os"
	"runtime"
	"testing"
	"time"

	"github.com/golang/glog"
	"github.com/google/mtail/internal/metrics"
	"github.com/google/mtail/internal/watcher"
)

const timeoutMultiplier = 3

// TestMakeServer makes a new Server for use in tests, but does not start
// the server.  It returns the server, or any errors the new server creates.
func TestMakeServer(tb testing.TB, pollInterval time.Duration, disableFsNotify bool, options ...func(*Server) error) (*Server, error) {
	tb.Helper()
	w, err := watcher.NewLogWatcher(pollInterval, !disableFsNotify)
	if err != nil {
		tb.Fatal(err)
	}

	return New(metrics.NewStore(), w, options...)
}

// TestStartServer creates a new Server and starts it running.  It
// returns the server, and a cleanup function.
func TestStartServer(tb testing.TB, pollInterval time.Duration, disableFsNotify bool, options ...func(*Server) error) (*Server, func()) {
	tb.Helper()
	options = append(options, BindAddress("", "0"))

	m, err := TestMakeServer(tb, pollInterval, disableFsNotify, options...)
	if err != nil {
		tb.Fatal(err)
	}

	errc := make(chan error, 1)
	go func() {
		err := m.Run()
		errc <- err
	}()

	glog.Infof("check that server is listening")
	count := 0
	for _, err := net.DialTimeout("tcp", m.Addr(), 10*time.Millisecond*timeoutMultiplier); err != nil && count < 10; count++ {
		glog.Infof("err: %s, retrying to dial %s", err, m.Addr())
		time.Sleep(100 * time.Millisecond * timeoutMultiplier)
	}
	if count >= 10 {
		tb.Fatal("server wasn't listening after 10 attempts")
	}

	return m, func() {
		err := m.Close()
		if err != nil {
			tb.Fatal(err)
		}
		select {
		case err = <-errc:
		case <-time.After(5 * time.Second):
			buf := make([]byte, 1<<16)
			n := runtime.Stack(buf, true)
			fmt.Fprintf(os.Stderr, "%s", buf[0:n])
			tb.Fatal("timeout waiting for shutdown")
		}

		if err != nil {
			tb.Fatal(err)
		}
	}
}

// TestGetMetric fetches the expvar metrics from the Server at addr, and
// returns the value of one named name.  Callers are responsible for type
// assertions on the returned value.
func TestGetMetric(tb testing.TB, addr, name string) interface{} {
	uri := fmt.Sprintf("http://%s/debug/vars", addr)
	client := &http.Client{
		Timeout: 5 * time.Second,
	}
	resp, err := client.Get(uri)
	if err != nil {
		tb.Fatal(err)
	}
	buf := new(bytes.Buffer)
	buf.ReadFrom(resp.Body)
	var r map[string]interface{}
	if err := json.Unmarshal(buf.Bytes(), &r); err != nil {
		tb.Fatalf("%s: body was %s", err, buf.String())
	}
	return r[name]
}

// ExpectMetricDelta checks to see if the difference between a and b is want;
// it assumes both values are float64s that came from a TestGetMetric.
func ExpectMetricDelta(tb testing.TB, a, b interface{}, want float64) {
	tb.Helper()
	if a == nil {
		a = 0.
	}
	if b == nil {
		b = 0.
	}
	if a.(float64)-b.(float64) != want {
		tb.Errorf("Unexpected delta: got %v - %v, want %g", a, b, want)
	}
}
<commit_msg>Handle error return value in test.<commit_after>// Copyright 2019 Google Inc. All Rights Reserved.
// This file is available under the Apache license.
// +build integration

package mtail

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"os"
	"runtime"
	"testing"
	"time"

	"github.com/golang/glog"
	"github.com/google/mtail/internal/metrics"
	"github.com/google/mtail/internal/testutil"
	"github.com/google/mtail/internal/watcher"
)

const timeoutMultiplier = 3

// TestMakeServer makes a new Server for use in tests, but does not start
// the server.  It returns the server, or any errors the new server creates.
func TestMakeServer(tb testing.TB, pollInterval time.Duration, disableFsNotify bool, options ...func(*Server) error) (*Server, error) {
	tb.Helper()
	w, err := watcher.NewLogWatcher(pollInterval, !disableFsNotify)
	if err != nil {
		tb.Fatal(err)
	}

	return New(metrics.NewStore(), w, options...)
}

// TestStartServer creates a new Server and starts it running.  It
// returns the server, and a cleanup function.
func TestStartServer(tb testing.TB, pollInterval time.Duration, disableFsNotify bool, options ...func(*Server) error) (*Server, func()) {
	tb.Helper()
	options = append(options, BindAddress("", "0"))

	m, err := TestMakeServer(tb, pollInterval, disableFsNotify, options...)
	if err != nil {
		tb.Fatal(err)
	}

	errc := make(chan error, 1)
	go func() {
		err := m.Run()
		errc <- err
	}()

	glog.Infof("check that server is listening")
	count := 0
	for _, err := net.DialTimeout("tcp", m.Addr(), 10*time.Millisecond*timeoutMultiplier); err != nil && count < 10; count++ {
		glog.Infof("err: %s, retrying to dial %s", err, m.Addr())
		time.Sleep(100 * time.Millisecond * timeoutMultiplier)
	}
	if count >= 10 {
		tb.Fatal("server wasn't listening after 10 attempts")
	}

	return m, func() {
		err := m.Close()
		if err != nil {
			tb.Fatal(err)
		}
		select {
		case err = <-errc:
		case <-time.After(5 * time.Second):
			buf := make([]byte, 1<<16)
			n := runtime.Stack(buf, true)
			fmt.Fprintf(os.Stderr, "%s", buf[0:n])
			tb.Fatal("timeout waiting for shutdown")
		}

		if err != nil {
			tb.Fatal(err)
		}
	}
}

// TestGetMetric fetches the expvar metrics from the Server at addr, and
// returns the value of one named name.  Callers are responsible for type
// assertions on the returned value.
func TestGetMetric(tb testing.TB, addr, name string) interface{} {
	uri := fmt.Sprintf("http://%s/debug/vars", addr)
	client := &http.Client{
		Timeout: 5 * time.Second,
	}
	resp, err := client.Get(uri)
	if err != nil {
		tb.Fatal(err)
	}
	buf := new(bytes.Buffer)
	n, err := buf.ReadFrom(resp.Body)
	testutil.FatalIfErr(tb, err)
	glog.Infof("Read %d bytes", n)
	var r map[string]interface{}
	if err := json.Unmarshal(buf.Bytes(), &r); err != nil {
		tb.Fatalf("%s: body was %s", err, buf.String())
	}
	return r[name]
}

// ExpectMetricDelta checks to see if the difference between a and b is want;
// it assumes both values are float64s that came from a TestGetMetric.
func ExpectMetricDelta(tb testing.TB, a, b interface{}, want float64) {
	tb.Helper()
	if a == nil {
		a = 0.
	}
	if b == nil {
		b = 0.
	}
	if a.(float64)-b.(float64) != want {
		tb.Errorf("Unexpected delta: got %v - %v, want %g", a, b, want)
	}
}
<|endoftext|>


<commit_before>// Copyright 2022 Google LLC
//
// 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 deviations documents and controls vendor deviation
// workarounds that exist in the featureprofiles test suite.
//
// This is a temporary workaround and will be deprecated in the
// future.
package deviations

import "flag"

// Vendor deviation flags.
var (
	InterfaceEnabled = flag.Bool("deviation_interface_enabled", true,
		"Device requires interface enabled leaf booleans to be explicitly set to true (b/197141773)")

	AggregateAtomicUpdate = flag.Bool("deviation_aggregate_atomic_update", true,
		"Device requires that aggregate Port-Channel and its members be defined in a single gNMI Update transaction at /interfaces; otherwise lag-type will be dropped, and no member can be added to the aggregate (b/201574574)")
)
<commit_msg>deviations' config (#251)<commit_after>// Copyright 2022 Google LLC
//
// 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 deviations documents and controls vendor deviation
// workarounds that exist in the featureprofiles test suite.
//
// This is a temporary workaround and will be deprecated in the
// future.
package deviations

import "flag"

// Vendor deviation flags.
var (
	InterfaceEnabled = flag.Bool("deviation_interface_enabled", false,
		"Device requires interface enabled leaf booleans to be explicitly set to true (b/197141773)")

	AggregateAtomicUpdate = flag.Bool("deviation_aggregate_atomic_update", true,
		"Device requires that aggregate Port-Channel and its members be defined in a single gNMI Update transaction at /interfaces; otherwise lag-type will be dropped, and no member can be added to the aggregate (b/201574574)")
)
<|endoftext|>


<commit_before>// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.

// Package prefix implements bit readers and writers that use prefix encoding.
package prefix

import (
	"sort"

	"github.com/dsnet/compress/internal"
)

const (
	countBits = 5  // Number of bits to store the bit-length of the code
	valueBits = 27 // Number of bits to store the code value

	countMask = (1 << countBits) - 1
)

type PrefixCode struct {
	Sym uint32 // The symbol being mapped
	Cnt uint32 // The number times this symbol is used
	Len uint32 // Bit-length of the prefix code
	Val uint32 // Value of the prefix code (must be in 0..(1<<Len)-1)
}
type PrefixCodes []PrefixCode

type prefixCodesBySymbol []PrefixCode

func (c prefixCodesBySymbol) Len() int           { return len(c) }
func (c prefixCodesBySymbol) Less(i, j int) bool { return c[i].Sym < c[j].Sym }
func (c prefixCodesBySymbol) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }

type prefixCodesByCount []PrefixCode

func (c prefixCodesByCount) Len() int           { return len(c) }
func (c prefixCodesByCount) Less(i, j int) bool { return c[i].Cnt < c[j].Cnt }
func (c prefixCodesByCount) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }

func (pc PrefixCodes) SortBySymbol() { sort.Sort(prefixCodesBySymbol(pc)) }
func (pc PrefixCodes) SortByCount()  { sort.Stable(prefixCodesByCount(pc)) }

// Length computes the total bit-length using the Len and Cnt fields.
func (pc PrefixCodes) Length() (nb uint) {
	for _, c := range pc {
		nb += uint(c.Len * c.Cnt)
	}
	return nb
}

// checkLengths reports whether the codes form a complete prefix tree.
func (pc PrefixCodes) checkLengths() bool {
	sum := 1 << valueBits
	for _, c := range pc {
		sum -= (1 << valueBits) >> uint(c.Len)
	}
	return sum == 0 || len(pc) == 0
}

// checkPrefixes reports whether all codes have non-overlapping prefixes.
func (pc PrefixCodes) checkPrefixes() bool {
	for i, c1 := range pc {
		for j, c2 := range pc {
			mask := uint32(1)<<c1.Len - 1
			if i != j && c1.Len <= c2.Len && c1.Val&mask == c2.Val&mask {
				return false
			}
		}
	}
	return true
}

// checkCanonical reports whether all codes are canonical.
func (pc PrefixCodes) checkCanonical() bool {
	// Rule #1: All codes of a given bit-length are consecutive values.
	var vals [valueBits + 1]PrefixCode
	for _, c := range pc {
		if c.Len > 0 {
			c.Val = internal.ReverseUint32N(c.Val, uint(c.Len))
			if vals[c.Len].Cnt > 0 && vals[c.Len].Val+1 != c.Val {
				return false
			}
			vals[c.Len].Val = c.Val
			vals[c.Len].Cnt++
		}
	}

	// Rule #2: Shorter codes lexicographically precede longer codes.
	var last PrefixCode
	for _, v := range vals {
		if v.Cnt > 0 {
			curVal := v.Val - v.Cnt + 1
			if last.Cnt != 0 && last.Val >= curVal {
				return false
			}
			last = v
		}
	}
	return true
}

// GenerateLengths assigns non-zero bit-lengths to all codes. Codes with high
// frequency counts will be assigned shorter codes to reduce bit entropy.
// This function is used primarily by compressors.
//
// The input codes must have the Cnt field populated, be sorted by count, and
// be densely packed. Even if a code has a count of 0, a non-zero bit-length
// will still be assigned.
//
// The result will have the Len field populated. The algorithm used guarantees
// that Len <= maxBits and that it is a complete prefix tree. The resulting
// codes will be sorted by count.
func GenerateLengths(codes PrefixCodes, maxBits uint) error {
	if len(codes) <= 1 {
		if len(codes) == 1 {
			codes[0].Len = 0
		}
		return nil
	}

	// Verify that the codes are in ascending order by count.
	cntLast := codes[0].Cnt
	for _, c := range codes[1:] {
		if c.Cnt < cntLast {
			return internal.ErrInvalid // Non-monotonically increasing
		}
		cntLast = c.Cnt
	}

	// Compute the number of symbols that exist for each bit-length.
	// This uses the Huffman algorithm, and runs in O(n), but assumes that
	// codes is sorted in increasing order of frequency.
	type node struct {
		cnt uint32

		// Either n0 or c0 is set. Either n1 or c1 is set.
		n0, n1 int // Index to child nodes
		c0, c1 *PrefixCode
	}
	var nodeIdx int
	var nodeArr [1024]node // Large enough to handle most cases on the stack
	nodes := nodeArr[:]
	if len(nodes) < len(codes) {
		nodes = make([]node, len(codes)) // Number of internal nodes < number of leaves
	}
	freqs, queue := codes, nodes[:0]
	for len(freqs)+len(queue) > 1 {
		// These are the two smallest nodes at the front of freqs and queue.
		var n node
		if len(queue) == 0 || (len(freqs) > 0 && freqs[0].Cnt <= queue[0].cnt) {
			n.c0, freqs = &freqs[0], freqs[1:]
			n.cnt += n.c0.Cnt
		} else {
			n.cnt += queue[0].cnt
			n.n0 = nodeIdx // nodeIdx is same as &queue[0] - &nodes[0]
			nodeIdx++
			queue = queue[1:]
		}
		if len(queue) == 0 || (len(freqs) > 0 && freqs[0].Cnt <= queue[0].cnt) {
			n.c1, freqs = &freqs[0], freqs[1:]
			n.cnt += n.c1.Cnt
		} else {
			n.cnt += queue[0].cnt
			n.n1 = nodeIdx // nodeIdx is same as &queue[0] - &nodes[0]
			nodeIdx++
			queue = queue[1:]
		}
		queue = append(queue, n)
	}

	// Search the whole binary tree, noting when we hit each leaf node.
	var fixBits bool
	var explore func(int, uint)
	explore = func(rootIdx int, level uint) {
		root := &nodes[rootIdx]
		if root.c0 == nil {
			explore(root.n0, level+1)
		} else {
			fixBits = fixBits || (level > maxBits)
			root.c0.Len = uint32(level)
		}
		if root.c1 == nil {
			explore(root.n1, level+1)
		} else {
			fixBits = fixBits || (level > maxBits)
			root.c1.Len = uint32(level)
		}
	}
	explore(nodeIdx, 1)

	// Fix the bit-lengths if we violate the maxBits requirement.
	if fixBits {
		// Create histogram for number of symbols with each bit-length.
		var symBitsArr [valueBits + 1]uint32
		symBits := symBitsArr[:] // symBits[nb] indicates number of symbols using nb bits
		for _, c := range codes {
			for int(c.Len) >= len(symBits) {
				symBits = append(symBits, 0)
			}
			symBits[c.Len]++
		}

		// Fudge the tree such that the largest bit-length is <= maxBits.
		// This is accomplish by effectively doing a tree rotation. That is, we
		// increase the bit-length of some higher frequency code, so that the
		// bit-lengths of many lower frequency codes can be decreased.
		var treeRotate func(uint)
		treeRotate = func(nb uint) {
			if symBits[nb-1] == 0 {
				treeRotate(nb - 1)
			}
			symBits[nb-1] -= 1 // Push this node to the level below
			symBits[nb] += 3   // This level gets one node from above, two from below
			symBits[nb+1] -= 2 // Push two nodes to the level above
		}
		for i := uint(len(symBits)) - 1; i > maxBits; i-- {
			for symBits[i] > 0 {
				treeRotate(i - 1)
			}
		}

		// Assign bit-lengths to each code. Since codes is sorted in increasing
		// order of frequency, that means that the most frequently used symbols
		// should have the shortest bit-lengths.  Thus, we copy symbols to codes
		// from the back of codes first.
		cs := codes
		for nb, cnt := range symBits {
			if cnt > 0 {
				pos := len(cs) - int(cnt)
				cs2 := cs[pos:]
				for i := range cs2 {
					cs2[i].Len = uint32(nb)
				}
				cs = cs[:pos]
			}
		}
		if len(cs) != 0 {
			panic("not all codes were used up")
		}
	}

	if internal.Debug && !codes.checkLengths() {
		panic("incomplete prefix tree detected")
	}
	return nil
}

// GeneratePrefixes assigns a prefix value to all codes according to the
// bit-lengths. This function is used by both compressors and decompressors.
//
// The input codes must have the Sym and Len fields populated, be sorted by
// symbol and be densely packed. The bit-lengths of each code must be properly
// allocated, such that it forms a complete tree.
//
// The result will have the Val field populated and will produce a canonical
// prefix tree.
func GeneratePrefixes(codes PrefixCodes) error {
	if len(codes) <= 1 {
		if len(codes) == 1 {
			if codes[0].Len != 0 {
				return internal.ErrInvalid
			}
			codes[0].Val = 0
		}
		return nil
	}

	// Compute basic statistics on the symbols.
	var bitCnts [valueBits + 1]uint
	c0 := codes[0]
	bitCnts[c0.Len]++
	minBits, maxBits, symLast := c0.Len, c0.Len, c0.Sym
	for _, c := range codes[1:] {
		if c.Sym <= symLast {
			return internal.ErrInvalid // Non-unique or non-monotonically increasing
		}
		if minBits > c.Len {
			minBits = c.Len
		}
		if maxBits < c.Len {
			maxBits = c.Len
		}
		bitCnts[c.Len]++ // Histogram of bit counts
		symLast = c.Sym  // Keep track of last symbol
	}
	if minBits == 0 {
		return internal.ErrInvalid // Bit-length is too short
	}

	// Compute the next code for a symbol of a given bit length.
	var nextCodes [valueBits + 1]uint
	var code uint
	for i := minBits; i <= maxBits; i++ {
		code <<= 1
		nextCodes[i] = code
		code += bitCnts[i]
	}
	if code != 1<<maxBits {
		return internal.ErrInvalid // Tree is under or over subscribed
	}

	// Assign the code to each symbol.
	for i, c := range codes {
		codes[i].Val = internal.ReverseUint32N(uint32(nextCodes[c.Len]), uint(c.Len))
		nextCodes[c.Len]++
	}

	if internal.Debug && !codes.checkPrefixes() {
		panic("overlapping prefixes detected")
	}
	if internal.Debug && !codes.checkCanonical() {
		panic("non-canonical prefixes detected")
	}
	return nil
}

func allocUint32s(s []uint32, n int) []uint32 {
	if cap(s) >= n {
		return s[:n]
	}
	return make([]uint32, n, n*3/2)
}

func extendSliceUint32s(s [][]uint32, n int) [][]uint32 {
	if cap(s) >= n {
		return s[:n]
	}
	ss := make([][]uint32, n, n*3/2)
	copy(ss, s[:cap(s)])
	return ss
}
<commit_msg>internal/prefix: add more documentation for the prefix logic<commit_after>// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.

// Package prefix implements bit readers and writers that use prefix encoding.
package prefix

import (
	"sort"

	"github.com/dsnet/compress/internal"
)

const (
	countBits = 5  // Number of bits to store the bit-length of the code
	valueBits = 27 // Number of bits to store the code value

	countMask = (1 << countBits) - 1
)

// PrefixCode is a representation of a prefix code, which is conceptually a
// mapping from some arbitrary symbol to some bit-string.
//
// The Sym and Cnt fields are typically provided by the user,
// while the Len and Val fields are generated by this package.
type PrefixCode struct {
	Sym uint32 // The symbol being mapped
	Cnt uint32 // The number times this symbol is used
	Len uint32 // Bit-length of the prefix code
	Val uint32 // Value of the prefix code (must be in 0..(1<<Len)-1)
}
type PrefixCodes []PrefixCode

type prefixCodesBySymbol []PrefixCode

func (c prefixCodesBySymbol) Len() int           { return len(c) }
func (c prefixCodesBySymbol) Less(i, j int) bool { return c[i].Sym < c[j].Sym }
func (c prefixCodesBySymbol) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }

type prefixCodesByCount []PrefixCode

func (c prefixCodesByCount) Len() int           { return len(c) }
func (c prefixCodesByCount) Less(i, j int) bool { return c[i].Cnt < c[j].Cnt }
func (c prefixCodesByCount) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }

func (pc PrefixCodes) SortBySymbol() { sort.Sort(prefixCodesBySymbol(pc)) }
func (pc PrefixCodes) SortByCount()  { sort.Stable(prefixCodesByCount(pc)) }

// Length computes the total bit-length using the Len and Cnt fields.
func (pc PrefixCodes) Length() (nb uint) {
	for _, c := range pc {
		nb += uint(c.Len * c.Cnt)
	}
	return nb
}

// checkLengths reports whether the codes form a complete prefix tree.
func (pc PrefixCodes) checkLengths() bool {
	sum := 1 << valueBits
	for _, c := range pc {
		sum -= (1 << valueBits) >> uint(c.Len)
	}
	return sum == 0 || len(pc) == 0
}

// checkPrefixes reports whether all codes have non-overlapping prefixes.
func (pc PrefixCodes) checkPrefixes() bool {
	for i, c1 := range pc {
		for j, c2 := range pc {
			mask := uint32(1)<<c1.Len - 1
			if i != j && c1.Len <= c2.Len && c1.Val&mask == c2.Val&mask {
				return false
			}
		}
	}
	return true
}

// checkCanonical reports whether all codes are canonical.
// That is, they have the following properties:
//
//	1. All codes of a given bit-length are consecutive values.
//	2. Shorter codes lexicographically precede longer codes.
//
// The codes must have unique symbols and be sorted by the symbol
// The Len and Val fields in each code must be populated.
func (pc PrefixCodes) checkCanonical() bool {
	// Rule 1.
	var vals [valueBits + 1]PrefixCode
	for _, c := range pc {
		if c.Len > 0 {
			c.Val = internal.ReverseUint32N(c.Val, uint(c.Len))
			if vals[c.Len].Cnt > 0 && vals[c.Len].Val+1 != c.Val {
				return false
			}
			vals[c.Len].Val = c.Val
			vals[c.Len].Cnt++
		}
	}

	// Rule 2.
	var last PrefixCode
	for _, v := range vals {
		if v.Cnt > 0 {
			curVal := v.Val - v.Cnt + 1
			if last.Cnt != 0 && last.Val >= curVal {
				return false
			}
			last = v
		}
	}
	return true
}

// GenerateLengths assigns non-zero bit-lengths to all codes. Codes with high
// frequency counts will be assigned shorter codes to reduce bit entropy.
// This function is used primarily by compressors.
//
// The input codes must have the Cnt field populated, be sorted by count.
// Even if a code has a count of 0, a non-zero bit-length will be assigned.
//
// The result will have the Len field populated. The algorithm used guarantees
// that Len <= maxBits and that it is a complete prefix tree. The resulting
// codes will remain sorted by count.
func GenerateLengths(codes PrefixCodes, maxBits uint) error {
	if len(codes) <= 1 {
		if len(codes) == 1 {
			codes[0].Len = 0
		}
		return nil
	}

	// Verify that the codes are in ascending order by count.
	cntLast := codes[0].Cnt
	for _, c := range codes[1:] {
		if c.Cnt < cntLast {
			return internal.ErrInvalid // Non-monotonically increasing
		}
		cntLast = c.Cnt
	}

	// Construct a Huffman tree used to generate the bit-lengths.
	//
	// The Huffman tree is a binary tree where each symbol lies as a leaf node
	// on this tree. The length of the prefix code to assign is the depth of
	// that leaf from the root. The Huffman algorithm, which runs in O(n),
	// is used to generate the tree. It assumes that codes are sorted in
	// increasing order of frequency.
	//
	// The algorithm is as follows:
	//	1. Start with two queues, F and Q, where F contains all of the starting
	//	symbols sorted such that symbols with lowest counts come first.
	//	2. While len(F)+len(Q) > 1:
	//		2a. Dequeue the node from F or Q that has the lowest weight as N0.
	//		2b. Dequeue the node from F or Q that has the lowest weight as N1.
	//		2c. Create a new node N that has N0 and N1 as its children.
	//		2d. Enqueue N into the back of Q.
	//	3. The tree's root node is Q[0].
	type node struct {
		cnt uint32

		// n0 or c0 represent the left child of this node.
		// Since Go does not have unions, only one of these will be set.
		// Similarly, n1 or c1 represent the right child of this node.
		//
		// If n0 or n1 is set, then it represents a "pointer" to another
		// node in the Huffman tree. Since Go's pointer analysis cannot reason
		// that these node pointers do not escape (golang.org/issue/13493),
		// we use an index to a node in the nodes slice as a pseudo-pointer.
		//
		// If c0 or c1 is set, then it represents a leaf "node" in the
		// Huffman tree. The leaves are the PrefixCode values themselves.
		n0, n1 int // Index to child nodes
		c0, c1 *PrefixCode
	}
	var nodeIdx int
	var nodeArr [1024]node // Large enough to handle most cases on the stack
	nodes := nodeArr[:]
	if len(nodes) < len(codes) {
		nodes = make([]node, len(codes)) // Number of internal nodes < number of leaves
	}
	freqs, queue := codes, nodes[:0]
	for len(freqs)+len(queue) > 1 {
		// These are the two smallest nodes at the front of freqs and queue.
		var n node
		if len(queue) == 0 || (len(freqs) > 0 && freqs[0].Cnt <= queue[0].cnt) {
			n.c0, freqs = &freqs[0], freqs[1:]
			n.cnt += n.c0.Cnt
		} else {
			n.cnt += queue[0].cnt
			n.n0 = nodeIdx // nodeIdx is same as &queue[0] - &nodes[0]
			nodeIdx++
			queue = queue[1:]
		}
		if len(queue) == 0 || (len(freqs) > 0 && freqs[0].Cnt <= queue[0].cnt) {
			n.c1, freqs = &freqs[0], freqs[1:]
			n.cnt += n.c1.Cnt
		} else {
			n.cnt += queue[0].cnt
			n.n1 = nodeIdx // nodeIdx is same as &queue[0] - &nodes[0]
			nodeIdx++
			queue = queue[1:]
		}
		queue = append(queue, n)
	}
	rootIdx := nodeIdx

	// Search the whole binary tree, noting when we hit each leaf node.
	// We do not care about the exact Huffman tree structure, but rather we only
	// care about depth of each of the leaf nodes. That is, the depth determines
	// how long each symbol is in bits.
	//
	// Since the number of leaves is n, there is at most n internal nodes.
	// Thus, this algorithm runs in O(n).
	var fixBits bool
	var explore func(int, uint)
	explore = func(rootIdx int, level uint) {
		root := &nodes[rootIdx]

		// Explore left branch.
		if root.c0 == nil {
			explore(root.n0, level+1)
		} else {
			fixBits = fixBits || (level > maxBits)
			root.c0.Len = uint32(level)
		}

		// Explore right branch.
		if root.c1 == nil {
			explore(root.n1, level+1)
		} else {
			fixBits = fixBits || (level > maxBits)
			root.c1.Len = uint32(level)
		}
	}
	explore(rootIdx, 1)

	// Fix the bit-lengths if we violate the maxBits requirement.
	if fixBits {
		// Create histogram for number of symbols with each bit-length.
		var symBitsArr [valueBits + 1]uint32
		symBits := symBitsArr[:] // symBits[nb] indicates number of symbols using nb bits
		for _, c := range codes {
			for int(c.Len) >= len(symBits) {
				symBits = append(symBits, 0)
			}
			symBits[c.Len]++
		}

		// Fudge the tree such that the largest bit-length is <= maxBits.
		// This is accomplish by effectively doing a tree rotation. That is, we
		// increase the bit-length of some higher frequency code, so that the
		// bit-lengths of lower frequency codes can be decreased.
		//
		// Visually, this looks like the following transform:
		//
		//	Level   Before       After
		//	          __          ___
		//	         /  \        /   \
		//	 n-1    X  / \      /\   /\
		//	 n        X  /\    X  X X  X
		//	 n+1        X  X
		//
		var treeRotate func(uint)
		treeRotate = func(nb uint) {
			if symBits[nb-1] == 0 {
				treeRotate(nb - 1)
			}
			symBits[nb-1] -= 1 // Push this node to the level below
			symBits[nb] += 3   // This level gets one node from above, two from below
			symBits[nb+1] -= 2 // Push two nodes to the level above
		}
		for i := uint(len(symBits)) - 1; i > maxBits; i-- {
			for symBits[i] > 0 {
				treeRotate(i - 1)
			}
		}

		// Assign bit-lengths to each code. Since codes is sorted in increasing
		// order of frequency, that means that the most frequently used symbols
		// should have the shortest bit-lengths. Thus, we copy symbols to codes
		// from the back of codes first.
		cs := codes
		for nb, cnt := range symBits {
			if cnt > 0 {
				pos := len(cs) - int(cnt)
				cs2 := cs[pos:]
				for i := range cs2 {
					cs2[i].Len = uint32(nb)
				}
				cs = cs[:pos]
			}
		}
		if len(cs) != 0 {
			panic("not all codes were used up")
		}
	}

	if internal.Debug && !codes.checkLengths() {
		panic("incomplete prefix tree detected")
	}
	return nil
}

// GeneratePrefixes assigns a prefix value to all codes according to the
// bit-lengths. This function is used by both compressors and decompressors.
//
// The input codes must have the Sym and Len fields populated and be
// sorted by symbol. The bit-lengths of each code must be properly allocated,
// such that it forms a complete tree.
//
// The result will have the Val field populated and will produce a canonical
// prefix tree. The resulting codes will remain sorted by symbol.
func GeneratePrefixes(codes PrefixCodes) error {
	if len(codes) <= 1 {
		if len(codes) == 1 {
			if codes[0].Len != 0 {
				return internal.ErrInvalid
			}
			codes[0].Val = 0
		}
		return nil
	}

	// Compute basic statistics on the symbols.
	var bitCnts [valueBits + 1]uint
	c0 := codes[0]
	bitCnts[c0.Len]++
	minBits, maxBits, symLast := c0.Len, c0.Len, c0.Sym
	for _, c := range codes[1:] {
		if c.Sym <= symLast {
			return internal.ErrInvalid // Non-unique or non-monotonically increasing
		}
		if minBits > c.Len {
			minBits = c.Len
		}
		if maxBits < c.Len {
			maxBits = c.Len
		}
		bitCnts[c.Len]++ // Histogram of bit counts
		symLast = c.Sym  // Keep track of last symbol
	}
	if minBits == 0 {
		return internal.ErrInvalid // Bit-length is too short
	}

	// Compute the next code for a symbol of a given bit length.
	var nextCodes [valueBits + 1]uint
	var code uint
	for i := minBits; i <= maxBits; i++ {
		code <<= 1
		nextCodes[i] = code
		code += bitCnts[i]
	}
	if code != 1<<maxBits {
		return internal.ErrInvalid // Tree is under or over subscribed
	}

	// Assign the code to each symbol.
	for i, c := range codes {
		codes[i].Val = internal.ReverseUint32N(uint32(nextCodes[c.Len]), uint(c.Len))
		nextCodes[c.Len]++
	}

	if internal.Debug && !codes.checkPrefixes() {
		panic("overlapping prefixes detected")
	}
	if internal.Debug && !codes.checkCanonical() {
		panic("non-canonical prefixes detected")
	}
	return nil
}

func allocUint32s(s []uint32, n int) []uint32 {
	if cap(s) >= n {
		return s[:n]
	}
	return make([]uint32, n, n*3/2)
}

func extendSliceUint32s(s [][]uint32, n int) [][]uint32 {
	if cap(s) >= n {
		return s[:n]
	}
	ss := make([][]uint32, n, n*3/2)
	copy(ss, s[:cap(s)])
	return ss
}
<|endoftext|>


<commit_before>package http

import (
	"fmt"
	"net/http/httputil"
	"os"
	"runtime"
	"time"

	"github.com/gin-gonic/gin"
	log "github.com/golang/glog"
)

func loggerHandler(c *gin.Context) {
	// Start timer
	start := time.Now()
	path := c.Request.URL.Path
	raw := c.Request.URL.RawQuery
	method := c.Request.Method

	// Process request
	c.Next()

	// Stop timer
	end := time.Now()
	latency := end.Sub(start)
	statusCode := c.Writer.Status()
	ecode := c.GetInt(contextErrCode)
	clientIP := c.ClientIP()
	if raw != "" {
		path = path + "?" + raw
	}
	log.Infof("METHOD:%s | PATH:%s | CODE:%d | IP:%s | TIME:%d | ECODE:%d", method, path, statusCode, clientIP, latency/time.Millisecond, ecode)
}

func recoverHandler(c *gin.Context) {
	defer func() {
		if err := recover(); err != nil {
			const size = 64 << 10
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			httprequest, _ := httputil.DumpRequest(c.Request, false)
			pnc := fmt.Sprintf("[Recovery] %s panic recovered:\n%s\n%s\n%s", time.Now().Format("2006-01-02 15:04:05"), string(httprequest), err, buf)
			fmt.Fprintf(os.Stderr, pnc)
			log.Error(pnc)
			c.AbortWithStatus(500)
		}
	}()
	c.Next()
}
<commit_msg>fix lint<commit_after>package http

import (
	"fmt"
	"net/http/httputil"
	"os"
	"runtime"
	"time"

	"github.com/gin-gonic/gin"
	log "github.com/golang/glog"
)

func loggerHandler(c *gin.Context) {
	// Start timer
	start := time.Now()
	path := c.Request.URL.Path
	raw := c.Request.URL.RawQuery
	method := c.Request.Method

	// Process request
	c.Next()

	// Stop timer
	end := time.Now()
	latency := end.Sub(start)
	statusCode := c.Writer.Status()
	ecode := c.GetInt(contextErrCode)
	clientIP := c.ClientIP()
	if raw != "" {
		path = path + "?" + raw
	}
	log.Infof("METHOD:%s | PATH:%s | CODE:%d | IP:%s | TIME:%d | ECODE:%d", method, path, statusCode, clientIP, latency/time.Millisecond, ecode)
}

func recoverHandler(c *gin.Context) {
	defer func() {
		if err := recover(); err != nil {
			const size = 64 << 10
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			httprequest, _ := httputil.DumpRequest(c.Request, false)
			pnc := fmt.Sprintf("[Recovery] %s panic recovered:\n%s\n%s\n%s", time.Now().Format("2006-01-02 15:04:05"), string(httprequest), err, buf)
			fmt.Fprint(os.Stderr, pnc)
			log.Error(pnc)
			c.AbortWithStatus(500)
		}
	}()
	c.Next()
}
<|endoftext|>


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

// Package series holds information about series supported in the
// charmstore.
package series // import "gopkg.in/juju/charmstore.v5/internal/series"

// Distribution represents a distribution supported by the charmstore.
// Every series will belong to a distribution.
type Distribution string

const (
	Ubuntu  Distribution = "ubuntu"
	CentOS  Distribution = "centos"
	Windows Distribution = "windows"
)

// SeriesInfo contains the information the charmstore knows about a
// series name.
type SeriesInfo struct {
	// CharmSeries holds whether this series name is for charms.
	CharmSeries bool

	// Distribution holds the Distribution this series belongs to.
	Distribution Distribution

	// SearchIndex holds wether charms in this series should be added
	// to the search index.
	SearchIndex bool

	// SearchBoost contains the relative boost given to charms in
	// this series when searching.
	SearchBoost float64
}

// Series contains the data charmstore knows about series names
var Series = map[string]SeriesInfo{
	// Bundle
	"bundle": {false, "", true, 1.1380},

	// Ubuntu
	"oneiric": {true, Ubuntu, false, 0},
	"precise": {true, Ubuntu, true, 1.1125},
	"quantal": {true, Ubuntu, false, 0},
	"raring":  {true, Ubuntu, false, 0},
	"saucy":   {true, Ubuntu, false, 0},
	"trusty":  {true, Ubuntu, true, 1.125},
	"utopic":  {true, Ubuntu, false, 0},
	"vivid":   {true, Ubuntu, false, 0},
	"wily":    {true, Ubuntu, false, 1.102},
	"xenial":  {true, Ubuntu, true, 1.1375},
	"yakkety": {true, Ubuntu, false, 0},
	"zesty":   {true, Ubuntu, false, 0},
	"artful":  {true, Ubuntu, true, 1.105},
	"bionic":  {true, Ubuntu, true, 1.15},
	"cosmic":  {true, Ubuntu, true, 0}, // TODO: make this higher (1.107) when cosmic is released

	// Windows
	"win2012hvr2": {true, Windows, true, 1.1},
	"win2012hv":   {true, Windows, true, 1.1},
	"win2012r2":   {true, Windows, true, 1.1},
	"win2012":     {true, Windows, true, 1.1},
	"win7":        {true, Windows, true, 1.1},
	"win8":        {true, Windows, true, 1.1},
	"win81":       {true, Windows, true, 1.1},
	"win10":       {true, Windows, true, 1.1},
	"win2016":     {true, Windows, true, 1.1},
	"win2016hv":   {true, Windows, true, 1.1},
	"win2016nano": {true, Windows, true, 1.1},

	// Centos
	"centos7": {true, CentOS, true, 1.1},
}
<commit_msg>Add Kubernetes series<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// Package series holds information about series supported in the
// charmstore.
package series // import "gopkg.in/juju/charmstore.v5/internal/series"

// Distribution represents a distribution supported by the charmstore.
// Every series will belong to a distribution.
type Distribution string

const (
	Ubuntu     Distribution = "ubuntu"
	CentOS     Distribution = "centos"
	Windows    Distribution = "windows"
	Kubernetes Distribution = "kubernetes"
)

// SeriesInfo contains the information the charmstore knows about a
// series name.
type SeriesInfo struct {
	// CharmSeries holds whether this series name is for charms.
	CharmSeries bool

	// Distribution holds the Distribution this series belongs to.
	Distribution Distribution

	// SearchIndex holds whether charms in this series should be added
	// to the search index.
	SearchIndex bool

	// SearchBoost contains the relative boost given to charms in
	// this series when searching.
	SearchBoost float64
}

// Series contains the data charmstore knows about series names
var Series = map[string]SeriesInfo{
	// Bundle
	"bundle": {false, "", true, 1.1380},

	// Ubuntu
	"oneiric": {true, Ubuntu, false, 0},
	"precise": {true, Ubuntu, true, 1.1125},
	"quantal": {true, Ubuntu, false, 0},
	"raring":  {true, Ubuntu, false, 0},
	"saucy":   {true, Ubuntu, false, 0},
	"trusty":  {true, Ubuntu, true, 1.125},
	"utopic":  {true, Ubuntu, false, 0},
	"vivid":   {true, Ubuntu, false, 0},
	"wily":    {true, Ubuntu, false, 1.102},
	"xenial":  {true, Ubuntu, true, 1.1375},
	"yakkety": {true, Ubuntu, false, 0},
	"zesty":   {true, Ubuntu, false, 0},
	"artful":  {true, Ubuntu, true, 1.105},
	"bionic":  {true, Ubuntu, true, 1.15},
	"cosmic":  {true, Ubuntu, true, 0}, // TODO: make this higher (1.107) when cosmic is released

	// Windows
	"win2012hvr2": {true, Windows, true, 1.1},
	"win2012hv":   {true, Windows, true, 1.1},
	"win2012r2":   {true, Windows, true, 1.1},
	"win2012":     {true, Windows, true, 1.1},
	"win7":        {true, Windows, true, 1.1},
	"win8":        {true, Windows, true, 1.1},
	"win81":       {true, Windows, true, 1.1},
	"win10":       {true, Windows, true, 1.1},
	"win2016":     {true, Windows, true, 1.1},
	"win2016hv":   {true, Windows, true, 1.1},
	"win2016nano": {true, Windows, true, 1.1},

	// Centos
	"centos7": {true, CentOS, true, 1.1},

	// Kubernetes
	"kubernetes": {true, Kubernetes, false, 0},
}
<|endoftext|>