<commit_before>package conductor

import (
	"bytes"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"testing"
)

type testResponse struct {
	Path    string
	Matches []string
}

func TestRegexpHandler(t *testing.T) {
	testcases := []struct {
		Method  string
		Path    string
		Body    url.Values
		Status  int
		Matches []string
	}{
		{
			Method:  http.MethodGet,
			Path:    "/posts",
			Status:  http.StatusOK,
			Matches: []string{"/posts"},
		},
		{
			Method:  http.MethodGet,
			Path:    "/posts/1",
			Status:  http.StatusOK,
			Matches: []string{"/posts/1", "1"},
		},
		{
			Method: http.MethodPost,
			Path:   "/posts",
			Body: url.Values{
				"title": {"sample post"},
				"body":  {"post body"},
			},
			Status:  http.StatusOK,
			Matches: []string{"/posts"},
		},
		{
			Method: http.MethodPut,
			Path:   "/posts/1",
			Body: url.Values{
				"body": {"updated post body"},
			},
			Status:  http.StatusOK,
			Matches: []string{"/posts/1", "1"},
		},
		{
			Method:  http.MethodDelete,
			Path:    "/posts/1",
			Status:  http.StatusOK,
			Matches: []string{"/posts/1", "1"},
		},
		{
			Method: http.MethodGet,
			Path:   "/posts/23/comments",
			Status: http.StatusNotFound,
		},
	}

	handler := func(w http.ResponseWriter, r *http.Request) {
		response := testResponse{Path: r.URL.Path}

		matches, ok := RegexpMatchesFromContext(r.Context())
		if ok {
			response.Matches = matches
		}

		output, err := json.Marshal(response)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		w.Header().Set("Content-Type", "application/json")
		w.Write(output)
	}

	// Create RESTful /posts resource
	routes := RegexpRouteMap{}
	routes.AddRouteFunc(http.MethodGet, `/posts[/]?$`, handler)
	routes.AddRouteFunc(http.MethodGet, `/posts/([0-9]+)$`, handler)
	routes.AddRouteFunc(http.MethodPost, `/posts[/]?$`, handler)
	routes.AddRouteFunc(http.MethodPut, `/posts/([0-9]+)$`, handler)
	routes.AddRouteFunc(http.MethodDelete, `/posts/([0-9]+)$`, handler)
	rh := RegexpHandler(routes)

	for _, tc := range testcases {
		body, err := json.Marshal(tc.Body)
		if err != nil {
			t.Fatal(err)
		}
		req, err := http.NewRequest(tc.Method, tc.Path, bytes.NewBuffer(body))
		if err != nil {
			t.Fatal(err)
		}

		w := httptest.NewRecorder()
		rh.ServeHTTP(w, req)

		status := w.Code
		if status != tc.Status {
			t.Errorf("handler status code %v, expected %v", status, tc.Status)
		}

		switch status {
		default:
			data := strings.TrimSpace(w.Body.String())
			if data != http.StatusText(tc.Status) {
				t.Errorf("handler error %s, expected %s", data, http.StatusText(tc.Status))
			}
		case http.StatusOK:
			var data testResponse
			err := json.Unmarshal(w.Body.Bytes(), &data)
			if err != nil {
				t.Fatalf("%v: %s", err, w.Body.String())
			}

			if data.Path != tc.Path {
				t.Errorf("handler path %s, expected %s", data.Path, tc.Path)
			}

			if len(data.Matches) != len(tc.Matches) {
				t.Errorf("handler regexp matches %+v, expected %+v", data.Matches, tc.Matches)
			} else {
				for i := 0; i < len(data.Matches); i++ {
					if data.Matches[i] != tc.Matches[i] {
						t.Errorf("handler match %v, expected %v", data.Matches[i], tc.Matches[i])
					}
				}
			}
		}
	}
}
<commit_msg>Refactor regexp tests to be paralell subtests<commit_after>package conductor

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"testing"
)

type testResponse struct {
	Path    string
	Matches []string
}

func TestRegexpHandler(t *testing.T) {
	testcases := []struct {
		Path    string
		Method  string
		Status  int
		Matches []string
		Body    url.Values
	}{
		{
			Path:    "/posts",
			Method:  http.MethodGet,
			Status:  http.StatusOK,
			Matches: []string{"/posts"},
		},
		{
			Path:    "/posts/1",
			Method:  http.MethodGet,
			Status:  http.StatusOK,
			Matches: []string{"/posts/1", "1"},
		},
		{
			Path:    "/posts",
			Method:  http.MethodPost,
			Status:  http.StatusOK,
			Matches: []string{"/posts"},
			Body: url.Values{
				"title": {"sample post"},
				"body":  {"post body"},
			},
		},
		{
			Path:    "/posts/1",
			Method:  http.MethodPut,
			Status:  http.StatusOK,
			Matches: []string{"/posts/1", "1"},
			Body: url.Values{
				"body": {"updated post body"},
			},
		},
		{
			Path:    "/posts/1",
			Method:  http.MethodDelete,
			Status:  http.StatusOK,
			Matches: []string{"/posts/1", "1"},
		},
		{
			Path:   "/posts/23/comments",
			Method: http.MethodGet,
			Status: http.StatusNotFound,
		},
	}

	handler := func(w http.ResponseWriter, r *http.Request) {
		response := testResponse{Path: r.URL.Path}

		matches, ok := RegexpMatchesFromContext(r.Context())
		if ok {
			response.Matches = matches
		}

		output, err := json.Marshal(response)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
		w.Header().Set("Content-Type", "application/json")
		w.Write(output)
	}

	// Create RESTful /posts resource
	routes := RegexpRouteMap{}
	routes.AddRouteFunc(http.MethodGet, `/posts[/]?$`, handler)
	routes.AddRouteFunc(http.MethodGet, `/posts/([0-9]+)$`, handler)
	routes.AddRouteFunc(http.MethodPost, `/posts[/]?$`, handler)
	routes.AddRouteFunc(http.MethodPut, `/posts/([0-9]+)$`, handler)
	routes.AddRouteFunc(http.MethodDelete, `/posts/([0-9]+)$`, handler)
	rh := RegexpHandler(routes)

	for _, tc := range testcases {
		tc := tc // capture range var
		name := fmt.Sprintf("%s %s", tc.Method, tc.Path)
		t.Run(name, func(t *testing.T) {
			t.Parallel()

			body, err := json.Marshal(tc.Body)
			if err != nil {
				t.Fatal(err)
			}

			req, err := http.NewRequest(tc.Method, tc.Path, bytes.NewBuffer(body))
			if err != nil {
				t.Fatal(err)
			}

			w := httptest.NewRecorder()
			rh.ServeHTTP(w, req)

			status := w.Code
			if status != tc.Status {
				t.Errorf("handler status code %v, expected %v", status, tc.Status)
			}

			switch status {
			default:
				data := strings.TrimSpace(w.Body.String())
				if data != http.StatusText(tc.Status) {
					t.Errorf("handler error %s, expected %s", data, http.StatusText(tc.Status))
				}
			case http.StatusOK:
				var data testResponse
				err := json.Unmarshal(w.Body.Bytes(), &data)
				if err != nil {
					t.Fatalf("%v: %s", err, w.Body.String())
				}

				if data.Path != tc.Path {
					t.Errorf("handler path %s, expected %s", data.Path, tc.Path)
				}

				if len(data.Matches) != len(tc.Matches) {
					t.Errorf("handler regexp matches %+v, expected %+v", data.Matches, tc.Matches)
				} else {
					for i := 0; i < len(data.Matches); i++ {
						if data.Matches[i] != tc.Matches[i] {
							t.Errorf("handler match %v, expected %v", data.Matches[i], tc.Matches[i])
						}
					}
				}
			}
		})
	}
}
<|endoftext|>


<commit_before>// GoChip8, a Chip8 emulator written in go
// 2014 Hans Wannop

package main

import (
	"bytes"
	"fmt"
	"time"
)

var font = [80]byte{
	0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
	0x20, 0x60, 0x20, 0x20, 0x70, // 1
	0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
	0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
	0x90, 0x90, 0xF0, 0x10, 0x10, // 4
	0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
	0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
	0xF0, 0x10, 0x20, 0x40, 0x40, // 7
	0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
	0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
	0xF0, 0x90, 0xF0, 0x90, 0x90, // A
	0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
	0xF0, 0x80, 0x80, 0x80, 0xF0, // C
	0xE0, 0x90, 0x90, 0x90, 0xE0, // D
	0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
	0xF0, 0x80, 0xF0, 0x80, 0x80, // F
}

type Chip8 struct {
	opcode     uint16
	memory     [4096]byte
	v          [16]byte
	stack      [16]uint16
	index      uint16
	pc         uint16
	delayTimer int
	soundTimer int
	width      int
	height     int
}

func NewChip8() *Chip8 {
	cpu := new(Chip8)
	cpu.pc = 0x200
	cpu.width = 64
	cpu.height = 32
	for i := 0; i < 80; i++ { // Load the font into the first 80 bytes of memory
		cpu.memory[i] = font[i]
	}
	return cpu
}

//Step a cpu cycle
func (chip *Chip8) Step() {
	// Fetch
	chip.opcode = uint16(chip.memory[chip.pc]<<8) | uint16(chip.memory[chip.pc+1]) // OR value of two consecutive addresses to get two byte opcode
	// Decode
	switch {
	// Execute
	}

}

// Renders the screen of the as a string.
func (chip8 *Chip8) String() string {
	var screenBuf bytes.Buffer
	for y := 0; y < chip8.height; y++ {
		for x := 0; x < chip8.width; x++ {
			b := byte(' ')
			//if associated pos in memory is 1 TODO
			//use a splice for screen?
			b = '*'
			screenBuf.WriteByte(b)
		}
		screenBuf.WriteByte('\n')
	}
	return screenBuf.String()
}

func main() {
	chip8 := NewChip8()
	for {
		chip8.Step() // Step cpu cycle
		// Should have check for draw flag here
		// Draw does not occur every cycle
		fmt.Print("\x0c", chip8)     // Refresh screen.
		time.Sleep(time.Second / 60) //Run at 60Hz
	}
}
<commit_msg>Now loading rom file into memory, filename specified by command line arg<commit_after>// GoChip8, a Chip8 emulator written in go
// 2014 Hans Wannop

package main

import (
	"bytes"
	"fmt"
	"time"
	"os"
	"io/ioutil"
)

var font = [80]byte{
	0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
	0x20, 0x60, 0x20, 0x20, 0x70, // 1
	0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
	0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
	0x90, 0x90, 0xF0, 0x10, 0x10, // 4
	0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
	0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
	0xF0, 0x10, 0x20, 0x40, 0x40, // 7
	0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
	0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
	0xF0, 0x90, 0xF0, 0x90, 0x90, // A
	0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
	0xF0, 0x80, 0x80, 0x80, 0xF0, // C
	0xE0, 0x90, 0x90, 0x90, 0xE0, // D
	0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
	0xF0, 0x80, 0xF0, 0x80, 0x80, // F
}

type Chip8 struct {
	opcode     uint16
	memory     [4096]byte
	v          [16]byte
	stack      [16]uint16
	index      uint16
	pc         uint16
	delayTimer int
	soundTimer int
	width      int
	height     int
}

// Takes filename of the rom to load and returns initialised Chip8
func NewChip8(fileName string) *Chip8 {
	cpu := new(Chip8)
	cpu.pc = 0x200
	cpu.width = 64
	cpu.height = 32
	for i := 0; i < 80; i++ { // Load the font into the first 80 bytes of memory
		cpu.memory[i] = font[i]
	}
	rom, error := ioutil.ReadFile(fileName); //Open rom file
	if error != nil {
		panic(error)
	}
	// Need check here to make sure rom fits in memory
	for i := 0; i < len(rom); i++ { // Read rom into memory
		cpu.memory[0x200 + i] = rom[i]
	}
	return cpu
}

//Step a cpu cycle
func (chip *Chip8) Step() {
	// Fetch
	chip.opcode = uint16(chip.memory[chip.pc]<<8) | uint16(chip.memory[chip.pc+1]) // OR value of two consecutive addresses to get two byte opcode
	// Decode
	switch {
	// Execute
	}

}

// Renders the screen of the as a string.
func (chip8 *Chip8) String() string {
	var screenBuf bytes.Buffer
	for y := 0; y < chip8.height; y++ {
		for x := 0; x < chip8.width; x++ {
			b := byte(' ')
			//if associated pos in memory is 1 TODO
			//use a splice for screen?
			b = '*'
			screenBuf.WriteByte(b)
		}
		screenBuf.WriteByte('\n')
	}
	return screenBuf.String()
}

func main() {
	args := os.Args;
	if len(args)>1 {
		chip8 := NewChip8(args[1]) // Assume
	//	for {  main loop off for developemnt
			chip8.Step() // Step cpu cycle
			// Should have check for draw flag here
			// Draw does not occur every cycle
			fmt.Print("\n", chip8)     // Refresh screen.
			time.Sleep(time.Second / 60) //Run at 60Hz
	//	}
		for i := 0; i < len(chip8.memory); i++ { // Print memory map to check things went well, for debug
			fmt.Print(" ", chip8.memory[i])
		}
	} else {
		fmt.Print("Must provide rom as argument")
	}

}
<|endoftext|>


<commit_before>package rcmgr

import (
	"github.com/elastic/gosigar"
)

// DynamicLimit is a limit with dynamic memory values, based on available (free) memory
type DynamicLimit struct {
	BaseLimit

	// MinMemory is the minimum memory for this limit
	MinMemory int64
	// MaxMemory is the maximum memory for this limit
	MaxMemory int64
	// MemoryFraction is the fraction of available memory allowed for this limit,
	// bounded by [MinMemory, MaxMemory]
	MemoryFraction float64
}

var _ Limit = (*DynamicLimit)(nil)

func (l *DynamicLimit) GetMemoryLimit() int64 {
	var mem gosigar.Mem
	if err := mem.Get(); err != nil {
		panic(err)
	}

	limit := int64(float64(mem.ActualFree) * l.MemoryFraction)
	if limit < l.MinMemory {
		limit = l.MinMemory
	} else if limit > l.MaxMemory {
		limit = l.MaxMemory
	}

	return limit
}

// NewDynamicLimiter creates a limiter with default limits and a memory cap dynamically computed
// based on available memory. minMemory and maxMemory specify the system memory bounds,
// while memFraction specifies the fraction of available memory available for the system, within
// the specified bounds.
func NewDynamicLimiter(memFraction float64, minMemory, maxMemory int64) *BasicLimiter {
	system := &DynamicLimit{
		MinMemory:      minMemory,
		MaxMemory:      maxMemory,
		MemoryFraction: memFraction,
		BaseLimit:      DefaultSystemBaseLimit(),
	}
	transient := &DynamicLimit{
		MinMemory:      minMemory / 16,
		MaxMemory:      maxMemory / 16,
		MemoryFraction: memFraction / 16,
		BaseLimit:      DefaultTransientBaseLimit(),
	}
	svc := &DynamicLimit{
		MinMemory:      minMemory / 2,
		MaxMemory:      maxMemory / 2,
		MemoryFraction: memFraction / 2,
		BaseLimit:      DefaultServiceBaseLimit(),
	}
	proto := &DynamicLimit{
		MinMemory:      minMemory / 4,
		MaxMemory:      maxMemory / 4,
		MemoryFraction: memFraction / 4,
		BaseLimit:      DefaultProtocolBaseLimit(),
	}
	peer := &DynamicLimit{
		MinMemory:      minMemory / 16,
		MaxMemory:      maxMemory / 16,
		MemoryFraction: memFraction / 16,
		BaseLimit:      DefaultPeerBaseLimit(),
	}
	conn := &StaticLimit{
		Memory:    16 << 20,
		BaseLimit: ConnBaseLimit(),
	}
	stream := &StaticLimit{
		Memory:    16 << 20,
		BaseLimit: StreamBaseLimit(),
	}

	return &BasicLimiter{
		SystemLimits:          system,
		TransientLimits:       transient,
		DefaultServiceLimits:  svc,
		DefaultProtocolLimits: proto,
		DefaultPeerLimits:     peer,
		ConnLimits:            conn,
		StreamLimits:          stream,
	}
}
<commit_msg>add appropriate build tags for dynamic limiter<commit_after>//go:build cgo && !ios

package rcmgr

import (
	"github.com/elastic/gosigar"
)

// DynamicLimit is a limit with dynamic memory values, based on available (free) memory
type DynamicLimit struct {
	BaseLimit

	// MinMemory is the minimum memory for this limit
	MinMemory int64
	// MaxMemory is the maximum memory for this limit
	MaxMemory int64
	// MemoryFraction is the fraction of available memory allowed for this limit,
	// bounded by [MinMemory, MaxMemory]
	MemoryFraction float64
}

var _ Limit = (*DynamicLimit)(nil)

func (l *DynamicLimit) GetMemoryLimit() int64 {
	var mem gosigar.Mem
	if err := mem.Get(); err != nil {
		panic(err)
	}

	limit := int64(float64(mem.ActualFree) * l.MemoryFraction)
	if limit < l.MinMemory {
		limit = l.MinMemory
	} else if limit > l.MaxMemory {
		limit = l.MaxMemory
	}

	return limit
}

// NewDynamicLimiter creates a limiter with default limits and a memory cap dynamically computed
// based on available memory. minMemory and maxMemory specify the system memory bounds,
// while memFraction specifies the fraction of available memory available for the system, within
// the specified bounds.
func NewDynamicLimiter(memFraction float64, minMemory, maxMemory int64) *BasicLimiter {
	system := &DynamicLimit{
		MinMemory:      minMemory,
		MaxMemory:      maxMemory,
		MemoryFraction: memFraction,
		BaseLimit:      DefaultSystemBaseLimit(),
	}
	transient := &DynamicLimit{
		MinMemory:      minMemory / 16,
		MaxMemory:      maxMemory / 16,
		MemoryFraction: memFraction / 16,
		BaseLimit:      DefaultTransientBaseLimit(),
	}
	svc := &DynamicLimit{
		MinMemory:      minMemory / 2,
		MaxMemory:      maxMemory / 2,
		MemoryFraction: memFraction / 2,
		BaseLimit:      DefaultServiceBaseLimit(),
	}
	proto := &DynamicLimit{
		MinMemory:      minMemory / 4,
		MaxMemory:      maxMemory / 4,
		MemoryFraction: memFraction / 4,
		BaseLimit:      DefaultProtocolBaseLimit(),
	}
	peer := &DynamicLimit{
		MinMemory:      minMemory / 16,
		MaxMemory:      maxMemory / 16,
		MemoryFraction: memFraction / 16,
		BaseLimit:      DefaultPeerBaseLimit(),
	}
	conn := &StaticLimit{
		Memory:    16 << 20,
		BaseLimit: ConnBaseLimit(),
	}
	stream := &StaticLimit{
		Memory:    16 << 20,
		BaseLimit: StreamBaseLimit(),
	}

	return &BasicLimiter{
		SystemLimits:          system,
		TransientLimits:       transient,
		DefaultServiceLimits:  svc,
		DefaultProtocolLimits: proto,
		DefaultPeerLimits:     peer,
		ConnLimits:            conn,
		StreamLimits:          stream,
	}
}
<|endoftext|>


<commit_before>package grafsy

import (
	"fmt"
	"strconv"
	"strings"
	"sync"
	"time"
)

// Monitoring structure.
// Based on this self-monitoring will be sent to Graphite.
type Monitoring struct {
	// User config.
	Conf *Config

	// Local config.
	Lc *LocalConfig

	// Structure with amount of metrics from client.
	got source

	// Statistic per carbon receiver
	stat map[string]*stat

	// Amount of invalid metrics.
	invalid int
}

// The source of metric daemon got.
type source struct {
	// Amount of metrics from network.
	net int

	// Amount of metrics from directory.
	dir int

	// Amount of metrics from retry file.
	retry int
}

// The statistic of metrics per backend
type stat struct {
	// Amount of saved metrics.
	saved int

	// Amount of sent metrics.
	sent int

	// Amount of dropped metrics.
	dropped int
}

var statLock sync.Mutex

// Self monitoring of Grafsy.
func (m *Monitoring) generateOwnMonitoring() {

	now := strconv.FormatInt(time.Now().Unix(), 10)
	path := m.Conf.MonitoringPath + ".grafsy"
	statLock.Lock()

	monitorSlice := []string{
		fmt.Sprintf("%s.got.net %v %v", path, m.got.net, now),
		fmt.Sprintf("%s.got.dir %v %v", path, m.got.dir, now),
		fmt.Sprintf("%s.got.retry %v %v", path, m.got.retry, now),
		fmt.Sprintf("%s.invalid %v %v", path, m.invalid, now),
	}

	for _, carbonAddrTCP := range m.Lc.carbonAddrsTCP {
		backend := carbonAddrTCP.String()
		backendString := strings.Replace(backend, ".", "_", -1)
		monitorSlice = append(monitorSlice, fmt.Sprintf("%s.%s.saved %v %v", path, backendString, m.stat[backend].saved, now))
		monitorSlice = append(monitorSlice, fmt.Sprintf("%s.%s.sent %v %v", path, backendString, m.stat[backend].sent, now))
		monitorSlice = append(monitorSlice, fmt.Sprintf("%s.%s.dropped %v %v", path, backendString, m.stat[backend].dropped, now))
	}

	statLock.Unlock()

	for _, metric := range monitorSlice {
		select {
		case m.Lc.monitoringChannel <- metric:
		default:
			m.Lc.lg.Printf("Too many metrics in the MON queue! This is very bad")
			for _, carbonAddrTCP := range m.Lc.carbonAddrsTCP {
				backend := carbonAddrTCP.String()
				m.Increase(&m.stat[backend].dropped, 1)
			}
		}
	}
}

// Reset values to 0s.
func (m *Monitoring) clean() {
	statLock.Lock()
	for _, carbonAddrTCP := range m.Lc.carbonAddrsTCP {
		backend := carbonAddrTCP.String()
		m.stat[backend].saved = 0
		m.stat[backend].sent = 0
		m.stat[backend].dropped = 0
	}
	m.invalid = 0
	m.got = source{0, 0, 0}
	statLock.Unlock()
}

// Increase metric value in the thread safe way
func (m *Monitoring) Increase(metric *int, value int) {
	statLock.Lock()
	*metric += value
	statLock.Unlock()
}

// Run monitoring.
// Should be run in separate goroutine.
func (m *Monitoring) Run() {
	statLock.Lock()
	m.stat = make(map[string]*stat)
	for _, carbonAddrTCP := range m.Lc.carbonAddrsTCP {
		backend := carbonAddrTCP.String()
		m.stat[backend] = &stat{
			0,
			0,
			0,
		}
	}
	statLock.Unlock()
	for ; ; time.Sleep(60 * time.Second) {
		m.generateOwnMonitoring()
		for _, carbonAddrTCP := range m.Lc.carbonAddrsTCP {
			backend := carbonAddrTCP.String()
			statLock.Lock()
			if m.stat[backend].dropped != 0 {
				m.Lc.lg.Printf("Too many metrics in the main buffer of %s server. Had to drop incommings: %d", backend, m.stat[backend].dropped)
			}
			statLock.Unlock()
		}
		m.clean()
	}
}
<commit_msg>Use lock in Run instead of clean<commit_after>package grafsy

import (
	"fmt"
	"strconv"
	"strings"
	"sync"
	"time"
)

// Monitoring structure.
// Based on this self-monitoring will be sent to Graphite.
type Monitoring struct {
	// User config.
	Conf *Config

	// Local config.
	Lc *LocalConfig

	// Structure with amount of metrics from client.
	got source

	// Statistic per carbon receiver
	stat map[string]*stat

	// Amount of invalid metrics.
	invalid int
}

// The source of metric daemon got.
type source struct {
	// Amount of metrics from network.
	net int

	// Amount of metrics from directory.
	dir int

	// Amount of metrics from retry file.
	retry int
}

// The statistic of metrics per backend
type stat struct {
	// Amount of saved metrics.
	saved int

	// Amount of sent metrics.
	sent int

	// Amount of dropped metrics.
	dropped int
}

var statLock sync.Mutex

// Self monitoring of Grafsy.
func (m *Monitoring) generateOwnMonitoring() {

	now := strconv.FormatInt(time.Now().Unix(), 10)
	path := m.Conf.MonitoringPath + ".grafsy"
	statLock.Lock()

	monitorSlice := []string{
		fmt.Sprintf("%s.got.net %v %v", path, m.got.net, now),
		fmt.Sprintf("%s.got.dir %v %v", path, m.got.dir, now),
		fmt.Sprintf("%s.got.retry %v %v", path, m.got.retry, now),
		fmt.Sprintf("%s.invalid %v %v", path, m.invalid, now),
	}

	for _, carbonAddrTCP := range m.Lc.carbonAddrsTCP {
		backend := carbonAddrTCP.String()
		backendString := strings.Replace(backend, ".", "_", -1)
		monitorSlice = append(monitorSlice, fmt.Sprintf("%s.%s.saved %v %v", path, backendString, m.stat[backend].saved, now))
		monitorSlice = append(monitorSlice, fmt.Sprintf("%s.%s.sent %v %v", path, backendString, m.stat[backend].sent, now))
		monitorSlice = append(monitorSlice, fmt.Sprintf("%s.%s.dropped %v %v", path, backendString, m.stat[backend].dropped, now))
	}

	statLock.Unlock()

	for _, metric := range monitorSlice {
		select {
		case m.Lc.monitoringChannel <- metric:
		default:
			m.Lc.lg.Printf("Too many metrics in the MON queue! This is very bad")
			for _, carbonAddrTCP := range m.Lc.carbonAddrsTCP {
				backend := carbonAddrTCP.String()
				m.Increase(&m.stat[backend].dropped, 1)
			}
		}
	}
}

// Reset values to 0s.
func (m *Monitoring) clean() {
	for _, carbonAddrTCP := range m.Lc.carbonAddrsTCP {
		backend := carbonAddrTCP.String()
		m.stat[backend].saved = 0
		m.stat[backend].sent = 0
		m.stat[backend].dropped = 0
	}
	m.invalid = 0
	m.got = source{0, 0, 0}
}

// Increase metric value in the thread safe way
func (m *Monitoring) Increase(metric *int, value int) {
	statLock.Lock()
	*metric += value
	statLock.Unlock()
}

// Run monitoring.
// Should be run in separate goroutine.
func (m *Monitoring) Run() {
	statLock.Lock()
	m.stat = make(map[string]*stat)
	for _, carbonAddrTCP := range m.Lc.carbonAddrsTCP {
		backend := carbonAddrTCP.String()
		m.stat[backend] = &stat{
			0,
			0,
			0,
		}
	}
	statLock.Unlock()
	for ; ; time.Sleep(60 * time.Second) {
		m.generateOwnMonitoring()
		statLock.Lock()
		for _, carbonAddrTCP := range m.Lc.carbonAddrsTCP {
			backend := carbonAddrTCP.String()
			if m.stat[backend].dropped != 0 {
				m.Lc.lg.Printf("Too many metrics in the main buffer of %s server. Had to drop incommings: %d", backend, m.stat[backend].dropped)
			}
		}
		m.clean()
		statLock.Unlock()
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 The Neugram Authors. All rights reserved.
// See the LICENSE file for rights to use this source code.

// Package tipe defines data structures representing Neugram types.
//
// Go took the usual spelling of type.
package tipe

import (
	"fmt"
	"reflect"
	"strings"
)

type Type interface {
	Sexp() string
	tipe()
}

type Func struct {
	Spec     Specialization
	Params   *Tuple
	Results  *Tuple
	Variadic bool // last value of Params is a slice
}

type Class struct {
	Spec        Specialization
	FieldNames  []string
	Fields      []Type
	MethodNames []string
	Methods     []Type
}

type Table struct {
	Type Type
}

type Tuple struct {
	Elems []Type
}

type Pointer struct {
	Elem Type
}

/*
TODO remove, replace with side table.
// Go is a type imported from Go.
// It has an equivalent type in this system.
//
// Either GoType or GoPkg is set.
//
// Technically in go/types a *gotypes.Package is not a type, but we
// model a package as a type for neugram, so we fake it.
type Go struct {
	GoType     gotypes.Type
	GoPkg      *gotypes.Package
	Equivalent Type
}
*/

type Package struct {
	IsGo    bool
	Path    string
	Exports map[string]Type
}

type Interface struct {
	Methods map[string]*Func
}

// Specialization carries any type specialization data particular to this type.
//
// Both *Func and *Class can be parameterized over the name num, which can
// take any of:
//
//	integer, int64, float, float32, float64, complex, complex128
//
// At the defnition of a class or function, the matching Type will have the
// Num filed set to Invalid if it is not parameterized, or Num if it is.
//
// On a value of a parameterized class or a Call of a parameterized function,
// Num will either Num or one of the basic numeric types (if specialized).
type Specialization struct {
	// Num is the specialization of the type parameter num in
	Num Basic
}

type Basic string

const (
	Invalid Basic = "invalid"
	Num     Basic = "num" // type parameter
	Bool    Basic = "bool"
	Integer Basic = "integer"
	Float   Basic = "float"
	Complex Basic = "complex"
	String  Basic = "string"

	Int64   Basic = "int64"
	Float32 Basic = "float32"
	Float64 Basic = "float64"

	GoInt Basic = "goint"

	UntypedBool    Basic = "untyped bool" // TODO remove if we are not going to have named types
	UntypedInteger Basic = "untyped integer"
	UntypedFloat   Basic = "untyped float"
	UntypedComplex Basic = "untyped complex"
)

type Unresolved struct {
	Package string
	Name    string
}

var (
	_ = Type(Basic(""))
	_ = Type((*Func)(nil))
	_ = Type((*Class)(nil))
	_ = Type((*Table)(nil))
	_ = Type((*Tuple)(nil))
	_ = Type((*Pointer)(nil))
	_ = Type((*Package)(nil))
	_ = Type((*Interface)(nil))
	_ = Type((*Unresolved)(nil))
)

func (t Basic) tipe()       {}
func (t *Func) tipe()       {}
func (t *Class) tipe()      {}
func (t *Table) tipe()      {}
func (t *Tuple) tipe()      {}
func (t *Pointer) tipe()    {}
func (t *Package) tipe()    {}
func (t *Interface) tipe()  {}
func (t *Unresolved) tipe() {}

func (e Specialization) Sexp() string {
	return fmt.Sprintf("(spec num=%s)", e.Num.Sexp())
}

func (e Basic) Sexp() string { return fmt.Sprintf("(basictype %s)", string(e)) }
func (e *Func) Sexp() string {
	p := "nilparams"
	if e.Params != nil {
		p = e.Params.Sexp()
	}
	r := "nilresults"
	if e.Results != nil {
		p = e.Results.Sexp()
	}
	return fmt.Sprintf("(functype %s %s %s)", e.Spec.Sexp(), p, r)
}
func (e *Class) Sexp() string {
	var s []string
	for i, tag := range e.FieldNames {
		s = append(s, fmt.Sprintf("(%s %s)", tag, e.Fields[i].Sexp()))
	}
	for i, tag := range e.MethodNames {
		s = append(s, fmt.Sprintf("(%s %s)", tag, e.Methods[i].Sexp()))
	}
	return fmt.Sprintf("(classtype %s %s)", e.Spec.Sexp(), strings.Join(s, " "))
}
func (e *Table) Sexp() string {
	u := "nil"
	if e.Type != nil {
		u = e.Type.Sexp()
	}
	return fmt.Sprintf("(tabletype %s)", u)
}
func (e *Tuple) Sexp() string {
	var elems []string
	for _, t := range e.Elems {
		ts := "<nil>"
		if t != nil {
			ts = t.Sexp()
		}
		elems = append(elems, ts)
	}
	return fmt.Sprintf("(tupletype %s)", strings.Join(elems, " "))
}
func (e *Pointer) Sexp() string {
	u := "nil"
	if e.Elem != nil {
		u = e.Elem.Sexp()
	}
	return fmt.Sprintf("(* %s)", u)
}

func (e *Package) Sexp() string {
	var elems []string
	for n, t := range e.Exports {
		ts := "<nil>"
		if t != nil {
			ts = t.Sexp()
		}
		elems = append(elems, "("+n+" "+ts+")")
	}
	return fmt.Sprintf("(package %s)", strings.Join(elems, " "))
}

func (e *Interface) Sexp() string {
	var s []string
	for name, fn := range e.Methods {
		s = append(s, fmt.Sprintf("(%s %s)", name, fn.Sexp()))
	}
	return fmt.Sprintf("(interfacetype %s)", strings.Join(s, " "))
}

func (e *Unresolved) Sexp() string {
	if e.Package == "" {
		return fmt.Sprintf("(unresolved %s)", e.Name)
	}
	return fmt.Sprintf("(unresolved %s.%s)", e.Package, e.Name)
}

func IsNumeric(t Type) bool {
	b, ok := t.(Basic)
	if !ok {
		return false
	}
	switch b {
	case Num, Integer, Float, Complex,
		Int64, Float32, Float64,
		GoInt,
		UntypedInteger, UntypedFloat, UntypedComplex:
		return true
	}
	return false
}

func UsesNum(t Type) bool {
	switch t := t.(type) {
	case *Func:
		if t.Params != nil {
			for _, t := range t.Params.Elems {
				if UsesNum(t) {
					return true
				}
			}
		}
		if t.Results != nil {
			for _, t := range t.Results.Elems {
				if UsesNum(t) {
					return true
				}
			}
		}
	case *Class:
		for _, t := range t.Fields {
			if UsesNum(t) {
				return true
			}
		}
		for _, t := range t.Methods {
			if UsesNum(t) {
				return true
			}
		}
	case *Table:
		if UsesNum(t.Type) {
			return true
		}
	case Basic:
		return t == Num
	}
	return false
}

func Equal(x, y Type) bool {
	if x == y {
		return true
	}
	switch x := x.(type) {
	case *Func:
		y, ok := y.(*Func)
		if !ok {
			return false
		}
		if x == nil || y == nil {
			return false
		}
		if x.Spec != y.Spec {
			return false
		}
		if !Equal(x.Params, y.Params) {
			return false
		}
		if !Equal(x.Results, y.Results) {
			return false
		}
		return true
	case *Class:
		y, ok := y.(*Class)
		if !ok {
			return false
		}
		if x == nil || y == nil {
			return false
		}
		if x.Spec != y.Spec {
			return false
		}
		if !reflect.DeepEqual(x.FieldNames, y.FieldNames) {
			return false
		}
		if len(x.Fields) != len(y.Fields) {
			return false
		}
		for i := range x.Fields {
			if !Equal(x.Fields[i], y.Fields[i]) {
				return false
			}
		}
		if !reflect.DeepEqual(x.MethodNames, y.MethodNames) {
			return false
		}
		if len(x.Methods) != len(y.Methods) {
			return false
		}
		for i := range x.Methods {
			if !Equal(x.Methods[i], y.Methods[i]) {
				return false
			}
		}
		return true
	case *Table:
		y, ok := y.(*Table)
		if !ok {
			return false
		}
		if x == nil || y == nil {
			return false
		}
		return Equal(x.Type, y.Type)
	case *Tuple:
		y, ok := y.(*Tuple)
		if !ok {
			return false
		}
		if x == nil && y == nil {
			return true
		}
		if x == nil || y == nil {
			return false
		}
		if len(x.Elems) != len(y.Elems) {
			return false
		}
		for i := range x.Elems {
			if !Equal(x.Elems[i], y.Elems[i]) {
				return false
			}
		}
		return true
	case *Package:
		y, ok := y.(*Package)
		if !ok {
			return false
		}
		if x == nil && y == nil {
			return true
		}
		if x == nil || y == nil {
			return false
		}
		if len(x.Exports) != len(y.Exports) {
			return false
		}
		for xn, xt := range x.Exports {
			yt, ok := y.Exports[xn]
			if !ok {
				return false
			}
			if !Equal(xt, yt) {
				return false
			}
		}
		return true
	case *Interface:
		y, ok := y.(*Interface)
		if !ok {
			return false
		}
		if x == nil && y == nil {
			return true
		}
		if x == nil || y == nil {
			return false
		}
		if len(x.Methods) != len(y.Methods) {
			return false
		}
		for xn, xt := range x.Methods {
			yt, ok := y.Methods[xn]
			if !ok {
				return false
			}
			if !Equal(xt, yt) {
				return false
			}
		}
		return true
	case *Pointer:
		y, ok := y.(*Pointer)
		if !ok {
			return false
		}
		if x == nil || y == nil {
			return false
		}
		return Equal(x.Elem, y.Elem)
	}
	fmt.Printf("tipe.Equal TODO %T\n", x)
	return false
}
<commit_msg>lang/tipe: try out a string method<commit_after>// Copyright 2015 The Neugram Authors. All rights reserved.
// See the LICENSE file for rights to use this source code.

// Package tipe defines data structures representing Neugram types.
//
// Go took the usual spelling of type.
package tipe

import (
	"fmt"
	"reflect"
	"strings"
)

type Type interface {
	Sexp() string
	tipe()
}

type Func struct {
	Spec     Specialization
	Params   *Tuple
	Results  *Tuple
	Variadic bool // last value of Params is a slice
}

type Class struct {
	Spec        Specialization
	FieldNames  []string
	Fields      []Type
	MethodNames []string
	Methods     []Type
}

type Table struct {
	Type Type
}

type Tuple struct {
	Elems []Type
}

type Pointer struct {
	Elem Type
}

/*
TODO remove, replace with side table.
// Go is a type imported from Go.
// It has an equivalent type in this system.
//
// Either GoType or GoPkg is set.
//
// Technically in go/types a *gotypes.Package is not a type, but we
// model a package as a type for neugram, so we fake it.
type Go struct {
	GoType     gotypes.Type
	GoPkg      *gotypes.Package
	Equivalent Type
}
*/

type Package struct {
	IsGo    bool
	Path    string
	Exports map[string]Type
}

type Interface struct {
	Methods map[string]*Func
}

// Specialization carries any type specialization data particular to this type.
//
// Both *Func and *Class can be parameterized over the name num, which can
// take any of:
//
//	integer, int64, float, float32, float64, complex, complex128
//
// At the defnition of a class or function, the matching Type will have the
// Num filed set to Invalid if it is not parameterized, or Num if it is.
//
// On a value of a parameterized class or a Call of a parameterized function,
// Num will either Num or one of the basic numeric types (if specialized).
type Specialization struct {
	// Num is the specialization of the type parameter num in
	Num Basic
}

type Basic string

const (
	Invalid Basic = "invalid"
	Num     Basic = "num" // type parameter
	Bool    Basic = "bool"
	Integer Basic = "integer"
	Float   Basic = "float"
	Complex Basic = "complex"
	String  Basic = "string"

	Int64   Basic = "int64"
	Float32 Basic = "float32"
	Float64 Basic = "float64"

	GoInt Basic = "goint"

	UntypedBool    Basic = "untyped bool" // TODO remove if we are not going to have named types
	UntypedInteger Basic = "untyped integer"
	UntypedFloat   Basic = "untyped float"
	UntypedComplex Basic = "untyped complex"
)

type Unresolved struct {
	Package string
	Name    string
}

var (
	_ = Type(Basic(""))
	_ = Type((*Func)(nil))
	_ = Type((*Class)(nil))
	_ = Type((*Table)(nil))
	_ = Type((*Tuple)(nil))
	_ = Type((*Pointer)(nil))
	_ = Type((*Package)(nil))
	_ = Type((*Interface)(nil))
	_ = Type((*Unresolved)(nil))
)

func (t Basic) tipe()       {}
func (t *Func) tipe()       {}
func (t *Class) tipe()      {}
func (t *Table) tipe()      {}
func (t *Tuple) tipe()      {}
func (t *Pointer) tipe()    {}
func (t *Package) tipe()    {}
func (t *Interface) tipe()  {}
func (t *Unresolved) tipe() {}

func (e Specialization) Sexp() string {
	return fmt.Sprintf("(spec num=%s)", e.Num.Sexp())
}

func (e Basic) Sexp() string { return fmt.Sprintf("(basictype %s)", string(e)) }
func (e *Func) Sexp() string {
	p := "nilparams"
	if e.Params != nil {
		p = e.Params.Sexp()
	}
	r := "nilresults"
	if e.Results != nil {
		p = e.Results.Sexp()
	}
	return fmt.Sprintf("(functype %s %s %s)", e.Spec.Sexp(), p, r)
}
func (e *Class) Sexp() string {
	var s []string
	for i, tag := range e.FieldNames {
		s = append(s, fmt.Sprintf("(%s %s)", tag, e.Fields[i].Sexp()))
	}
	for i, tag := range e.MethodNames {
		s = append(s, fmt.Sprintf("(%s %s)", tag, e.Methods[i].Sexp()))
	}
	return fmt.Sprintf("(classtype %s %s)", e.Spec.Sexp(), strings.Join(s, " "))
}
func (e *Table) Sexp() string {
	u := "nil"
	if e.Type != nil {
		u = e.Type.Sexp()
	}
	return fmt.Sprintf("(tabletype %s)", u)
}
func (e *Tuple) Sexp() string {
	var elems []string
	for _, t := range e.Elems {
		ts := "<nil>"
		if t != nil {
			ts = t.Sexp()
		}
		elems = append(elems, ts)
	}
	return fmt.Sprintf("(tupletype %s)", strings.Join(elems, " "))
}
func (e *Pointer) Sexp() string {
	u := "nil"
	if e.Elem != nil {
		u = e.Elem.Sexp()
	}
	return fmt.Sprintf("(* %s)", u)
}

func (e *Package) Sexp() string {
	var elems []string
	for n, t := range e.Exports {
		ts := "<nil>"
		if t != nil {
			ts = t.Sexp()
		}
		elems = append(elems, "("+n+" "+ts+")")
	}
	return fmt.Sprintf("(package %s)", strings.Join(elems, " "))
}

func (e *Interface) Sexp() string {
	var s []string
	for name, fn := range e.Methods {
		s = append(s, fmt.Sprintf("(%s %s)", name, fn.Sexp()))
	}
	return fmt.Sprintf("(interfacetype %s)", strings.Join(s, " "))
}

func (e *Unresolved) Sexp() string {
	if e.Package == "" {
		return fmt.Sprintf("(unresolved %s)", e.Name)
	}
	return fmt.Sprintf("(unresolved %s.%s)", e.Package, e.Name)
}

func IsNumeric(t Type) bool {
	b, ok := t.(Basic)
	if !ok {
		return false
	}
	switch b {
	case Num, Integer, Float, Complex,
		Int64, Float32, Float64,
		GoInt,
		UntypedInteger, UntypedFloat, UntypedComplex:
		return true
	}
	return false
}

func UsesNum(t Type) bool {
	switch t := t.(type) {
	case *Func:
		if t.Params != nil {
			for _, t := range t.Params.Elems {
				if UsesNum(t) {
					return true
				}
			}
		}
		if t.Results != nil {
			for _, t := range t.Results.Elems {
				if UsesNum(t) {
					return true
				}
			}
		}
	case *Class:
		for _, t := range t.Fields {
			if UsesNum(t) {
				return true
			}
		}
		for _, t := range t.Methods {
			if UsesNum(t) {
				return true
			}
		}
	case *Table:
		if UsesNum(t.Type) {
			return true
		}
	case Basic:
		return t == Num
	}
	return false
}

func Equal(x, y Type) bool {
	if x == y {
		return true
	}
	switch x := x.(type) {
	case *Func:
		y, ok := y.(*Func)
		if !ok {
			return false
		}
		if x == nil || y == nil {
			return false
		}
		if x.Spec != y.Spec {
			return false
		}
		if !Equal(x.Params, y.Params) {
			return false
		}
		if !Equal(x.Results, y.Results) {
			return false
		}
		return true
	case *Class:
		y, ok := y.(*Class)
		if !ok {
			return false
		}
		if x == nil || y == nil {
			return false
		}
		if x.Spec != y.Spec {
			return false
		}
		if !reflect.DeepEqual(x.FieldNames, y.FieldNames) {
			return false
		}
		if len(x.Fields) != len(y.Fields) {
			return false
		}
		for i := range x.Fields {
			if !Equal(x.Fields[i], y.Fields[i]) {
				return false
			}
		}
		if !reflect.DeepEqual(x.MethodNames, y.MethodNames) {
			return false
		}
		if len(x.Methods) != len(y.Methods) {
			return false
		}
		for i := range x.Methods {
			if !Equal(x.Methods[i], y.Methods[i]) {
				return false
			}
		}
		return true
	case *Table:
		y, ok := y.(*Table)
		if !ok {
			return false
		}
		if x == nil || y == nil {
			return false
		}
		return Equal(x.Type, y.Type)
	case *Tuple:
		y, ok := y.(*Tuple)
		if !ok {
			return false
		}
		if x == nil && y == nil {
			return true
		}
		if x == nil || y == nil {
			return false
		}
		if len(x.Elems) != len(y.Elems) {
			return false
		}
		for i := range x.Elems {
			if !Equal(x.Elems[i], y.Elems[i]) {
				return false
			}
		}
		return true
	case *Package:
		y, ok := y.(*Package)
		if !ok {
			return false
		}
		if x == nil && y == nil {
			return true
		}
		if x == nil || y == nil {
			return false
		}
		if len(x.Exports) != len(y.Exports) {
			return false
		}
		for xn, xt := range x.Exports {
			yt, ok := y.Exports[xn]
			if !ok {
				return false
			}
			if !Equal(xt, yt) {
				return false
			}
		}
		return true
	case *Interface:
		y, ok := y.(*Interface)
		if !ok {
			return false
		}
		if x == nil && y == nil {
			return true
		}
		if x == nil || y == nil {
			return false
		}
		if len(x.Methods) != len(y.Methods) {
			return false
		}
		for xn, xt := range x.Methods {
			yt, ok := y.Methods[xn]
			if !ok {
				return false
			}
			if !Equal(xt, yt) {
				return false
			}
		}
		return true
	case *Pointer:
		y, ok := y.(*Pointer)
		if !ok {
			return false
		}
		if x == nil || y == nil {
			return false
		}
		return Equal(x.Elem, y.Elem)
	}
	fmt.Printf("tipe.Equal TODO %T\n", x)
	return false
}

func (t Interface) String() string {
	if len(t.Methods) == 0 {
		return "interface{}"
	}
	s := "interface{"
	for name, m := range t.Methods {
		s += "\t" + name + m.Sexp() // TODO .String()
	}
	s += "\n}"
	return s
}
<|endoftext|>


<commit_before>package c

import (
	. "github.com/alecthomas/chroma" // nolint
	"github.com/alecthomas/chroma/lexers/internal"
)

// C lexer.
var C = internal.Register(MustNewLazyLexer(
	&Config{
		Name:      "C",
		Aliases:   []string{"c"},
		Filenames: []string{"*.c", "*.h", "*.idc", "*.x[bp]m"},
		MimeTypes: []string{"text/x-chdr", "text/x-csrc", "image/x-xbitmap", "image/x-xpixmap"},
		EnsureNL:  true,
	},
	cRules,
))

func cRules() Rules {
	return Rules{
		"whitespace": {
			{`^#if\s+0`, CommentPreproc, Push("if0")},
			{`^#`, CommentPreproc, Push("macro")},
			{`^(\s*(?:/[*].*?[*]/\s*)?)(#if\s+0)`, ByGroups(UsingSelf("root"), CommentPreproc), Push("if0")},
			{`^(\s*(?:/[*].*?[*]/\s*)?)(#)`, ByGroups(UsingSelf("root"), CommentPreproc), Push("macro")},
			{`\n`, Text, nil},
			{`\s+`, Text, nil},
			{`\\\n`, Text, nil},
			{`//(\n|[\w\W]*?[^\\]\n)`, CommentSingle, nil},
			{`/(\\\n)?[*][\w\W]*?[*](\\\n)?/`, CommentMultiline, nil},
			{`/(\\\n)?[*][\w\W]*`, CommentMultiline, nil},
		},
		"statements": {
			{`(L?)(")`, ByGroups(LiteralStringAffix, LiteralString), Push("string")},
			{`(L?)(')(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|[^\\\'\n])(')`, ByGroups(LiteralStringAffix, LiteralStringChar, LiteralStringChar, LiteralStringChar), nil},
			{`(\d+\.\d*|\.\d+|\d+)[eE][+-]?\d+[LlUu]*`, LiteralNumberFloat, nil},
			{`(\d+\.\d*|\.\d+|\d+[fF])[fF]?`, LiteralNumberFloat, nil},
			{`0x[0-9a-fA-F]+[LlUu]*`, LiteralNumberHex, nil},
			{`0[0-7]+[LlUu]*`, LiteralNumberOct, nil},
			{`\d+[LlUu]*`, LiteralNumberInteger, nil},
			{`\*/`, Error, nil},
			{`[~!%^&*+=|?:<>/-]`, Operator, nil},
			{`[()\[\],.]`, Punctuation, nil},
			{Words(``, `\b`, `asm`, `auto`, `break`, `case`, `const`, `continue`, `default`, `do`, `else`, `enum`, `extern`, `for`, `goto`, `if`, `register`, `restricted`, `return`, `sizeof`, `static`, `struct`, `switch`, `typedef`, `union`, `volatile`, `while`), Keyword, nil},
			{`(bool|int|long|float|short|double|char|unsigned|signed|void)\b`, KeywordType, nil},
			{Words(``, `\b`, `inline`, `_inline`, `__inline`, `naked`, `restrict`, `thread`, `typename`), KeywordReserved, nil},
			{`(__m(128i|128d|128|64))\b`, KeywordReserved, nil},
			{Words(`__`, `\b`, `asm`, `int8`, `based`, `except`, `int16`, `stdcall`, `cdecl`, `fastcall`, `int32`, `declspec`, `finally`, `int64`, `try`, `leave`, `wchar_t`, `w64`, `unaligned`, `raise`, `noop`, `identifier`, `forceinline`, `assume`), KeywordReserved, nil},
			{`(true|false|NULL)\b`, NameBuiltin, nil},
			{`([a-zA-Z_]\w*)(\s*)(:)(?!:)`, ByGroups(NameLabel, Text, Punctuation), nil},
			{`[a-zA-Z_]\w*`, Name, nil},
		},
		"root": {
			Include("whitespace"),
			{`((?:[\w*\s])+?(?:\s|[*]))([a-zA-Z_]\w*)(\s*\([^;]*?\))([^;{]*)(\{)`, ByGroups(UsingSelf("root"), NameFunction, UsingSelf("root"), UsingSelf("root"), Punctuation), Push("function")},
			{`((?:[\w*\s])+?(?:\s|[*]))([a-zA-Z_]\w*)(\s*\([^;]*?\))([^;]*)(;)`, ByGroups(UsingSelf("root"), NameFunction, UsingSelf("root"), UsingSelf("root"), Punctuation), nil},
			Default(Push("statement")),
		},
		"statement": {
			Include("whitespace"),
			Include("statements"),
			{`[{}]`, Punctuation, nil},
			{`;`, Punctuation, Pop(1)},
		},
		"function": {
			Include("whitespace"),
			Include("statements"),
			{`;`, Punctuation, nil},
			{`\{`, Punctuation, Push()},
			{`\}`, Punctuation, Pop(1)},
		},
		"string": {
			{`"`, LiteralString, Pop(1)},
			{`\\([\\abfnrtv"\']|x[a-fA-F0-9]{2,4}|u[a-fA-F0-9]{4}|U[a-fA-F0-9]{8}|[0-7]{1,3})`, LiteralStringEscape, nil},
			{`[^\\"\n]+`, LiteralString, nil},
			{`\\\n`, LiteralString, nil},
			{`\\`, LiteralString, nil},
		},
		"macro": {
			{`(include)(\s*(?:/[*].*?[*]/\s*)?)([^\n]+)`, ByGroups(CommentPreproc, Text, CommentPreprocFile), nil},
			{`[^/\n]+`, CommentPreproc, nil},
			{`/[*](.|\n)*?[*]/`, CommentMultiline, nil},
			{`//.*?\n`, CommentSingle, Pop(1)},
			{`/`, CommentPreproc, nil},
			{`(?<=\\)\n`, CommentPreproc, nil},
			{`\n`, CommentPreproc, Pop(1)},
		},
		"if0": {
			{`^\s*#if.*?(?<!\\)\n`, CommentPreproc, Push()},
			{`^\s*#el(?:se|if).*\n`, CommentPreproc, Pop(1)},
			{`^\s*#endif.*?(?<!\\)\n`, CommentPreproc, Pop(1)},
			{`.*?\n`, Comment, nil},
		},
	}
}
<commit_msg>Added uint8_t to c lexer.<commit_after>package c

import (
	. "github.com/alecthomas/chroma" // nolint
	"github.com/alecthomas/chroma/lexers/internal"
)

// C lexer.
var C = internal.Register(MustNewLazyLexer(
	&Config{
		Name:      "C",
		Aliases:   []string{"c"},
		Filenames: []string{"*.c", "*.h", "*.idc", "*.x[bp]m"},
		MimeTypes: []string{"text/x-chdr", "text/x-csrc", "image/x-xbitmap", "image/x-xpixmap"},
		EnsureNL:  true,
	},
	cRules,
))

func cRules() Rules {
	return Rules{
		"whitespace": {
			{`^#if\s+0`, CommentPreproc, Push("if0")},
			{`^#`, CommentPreproc, Push("macro")},
			{`^(\s*(?:/[*].*?[*]/\s*)?)(#if\s+0)`, ByGroups(UsingSelf("root"), CommentPreproc), Push("if0")},
			{`^(\s*(?:/[*].*?[*]/\s*)?)(#)`, ByGroups(UsingSelf("root"), CommentPreproc), Push("macro")},
			{`\n`, Text, nil},
			{`\s+`, Text, nil},
			{`\\\n`, Text, nil},
			{`//(\n|[\w\W]*?[^\\]\n)`, CommentSingle, nil},
			{`/(\\\n)?[*][\w\W]*?[*](\\\n)?/`, CommentMultiline, nil},
			{`/(\\\n)?[*][\w\W]*`, CommentMultiline, nil},
		},
		"statements": {
			{`(L?)(")`, ByGroups(LiteralStringAffix, LiteralString), Push("string")},
			{`(L?)(')(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|[^\\\'\n])(')`, ByGroups(LiteralStringAffix, LiteralStringChar, LiteralStringChar, LiteralStringChar), nil},
			{`(\d+\.\d*|\.\d+|\d+)[eE][+-]?\d+[LlUu]*`, LiteralNumberFloat, nil},
			{`(\d+\.\d*|\.\d+|\d+[fF])[fF]?`, LiteralNumberFloat, nil},
			{`0x[0-9a-fA-F]+[LlUu]*`, LiteralNumberHex, nil},
			{`0[0-7]+[LlUu]*`, LiteralNumberOct, nil},
			{`\d+[LlUu]*`, LiteralNumberInteger, nil},
			{`\*/`, Error, nil},
			{`[~!%^&*+=|?:<>/-]`, Operator, nil},
			{`[()\[\],.]`, Punctuation, nil},
			{Words(``, `\b`, `asm`, `auto`, `break`, `case`, `const`, `continue`, `default`, `do`, `else`, `enum`, `extern`, `for`, `goto`, `if`, `register`, `restricted`, `return`, `sizeof`, `static`, `struct`, `switch`, `typedef`, `union`, `volatile`, `while`), Keyword, nil},
			{`(bool|int|long|float|short|double|char((8|16|32)_t)?|unsigned|signed|void|u?int(_fast|_least|)(8|16|32|64)_t)\b`, KeywordType, nil},
			{Words(``, `\b`, `inline`, `_inline`, `__inline`, `naked`, `restrict`, `thread`, `typename`), KeywordReserved, nil},
			{`(__m(128i|128d|128|64))\b`, KeywordReserved, nil},
			{Words(`__`, `\b`, `asm`, `int8`, `based`, `except`, `int16`, `stdcall`, `cdecl`, `fastcall`, `int32`, `declspec`, `finally`, `int64`, `try`, `leave`, `wchar_t`, `w64`, `unaligned`, `raise`, `noop`, `identifier`, `forceinline`, `assume`), KeywordReserved, nil},
			{`(true|false|NULL)\b`, NameBuiltin, nil},
			{`([a-zA-Z_]\w*)(\s*)(:)(?!:)`, ByGroups(NameLabel, Text, Punctuation), nil},
			{`[a-zA-Z_]\w*`, Name, nil},
		},
		"root": {
			Include("whitespace"),
			{`((?:[\w*\s])+?(?:\s|[*]))([a-zA-Z_]\w*)(\s*\([^;]*?\))([^;{]*)(\{)`, ByGroups(UsingSelf("root"), NameFunction, UsingSelf("root"), UsingSelf("root"), Punctuation), Push("function")},
			{`((?:[\w*\s])+?(?:\s|[*]))([a-zA-Z_]\w*)(\s*\([^;]*?\))([^;]*)(;)`, ByGroups(UsingSelf("root"), NameFunction, UsingSelf("root"), UsingSelf("root"), Punctuation), nil},
			Default(Push("statement")),
		},
		"statement": {
			Include("whitespace"),
			Include("statements"),
			{`[{}]`, Punctuation, nil},
			{`;`, Punctuation, Pop(1)},
		},
		"function": {
			Include("whitespace"),
			Include("statements"),
			{`;`, Punctuation, nil},
			{`\{`, Punctuation, Push()},
			{`\}`, Punctuation, Pop(1)},
		},
		"string": {
			{`"`, LiteralString, Pop(1)},
			{`\\([\\abfnrtv"\']|x[a-fA-F0-9]{2,4}|u[a-fA-F0-9]{4}|U[a-fA-F0-9]{8}|[0-7]{1,3})`, LiteralStringEscape, nil},
			{`[^\\"\n]+`, LiteralString, nil},
			{`\\\n`, LiteralString, nil},
			{`\\`, LiteralString, nil},
		},
		"macro": {
			{`(include)(\s*(?:/[*].*?[*]/\s*)?)([^\n]+)`, ByGroups(CommentPreproc, Text, CommentPreprocFile), nil},
			{`[^/\n]+`, CommentPreproc, nil},
			{`/[*](.|\n)*?[*]/`, CommentMultiline, nil},
			{`//.*?\n`, CommentSingle, Pop(1)},
			{`/`, CommentPreproc, nil},
			{`(?<=\\)\n`, CommentPreproc, nil},
			{`\n`, CommentPreproc, Pop(1)},
		},
		"if0": {
			{`^\s*#if.*?(?<!\\)\n`, CommentPreproc, Push()},
			{`^\s*#el(?:se|if).*\n`, CommentPreproc, Pop(1)},
			{`^\s*#endif.*?(?<!\\)\n`, CommentPreproc, Pop(1)},
			{`.*?\n`, Comment, nil},
		},
	}
}
<|endoftext|>


<commit_before>// package bitswap implements the IPFS Exchange interface with the BitSwap
// bilateral exchange protocol.
package bitswap

import (
	"time"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"

	blocks "github.com/jbenet/go-ipfs/blocks"
	blockstore "github.com/jbenet/go-ipfs/blockstore"
	exchange "github.com/jbenet/go-ipfs/exchange"
	bsmsg "github.com/jbenet/go-ipfs/exchange/bitswap/message"
	bsnet "github.com/jbenet/go-ipfs/exchange/bitswap/network"
	notifications "github.com/jbenet/go-ipfs/exchange/bitswap/notifications"
	strategy "github.com/jbenet/go-ipfs/exchange/bitswap/strategy"
	peer "github.com/jbenet/go-ipfs/peer"
	u "github.com/jbenet/go-ipfs/util"
	"github.com/jbenet/go-ipfs/util/eventlog"
)

var log = eventlog.Logger("bitswap")

// New initializes a BitSwap instance that communicates over the
// provided BitSwapNetwork. This function registers the returned instance as
// the network delegate.
// Runs until context is cancelled
func New(ctx context.Context, p peer.Peer,
	network bsnet.BitSwapNetwork, routing bsnet.Routing,
	d ds.ThreadSafeDatastore, nice bool) exchange.Interface {

	notif := notifications.New()
	go func() {
		<-ctx.Done()
		notif.Shutdown()
	}()

	bs := &bitswap{
		blockstore:    blockstore.NewBlockstore(d),
		notifications: notif,
		strategy:      strategy.New(nice),
		routing:       routing,
		sender:        network,
		wantlist:      u.NewKeySet(),
		blockReq:      make(chan u.Key, 32),
	}
	network.SetDelegate(bs)
	go bs.run(ctx)

	return bs
}

// bitswap instances implement the bitswap protocol.
type bitswap struct {

	// sender delivers messages on behalf of the session
	sender bsnet.BitSwapNetwork

	// blockstore is the local database
	// NB: ensure threadsafety
	blockstore blockstore.Blockstore

	// routing interface for communication
	routing bsnet.Routing

	notifications notifications.PubSub

	blockReq chan u.Key

	// strategy listens to network traffic and makes decisions about how to
	// interact with partners.
	// TODO(brian): save the strategy's state to the datastore
	strategy strategy.Strategy

	wantlist u.KeySet
}

// GetBlock attempts to retrieve a particular block from peers within the
// deadline enforced by the context
//
// TODO ensure only one active request per key
func (bs *bitswap) GetBlock(parent context.Context, k u.Key) (*blocks.Block, error) {

	// make sure to derive a new |ctx| and pass it to children. It's correct to
	// listen on |parent| here, but incorrect to pass |parent| to new async
	// functions. This is difficult to enforce. May this comment keep you safe.

	ctx, cancelFunc := context.WithCancel(parent)
	defer cancelFunc()

	ctx = eventlog.ContextWithMetadata(ctx, eventlog.Uuid("BitswapGetBlockRequest"))
	log.Event(ctx, "BitswapGetBlockRequestBegin", &k)

	defer func() {
		log.Event(ctx, "BitSwapGetBlockRequestEnd", &k)
	}()

	bs.wantlist.Add(k)
	promise := bs.notifications.Subscribe(ctx, k)

	select {
	case bs.blockReq <- k:
	case <-parent.Done():
		return nil, parent.Err()
	}

	select {
	case block := <-promise:
		bs.wantlist.Remove(k)
		return &block, nil
	case <-parent.Done():
		return nil, parent.Err()
	}
}

func (bs *bitswap) GetBlocks(parent context.Context, ks []u.Key) (*blocks.Block, error) {
	// TODO: something smart
	return nil, nil
}

func (bs *bitswap) sendWantListTo(ctx context.Context, peers <-chan peer.Peer) error {
	message := bsmsg.New()
	for _, wanted := range bs.wantlist.Keys() {
		message.AddWanted(wanted)
	}
	for peerToQuery := range peers {
		log.Debugf("bitswap got peersToQuery: %s", peerToQuery)
		go func(p peer.Peer) {

			log.Debugf("bitswap dialing peer: %s", p)
			err := bs.sender.DialPeer(ctx, p)
			if err != nil {
				log.Errorf("Error sender.DialPeer(%s)", p)
				return
			}

			response, err := bs.sender.SendRequest(ctx, p, message)
			if err != nil {
				log.Errorf("Error sender.SendRequest(%s) = %s", p, err)
				return
			}
			// FIXME ensure accounting is handled correctly when
			// communication fails. May require slightly different API to
			// get better guarantees. May need shared sequence numbers.
			bs.strategy.MessageSent(p, message)

			if response == nil {
				return
			}
			bs.ReceiveMessage(ctx, p, response)
		}(peerToQuery)
	}
	return nil
}

func (bs *bitswap) run(ctx context.Context) {
	var sendlist <-chan peer.Peer

	// Every so often, we should resend out our current want list
	rebroadcastTime := time.Second * 5

	// Time to wait before sending out wantlists to better batch up requests
	bufferTime := time.Millisecond * 3
	peersPerSend := 6

	timeout := time.After(rebroadcastTime)
	threshold := 10
	unsent := 0
	for {
		select {
		case <-timeout:
			wantlist := bs.wantlist.Keys()
			if len(wantlist) == 0 {
				continue
			}
			if sendlist == nil {
				// rely on semi randomness of maps
				firstKey := wantlist[0]
				sendlist = bs.routing.FindProvidersAsync(ctx, firstKey, 6)
			}
			err := bs.sendWantListTo(ctx, sendlist)
			if err != nil {
				log.Error("error sending wantlist: %s", err)
			}
			sendlist = nil
			timeout = time.After(rebroadcastTime)
		case k := <-bs.blockReq:
			if unsent == 0 {
				sendlist = bs.routing.FindProvidersAsync(ctx, k, peersPerSend)
			}
			unsent++

			if unsent >= threshold {
				// send wantlist to sendlist
				err := bs.sendWantListTo(ctx, sendlist)
				if err != nil {
					log.Errorf("error sending wantlist: %s", err)
				}
				unsent = 0
				timeout = time.After(rebroadcastTime)
				sendlist = nil
			} else {
				// set a timeout to wait for more blocks or send current wantlist

				timeout = time.After(bufferTime)
			}
		case <-ctx.Done():
			return
		}
	}
}

// HasBlock announces the existance of a block to this bitswap service. The
// service will potentially notify its peers.
func (bs *bitswap) HasBlock(ctx context.Context, blk blocks.Block) error {
	log.Debugf("Has Block %v", blk.Key())
	bs.wantlist.Remove(blk.Key())
	bs.sendToPeersThatWant(ctx, blk)
	return bs.routing.Provide(ctx, blk.Key())
}

// TODO(brian): handle errors
func (bs *bitswap) ReceiveMessage(ctx context.Context, p peer.Peer, incoming bsmsg.BitSwapMessage) (
	peer.Peer, bsmsg.BitSwapMessage) {
	log.Debugf("ReceiveMessage from %v", p.Key())
	log.Debugf("Message wantlist: %v", incoming.Wantlist())

	if p == nil {
		log.Error("Received message from nil peer!")
		// TODO propagate the error upward
		return nil, nil
	}
	if incoming == nil {
		log.Error("Got nil bitswap message!")
		// TODO propagate the error upward
		return nil, nil
	}

	// Record message bytes in ledger
	// TODO: this is bad, and could be easily abused.
	// Should only track *useful* messages in ledger
	bs.strategy.MessageReceived(p, incoming) // FIRST

	for _, block := range incoming.Blocks() {
		// TODO verify blocks?
		if err := bs.blockstore.Put(&block); err != nil {
			continue // FIXME(brian): err ignored
		}
		bs.notifications.Publish(block)
		err := bs.HasBlock(ctx, block)
		if err != nil {
			log.Warningf("HasBlock errored: %s", err)
		}
	}

	message := bsmsg.New()
	for _, wanted := range bs.wantlist.Keys() {
		message.AddWanted(wanted)
	}
	for _, key := range incoming.Wantlist() {
		// TODO: might be better to check if we have the block before checking
		//			if we should send it to someone
		if bs.strategy.ShouldSendBlockToPeer(key, p) {
			if block, errBlockNotFound := bs.blockstore.Get(key); errBlockNotFound != nil {
				continue
			} else {
				message.AddBlock(*block)
			}
		}
	}

	bs.strategy.MessageSent(p, message)
	log.Debug("Returning message.")
	return p, message
}

func (bs *bitswap) ReceiveError(err error) {
	log.Errorf("Bitswap ReceiveError: %s", err)
	// TODO log the network error
	// TODO bubble the network error up to the parent context/error logger
}

// send strives to ensure that accounting is always performed when a message is
// sent
func (bs *bitswap) send(ctx context.Context, p peer.Peer, m bsmsg.BitSwapMessage) {
	bs.sender.SendMessage(ctx, p, m)
	bs.strategy.MessageSent(p, m)
}

func (bs *bitswap) sendToPeersThatWant(ctx context.Context, block blocks.Block) {
	log.Debugf("Sending %v to peers that want it", block.Key())

	for _, p := range bs.strategy.Peers() {
		if bs.strategy.BlockIsWantedByPeer(block.Key(), p) {
			log.Debugf("%v wants %v", p, block.Key())
			if bs.strategy.ShouldSendBlockToPeer(block.Key(), p) {
				message := bsmsg.New()
				message.AddBlock(block)
				for _, wanted := range bs.wantlist.Keys() {
					message.AddWanted(wanted)
				}
				bs.send(ctx, p, message)
			}
		}
	}
}
<commit_msg>fix(bitswap) consistent event names<commit_after>// package bitswap implements the IPFS Exchange interface with the BitSwap
// bilateral exchange protocol.
package bitswap

import (
	"time"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"

	blocks "github.com/jbenet/go-ipfs/blocks"
	blockstore "github.com/jbenet/go-ipfs/blockstore"
	exchange "github.com/jbenet/go-ipfs/exchange"
	bsmsg "github.com/jbenet/go-ipfs/exchange/bitswap/message"
	bsnet "github.com/jbenet/go-ipfs/exchange/bitswap/network"
	notifications "github.com/jbenet/go-ipfs/exchange/bitswap/notifications"
	strategy "github.com/jbenet/go-ipfs/exchange/bitswap/strategy"
	peer "github.com/jbenet/go-ipfs/peer"
	u "github.com/jbenet/go-ipfs/util"
	"github.com/jbenet/go-ipfs/util/eventlog"
)

var log = eventlog.Logger("bitswap")

// New initializes a BitSwap instance that communicates over the
// provided BitSwapNetwork. This function registers the returned instance as
// the network delegate.
// Runs until context is cancelled
func New(ctx context.Context, p peer.Peer,
	network bsnet.BitSwapNetwork, routing bsnet.Routing,
	d ds.ThreadSafeDatastore, nice bool) exchange.Interface {

	notif := notifications.New()
	go func() {
		<-ctx.Done()
		notif.Shutdown()
	}()

	bs := &bitswap{
		blockstore:    blockstore.NewBlockstore(d),
		notifications: notif,
		strategy:      strategy.New(nice),
		routing:       routing,
		sender:        network,
		wantlist:      u.NewKeySet(),
		blockReq:      make(chan u.Key, 32),
	}
	network.SetDelegate(bs)
	go bs.run(ctx)

	return bs
}

// bitswap instances implement the bitswap protocol.
type bitswap struct {

	// sender delivers messages on behalf of the session
	sender bsnet.BitSwapNetwork

	// blockstore is the local database
	// NB: ensure threadsafety
	blockstore blockstore.Blockstore

	// routing interface for communication
	routing bsnet.Routing

	notifications notifications.PubSub

	blockReq chan u.Key

	// strategy listens to network traffic and makes decisions about how to
	// interact with partners.
	// TODO(brian): save the strategy's state to the datastore
	strategy strategy.Strategy

	wantlist u.KeySet
}

// GetBlock attempts to retrieve a particular block from peers within the
// deadline enforced by the context
//
// TODO ensure only one active request per key
func (bs *bitswap) GetBlock(parent context.Context, k u.Key) (*blocks.Block, error) {

	// make sure to derive a new |ctx| and pass it to children. It's correct to
	// listen on |parent| here, but incorrect to pass |parent| to new async
	// functions. This is difficult to enforce. May this comment keep you safe.

	ctx, cancelFunc := context.WithCancel(parent)
	defer cancelFunc()

	ctx = eventlog.ContextWithMetadata(ctx, eventlog.Uuid("GetBlockRequest"))
	log.Event(ctx, "GetBlockRequestBegin", &k)

	defer func() {
		log.Event(ctx, "GetBlockRequestEnd", &k)
	}()

	bs.wantlist.Add(k)
	promise := bs.notifications.Subscribe(ctx, k)

	select {
	case bs.blockReq <- k:
	case <-parent.Done():
		return nil, parent.Err()
	}

	select {
	case block := <-promise:
		bs.wantlist.Remove(k)
		return &block, nil
	case <-parent.Done():
		return nil, parent.Err()
	}
}

func (bs *bitswap) GetBlocks(parent context.Context, ks []u.Key) (*blocks.Block, error) {
	// TODO: something smart
	return nil, nil
}

func (bs *bitswap) sendWantListTo(ctx context.Context, peers <-chan peer.Peer) error {
	message := bsmsg.New()
	for _, wanted := range bs.wantlist.Keys() {
		message.AddWanted(wanted)
	}
	for peerToQuery := range peers {
		log.Debugf("bitswap got peersToQuery: %s", peerToQuery)
		go func(p peer.Peer) {

			log.Debugf("bitswap dialing peer: %s", p)
			err := bs.sender.DialPeer(ctx, p)
			if err != nil {
				log.Errorf("Error sender.DialPeer(%s)", p)
				return
			}

			response, err := bs.sender.SendRequest(ctx, p, message)
			if err != nil {
				log.Errorf("Error sender.SendRequest(%s) = %s", p, err)
				return
			}
			// FIXME ensure accounting is handled correctly when
			// communication fails. May require slightly different API to
			// get better guarantees. May need shared sequence numbers.
			bs.strategy.MessageSent(p, message)

			if response == nil {
				return
			}
			bs.ReceiveMessage(ctx, p, response)
		}(peerToQuery)
	}
	return nil
}

func (bs *bitswap) run(ctx context.Context) {
	var sendlist <-chan peer.Peer

	// Every so often, we should resend out our current want list
	rebroadcastTime := time.Second * 5

	// Time to wait before sending out wantlists to better batch up requests
	bufferTime := time.Millisecond * 3
	peersPerSend := 6

	timeout := time.After(rebroadcastTime)
	threshold := 10
	unsent := 0
	for {
		select {
		case <-timeout:
			wantlist := bs.wantlist.Keys()
			if len(wantlist) == 0 {
				continue
			}
			if sendlist == nil {
				// rely on semi randomness of maps
				firstKey := wantlist[0]
				sendlist = bs.routing.FindProvidersAsync(ctx, firstKey, 6)
			}
			err := bs.sendWantListTo(ctx, sendlist)
			if err != nil {
				log.Error("error sending wantlist: %s", err)
			}
			sendlist = nil
			timeout = time.After(rebroadcastTime)
		case k := <-bs.blockReq:
			if unsent == 0 {
				sendlist = bs.routing.FindProvidersAsync(ctx, k, peersPerSend)
			}
			unsent++

			if unsent >= threshold {
				// send wantlist to sendlist
				err := bs.sendWantListTo(ctx, sendlist)
				if err != nil {
					log.Errorf("error sending wantlist: %s", err)
				}
				unsent = 0
				timeout = time.After(rebroadcastTime)
				sendlist = nil
			} else {
				// set a timeout to wait for more blocks or send current wantlist

				timeout = time.After(bufferTime)
			}
		case <-ctx.Done():
			return
		}
	}
}

// HasBlock announces the existance of a block to this bitswap service. The
// service will potentially notify its peers.
func (bs *bitswap) HasBlock(ctx context.Context, blk blocks.Block) error {
	log.Debugf("Has Block %v", blk.Key())
	bs.wantlist.Remove(blk.Key())
	bs.sendToPeersThatWant(ctx, blk)
	return bs.routing.Provide(ctx, blk.Key())
}

// TODO(brian): handle errors
func (bs *bitswap) ReceiveMessage(ctx context.Context, p peer.Peer, incoming bsmsg.BitSwapMessage) (
	peer.Peer, bsmsg.BitSwapMessage) {
	log.Debugf("ReceiveMessage from %v", p.Key())
	log.Debugf("Message wantlist: %v", incoming.Wantlist())

	if p == nil {
		log.Error("Received message from nil peer!")
		// TODO propagate the error upward
		return nil, nil
	}
	if incoming == nil {
		log.Error("Got nil bitswap message!")
		// TODO propagate the error upward
		return nil, nil
	}

	// Record message bytes in ledger
	// TODO: this is bad, and could be easily abused.
	// Should only track *useful* messages in ledger
	bs.strategy.MessageReceived(p, incoming) // FIRST

	for _, block := range incoming.Blocks() {
		// TODO verify blocks?
		if err := bs.blockstore.Put(&block); err != nil {
			continue // FIXME(brian): err ignored
		}
		bs.notifications.Publish(block)
		err := bs.HasBlock(ctx, block)
		if err != nil {
			log.Warningf("HasBlock errored: %s", err)
		}
	}

	message := bsmsg.New()
	for _, wanted := range bs.wantlist.Keys() {
		message.AddWanted(wanted)
	}
	for _, key := range incoming.Wantlist() {
		// TODO: might be better to check if we have the block before checking
		//			if we should send it to someone
		if bs.strategy.ShouldSendBlockToPeer(key, p) {
			if block, errBlockNotFound := bs.blockstore.Get(key); errBlockNotFound != nil {
				continue
			} else {
				message.AddBlock(*block)
			}
		}
	}

	bs.strategy.MessageSent(p, message)
	log.Debug("Returning message.")
	return p, message
}

func (bs *bitswap) ReceiveError(err error) {
	log.Errorf("Bitswap ReceiveError: %s", err)
	// TODO log the network error
	// TODO bubble the network error up to the parent context/error logger
}

// send strives to ensure that accounting is always performed when a message is
// sent
func (bs *bitswap) send(ctx context.Context, p peer.Peer, m bsmsg.BitSwapMessage) {
	bs.sender.SendMessage(ctx, p, m)
	bs.strategy.MessageSent(p, m)
}

func (bs *bitswap) sendToPeersThatWant(ctx context.Context, block blocks.Block) {
	log.Debugf("Sending %v to peers that want it", block.Key())

	for _, p := range bs.strategy.Peers() {
		if bs.strategy.BlockIsWantedByPeer(block.Key(), p) {
			log.Debugf("%v wants %v", p, block.Key())
			if bs.strategy.ShouldSendBlockToPeer(block.Key(), p) {
				message := bsmsg.New()
				message.AddBlock(block)
				for _, wanted := range bs.wantlist.Keys() {
					message.AddWanted(wanted)
				}
				bs.send(ctx, p, message)
			}
		}
	}
}
<|endoftext|>


<commit_before>package gog

import (
	"fmt"
	"go/ast"
	"path/filepath"
	"strings"

	"sourcegraph.com/sourcegraph/srclib-go/gog/definfo"

	"go/types"

	"golang.org/x/tools/go/loader"
)

type DefKey struct {
	PackageImportPath string
	Path              []string
}

func (s *DefKey) String() string {
	return s.PackageImportPath + "#" + strings.Join(s.Path, ".")
}

type Def struct {
	Name string

	*DefKey

	File      string
	IdentSpan [2]uint32
	DeclSpan  [2]uint32

	definfo.DefInfo
}

// NewDef creates a new Def.
func (g *Grapher) NewDef(obj types.Object, declIdent *ast.Ident) (*Def, error) {
	// Find the AST node that declares this def.
	var declNode ast.Node
	_, astPath, _ := g.program.PathEnclosingInterval(declIdent.Pos(), declIdent.End())
	for _, node := range astPath {
		switch node.(type) {
		case *ast.FuncDecl, *ast.GenDecl, *ast.ValueSpec, *ast.TypeSpec, *ast.Field, *ast.DeclStmt, *ast.AssignStmt:
			declNode = node
			goto found
		}
	}
found:
	if declNode == nil {
		return nil, fmt.Errorf("On ident %s at %s: no DeclNode found (using PathEnclosingInterval)", declIdent.Name, g.program.Fset.Position(declIdent.Pos()))
	}

	key, info, err := g.defInfo(obj)
	if err != nil {
		return nil, err
	}

	si := definfo.DefInfo{
		Exported: info.exported,
		PkgScope: info.pkgscope,
		PkgName:  obj.Pkg().Name(),
		Kind:     defKind(obj),
	}

	if typ := obj.Type(); typ != nil {
		si.TypeString = typ.String()
		if utyp := typ.Underlying(); utyp != nil {
			si.UnderlyingTypeString = utyp.String()
		}
	}

	switch obj := obj.(type) {
	case *types.Var:
		if obj.IsField() {
			if fieldStruct, ok := g.structFields[obj]; ok {
				if struct_, ok := fieldStruct.parent.(*types.Named); ok {
					si.FieldOfStruct = struct_.Obj().Name()
				}
			}
		}
	case *types.Func:
		sig := obj.Type().(*types.Signature)
		if recv := sig.Recv(); recv != nil && recv.Type() != nil {
			// omit package path; just get receiver type name
			si.Receiver = strings.Replace(recv.Type().String(), obj.Pkg().Path()+".", "", 1)
		}
	}

	return &Def{
		Name: obj.Name(),

		DefKey: key,

		File:      g.program.Fset.Position(declIdent.Pos()).Filename,
		IdentSpan: makeSpan(g.program.Fset, declIdent),
		DeclSpan:  makeSpan(g.program.Fset, declNode),

		DefInfo: si,
	}, nil
}

// NewPackageDef creates a new Def that represents a Go package.
func (g *Grapher) NewPackageDef(pkgInfo *loader.PackageInfo, pkg *types.Package) (*Def, error) {
	var pkgDir string
	if len(pkgInfo.Files) > 0 {
		pkgDir = filepath.Dir(g.program.Fset.Position(pkgInfo.Files[0].Package).Filename)
	}

	return &Def{
		Name: pkg.Name(),

		DefKey: &DefKey{PackageImportPath: pkg.Path(), Path: []string{}},

		File: pkgDir,

		DefInfo: definfo.DefInfo{
			Exported: true,
			PkgName:  pkg.Name(),
			Kind:     definfo.Package,
		},
	}, nil
}

func defKind(obj types.Object) string {
	switch obj := obj.(type) {
	case *types.PkgName:
		return definfo.Package
	case *types.Const:
		return definfo.Const
	case *types.TypeName:
		return definfo.Type
	case *types.Var:
		if obj.IsField() {
			return definfo.Field
		}
		return definfo.Var
	case *types.Func:
		sig := obj.Type().(*types.Signature)
		if sig.Recv() == nil {
			return definfo.Func
		} else {
			return definfo.Method
		}
	default:
		panic(fmt.Sprintf("unhandled obj type %T", obj))
	}
}
<commit_msg>gog: special-case to handle builtin type string<commit_after>package gog

import (
	"fmt"
	"go/ast"
	"path/filepath"
	"strings"

	"sourcegraph.com/sourcegraph/srclib-go/gog/definfo"

	"go/types"

	"golang.org/x/tools/go/loader"
)

type DefKey struct {
	PackageImportPath string
	Path              []string
}

func (s *DefKey) String() string {
	return s.PackageImportPath + "#" + strings.Join(s.Path, ".")
}

type Def struct {
	Name string

	*DefKey

	File      string
	IdentSpan [2]uint32
	DeclSpan  [2]uint32

	definfo.DefInfo
}

// NewDef creates a new Def.
func (g *Grapher) NewDef(obj types.Object, declIdent *ast.Ident) (*Def, error) {
	// Find the AST node that declares this def.
	var declNode ast.Node
	_, astPath, _ := g.program.PathEnclosingInterval(declIdent.Pos(), declIdent.End())
	for _, node := range astPath {
		switch node.(type) {
		case *ast.FuncDecl, *ast.GenDecl, *ast.ValueSpec, *ast.TypeSpec, *ast.Field, *ast.DeclStmt, *ast.AssignStmt:
			declNode = node
			goto found
		}
	}
found:
	if declNode == nil {
		return nil, fmt.Errorf("On ident %s at %s: no DeclNode found (using PathEnclosingInterval)", declIdent.Name, g.program.Fset.Position(declIdent.Pos()))
	}

	key, info, err := g.defInfo(obj)
	if err != nil {
		return nil, err
	}

	si := definfo.DefInfo{
		Exported: info.exported,
		PkgScope: info.pkgscope,
		PkgName:  obj.Pkg().Name(),
		Kind:     defKind(obj),
	}

	if typ := obj.Type(); typ != nil {
		si.TypeString = typ.String()
		if key.PackageImportPath == "builtin" {
			si.UnderlyingTypeString = "builtin"
		} else if utyp := typ.Underlying(); utyp != nil {
			si.UnderlyingTypeString = utyp.String()
		}
	}

	switch obj := obj.(type) {
	case *types.Var:
		if obj.IsField() {
			if fieldStruct, ok := g.structFields[obj]; ok {
				if struct_, ok := fieldStruct.parent.(*types.Named); ok {
					si.FieldOfStruct = struct_.Obj().Name()
				}
			}
		}
	case *types.Func:
		sig := obj.Type().(*types.Signature)
		if recv := sig.Recv(); recv != nil && recv.Type() != nil {
			// omit package path; just get receiver type name
			si.Receiver = strings.Replace(recv.Type().String(), obj.Pkg().Path()+".", "", 1)
		}
	}

	return &Def{
		Name: obj.Name(),

		DefKey: key,

		File:      g.program.Fset.Position(declIdent.Pos()).Filename,
		IdentSpan: makeSpan(g.program.Fset, declIdent),
		DeclSpan:  makeSpan(g.program.Fset, declNode),

		DefInfo: si,
	}, nil
}

// NewPackageDef creates a new Def that represents a Go package.
func (g *Grapher) NewPackageDef(pkgInfo *loader.PackageInfo, pkg *types.Package) (*Def, error) {
	var pkgDir string
	if len(pkgInfo.Files) > 0 {
		pkgDir = filepath.Dir(g.program.Fset.Position(pkgInfo.Files[0].Package).Filename)
	}

	return &Def{
		Name: pkg.Name(),

		DefKey: &DefKey{PackageImportPath: pkg.Path(), Path: []string{}},

		File: pkgDir,

		DefInfo: definfo.DefInfo{
			Exported: true,
			PkgName:  pkg.Name(),
			Kind:     definfo.Package,
		},
	}, nil
}

func defKind(obj types.Object) string {
	switch obj := obj.(type) {
	case *types.PkgName:
		return definfo.Package
	case *types.Const:
		return definfo.Const
	case *types.TypeName:
		return definfo.Type
	case *types.Var:
		if obj.IsField() {
			return definfo.Field
		}
		return definfo.Var
	case *types.Func:
		sig := obj.Type().(*types.Signature)
		if sig.Recv() == nil {
			return definfo.Func
		} else {
			return definfo.Method
		}
	default:
		panic(fmt.Sprintf("unhandled obj type %T", obj))
	}
}
<|endoftext|>


<commit_before>package lfs

// The LFS error system provides a simple wrapper around Go errors and the
// ability to inspect errors. It is strongly influenced by Dave Cheney's post
// at http://dave.cheney.net/2014/12/24/inspecting-errors.
//
// When passing errors out of lfs package functions, the return type should
// always be `error`. The wrappedError details are not exported. If an error is
// the kind of error a caller should need to investigate, an IsXError()
// function is provided that tells the caller if the error is of that type.
// There should only be a handfull of cases where a simple `error` is
// insufficient.
//
// The error behaviors can be nested when created. For example, the not
// implemented error can also be marked as a fatal error:
//
//	func LfsFunction() error {
//		err := functionCall()
//		if err != nil {
//			return newFatalError(newNotImplementedError(err))
//		}
//		return nil
//	}
//
// Then in the caller:
//
//	err := lfs.LfsFunction()
//	if lfs.IsNotImplementedError(err) {
//		log.Print("feature not implemented")
//	}
//	if lfs.IsFatalError(err) {
//		os.Exit(1)
//	}
//
// Wrapped errors contain a context, which is a map[string]string. These
// contexts can be accessed through the Error*Context functions. Calling these
// functions on a regular Go error will have no effect.
//
// Example:
//
//	err := lfs.SomeFunction()
//	lfs.ErrorSetContext(err, "foo", "bar")
//	lfs.ErrorGetContext(err, "foo") // => "bar"
//	lfs.ErrorDelContext(err, "foo")
//
// Wrapped errors also contain the stack from the point at which they are
// called. The stack is accessed via ErrorStack(). Calling ErrorStack() on a
// regular Go error will return an empty byte slice.

import (
	"errors"
	"fmt"
	"runtime"
)

// IsFatalError indicates that the error is fatal and the process should exit
// immediately after handling the error.
func IsFatalError(err error) bool {
	if e, ok := err.(interface {
		Fatal() bool
	}); ok {
		return e.Fatal()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsFatalError(e.InnerError())
	}
	return false
}

// IsNotImplementedError indicates the client attempted to use a feature the
// server has not implemented (e.g. the batch endpoint).
func IsNotImplementedError(err error) bool {
	if e, ok := err.(interface {
		NotImplemented() bool
	}); ok {
		return e.NotImplemented()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsNotImplementedError(e.InnerError())
	}
	return false
}

// IsInvalidPointerError indicates an attempt to parse data that was not a
// valid pointer.
func IsInvalidPointerError(err error) bool {
	if e, ok := err.(interface {
		InvalidPointer() bool
	}); ok {
		return e.InvalidPointer()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsInvalidPointerError(e.InnerError())
	}
	return false
}

// IsInvalidRepoError indicates an operation was attempted from outside a git
// repository.
func IsInvalidRepoError(err error) bool {
	if e, ok := err.(interface {
		InvalidRepo() bool
	}); ok {
		return e.InvalidRepo()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsInvalidRepoError(e.InnerError())
	}
	return false
}

// IsSmudgeError indicates an error while smudging a files.
func IsSmudgeError(err error) bool {
	if e, ok := err.(interface {
		SmudgeError() bool
	}); ok {
		return e.SmudgeError()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsSmudgeError(e.InnerError())
	}
	return false
}

// IsCleanPointerError indicates an error while cleaning a file. Because of the
// structure of the code, this check also returns a *CleanPointerError because
// that's how a Pointer and []byte were passed up to the caller. This is not
// very clean and should be refactored. The returned *CleanPointerError MUST
// NOT be accessed if the bool value is false.
func IsCleanPointerError(err error) bool {
	if e, ok := err.(interface {
		CleanPointerError() bool
	}); ok {
		return e.CleanPointerError()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsCleanPointerError(e.InnerError())
	}
	return false
}

// IsNotAPointerError indicates the parsed data is not an LFS pointer.
func IsNotAPointerError(err error) bool {
	if e, ok := err.(interface {
		NotAPointerError() bool
	}); ok {
		return e.NotAPointerError()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsNotAPointerError(e.InnerError())
	}
	return false
}

// IsDownloadDeclinedError indicates that the smudge operation should not download.
// TODO: I don't really like using errors to control that flow, it should be refactored.
func IsDownloadDeclinedError(err error) bool {
	if e, ok := err.(interface {
		DownloadDeclinedError() bool
	}); ok {
		return e.DownloadDeclinedError()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsDownloadDeclinedError(e.InnerError())
	}
	return false
}

// Error wraps an error with an empty message.
func Error(err error) error {
	return Errorf(err, "")
}

// Errorf wraps an error with an additional formatted message.
func Errorf(err error, format string, args ...interface{}) error {
	if err == nil {
		err = errors.New("")
	}

	message := ""
	if len(format) > 0 {
		message = fmt.Sprintf(format, args...)
	}

	return newWrappedError(err, message)
}

// ErrorSetContext sets a value in the error's context. If the error has not
// been wrapped, it does nothing.
func ErrorSetContext(err error, key string, value interface{}) {
	if e, ok := err.(errorWrapper); ok {
		e.Set(key, value)
	}
}

// ErrorGetContext gets a value from the error's context. If the error has not
// been wrapped, it returns an empty string.
func ErrorGetContext(err error, key string) interface{} {
	if e, ok := err.(errorWrapper); ok {
		return e.Get(key)
	}
	return ""
}

// ErrorDelContext removes a value from the error's context. If the error has
// not been wrapped, it does nothing.
func ErrorDelContext(err error, key string) {
	if e, ok := err.(errorWrapper); ok {
		e.Del(key)
	}
}

// ErrorStack returns the stack for an error if it is a wrappedError. If it is
// not a wrappedError it will return an empty byte slice.
func ErrorStack(err error) []byte {
	if e, ok := err.(errorWrapper); ok {
		return e.Stack()
	}
	return nil
}

// ErrorContext returns the context map for an error if it is a wrappedError.
// If it is not a wrappedError it will return an empty map.
func ErrorContext(err error) map[string]interface{} {
	if e, ok := err.(errorWrapper); ok {
		return e.Context()
	}
	return nil
}

type errorWrapper interface {
	InnerError() error
	Error() string
	Set(string, interface{})
	Get(string) interface{}
	Del(string)
	Context() map[string]interface{}
	Stack() []byte
}

// wrappedError is the base error wrapper. It provides a Message string, a
// stack, and a context map around a regular Go error.
type wrappedError struct {
	Message string
	stack   []byte
	context map[string]interface{}
	error
}

// newWrappedError creates a wrappedError. If the error has already been
// wrapped it is simply returned as is.
func newWrappedError(err error, message string) errorWrapper {
	if e, ok := err.(errorWrapper); ok {
		return e
	}

	if err == nil {
		err = errors.New("LFS Error")
	}

	if message == "" {
		message = err.Error()
	}

	return wrappedError{
		Message: message,
		stack:   Stack(),
		context: make(map[string]interface{}),
		error:   err,
	}
}

// Error will return the wrapped error's Message if it has one, otherwise it
// will call the underlying error's Error() function.
func (e wrappedError) Error() string {
	if e.Message == "" {
		return e.error.Error()
	}
	return e.Message
}

// InnerError returns the underlying error. This could be a Go error or another wrappedError.
func (e wrappedError) InnerError() error {
	return e.error
}

// Set sets the value for the key in the context.
func (e wrappedError) Set(key string, val interface{}) {
	e.context[key] = val
}

// Get gets the value for a key in the context.
func (e wrappedError) Get(key string) interface{} {
	return e.context[key]
}

// Del removes a key from the context.
func (e wrappedError) Del(key string) {
	delete(e.context, key)
}

// Context returns the underlying context.
func (e wrappedError) Context() map[string]interface{} {
	return e.context
}

// Stack returns the stack.
func (e wrappedError) Stack() []byte {
	return e.stack
}

// Definitions for IsFatalError()

type fatalError struct {
	errorWrapper
}

func (e fatalError) InnerError() error {
	return e.errorWrapper
}

func (e fatalError) Fatal() bool {
	return true
}

func newFatalError(err error) error {
	return fatalError{newWrappedError(err, "Fatal error")}
}

// Definitions for IsNotImplementedError()

type notImplementedError struct {
	errorWrapper
}

func (e notImplementedError) InnerError() error {
	return e.errorWrapper
}

func (e notImplementedError) NotImplemented() bool {
	return true
}

func newNotImplementedError(err error) error {
	return notImplementedError{newWrappedError(err, "Not implemented")}
}

// Definitions for IsInvalidPointerError()

type invalidPointerError struct {
	errorWrapper
}

func (e invalidPointerError) InnerError() error {
	return e.errorWrapper
}

func (e invalidPointerError) InvalidPointer() bool {
	return true
}

func newInvalidPointerError(err error) error {
	return invalidPointerError{newWrappedError(err, "Invalid pointer")}
}

// Definitions for IsInvalidRepoError()

type invalidRepoError struct {
	errorWrapper
}

func (e invalidRepoError) InnerError() error {
	return e.errorWrapper
}

func (e invalidRepoError) InvalidRepo() bool {
	return true
}

func newInvalidRepoError(err error) error {
	return invalidRepoError{newWrappedError(err, "Not in a repository")}
}

// Definitions for IsSmudgeError()

type smudgeError struct {
	errorWrapper
}

func (e smudgeError) InnerError() error {
	return e.errorWrapper
}

func (e smudgeError) SmudgeError() bool {
	return true
}

func newSmudgeError(err error, oid, filename string) error {
	e := smudgeError{newWrappedError(err, "Smudge error")}
	ErrorSetContext(e, "OID", oid)
	ErrorSetContext(e, "FileName", filename)
	return e
}

// Definitions for IsCleanPointerError()

// cleanPointerError is used to pass the Pointer and contents back up to the
// caller.
type cleanPointerError struct {
	errorWrapper
}

func (e cleanPointerError) InnerError() error {
	return e.errorWrapper
}

func (e cleanPointerError) CleanPointerError() bool {
	return true
}

func newCleanPointerError(err error, pointer *Pointer, bytes []byte) error {
	e := cleanPointerError{newWrappedError(err, "Clean pointer error")}
	ErrorSetContext(e, "pointer", pointer)
	ErrorSetContext(e, "bytes", bytes)
	return e
}

// Definitions for IsNotAPointerError()

type notAPointerError struct {
	errorWrapper
}

func (e notAPointerError) InnerError() error {
	return e.errorWrapper
}

func (e notAPointerError) NotAPointerError() bool {
	return true
}

func newNotAPointerError(err error) error {
	return notAPointerError{newWrappedError(err, "Not a valid Git LFS pointer file.")}
}

// Definitions for IsDownloadDeclinedError()

type downloadDeclinedError struct {
	errorWrapper
}

func (e downloadDeclinedError) InnerError() error {
	return e.errorWrapper
}

func (e downloadDeclinedError) DownloadDeclinedError() bool {
	return true
}

func newDownloadDeclinedError(err error) error {
	return downloadDeclinedError{newWrappedError(err, "File missing and download is not allowed")}
}

// Stack returns a byte slice containing the runtime.Stack()
func Stack() []byte {
	stackBuf := make([]byte, 1024*1024)
	written := runtime.Stack(stackBuf, false)
	return stackBuf[:written]
}
<commit_msg>ンンー ンンンン ンーンン<commit_after>package lfs

// The LFS error system provides a simple wrapper around Go errors and the
// ability to inspect errors. It is strongly influenced by Dave Cheney's post
// at http://dave.cheney.net/2014/12/24/inspecting-errors.
//
// When passing errors out of lfs package functions, the return type should
// always be `error`. The wrappedError details are not exported. If an error is
// the kind of error a caller should need to investigate, an IsXError()
// function is provided that tells the caller if the error is of that type.
// There should only be a handfull of cases where a simple `error` is
// insufficient.
//
// The error behaviors can be nested when created. For example, the not
// implemented error can also be marked as a fatal error:
//
//	func LfsFunction() error {
//		err := functionCall()
//		if err != nil {
//			return newFatalError(newNotImplementedError(err))
//		}
//		return nil
//	}
//
// Then in the caller:
//
//	err := lfs.LfsFunction()
//	if lfs.IsNotImplementedError(err) {
//		log.Print("feature not implemented")
//	}
//	if lfs.IsFatalError(err) {
//		os.Exit(1)
//	}
//
// Wrapped errors contain a context, which is a map[string]string. These
// contexts can be accessed through the Error*Context functions. Calling these
// functions on a regular Go error will have no effect.
//
// Example:
//
//	err := lfs.SomeFunction()
//	lfs.ErrorSetContext(err, "foo", "bar")
//	lfs.ErrorGetContext(err, "foo") // => "bar"
//	lfs.ErrorDelContext(err, "foo")
//
// Wrapped errors also contain the stack from the point at which they are
// called. The stack is accessed via ErrorStack(). Calling ErrorStack() on a
// regular Go error will return an empty byte slice.

import (
	"errors"
	"fmt"
	"runtime"
)

// IsFatalError indicates that the error is fatal and the process should exit
// immediately after handling the error.
func IsFatalError(err error) bool {
	if e, ok := err.(interface {
		Fatal() bool
	}); ok {
		return e.Fatal()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsFatalError(e.InnerError())
	}
	return false
}

// IsNotImplementedError indicates the client attempted to use a feature the
// server has not implemented (e.g. the batch endpoint).
func IsNotImplementedError(err error) bool {
	if e, ok := err.(interface {
		NotImplemented() bool
	}); ok {
		return e.NotImplemented()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsNotImplementedError(e.InnerError())
	}
	return false
}

// IsInvalidPointerError indicates an attempt to parse data that was not a
// valid pointer.
func IsInvalidPointerError(err error) bool {
	if e, ok := err.(interface {
		InvalidPointer() bool
	}); ok {
		return e.InvalidPointer()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsInvalidPointerError(e.InnerError())
	}
	return false
}

// IsInvalidRepoError indicates an operation was attempted from outside a git
// repository.
func IsInvalidRepoError(err error) bool {
	if e, ok := err.(interface {
		InvalidRepo() bool
	}); ok {
		return e.InvalidRepo()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsInvalidRepoError(e.InnerError())
	}
	return false
}

// IsSmudgeError indicates an error while smudging a files.
func IsSmudgeError(err error) bool {
	if e, ok := err.(interface {
		SmudgeError() bool
	}); ok {
		return e.SmudgeError()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsSmudgeError(e.InnerError())
	}
	return false
}

// IsCleanPointerError indicates an error while cleaning a file.
func IsCleanPointerError(err error) bool {
	if e, ok := err.(interface {
		CleanPointerError() bool
	}); ok {
		return e.CleanPointerError()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsCleanPointerError(e.InnerError())
	}
	return false
}

// IsNotAPointerError indicates the parsed data is not an LFS pointer.
func IsNotAPointerError(err error) bool {
	if e, ok := err.(interface {
		NotAPointerError() bool
	}); ok {
		return e.NotAPointerError()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsNotAPointerError(e.InnerError())
	}
	return false
}

// IsDownloadDeclinedError indicates that the smudge operation should not download.
// TODO: I don't really like using errors to control that flow, it should be refactored.
func IsDownloadDeclinedError(err error) bool {
	if e, ok := err.(interface {
		DownloadDeclinedError() bool
	}); ok {
		return e.DownloadDeclinedError()
	}
	if e, ok := err.(errorWrapper); ok {
		return IsDownloadDeclinedError(e.InnerError())
	}
	return false
}

// Error wraps an error with an empty message.
func Error(err error) error {
	return Errorf(err, "")
}

// Errorf wraps an error with an additional formatted message.
func Errorf(err error, format string, args ...interface{}) error {
	if err == nil {
		err = errors.New("")
	}

	message := ""
	if len(format) > 0 {
		message = fmt.Sprintf(format, args...)
	}

	return newWrappedError(err, message)
}

// ErrorSetContext sets a value in the error's context. If the error has not
// been wrapped, it does nothing.
func ErrorSetContext(err error, key string, value interface{}) {
	if e, ok := err.(errorWrapper); ok {
		e.Set(key, value)
	}
}

// ErrorGetContext gets a value from the error's context. If the error has not
// been wrapped, it returns an empty string.
func ErrorGetContext(err error, key string) interface{} {
	if e, ok := err.(errorWrapper); ok {
		return e.Get(key)
	}
	return ""
}

// ErrorDelContext removes a value from the error's context. If the error has
// not been wrapped, it does nothing.
func ErrorDelContext(err error, key string) {
	if e, ok := err.(errorWrapper); ok {
		e.Del(key)
	}
}

// ErrorStack returns the stack for an error if it is a wrappedError. If it is
// not a wrappedError it will return an empty byte slice.
func ErrorStack(err error) []byte {
	if e, ok := err.(errorWrapper); ok {
		return e.Stack()
	}
	return nil
}

// ErrorContext returns the context map for an error if it is a wrappedError.
// If it is not a wrappedError it will return an empty map.
func ErrorContext(err error) map[string]interface{} {
	if e, ok := err.(errorWrapper); ok {
		return e.Context()
	}
	return nil
}

type errorWrapper interface {
	InnerError() error
	Error() string
	Set(string, interface{})
	Get(string) interface{}
	Del(string)
	Context() map[string]interface{}
	Stack() []byte
}

// wrappedError is the base error wrapper. It provides a Message string, a
// stack, and a context map around a regular Go error.
type wrappedError struct {
	Message string
	stack   []byte
	context map[string]interface{}
	error
}

// newWrappedError creates a wrappedError. If the error has already been
// wrapped it is simply returned as is.
func newWrappedError(err error, message string) errorWrapper {
	if e, ok := err.(errorWrapper); ok {
		return e
	}

	if err == nil {
		err = errors.New("LFS Error")
	}

	if message == "" {
		message = err.Error()
	}

	return wrappedError{
		Message: message,
		stack:   Stack(),
		context: make(map[string]interface{}),
		error:   err,
	}
}

// Error will return the wrapped error's Message if it has one, otherwise it
// will call the underlying error's Error() function.
func (e wrappedError) Error() string {
	if e.Message == "" {
		return e.error.Error()
	}
	return e.Message
}

// InnerError returns the underlying error. This could be a Go error or another wrappedError.
func (e wrappedError) InnerError() error {
	return e.error
}

// Set sets the value for the key in the context.
func (e wrappedError) Set(key string, val interface{}) {
	e.context[key] = val
}

// Get gets the value for a key in the context.
func (e wrappedError) Get(key string) interface{} {
	return e.context[key]
}

// Del removes a key from the context.
func (e wrappedError) Del(key string) {
	delete(e.context, key)
}

// Context returns the underlying context.
func (e wrappedError) Context() map[string]interface{} {
	return e.context
}

// Stack returns the stack.
func (e wrappedError) Stack() []byte {
	return e.stack
}

// Definitions for IsFatalError()

type fatalError struct {
	errorWrapper
}

func (e fatalError) InnerError() error {
	return e.errorWrapper
}

func (e fatalError) Fatal() bool {
	return true
}

func newFatalError(err error) error {
	return fatalError{newWrappedError(err, "Fatal error")}
}

// Definitions for IsNotImplementedError()

type notImplementedError struct {
	errorWrapper
}

func (e notImplementedError) InnerError() error {
	return e.errorWrapper
}

func (e notImplementedError) NotImplemented() bool {
	return true
}

func newNotImplementedError(err error) error {
	return notImplementedError{newWrappedError(err, "Not implemented")}
}

// Definitions for IsInvalidPointerError()

type invalidPointerError struct {
	errorWrapper
}

func (e invalidPointerError) InnerError() error {
	return e.errorWrapper
}

func (e invalidPointerError) InvalidPointer() bool {
	return true
}

func newInvalidPointerError(err error) error {
	return invalidPointerError{newWrappedError(err, "Invalid pointer")}
}

// Definitions for IsInvalidRepoError()

type invalidRepoError struct {
	errorWrapper
}

func (e invalidRepoError) InnerError() error {
	return e.errorWrapper
}

func (e invalidRepoError) InvalidRepo() bool {
	return true
}

func newInvalidRepoError(err error) error {
	return invalidRepoError{newWrappedError(err, "Not in a repository")}
}

// Definitions for IsSmudgeError()

type smudgeError struct {
	errorWrapper
}

func (e smudgeError) InnerError() error {
	return e.errorWrapper
}

func (e smudgeError) SmudgeError() bool {
	return true
}

func newSmudgeError(err error, oid, filename string) error {
	e := smudgeError{newWrappedError(err, "Smudge error")}
	ErrorSetContext(e, "OID", oid)
	ErrorSetContext(e, "FileName", filename)
	return e
}

// Definitions for IsCleanPointerError()

// cleanPointerError is used to pass the Pointer and contents back up to the
// caller.
type cleanPointerError struct {
	errorWrapper
}

func (e cleanPointerError) InnerError() error {
	return e.errorWrapper
}

func (e cleanPointerError) CleanPointerError() bool {
	return true
}

func newCleanPointerError(err error, pointer *Pointer, bytes []byte) error {
	e := cleanPointerError{newWrappedError(err, "Clean pointer error")}
	ErrorSetContext(e, "pointer", pointer)
	ErrorSetContext(e, "bytes", bytes)
	return e
}

// Definitions for IsNotAPointerError()

type notAPointerError struct {
	errorWrapper
}

func (e notAPointerError) InnerError() error {
	return e.errorWrapper
}

func (e notAPointerError) NotAPointerError() bool {
	return true
}

func newNotAPointerError(err error) error {
	return notAPointerError{newWrappedError(err, "Not a valid Git LFS pointer file.")}
}

// Definitions for IsDownloadDeclinedError()

type downloadDeclinedError struct {
	errorWrapper
}

func (e downloadDeclinedError) InnerError() error {
	return e.errorWrapper
}

func (e downloadDeclinedError) DownloadDeclinedError() bool {
	return true
}

func newDownloadDeclinedError(err error) error {
	return downloadDeclinedError{newWrappedError(err, "File missing and download is not allowed")}
}

// Stack returns a byte slice containing the runtime.Stack()
func Stack() []byte {
	stackBuf := make([]byte, 1024*1024)
	written := runtime.Stack(stackBuf, false)
	return stackBuf[:written]
}
<|endoftext|>