<commit_before>package main

import (
	"database/sql"
	"fmt"
	"regexp"
	"strings"

	_ "github.com/mattn/go-sqlite3"
)

const wordsTablename = "words"
const customwordsTablename = "customwords"
const kanjipointsTablename = "kanjipoints"
const addCustomWordSavePoint = "AddCustomWord"
const removeCustomWordSavePoint = "RemoveCustomWord"
const kanaExp = `(\p{Katakana}|\p{Hiragana}|ー)([ゃャょョゅュ])?`

var wordsdb *sql.DB
var endKanaExp = regexp.MustCompile(fmt.Sprintf("%s$", kanaExp))
var beginKanaExp = regexp.MustCompile(fmt.Sprintf("^%s", kanaExp))
var endsInNExp = regexp.MustCompile(`(ん|ン)$`)

func getWordPts(chatID int64, theWord string, lastEntry *wordEntry) (int, string) {
	// If points are zero or not found, then return zero. Probably ends in 'n', or not a noun.
	kana, pts := lookupKana(chatID, theWord)
	if lastEntry != nil {
		// Get kana of last word.
		lastEntryKana, _ := lookupKana(chatID, lastEntry.word)
		// If first kana of new word does not match ending kana of last word, then return zero.
		if !matchKana(lastEntryKana, kana) {
			return 0, fmt.Sprintf("初めの仮名は終わりのかなと一致しません: %s「%s」-> %s「%s」", lastEntry.word, lastEntryKana, theWord, kana)
		}
	} else if pts == 0 {
		if endsInN(kana) {
			return pts, fmt.Sprintf("言葉は'ん'が終わることが禁止されています: %s", theWord)
		}
		return pts, fmt.Sprintf("無効言葉: %s", theWord)
	}
	return pts, ""
}

func lookupKana(chatID int64, theWord string) (string, int) {
	found, kana, pts := lookupStandardKana(chatID, theWord)
	if !found || pts == 0 {
		var customkana string
		found, customkana, pts = lookupCustomKana(chatID, theWord)
		if !found {
			return kana, 0
		}
		kana = customkana
	}
	return kana, pts
}

func lookupStandardKana(chatID int64, theWord string) (bool, string, int) {
	var kana string
	var pts int
	found := gamedb.Query(fmt.Sprintf("SELECT kana, points FROM %s WHERE kanji = '%s'", wordsTablename, theWord), &kana, &pts)
	return found, kana, pts
}

func lookupCustomKana(chatID int64, theWord string) (bool, string, int) {
	var kana string
	var pts int
	found := gamedb.Query(fmt.Sprintf("SELECT kana, points FROM %s WHERE chatid = %d AND kanji = '%s'", customwordsTablename, chatID, theWord), &kana, &pts)
	return found, kana, pts
}

func matchKana(lastWordKana string, newWordKana string) bool {
	lastKana := strings.Split(lastWordKana, ",")
	newKana := strings.Split(newWordKana, ",")
	for _, lk := range lastKana {
		endingMatch := endKanaExp.FindStringSubmatch(lk)
		for _, nk := range newKana {
			if endAndBeginMatch(endingMatch, beginKanaExp.FindStringSubmatch(nk)) {
				return true
			}
		}
	}
	return false
}

func endAndBeginMatch(endingMatch []string, beginningMatch []string) bool {
	// If the word ends in a combined phonic (i.e., しゃ), then the
	// next word must begin with that same combination.
	// However, if the word ends in just し, then the next word can
	// optionally start with combined phonic (i.e., しゃ) or just し.
	for index := 1; index < len(endingMatch); index++ {
		if len(endingMatch[index]) > 0 && endingMatch[index] != beginningMatch[index] {
			return false
		}
	}
	return true
}

func endsInN(kana string) bool {
	// Check for ending in ん.
	for _, k := range strings.Split(kana, ",") {
		if endsInNExp.MatchString(k) {
			return true
		}
	}
	return false
}

func calcWordPoints(kanji string) int {
	// Words entirely of hiragana or katakana are worth 1 point.
	pts := 1
	if kanjiExp.MatchString(kanji) {
		for _, k := range kanji {
			kpts := getKanjiPoints(string(k))
			if kpts > pts {
				// The word pts is equal to the highest kanji pts in the word.
				pts = kpts
			}
		}
	}
	return pts
}

func getKanjiPoints(kanjiCharacter string) int {
	var pts int
	if !gamedb.Query(fmt.Sprintf("SELECT points FROM %s WHERE kanji = '%s'", kanjipointsTablename, kanjiCharacter), &pts) {
		return 0
	}
	return pts
}

func addCustomWord(chatID int64, userid int, kanji string, kana string) bool {
	wordpts := calcWordPoints(kanji)
	gamedb.CreateSavePoint(addCustomWordSavePoint)
	// Replace any existing custom word with the updated version of it.
	return gamedb.CommitSavePointOnSuccess(addCustomWordSavePoint,
		removeCustomWord(chatID, kanji) &&
			gamedb.Exec(fmt.Sprintf("INSERT INTO %s (chatid, userid, kanji, kana, points) VALUES (?, ?, ?, ?, ?)", customwordsTablename), chatID, userid, kanji, kana, wordpts) &&
			updatePlayerScore(chatID, userid, addWordPts))
}

func removeCustomWord(chatID int64, kanji string) bool {
	// Get userid that submitted the custom word.
	var userid int
	if !gamedb.Query(fmt.Sprintf("SELECT userid from %s where chatid = %d AND kanji = '%s'", customwordsTablename, chatID, kanji), &userid) {
		// Custom word does not exist, so it has been removed.
		return true
	}
	gamedb.CreateSavePoint(removeCustomWordSavePoint)
	return gamedb.CommitSavePointOnSuccess(removeCustomWordSavePoint,
		gamedb.Exec(fmt.Sprintf("DELETE FROM %s WHERE chatid = %d AND kanji = '%s'", customwordsTablename, chatID, kanji)) &&
			updatePlayerScore(chatID, userid, -addWordPts))
}
<commit_msg>Fix crash when looking up a word that is not found.<commit_after>package main

import (
	"database/sql"
	"fmt"
	"regexp"
	"strings"

	_ "github.com/mattn/go-sqlite3"
)

const wordsTablename = "words"
const customwordsTablename = "customwords"
const kanjipointsTablename = "kanjipoints"
const addCustomWordSavePoint = "AddCustomWord"
const removeCustomWordSavePoint = "RemoveCustomWord"
const kanaExp = `(\p{Katakana}|\p{Hiragana}|ー)([ゃャょョゅュ])?`

var wordsdb *sql.DB
var endKanaExp = regexp.MustCompile(fmt.Sprintf("%s$", kanaExp))
var beginKanaExp = regexp.MustCompile(fmt.Sprintf("^%s", kanaExp))
var endsInNExp = regexp.MustCompile(`(ん|ン)$`)

func getWordPts(chatID int64, theWord string, lastEntry *wordEntry) (int, string) {
	// If points are zero or not found, then return zero. Probably ends in 'n', or not a noun.
	kana, pts := lookupKana(chatID, theWord)
	if lastEntry != nil && pts != 0 {
		// Get kana of last word.
		lastEntryKana, _ := lookupKana(chatID, lastEntry.word)
		// If first kana of new word does not match ending kana of last word, then return zero.
		if !matchKana(lastEntryKana, kana) {
			return 0, fmt.Sprintf("初めの仮名は終わりのかなと一致しません: %s「%s」-> %s「%s」", lastEntry.word, lastEntryKana, theWord, kana)
		}
	} else if pts == 0 {
		if endsInN(kana) {
			return pts, fmt.Sprintf("言葉は'ん'が終わることが禁止されています: %s", theWord)
		}
		return pts, fmt.Sprintf("無効言葉: %s", theWord)
	}
	return pts, ""
}

func lookupKana(chatID int64, theWord string) (string, int) {
	found, kana, pts := lookupStandardKana(chatID, theWord)
	if !found || pts == 0 {
		var customkana string
		found, customkana, pts = lookupCustomKana(chatID, theWord)
		if !found {
			return kana, 0
		}
		kana = customkana
	}
	return kana, pts
}

func lookupStandardKana(chatID int64, theWord string) (bool, string, int) {
	var kana string
	var pts int
	found := gamedb.Query(fmt.Sprintf("SELECT kana, points FROM %s WHERE kanji = '%s'", wordsTablename, theWord), &kana, &pts)
	return found, kana, pts
}

func lookupCustomKana(chatID int64, theWord string) (bool, string, int) {
	var kana string
	var pts int
	found := gamedb.Query(fmt.Sprintf("SELECT kana, points FROM %s WHERE chatid = %d AND kanji = '%s'", customwordsTablename, chatID, theWord), &kana, &pts)
	return found, kana, pts
}

func matchKana(lastWordKana string, newWordKana string) bool {
	lastKana := strings.Split(lastWordKana, ",")
	newKana := strings.Split(newWordKana, ",")
	for _, lk := range lastKana {
		endingMatch := endKanaExp.FindStringSubmatch(lk)
		for _, nk := range newKana {
			if endAndBeginMatch(endingMatch, beginKanaExp.FindStringSubmatch(nk)) {
				return true
			}
		}
	}
	return false
}

func endAndBeginMatch(endingMatch []string, beginningMatch []string) bool {
	// If the word ends in a combined phonic (i.e., しゃ), then the
	// next word must begin with that same combination.
	// However, if the word ends in just し, then the next word can
	// optionally start with combined phonic (i.e., しゃ) or just し.
	if len(beginningMatch) < len(endingMatch) {
		return false
	}
	for index := 1; index < len(endingMatch); index++ {
		if len(endingMatch[index]) > 0 && endingMatch[index] != beginningMatch[index] {
			return false
		}
	}
	return true
}

func endsInN(kana string) bool {
	// Check for ending in ん.
	for _, k := range strings.Split(kana, ",") {
		if endsInNExp.MatchString(k) {
			return true
		}
	}
	return false
}

func calcWordPoints(kanji string) int {
	// Words entirely of hiragana or katakana are worth 1 point.
	pts := 1
	if kanjiExp.MatchString(kanji) {
		for _, k := range kanji {
			kpts := getKanjiPoints(string(k))
			if kpts > pts {
				// The word pts is equal to the highest kanji pts in the word.
				pts = kpts
			}
		}
	}
	return pts
}

func getKanjiPoints(kanjiCharacter string) int {
	var pts int
	if !gamedb.Query(fmt.Sprintf("SELECT points FROM %s WHERE kanji = '%s'", kanjipointsTablename, kanjiCharacter), &pts) {
		return 0
	}
	return pts
}

func addCustomWord(chatID int64, userid int, kanji string, kana string) bool {
	wordpts := calcWordPoints(kanji)
	gamedb.CreateSavePoint(addCustomWordSavePoint)
	// Replace any existing custom word with the updated version of it.
	return gamedb.CommitSavePointOnSuccess(addCustomWordSavePoint,
		removeCustomWord(chatID, kanji) &&
			gamedb.Exec(fmt.Sprintf("INSERT INTO %s (chatid, userid, kanji, kana, points) VALUES (?, ?, ?, ?, ?)", customwordsTablename), chatID, userid, kanji, kana, wordpts) &&
			updatePlayerScore(chatID, userid, addWordPts))
}

func removeCustomWord(chatID int64, kanji string) bool {
	// Get userid that submitted the custom word.
	var userid int
	if !gamedb.Query(fmt.Sprintf("SELECT userid from %s where chatid = %d AND kanji = '%s'", customwordsTablename, chatID, kanji), &userid) {
		// Custom word does not exist, so it has been removed.
		return true
	}
	gamedb.CreateSavePoint(removeCustomWordSavePoint)
	return gamedb.CommitSavePointOnSuccess(removeCustomWordSavePoint,
		gamedb.Exec(fmt.Sprintf("DELETE FROM %s WHERE chatid = %d AND kanji = '%s'", customwordsTablename, chatID, kanji)) &&
			updatePlayerScore(chatID, userid, -addWordPts))
}
<|endoftext|>


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

// +build linux,amd64

package fdbased

import (
	"encoding/binary"
	"fmt"
	"syscall"
	"unsafe"

	"github.com/google/netstack/tcpip"
	"github.com/google/netstack/tcpip/buffer"
	"github.com/google/netstack/tcpip/header"
	"github.com/google/netstack/tcpip/link/rawfile"
	"golang.org/x/sys/unix"
)

const (
	tPacketAlignment = uintptr(16)
	tpStatusKernel   = 0
	tpStatusUser     = 1
	tpStatusCopy     = 2
	tpStatusLosing   = 4
)

// We overallocate the frame size to accommodate space for the
// TPacketHdr+RawSockAddrLinkLayer+MAC header and any padding.
//
// Memory allocated for the ring buffer: tpBlockSize * tpBlockNR = 2 MiB
//
// NOTE: Frames need to be aligned at 16 byte boundaries.
const (
	tpFrameSize = 65536 + 128
	tpBlockSize = tpFrameSize * 32
	tpBlockNR   = 1
	tpFrameNR   = (tpBlockSize * tpBlockNR) / tpFrameSize
)

// tPacketAlign aligns the pointer v at a tPacketAlignment boundary. Direct
// translation of the TPACKET_ALIGN macro in <linux/if_packet.h>.
func tPacketAlign(v uintptr) uintptr {
	return (v + tPacketAlignment - 1) & uintptr(^(tPacketAlignment - 1))
}

// tPacketHdrlen is the TPACKET_HDRLEN variable defined in <linux/if_packet.h>.
var tPacketHdrlen = tPacketAlign(unsafe.Sizeof(tPacketHdr{}) + unsafe.Sizeof(syscall.RawSockaddrLinklayer{}))

// tPacketReq is the tpacket_req structure as described in
// https://www.kernel.org/doc/Documentation/networking/packet_mmap.txt
type tPacketReq struct {
	tpBlockSize uint32
	tpBlockNR   uint32
	tpFrameSize uint32
	tpFrameNR   uint32
}

// tPacketHdr is tpacket_hdr structure as described in <linux/if_packet.h>
type tPacketHdr []byte

const (
	tpStatusOffset  = 0
	tpLenOffset     = 8
	tpSnapLenOffset = 12
	tpMacOffset     = 16
	tpNetOffset     = 18
	tpSecOffset     = 20
	tpUSecOffset    = 24
)

func (t tPacketHdr) tpStatus() uint32 {
	return binary.LittleEndian.Uint32(t[tpStatusOffset:])
}

func (t tPacketHdr) setTPStatus(status uint32) {
	binary.LittleEndian.PutUint32(t[tpStatusOffset:], status)
}

func (t tPacketHdr) tpLen() uint32 {
	return binary.LittleEndian.Uint32(t[tpLenOffset:])
}

func (t tPacketHdr) tpSnapLen() uint32 {
	return binary.LittleEndian.Uint32(t[tpSnapLenOffset:])
}

func (t tPacketHdr) tpMac() uint16 {
	return binary.LittleEndian.Uint16(t[tpMacOffset:])
}

func (t tPacketHdr) tpNet() uint16 {
	return binary.LittleEndian.Uint16(t[tpNetOffset:])
}

func (t tPacketHdr) tpSec() uint32 {
	return binary.LittleEndian.Uint32(t[tpSecOffset:])
}

func (t tPacketHdr) tpUSec() uint32 {
	return binary.LittleEndian.Uint32(t[tpUSecOffset:])
}

func (t tPacketHdr) Payload() []byte {
	return t[uint32(t.tpMac()) : uint32(t.tpMac())+t.tpSnapLen()]
}

func (e *endpoint) setupPacketRXRing() error {
	tReq := tPacketReq{
		tpBlockSize: uint32(tpBlockSize),
		tpBlockNR:   uint32(tpBlockNR),
		tpFrameSize: uint32(tpFrameSize),
		tpFrameNR:   uint32(tpFrameNR),
	}
	// Setup PACKET_RX_RING.
	if err := setsockopt(e.fd, syscall.SOL_PACKET, syscall.PACKET_RX_RING, unsafe.Pointer(&tReq), unsafe.Sizeof(tReq)); err != nil {
		return fmt.Errorf("failed to enable PACKET_RX_RING: %v", err)
	}
	// Let's mmap the blocks.
	sz := tpBlockSize * tpBlockNR
	buf, err := syscall.Mmap(e.fd, 0, sz, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
	if err != nil {
		return fmt.Errorf("syscall.Mmap(...,0, %v, ...) failed = %v", sz, err)
	}
	e.ringBuffer = buf
	return nil
}

func (e *endpoint) readMMappedPacket() ([]byte, *tcpip.Error) {
	hdr := (tPacketHdr)(e.ringBuffer[0+e.ringOffset*tpFrameSize:])
	for (hdr.tpStatus() & tpStatusUser) == 0 {
		event := rawfile.PollEvent{
			FD:     int32(e.fd),
			Events: unix.POLLIN | unix.POLLERR,
		}
		_, errno := rawfile.BlockingPoll(&event, 1, -1)
		if errno != 0 {
			if errno == syscall.EINTR {
				continue
			}
			return nil, rawfile.TranslateErrno(errno)
		}
		if hdr.tpStatus()&tpStatusCopy != 0 {
			continue
		}
		if hdr.tpStatus()&tpStatusLosing != 0 {
			continue
		}
	}

	// Copy out the packet from the mmapped frame to a locally owned buffer.
	pkt := make([]byte, hdr.tpSnapLen())
	copy(pkt, hdr.Payload())
	// Release packet to kernel.
	hdr.setTPStatus(tpStatusKernel)
	e.ringOffset = (e.ringOffset + 1) % tpFrameNR
	return pkt, nil
}

// packetMMapDispatch reads packets from an mmaped ring buffer and dispatches
// them to the network stack.
func (e *endpoint) packetMMapDispatch() (bool, *tcpip.Error) {
	pkt, err := e.readMMappedPacket()
	if err != nil {
		return false, err
	}
	var (
		p             tcpip.NetworkProtocolNumber
		remote, local tcpip.LinkAddress
	)
	if e.hdrSize > 0 {
		eth := header.Ethernet(pkt)
		p = eth.Type()
		remote = eth.SourceAddress()
		local = eth.DestinationAddress()
	} else {
		// We don't get any indication of what the packet is, so try to guess
		// if it's an IPv4 or IPv6 packet.
		switch header.IPVersion(pkt) {
		case header.IPv4Version:
			p = header.IPv4ProtocolNumber
		case header.IPv6Version:
			p = header.IPv6ProtocolNumber
		default:
			return true, nil
		}
	}

	pkt = pkt[e.hdrSize:]
	e.dispatcher.DeliverNetworkPacket(e, remote, local, p, buffer.NewVectorisedView(len(pkt), []buffer.View{buffer.View(pkt)}))
	return true, nil
}

func setsockopt(fd, level, name int, val unsafe.Pointer, vallen uintptr) error {
	if _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(val), vallen, 0); errno != 0 {
		return error(errno)
	}

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

// +build linux,amd64

package fdbased

import (
	"encoding/binary"
	"fmt"
	"sync/atomic"
	"syscall"
	"unsafe"

	"github.com/google/netstack/tcpip"
	"github.com/google/netstack/tcpip/buffer"
	"github.com/google/netstack/tcpip/header"
	"github.com/google/netstack/tcpip/link/rawfile"
	"golang.org/x/sys/unix"
)

const (
	tPacketAlignment = uintptr(16)
	tpStatusKernel   = 0
	tpStatusUser     = 1
	tpStatusCopy     = 2
	tpStatusLosing   = 4
)

// We overallocate the frame size to accommodate space for the
// TPacketHdr+RawSockAddrLinkLayer+MAC header and any padding.
//
// Memory allocated for the ring buffer: tpBlockSize * tpBlockNR = 2 MiB
//
// NOTE:
//   Frames need to be aligned at 16 byte boundaries.
//   BlockSize needs to be page aligned.
//
//   For details see PACKET_MMAP setting constraints in
//   https://www.kernel.org/doc/Documentation/networking/packet_mmap.txt
const (
	tpFrameSize = 65536 + 128
	tpBlockSize = tpFrameSize * 32
	tpBlockNR   = 1
	tpFrameNR   = (tpBlockSize * tpBlockNR) / tpFrameSize
)

// tPacketAlign aligns the pointer v at a tPacketAlignment boundary. Direct
// translation of the TPACKET_ALIGN macro in <linux/if_packet.h>.
func tPacketAlign(v uintptr) uintptr {
	return (v + tPacketAlignment - 1) & uintptr(^(tPacketAlignment - 1))
}

// tPacketHdrlen is the TPACKET_HDRLEN variable defined in <linux/if_packet.h>.
var tPacketHdrlen = tPacketAlign(unsafe.Sizeof(tPacketHdr{}) + unsafe.Sizeof(syscall.RawSockaddrLinklayer{}))

// tPacketReq is the tpacket_req structure as described in
// https://www.kernel.org/doc/Documentation/networking/packet_mmap.txt
type tPacketReq struct {
	tpBlockSize uint32
	tpBlockNR   uint32
	tpFrameSize uint32
	tpFrameNR   uint32
}

// tPacketHdr is tpacket_hdr structure as described in <linux/if_packet.h>
type tPacketHdr []byte

const (
	tpStatusOffset  = 0
	tpLenOffset     = 8
	tpSnapLenOffset = 12
	tpMacOffset     = 16
	tpNetOffset     = 18
	tpSecOffset     = 20
	tpUSecOffset    = 24
)

// tpStatus returns the frame status field.
// The status is concurrently updated by the kernel as a result we must
// use atomic operations to prevent races.
func (t tPacketHdr) tpStatus() uint32 {
	hdr := unsafe.Pointer(&t[0])
	statusPtr := unsafe.Pointer(uintptr(hdr) + uintptr(tpStatusOffset))
	return atomic.LoadUint32((*uint32)(statusPtr))
}

// setTPStatus set's the frame status to the provided status.
// The status is concurrently updated by the kernel as a result we must
// use atomic operations to prevent races.
func (t tPacketHdr) setTPStatus(status uint32) {
	hdr := unsafe.Pointer(&t[0])
	statusPtr := unsafe.Pointer(uintptr(hdr) + uintptr(tpStatusOffset))
	atomic.StoreUint32((*uint32)(statusPtr), status)
}

func (t tPacketHdr) tpLen() uint32 {
	return binary.LittleEndian.Uint32(t[tpLenOffset:])
}

func (t tPacketHdr) tpSnapLen() uint32 {
	return binary.LittleEndian.Uint32(t[tpSnapLenOffset:])
}

func (t tPacketHdr) tpMac() uint16 {
	return binary.LittleEndian.Uint16(t[tpMacOffset:])
}

func (t tPacketHdr) tpNet() uint16 {
	return binary.LittleEndian.Uint16(t[tpNetOffset:])
}

func (t tPacketHdr) tpSec() uint32 {
	return binary.LittleEndian.Uint32(t[tpSecOffset:])
}

func (t tPacketHdr) tpUSec() uint32 {
	return binary.LittleEndian.Uint32(t[tpUSecOffset:])
}

func (t tPacketHdr) Payload() []byte {
	return t[uint32(t.tpMac()) : uint32(t.tpMac())+t.tpSnapLen()]
}

func (e *endpoint) setupPacketRXRing() error {
	pageSize := unix.Getpagesize()
	if tpBlockSize%pageSize != 0 {
		return fmt.Errorf("tpBlockSize: %d is not page aligned, pagesize: %d", tpBlockSize, pageSize)
	}
	tReq := tPacketReq{
		tpBlockSize: uint32(tpBlockSize),
		tpBlockNR:   uint32(tpBlockNR),
		tpFrameSize: uint32(tpFrameSize),
		tpFrameNR:   uint32(tpFrameNR),
	}
	// Setup PACKET_RX_RING.
	if err := setsockopt(e.fd, syscall.SOL_PACKET, syscall.PACKET_RX_RING, unsafe.Pointer(&tReq), unsafe.Sizeof(tReq)); err != nil {
		return fmt.Errorf("failed to enable PACKET_RX_RING: %v", err)
	}
	// Let's mmap the blocks.
	sz := tpBlockSize * tpBlockNR
	buf, err := syscall.Mmap(e.fd, 0, sz, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED)
	if err != nil {
		return fmt.Errorf("syscall.Mmap(...,0, %v, ...) failed = %v", sz, err)
	}
	e.ringBuffer = buf
	return nil
}

func (e *endpoint) readMMappedPacket() ([]byte, *tcpip.Error) {
	hdr := (tPacketHdr)(e.ringBuffer[e.ringOffset*tpFrameSize:])
	for hdr.tpStatus()&tpStatusUser == 0 {
		event := rawfile.PollEvent{
			FD:     int32(e.fd),
			Events: unix.POLLIN | unix.POLLERR,
		}
		_, errno := rawfile.BlockingPoll(&event, 1, -1)
		if errno != 0 {
			if errno == syscall.EINTR {
				continue
			}
			return nil, rawfile.TranslateErrno(errno)
		}
		if hdr.tpStatus()&tpStatusCopy != 0 {
			// This frame is truncated so skip it after flipping the
			// buffer to the kernel.
			hdr.setTPStatus(tpStatusKernel)
			e.ringOffset = (e.ringOffset + 1) % tpFrameNR
			hdr = (tPacketHdr)(e.ringBuffer[e.ringOffset*tpFrameSize:])
			continue
		}
	}

	// Copy out the packet from the mmapped frame to a locally owned buffer.
	pkt := make([]byte, hdr.tpSnapLen())
	copy(pkt, hdr.Payload())
	// Release packet to kernel.
	hdr.setTPStatus(tpStatusKernel)
	e.ringOffset = (e.ringOffset + 1) % tpFrameNR
	return pkt, nil
}

// packetMMapDispatch reads packets from an mmaped ring buffer and dispatches
// them to the network stack.
func (e *endpoint) packetMMapDispatch() (bool, *tcpip.Error) {
	pkt, err := e.readMMappedPacket()
	if err != nil {
		return false, err
	}
	var (
		p             tcpip.NetworkProtocolNumber
		remote, local tcpip.LinkAddress
	)
	if e.hdrSize > 0 {
		eth := header.Ethernet(pkt)
		p = eth.Type()
		remote = eth.SourceAddress()
		local = eth.DestinationAddress()
	} else {
		// We don't get any indication of what the packet is, so try to guess
		// if it's an IPv4 or IPv6 packet.
		switch header.IPVersion(pkt) {
		case header.IPv4Version:
			p = header.IPv4ProtocolNumber
		case header.IPv6Version:
			p = header.IPv6ProtocolNumber
		default:
			return true, nil
		}
	}

	pkt = pkt[e.hdrSize:]
	e.dispatcher.DeliverNetworkPacket(e, remote, local, p, buffer.NewVectorisedView(len(pkt), []buffer.View{buffer.View(pkt)}))
	return true, nil
}

func setsockopt(fd, level, name int, val unsafe.Pointer, vallen uintptr) error {
	if _, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(val), vallen, 0); errno != 0 {
		return error(errno)
	}

	return nil
}
<|endoftext|>


<commit_before>package gin

import (
	"log"
	"os"
	"time"
)

func ErrorLogger() HandlerFunc {
	return ErrorLoggerT(ErrorTypeAll)
}

func ErrorLoggerT(typ uint32) HandlerFunc {
	return func(c *Context) {
		c.Next()

		errs := c.Errors.ByType(typ)
		if len(errs) > 0 {
			// -1 status code = do not change current one
			c.JSON(-1, c.Errors)
		}
	}
}

var (
	green  = string([]byte{27, 91, 57, 55, 59, 52, 50, 109})
	white  = string([]byte{27, 91, 57, 48, 59, 52, 55, 109})
	yellow = string([]byte{27, 91, 57, 55, 59, 52, 51, 109})
	red    = string([]byte{27, 91, 57, 55, 59, 52, 49, 109})
	reset  = string([]byte{27, 91, 48, 109})
)

func Logger() HandlerFunc {
	stdlogger := log.New(os.Stdout, "", 0)
	//errlogger := log.New(os.Stderr, "", 0)

	return func(c *Context) {
		// Start timer
		start := time.Now()

		// Process request
		c.Next()

		// save the IP of the requester
		requester := c.Request.Header.Get("X-Real-IP")
		// if the requester-header is empty, check the forwarded-header
		if requester == "" {
			requester = c.Request.Header.Get("X-Forwarded-For")
		}

		// if the requester is still empty, use the hard-coded address from the socket
		if requester == "" {
			requester = c.Request.RemoteAddr
		}

		var color string
		code := c.Writer.Status()
		switch {
		case code >= 200 && code <= 299:
			color = green
		case code >= 300 && code <= 399:
			color = white
		case code >= 400 && code <= 499:
			color = yellow
		default:
			color = red
		}
		end := time.Now()
		latency := end.Sub(start)
		stdlogger.Printf("[GIN] %v |%s %3d %s| %12v | %s %4s %s\n%s",
			end.Format("2006/01/02 - 15:04:05"),
			color, code, reset,
			latency,
			requester,
			c.Request.Method, c.Request.URL.Path,
			c.Errors.String(),
		)
	}
}
<commit_msg>Check existence of X-Forwarded-For by comparing the length<commit_after>package gin

import (
	"log"
	"os"
	"time"
)

func ErrorLogger() HandlerFunc {
	return ErrorLoggerT(ErrorTypeAll)
}

func ErrorLoggerT(typ uint32) HandlerFunc {
	return func(c *Context) {
		c.Next()

		errs := c.Errors.ByType(typ)
		if len(errs) > 0 {
			// -1 status code = do not change current one
			c.JSON(-1, c.Errors)
		}
	}
}

var (
	green  = string([]byte{27, 91, 57, 55, 59, 52, 50, 109})
	white  = string([]byte{27, 91, 57, 48, 59, 52, 55, 109})
	yellow = string([]byte{27, 91, 57, 55, 59, 52, 51, 109})
	red    = string([]byte{27, 91, 57, 55, 59, 52, 49, 109})
	reset  = string([]byte{27, 91, 48, 109})
)

func Logger() HandlerFunc {
	stdlogger := log.New(os.Stdout, "", 0)
	//errlogger := log.New(os.Stderr, "", 0)

	return func(c *Context) {
		// Start timer
		start := time.Now()

		// Process request
		c.Next()

		// save the IP of the requester
		requester := c.Request.Header.Get("X-Real-IP")
		// if the requester-header is empty, check the forwarded-header
		if len(requester) == 0 {
			requester = c.Request.Header.Get("X-Forwarded-For")
		}

		// if the requester is still empty, use the hard-coded address from the socket
		if len(requester) == 0 {
			requester = c.Request.RemoteAddr
		}

		var color string
		code := c.Writer.Status()
		switch {
		case code >= 200 && code <= 299:
			color = green
		case code >= 300 && code <= 399:
			color = white
		case code >= 400 && code <= 499:
			color = yellow
		default:
			color = red
		}
		end := time.Now()
		latency := end.Sub(start)
		stdlogger.Printf("[GIN] %v |%s %3d %s| %12v | %s %4s %s\n%s",
			end.Format("2006/01/02 - 15:04:05"),
			color, code, reset,
			latency,
			requester,
			c.Request.Method, c.Request.URL.Path,
			c.Errors.String(),
		)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/url"
	"time"

	cfclient "github.com/cloudfoundry-community/go-cfclient"
)

func QuotaGauge(c *Client, interval time.Duration) MetricReadCloser {
	return NewMetricPoller(interval, func(w MetricWriter) error {
		orgs, err := c.cf.ListOrgs()
		if err != nil {
			return err
		}

		reservedMemory := 0
		reservedServices := 0
		allocatedMemory := 0
		allocatedServices := 0
		reservedRoutes := 0

		for _, org := range orgs {
			quota, err := org.Quota()
			if err != nil {
				return err
			}
			reservedMemory += quota.MemoryLimit
			reservedServices += quota.TotalServices
			reservedRoutes += quota.TotalRoutes
		}

		apps, err := c.cf.ListApps()
		if err != nil {
			return err
		}
		for _, app := range apps {
			allocatedMemory += (app.Memory * app.Instances)
		}

		allocatedServices, err = c.CountServiceInstances()
		if err != nil {
			return err
		}

		return w.WriteMetrics([]Metric{
			{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.quota.services.reserved", // number of services reserved by quotas
				Value: float64(reservedServices),
			},
			{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.quota.services.allocated", // number of services in use
				Value: float64(allocatedServices),
			},
			{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.quota.memory.reserved", // memory reserved by org quotas
				Value: float64(reservedMemory),
			},
			{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.quota.memory.allocated", // memory allocated to apps
				Value: float64(allocatedMemory),
			},
			{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.quota.routes.reserved", // number of routes reserved
				Value: float64(reservedRoutes),
			},
		})
	})
}

func UserCountGauge(c *Client, interval time.Duration) MetricReadCloser {
	return NewMetricPoller(interval, func(w MetricWriter) error {
		// global auditor role cannot use /v2/users
		// so we have to fetch users from each org
		orgs, err := c.cf.ListOrgs()
		if err != nil {
			return err
		}

		userGuids := map[string]bool{}

		for _, org := range orgs {
			users, err := c.OrgUsers(org.Guid)
			if err != nil {
				return err
			}
			for _, u := range users {
				userGuids[u.Guid] = true
			}
		}

		return w.WriteMetrics([]Metric{
			{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.users.count",
				Value: float64(len(userGuids)),
			},
		})
	})
}

func AppCountGauge(c *Client, interval time.Duration) MetricReadCloser {
	return NewMetricPoller(interval, func(w MetricWriter) error {
		apps, err := c.cf.ListApps()
		if err != nil {
			return err
		}
		spaces, err := c.cf.ListSpaces()
		if err != nil {
			return err
		}
		orgs, err := c.cf.ListOrgs()
		if err != nil {
			return err
		}
		orgQuotas, err := c.cf.ListOrgQuotas()
		if err != nil {
			return err
		}

		// Number of relevant apps in
		// - APP_STATE: string of whether each app is "started" or "stopped"
		// - ORG_IS_TRIAL: boolean of whether each app is owned by a trial organisation
		// counters[APP_STATE][ORG_IS_TRIAL]
		counters := map[string]map[bool]int{
			"started": map[bool]int{},
			"stopped": map[bool]int{},
		}
		for _, app := range apps {
			space := findSpace(spaces, app.SpaceGuid)
			if space == nil {
				log.Printf("Space was not found for app %s\n", app.Guid)
				continue
			}
			org := findOrg(orgs, space.OrganizationGuid)
			if org == nil {
				log.Printf("Org was not found for app %s in space %s\n", app.Guid, space.Guid)
				continue
			}
			orgQuota := findOrgQuota(orgQuotas, org.QuotaDefinitionGuid)
			if orgQuota == nil {
				log.Printf("Org Quota was not found for app %s in org %s\n", app.Guid, org.Guid)
				continue
			}
			orgIsTrial := isOrgQuotaTrial(orgQuota)
			if app.State == "STARTED" {
				counters["started"][orgIsTrial]++
			}
			if app.State == "STOPPED" {
				counters["stopped"][orgIsTrial]++
			}
		}

		metrics := []Metric{}
		for state, countByTrial := range counters {
			for orgIsTrial, count := range countByTrial {
				metrics = append(metrics, Metric{
					Kind:  Gauge,
					Time:  time.Now(),
					Name:  "op.apps.count",
					Value: float64(count),
					Tags: []string{
						"state:" + state,
						fmt.Sprintf("trial_org:%t", orgIsTrial),
					},
				})
			}
		}
		return w.WriteMetrics(metrics)
	})
}

func ServiceCountGauge(c *Client, interval time.Duration) MetricReadCloser {
	return NewMetricPoller(interval, func(w MetricWriter) error {
		serviceInstances, err := c.cf.ListServiceInstances()
		if err != nil {
			return err
		}
		services, err := c.cf.ListServices()
		if err != nil {
			return nil
		}
		servicePlans, err := c.cf.ListServicePlans()
		if err != nil {
			return nil
		}
		spaces, err := c.cf.ListSpaces()
		if err != nil {
			return err
		}
		orgs, err := c.cf.ListOrgs()
		if err != nil {
			return err
		}
		orgQuotas, err := c.cf.ListOrgQuotas()
		if err != nil {
			return err
		}

		// Number of relevant service instances in
		// - ORG_IS_TRIAL: boolean of whether each instance is owned by a trial organisation
		// - SERVICE_PLAN_IS_FREE: whether the instance's service plan is free
		// - NAME_OF_SERVICE: e.g., "mysql" or "postgres"
		// counters[ORG_IS_TRIAL][SERVICE_PLAN_IS_FREE][NAME_OF_SERVICE]
		counters := map[bool]map[bool]map[string]int{
			true: map[bool]map[string]int{
				true:  map[string]int{},
				false: map[string]int{},
			},
			false: map[bool]map[string]int{
				true:  map[string]int{},
				false: map[string]int{},
			},
		}
		for _, instance := range serviceInstances {
			service := findService(services, instance.ServiceGuid)
			if service == nil {
				log.Printf("Service was not found for service instance %s\n", instance.Guid)
				continue
			}
			if service.Label == "" {
				log.Printf("Service label was empty for service %s and service instance %s\n", service.Guid, instance.Guid)
				continue
			}
			servicePlan := findServicePlan(servicePlans, instance.ServicePlanGuid)
			if servicePlan == nil {
				log.Printf("Error finding service plan for service instance %s: %s\n", instance.Guid, err)
				continue
			}
			space := findSpace(spaces, instance.SpaceGuid)
			if space == nil {
				log.Printf("Space was not found for service instance %s\n", instance.Guid)
				continue
			}
			org := findOrg(orgs, space.OrganizationGuid)
			if org == nil {
				log.Printf("Org was not found for service instance %s in space %s\n", instance.Guid, space.Guid)
				continue
			}
			orgQuota := findOrgQuota(orgQuotas, org.QuotaDefinitionGuid)
			if err != nil {
				log.Printf("Org Quota was not found for service instance %s in org %s\n", instance.Guid, org.Guid)
				continue
			}
			orgIsTrial := isOrgQuotaTrial(orgQuota)
			servicePlanIsFree := isServicePlanFree(servicePlan)
			counters[orgIsTrial][servicePlanIsFree][service.Label]++
		}

		metrics := []Metric{}
		for orgIsTrial, x := range counters {
			for servicePlanIsFree, y := range x {
				for serviceLabel, count := range y {
					metrics = append(metrics, Metric{
						Kind:  Gauge,
						Time:  time.Now(),
						Name:  "op.services.provisioned",
						Value: float64(count),
						Tags: []string{
							"type:" + serviceLabel,
							fmt.Sprintf("trial_org:%t", orgIsTrial),
							fmt.Sprintf("free_service:%t", servicePlanIsFree),
						},
					})
				}
			}
		}
		return w.WriteMetrics(metrics)
	})
}

func OrgCountGauge(c *Client, interval time.Duration) MetricReadCloser {
	return NewMetricPoller(interval, func(w MetricWriter) error {
		orgs, err := c.cf.ListOrgs()
		if err != nil {
			return err
		}
		counters := map[string]int{}
		for _, org := range orgs {
			quota, err := org.Quota()
			if err != nil {
				log.Printf("Error finding org quota for org %s: %s\n", org.Guid, err)
				continue
			}
			counters[quota.Name]++
		}
		metrics := []Metric{}
		for name, count := range counters {
			metrics = append(metrics, Metric{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.orgs.count",
				Value: float64(count),
				Tags:  []string{"quota:" + name},
			})
		}
		return w.WriteMetrics(metrics)
	})
}

func SpaceCountGauge(c *Client, interval time.Duration) MetricReadCloser {
	return NewMetricPoller(interval, func(w MetricWriter) error {
		spaces, err := c.cf.ListSpaces()
		if err != nil {
			return err
		}
		return w.WriteMetrics([]Metric{
			{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.spaces.count",
				Value: float64(len(spaces)),
			},
		})
	})
}

func EventCountGauge(c *Client, eventType string, interval time.Duration) MetricReadCloser {
	return NewMetricPoller(interval, func(w MetricWriter) error {
		u, err := url.Parse("/v2/events")
		if err != nil {
			return err
		}
		maxAge := time.Now().Add(-1 * interval)
		q := u.Query()
		q.Set("order-direction", "desc")
		q.Set("results-per-page", "100")
		q.Add("q", "type:"+eventType)
		q.Add("q", "timestamp>"+maxAge.Format(time.RFC3339Nano))
		u.RawQuery = q.Encode()
		batchUrl := u.String()
		gauge := Metric{
			Time: time.Now(),
			Kind: Gauge,
			Name: "op.events." + eventType,
		}
		for batchUrl != "" {
			var batch struct {
				NextUrl   string          `json:"next_url"`
				Resources []AppUsageEvent `json:"resources"`
			}
			if err := c.get(batchUrl, &batch); err != nil {
				return err
			}
			for _, res := range batch.Resources {
				if res.MetaData.CreatedAt.Before(maxAge) {
					break
				}
				gauge.Value += 1
			}
			batchUrl = batch.NextUrl
		}
		return w.WriteMetrics([]Metric{gauge})
	})
}

func findService(services []cfclient.Service, guid string) *cfclient.Service {
	for _, service := range services {
		if service.Guid == guid {
			return &service
		}
	}
	return nil
}

func findServicePlan(servicePlans []cfclient.ServicePlan, guid string) *cfclient.ServicePlan {
	for _, servicePlan := range servicePlans {
		if servicePlan.Guid == guid {
			return &servicePlan
		}
	}
	return nil
}

func findSpace(spaces []cfclient.Space, guid string) *cfclient.Space {
	for _, space := range spaces {
		if space.Guid == guid {
			return &space
		}
	}
	return nil
}

func findOrg(orgs []cfclient.Org, guid string) *cfclient.Org {
	for _, org := range orgs {
		if org.Guid == guid {
			return &org
		}
	}
	return nil
}

func findOrgQuota(orgQuotas []cfclient.OrgQuota, guid string) *cfclient.OrgQuota {
	for _, orgQuota := range orgQuotas {
		if orgQuota.Guid == guid {
			return &orgQuota
		}
	}
	return nil
}

// Determine if an organisation is on a trial plan.
func isOrgQuotaTrial(quota *cfclient.OrgQuota) bool {
	return quota.Name == "default"
}

// Determine if a service plan is free.
func isServicePlanFree(plan *cfclient.ServicePlan) bool {
	return plan.Name == "Free"
}
<commit_msg>Update the names considered free in the gauges<commit_after>package main

import (
	"fmt"
	"log"
	"net/url"
	"strings"
	"time"

	cfclient "github.com/cloudfoundry-community/go-cfclient"
)

func QuotaGauge(c *Client, interval time.Duration) MetricReadCloser {
	return NewMetricPoller(interval, func(w MetricWriter) error {
		orgs, err := c.cf.ListOrgs()
		if err != nil {
			return err
		}

		reservedMemory := 0
		reservedServices := 0
		allocatedMemory := 0
		allocatedServices := 0
		reservedRoutes := 0

		for _, org := range orgs {
			quota, err := org.Quota()
			if err != nil {
				return err
			}
			reservedMemory += quota.MemoryLimit
			reservedServices += quota.TotalServices
			reservedRoutes += quota.TotalRoutes
		}

		apps, err := c.cf.ListApps()
		if err != nil {
			return err
		}
		for _, app := range apps {
			allocatedMemory += (app.Memory * app.Instances)
		}

		allocatedServices, err = c.CountServiceInstances()
		if err != nil {
			return err
		}

		return w.WriteMetrics([]Metric{
			{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.quota.services.reserved", // number of services reserved by quotas
				Value: float64(reservedServices),
			},
			{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.quota.services.allocated", // number of services in use
				Value: float64(allocatedServices),
			},
			{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.quota.memory.reserved", // memory reserved by org quotas
				Value: float64(reservedMemory),
			},
			{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.quota.memory.allocated", // memory allocated to apps
				Value: float64(allocatedMemory),
			},
			{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.quota.routes.reserved", // number of routes reserved
				Value: float64(reservedRoutes),
			},
		})
	})
}

func UserCountGauge(c *Client, interval time.Duration) MetricReadCloser {
	return NewMetricPoller(interval, func(w MetricWriter) error {
		// global auditor role cannot use /v2/users
		// so we have to fetch users from each org
		orgs, err := c.cf.ListOrgs()
		if err != nil {
			return err
		}

		userGuids := map[string]bool{}

		for _, org := range orgs {
			users, err := c.OrgUsers(org.Guid)
			if err != nil {
				return err
			}
			for _, u := range users {
				userGuids[u.Guid] = true
			}
		}

		return w.WriteMetrics([]Metric{
			{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.users.count",
				Value: float64(len(userGuids)),
			},
		})
	})
}

func AppCountGauge(c *Client, interval time.Duration) MetricReadCloser {
	return NewMetricPoller(interval, func(w MetricWriter) error {
		apps, err := c.cf.ListApps()
		if err != nil {
			return err
		}
		spaces, err := c.cf.ListSpaces()
		if err != nil {
			return err
		}
		orgs, err := c.cf.ListOrgs()
		if err != nil {
			return err
		}
		orgQuotas, err := c.cf.ListOrgQuotas()
		if err != nil {
			return err
		}

		// Number of relevant apps in
		// - APP_STATE: string of whether each app is "started" or "stopped"
		// - ORG_IS_TRIAL: boolean of whether each app is owned by a trial organisation
		// counters[APP_STATE][ORG_IS_TRIAL]
		counters := map[string]map[bool]int{
			"started": map[bool]int{},
			"stopped": map[bool]int{},
		}
		for _, app := range apps {
			space := findSpace(spaces, app.SpaceGuid)
			if space == nil {
				log.Printf("Space was not found for app %s\n", app.Guid)
				continue
			}
			org := findOrg(orgs, space.OrganizationGuid)
			if org == nil {
				log.Printf("Org was not found for app %s in space %s\n", app.Guid, space.Guid)
				continue
			}
			orgQuota := findOrgQuota(orgQuotas, org.QuotaDefinitionGuid)
			if orgQuota == nil {
				log.Printf("Org Quota was not found for app %s in org %s\n", app.Guid, org.Guid)
				continue
			}
			orgIsTrial := isOrgQuotaTrial(orgQuota)
			if app.State == "STARTED" {
				counters["started"][orgIsTrial]++
			}
			if app.State == "STOPPED" {
				counters["stopped"][orgIsTrial]++
			}
		}

		metrics := []Metric{}
		for state, countByTrial := range counters {
			for orgIsTrial, count := range countByTrial {
				metrics = append(metrics, Metric{
					Kind:  Gauge,
					Time:  time.Now(),
					Name:  "op.apps.count",
					Value: float64(count),
					Tags: []string{
						"state:" + state,
						fmt.Sprintf("trial_org:%t", orgIsTrial),
					},
				})
			}
		}
		return w.WriteMetrics(metrics)
	})
}

func ServiceCountGauge(c *Client, interval time.Duration) MetricReadCloser {
	return NewMetricPoller(interval, func(w MetricWriter) error {
		serviceInstances, err := c.cf.ListServiceInstances()
		if err != nil {
			return err
		}
		services, err := c.cf.ListServices()
		if err != nil {
			return nil
		}
		servicePlans, err := c.cf.ListServicePlans()
		if err != nil {
			return nil
		}
		spaces, err := c.cf.ListSpaces()
		if err != nil {
			return err
		}
		orgs, err := c.cf.ListOrgs()
		if err != nil {
			return err
		}
		orgQuotas, err := c.cf.ListOrgQuotas()
		if err != nil {
			return err
		}

		// Number of relevant service instances in
		// - ORG_IS_TRIAL: boolean of whether each instance is owned by a trial organisation
		// - SERVICE_PLAN_IS_FREE: whether the instance's service plan is free
		// - NAME_OF_SERVICE: e.g., "mysql" or "postgres"
		// counters[ORG_IS_TRIAL][SERVICE_PLAN_IS_FREE][NAME_OF_SERVICE]
		counters := map[bool]map[bool]map[string]int{
			true: map[bool]map[string]int{
				true:  map[string]int{},
				false: map[string]int{},
			},
			false: map[bool]map[string]int{
				true:  map[string]int{},
				false: map[string]int{},
			},
		}
		for _, instance := range serviceInstances {
			service := findService(services, instance.ServiceGuid)
			if service == nil {
				log.Printf("Service was not found for service instance %s\n", instance.Guid)
				continue
			}
			if service.Label == "" {
				log.Printf("Service label was empty for service %s and service instance %s\n", service.Guid, instance.Guid)
				continue
			}
			servicePlan := findServicePlan(servicePlans, instance.ServicePlanGuid)
			if servicePlan == nil {
				log.Printf("Error finding service plan for service instance %s: %s\n", instance.Guid, err)
				continue
			}
			space := findSpace(spaces, instance.SpaceGuid)
			if space == nil {
				log.Printf("Space was not found for service instance %s\n", instance.Guid)
				continue
			}
			org := findOrg(orgs, space.OrganizationGuid)
			if org == nil {
				log.Printf("Org was not found for service instance %s in space %s\n", instance.Guid, space.Guid)
				continue
			}
			orgQuota := findOrgQuota(orgQuotas, org.QuotaDefinitionGuid)
			if err != nil {
				log.Printf("Org Quota was not found for service instance %s in org %s\n", instance.Guid, org.Guid)
				continue
			}
			orgIsTrial := isOrgQuotaTrial(orgQuota)
			servicePlanIsFree := isServicePlanFree(servicePlan)
			counters[orgIsTrial][servicePlanIsFree][service.Label]++
		}

		metrics := []Metric{}
		for orgIsTrial, x := range counters {
			for servicePlanIsFree, y := range x {
				for serviceLabel, count := range y {
					metrics = append(metrics, Metric{
						Kind:  Gauge,
						Time:  time.Now(),
						Name:  "op.services.provisioned",
						Value: float64(count),
						Tags: []string{
							"type:" + serviceLabel,
							fmt.Sprintf("trial_org:%t", orgIsTrial),
							fmt.Sprintf("free_service:%t", servicePlanIsFree),
						},
					})
				}
			}
		}
		return w.WriteMetrics(metrics)
	})
}

func OrgCountGauge(c *Client, interval time.Duration) MetricReadCloser {
	return NewMetricPoller(interval, func(w MetricWriter) error {
		orgs, err := c.cf.ListOrgs()
		if err != nil {
			return err
		}
		counters := map[string]int{}
		for _, org := range orgs {
			quota, err := org.Quota()
			if err != nil {
				log.Printf("Error finding org quota for org %s: %s\n", org.Guid, err)
				continue
			}
			counters[quota.Name]++
		}
		metrics := []Metric{}
		for name, count := range counters {
			metrics = append(metrics, Metric{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.orgs.count",
				Value: float64(count),
				Tags:  []string{"quota:" + name},
			})
		}
		return w.WriteMetrics(metrics)
	})
}

func SpaceCountGauge(c *Client, interval time.Duration) MetricReadCloser {
	return NewMetricPoller(interval, func(w MetricWriter) error {
		spaces, err := c.cf.ListSpaces()
		if err != nil {
			return err
		}
		return w.WriteMetrics([]Metric{
			{
				Kind:  Gauge,
				Time:  time.Now(),
				Name:  "op.spaces.count",
				Value: float64(len(spaces)),
			},
		})
	})
}

func EventCountGauge(c *Client, eventType string, interval time.Duration) MetricReadCloser {
	return NewMetricPoller(interval, func(w MetricWriter) error {
		u, err := url.Parse("/v2/events")
		if err != nil {
			return err
		}
		maxAge := time.Now().Add(-1 * interval)
		q := u.Query()
		q.Set("order-direction", "desc")
		q.Set("results-per-page", "100")
		q.Add("q", "type:"+eventType)
		q.Add("q", "timestamp>"+maxAge.Format(time.RFC3339Nano))
		u.RawQuery = q.Encode()
		batchUrl := u.String()
		gauge := Metric{
			Time: time.Now(),
			Kind: Gauge,
			Name: "op.events." + eventType,
		}
		for batchUrl != "" {
			var batch struct {
				NextUrl   string          `json:"next_url"`
				Resources []AppUsageEvent `json:"resources"`
			}
			if err := c.get(batchUrl, &batch); err != nil {
				return err
			}
			for _, res := range batch.Resources {
				if res.MetaData.CreatedAt.Before(maxAge) {
					break
				}
				gauge.Value += 1
			}
			batchUrl = batch.NextUrl
		}
		return w.WriteMetrics([]Metric{gauge})
	})
}

func findService(services []cfclient.Service, guid string) *cfclient.Service {
	for _, service := range services {
		if service.Guid == guid {
			return &service
		}
	}
	return nil
}

func findServicePlan(servicePlans []cfclient.ServicePlan, guid string) *cfclient.ServicePlan {
	for _, servicePlan := range servicePlans {
		if servicePlan.Guid == guid {
			return &servicePlan
		}
	}
	return nil
}

func findSpace(spaces []cfclient.Space, guid string) *cfclient.Space {
	for _, space := range spaces {
		if space.Guid == guid {
			return &space
		}
	}
	return nil
}

func findOrg(orgs []cfclient.Org, guid string) *cfclient.Org {
	for _, org := range orgs {
		if org.Guid == guid {
			return &org
		}
	}
	return nil
}

func findOrgQuota(orgQuotas []cfclient.OrgQuota, guid string) *cfclient.OrgQuota {
	for _, orgQuota := range orgQuotas {
		if orgQuota.Guid == guid {
			return &orgQuota
		}
	}
	return nil
}

// Determine if an organisation is on a trial plan.
func isOrgQuotaTrial(quota *cfclient.OrgQuota) bool {
	return quota.Name == "default"
}

// Determine if a service plan is free.
func isServicePlanFree(plan *cfclient.ServicePlan) bool {
	return strings.HasPrefix(plan.Name, "tiny-")
}
<|endoftext|>


<commit_before>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package main

import (
	"archive/zip"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"os"
	"regexp"
	"runtime"
	"sync"
	"sync/atomic"
	"time"

	"github.com/google/syzkaller/ipc"
	"github.com/google/syzkaller/prog"
)

var (
	flagCorpus   = flag.String("corpus", "", "corpus directory")
	flagExecutor = flag.String("executor", "", "path to executor binary")
	flagOutput   = flag.Bool("output", false, "print executor output to console")
	flagDebug    = flag.Bool("debug", false, "executor debug output")
	flagProcs    = flag.Int("procs", 2*runtime.NumCPU(), "number of parallel processes")
	flagThreaded = flag.Bool("threaded", true, "use threaded mode in executor")
	flagCollide  = flag.Bool("collide", true, "collide syscalls to provoke data races")
	flagNobody   = flag.Bool("nobody", true, "impersonate into nobody")
	flagNoPgid   = flag.Bool("nopgid", false, "don't use setpgid syscall")
	flagTimeout  = flag.Duration("timeout", 10*time.Second, "executor timeout")
	flagLogProg  = flag.Bool("logprog", false, "print programs before execution")

	failedRe = regexp.MustCompile("runtime error: |panic: |Panic: ")

	statExec uint64
	gate     *ipc.Gate
)

const programLength = 30

func main() {
	flag.Parse()
	corpus := readCorpus()
	log.Printf("parsed %v programs", len(corpus))
	var flags uint64
	if *flagThreaded {
		flags |= ipc.FlagThreaded
	}
	if *flagCollide {
		flags |= ipc.FlagCollide
	}
	if *flagNobody {
		flags |= ipc.FlagDropPrivs
	}
	if *flagDebug {
		flags |= ipc.FlagDebug
	}
	if *flagNoPgid {
		flags |= ipc.FlagNoSetpgid
	}

	gate = ipc.NewGate(2 * *flagProcs)
	for pid := 0; pid < *flagProcs; pid++ {
		pid := pid
		go func() {
			env, err := ipc.MakeEnv(*flagExecutor, *flagTimeout, flags)
			if err != nil {
				failf("failed to create execution environment: %v", err)
			}
			rs := rand.NewSource(time.Now().UnixNano() + int64(pid)*1e12)
			rnd := rand.New(rs)
			for i := 0; ; i++ {
				var p *prog.Prog
				if len(corpus) == 0 || i%2 != 0 {
					p = prog.Generate(rs, programLength, nil)
					execute(pid, env, p)
					p.Mutate(rs, programLength, nil)
					execute(pid, env, p)
				} else {
					p = corpus[rnd.Intn(len(corpus))].Clone()
					p.Mutate(rs, programLength, nil)
					execute(pid, env, p)
					p.Mutate(rs, programLength, nil)
					execute(pid, env, p)
				}
			}
		}()
	}
	for range time.NewTicker(5 * time.Second).C {
		log.Printf("executed %v programs", atomic.LoadUint64(&statExec))
	}
}

var outMu sync.Mutex

func execute(pid int, env *ipc.Env, p *prog.Prog) {
	if *flagExecutor == "" {
		return
	}
	atomic.AddUint64(&statExec, 1)
	if *flagLogProg {
		ticket := gate.Enter()
		defer gate.Leave(ticket, nil)
		outMu.Lock()
		fmt.Printf("executing program %v\n%s\n", pid, p.Serialize())
		outMu.Unlock()
	}

	output, _, _, _, _, _, err := env.Exec(p)
	if err != nil {
		fmt.Printf("failed to execute executor: %v\n", err)
	}
	failed := failedRe.Match(output)
	if failed {
		fmt.Printf("PROGRAM:\n%s\n", p.Serialize())
	}
	if failed || *flagOutput {
		os.Stdout.Write(output)
	}
}

func readCorpus() []*prog.Prog {
	if *flagCorpus == "" {
		return nil
	}
	zipr, err := zip.OpenReader(*flagCorpus)
	if err != nil {
		failf("failed to open bin file: %v", err)
	}
	var progs []*prog.Prog
	for _, zipf := range zipr.File {
		r, err := zipf.Open()
		if err != nil {
			failf("failed to uzip file from input archive: %v", err)
		}
		data, err := ioutil.ReadAll(r)
		if err != nil {
			failf("failed to read corpus file: %v", err)
		}
		p, err := prog.Deserialize(data)
		if err != nil {
			failf("failed to deserialize corpus program: %v", err)
		}
		progs = append(progs, p)
		r.Close()
	}
	zipr.Close()
	return progs
}

func failf(msg string, args ...interface{}) {
	log.Fatalf(msg, args...)
}
<commit_msg>tools/stress: disable unsupported syscalls<commit_after>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package main

import (
	"archive/zip"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"os"
	"regexp"
	"runtime"
	"sync"
	"sync/atomic"
	"time"

	"github.com/google/syzkaller/host"
	"github.com/google/syzkaller/ipc"
	"github.com/google/syzkaller/prog"
	"github.com/google/syzkaller/sys"
)

var (
	flagCorpus   = flag.String("corpus", "", "corpus directory")
	flagExecutor = flag.String("executor", "", "path to executor binary")
	flagOutput   = flag.Bool("output", false, "print executor output to console")
	flagDebug    = flag.Bool("debug", false, "executor debug output")
	flagProcs    = flag.Int("procs", 2*runtime.NumCPU(), "number of parallel processes")
	flagThreaded = flag.Bool("threaded", true, "use threaded mode in executor")
	flagCollide  = flag.Bool("collide", true, "collide syscalls to provoke data races")
	flagNobody   = flag.Bool("nobody", true, "impersonate into nobody")
	flagNoPgid   = flag.Bool("nopgid", false, "don't use setpgid syscall")
	flagTimeout  = flag.Duration("timeout", 10*time.Second, "executor timeout")
	flagLogProg  = flag.Bool("logprog", false, "print programs before execution")

	failedRe = regexp.MustCompile("runtime error: |panic: |Panic: ")

	statExec uint64
	gate     *ipc.Gate
)

const programLength = 30

func main() {
	flag.Parse()
	corpus := readCorpus()
	log.Printf("parsed %v programs", len(corpus))

	calls := buildCallList()
	prios := prog.CalculatePriorities(corpus)
	ct := prog.BuildChoiceTable(prios, calls)

	var flags uint64
	if *flagThreaded {
		flags |= ipc.FlagThreaded
	}
	if *flagCollide {
		flags |= ipc.FlagCollide
	}
	if *flagNobody {
		flags |= ipc.FlagDropPrivs
	}
	if *flagDebug {
		flags |= ipc.FlagDebug
	}
	if *flagNoPgid {
		flags |= ipc.FlagNoSetpgid
	}

	gate = ipc.NewGate(2 * *flagProcs)
	for pid := 0; pid < *flagProcs; pid++ {
		pid := pid
		go func() {
			env, err := ipc.MakeEnv(*flagExecutor, *flagTimeout, flags)
			if err != nil {
				failf("failed to create execution environment: %v", err)
			}
			rs := rand.NewSource(time.Now().UnixNano() + int64(pid)*1e12)
			rnd := rand.New(rs)
			for i := 0; ; i++ {
				var p *prog.Prog
				if len(corpus) == 0 || i%4 != 0 {
					p = prog.Generate(rs, programLength, ct)
					execute(pid, env, p)
					p.Mutate(rs, programLength, ct)
					execute(pid, env, p)
				} else {
					p = corpus[rnd.Intn(len(corpus))].Clone()
					p.Mutate(rs, programLength, ct)
					execute(pid, env, p)
					p.Mutate(rs, programLength, ct)
					execute(pid, env, p)
				}
			}
		}()
	}
	for range time.NewTicker(5 * time.Second).C {
		log.Printf("executed %v programs", atomic.LoadUint64(&statExec))
	}
}

var outMu sync.Mutex

func execute(pid int, env *ipc.Env, p *prog.Prog) {
	if *flagExecutor == "" {
		return
	}
	atomic.AddUint64(&statExec, 1)
	if *flagLogProg {
		ticket := gate.Enter()
		defer gate.Leave(ticket, nil)
		outMu.Lock()
		fmt.Printf("executing program %v\n%s\n", pid, p.Serialize())
		outMu.Unlock()
	}

	output, _, _, _, _, _, err := env.Exec(p)
	if err != nil {
		fmt.Printf("failed to execute executor: %v\n", err)
	}
	failed := failedRe.Match(output)
	if failed {
		fmt.Printf("PROGRAM:\n%s\n", p.Serialize())
	}
	if failed || *flagOutput {
		os.Stdout.Write(output)
	}
}

func readCorpus() []*prog.Prog {
	if *flagCorpus == "" {
		return nil
	}
	zipr, err := zip.OpenReader(*flagCorpus)
	if err != nil {
		failf("failed to open bin file: %v", err)
	}
	var progs []*prog.Prog
	for _, zipf := range zipr.File {
		r, err := zipf.Open()
		if err != nil {
			failf("failed to uzip file from input archive: %v", err)
		}
		data, err := ioutil.ReadAll(r)
		if err != nil {
			failf("failed to read corpus file: %v", err)
		}
		p, err := prog.Deserialize(data)
		if err != nil {
			failf("failed to deserialize corpus program: %v", err)
		}
		progs = append(progs, p)
		r.Close()
	}
	zipr.Close()
	return progs
}

func buildCallList() map[*sys.Call]bool {
	calls, err := host.DetectSupportedSyscalls()
	if err != nil {
		log.Printf("failed to detect host supported syscalls: %v", err)
		for _, c := range sys.Calls {
			calls[c] = true
		}
	}
	for _, c := range sys.Calls {
		if !calls[c] {
			log.Printf("disabling unsupported syscall: %v", c.Name)
		}
	}
	trans := sys.TransitivelyEnabledCalls(calls)
	for c := range calls {
		if !trans[c] {
			log.Printf("disabling transitively unsupported syscall: %v", c.Name)
			delete(calls, c)
		}
	}
	return calls
}

func failf(msg string, args ...interface{}) {
	log.Fatalf(msg, args...)
}
<|endoftext|>


<commit_before>package rx

import (
	"time"
)

// This example guides code generation by explicitly using the generics we want expanded into this package.
func Example_generate() {
	/*
		Observable Types
	*/

	var o Observable
	var b ObservableBool
	var i ObservableInt
	var oo ObservableObservable

	/*
		Observable Operator Methods
	*/

	o.All(func(next interface{}) bool { return true })
	o.AsObservableBool()
	o.AsObservableInt()
	b.AsObservable()
	i.AsObservable()
	i.Average()
	o.Catch(o)
	oo.CombineAll()
	o.Concat()
	oo.ConcatAll()
	o.Count()
	o.Debounce(time.Millisecond)
	o.Delay(time.Millisecond)
	o.Distinct()
	o.Do(func(interface{}) {})
	o.DoOnComplete(func() {})
	o.DoOnError(func(error) {})
	o.ElementAt(0)
	o.Filter(func(interface{}) bool { return true })
	o.Finally(func() {})
	o.First()
	o.IgnoreCompletion()
	o.IgnoreElements()
	o.Last()
	o.Map(func(interface{}) interface{} { return zero })
	i.MapObservable(func(int) Observable { return zeroObservable })
	i.Max()
	o.Merge()
	oo.MergeAll()
	o.MergeDelayError()
	o.MergeMap(func(interface{}) Observable { return o })
	i.Min()
	o.ObserveOn(CurrentGoroutineScheduler())
	o.OnlyBool()
	o.OnlyInt()
	// Passthrough
	o.Reduce(func(acc interface{}, value interface{}) interface{} { return zero }, zero)
	o.Repeat(1)
	o.Retry()
	o.Sample(time.Millisecond)
	o.Scan(func(acc interface{}, value interface{}) interface{} { return zero }, zero)
	// Serialize
	o.Single()
	o.Skip(1)
	o.SkipLast(1)
	o.SubscribeOn(CurrentGoroutineScheduler())
	i.Sum()
	oo.SwitchAll()
	o.SwitchMap(func(interface{}) Observable { return o })
	o.Take(1)
	i.Take(1)
	o.TakeLast(1)
	o.TakeUntil(o)
	o.TakeWhile(func(interface{}) bool { return true })
	o.Timeout(time.Millisecond)

	/*
		Observable Create Functions
	*/

	Create(func(Observer) {})
	Defer(func() Observable { return o })
	Empty()
	Error(RxError("sad"))
	From(1, 2)
	FromChan(make(chan interface{}))
	FromSlice([]interface{}{1, 2})
	Froms(1, 2)
	Interval(time.Millisecond)
	Just(1)
	Concat(o)
	Merge(o)
	Never()
	Range(1, 2)
	Repeat(zero, 1)
	Start(func() (interface{}, error) { return o, nil })
	Throw(RxError("sad"))

	/*
		Observable Subscribe Methods
	*/

	// Println
	o.Println()
	b.Println()
	i.Println()
	o.Subscribe(func(interface{}, error, bool) {})
	b.Subscribe(func(bool, error, bool) {})
	i.Subscribe(func(int, error, bool) {})
	o.SubscribeNext(func(interface{}) {})
	b.SubscribeNext(func(bool) {})
	i.SubscribeNext(func(int) {})
	o.ToChan()
	b.ToChan()
	i.ToChan()
	o.ToSingle()
	b.ToSingle()
	i.ToSingle()
	o.ToSlice()
	b.ToSlice()
	i.ToSlice()
	o.Wait()
	b.Wait()
	i.Wait()

	/*
		Connectable Types, Operator Methods and Subscribe Methods
	*/

	// var c Connectable
	// o.Publish()
	// p.PublishReplay()
	// c.Connect()
	// c.AutoConnect()
	// c.RefCount()

	/*
		Subject Types
	*/

	// Subject
	// ReplaySubject
}
<commit_msg>Change the way the expansion of rx/generics library is done with jig.<commit_after>package rx

import (
	"testing"
	"time"
)

func TestGenerate(t *testing.T) {
	// This test sole purpose is to guide code generation by explicitly using
	// the generics we want expanded into this package.
	return

	/*
		Observable Types
	*/

	var o Observable
	var b ObservableBool
	var i ObservableInt
	var oo ObservableObservable

	/*
		Observable Operator Methods
	*/

	o.All(func(next interface{}) bool { return true })
	o.AsObservableBool()
	o.AsObservableInt()
	b.AsObservable()
	i.AsObservable()
	i.Average()
	o.Catch(o)
	oo.CombineAll()
	o.Concat()
	oo.ConcatAll()
	o.Count()
	o.Debounce(time.Millisecond)
	o.Delay(time.Millisecond)
	o.Distinct()
	o.Do(func(interface{}) {})
	o.DoOnComplete(func() {})
	o.DoOnError(func(error) {})
	o.ElementAt(0)
	o.Filter(func(interface{}) bool { return true })
	o.Finally(func() {})
	o.First()
	o.IgnoreCompletion()
	o.IgnoreElements()
	o.Last()
	o.Map(func(interface{}) interface{} { return zero })
	i.MapObservable(func(int) Observable { return zeroObservable })
	i.Max()
	o.Merge()
	oo.MergeAll()
	o.MergeDelayError()
	o.MergeMap(func(interface{}) Observable { return o })
	i.Min()
	o.ObserveOn(CurrentGoroutineScheduler())
	o.OnlyBool()
	o.OnlyInt()
	// Passthrough
	o.Reduce(func(acc interface{}, value interface{}) interface{} { return zero }, zero)
	o.Repeat(1)
	o.Retry()
	o.Sample(time.Millisecond)
	o.Scan(func(acc interface{}, value interface{}) interface{} { return zero }, zero)
	// Serialize
	o.Single()
	o.Skip(1)
	o.SkipLast(1)
	o.SubscribeOn(CurrentGoroutineScheduler())
	i.Sum()
	oo.SwitchAll()
	o.SwitchMap(func(interface{}) Observable { return o })
	o.Take(1)
	i.Take(1)
	o.TakeLast(1)
	o.TakeUntil(o)
	o.TakeWhile(func(interface{}) bool { return true })
	o.Timeout(time.Millisecond)

	/*
		Observable Create Functions
	*/

	Create(func(Observer) {})
	Defer(func() Observable { return o })
	Empty()
	Error(RxError("sad"))
	From(1, 2)
	FromChan(make(chan interface{}))
	FromSlice([]interface{}{1, 2})
	Froms(1, 2)
	Interval(time.Millisecond)
	Just(1)
	Concat(o)
	Merge(o)
	Never()
	Range(1, 2)
	Repeat(zero, 1)
	Start(func() (interface{}, error) { return o, nil })
	Throw(RxError("sad"))

	/*
		Observable Subscribe Methods
	*/

	// Println
	o.Println()
	b.Println()
	i.Println()
	o.Subscribe(func(interface{}, error, bool) {})
	b.Subscribe(func(bool, error, bool) {})
	i.Subscribe(func(int, error, bool) {})
	o.SubscribeNext(func(interface{}) {})
	b.SubscribeNext(func(bool) {})
	i.SubscribeNext(func(int) {})
	o.ToChan()
	b.ToChan()
	i.ToChan()
	o.ToSingle()
	b.ToSingle()
	i.ToSingle()
	o.ToSlice()
	b.ToSlice()
	i.ToSlice()
	o.Wait()
	b.Wait()
	i.Wait()

	/*
		Connectable Types, Operator Methods and Subscribe Methods
	*/

	// var c Connectable
	// o.Publish()
	// p.PublishReplay()
	// c.Connect()
	// c.AutoConnect()
	// c.RefCount()

	/*
		Subject Types
	*/

	// Subject
	// ReplaySubject
}
<|endoftext|>


<commit_before>package grep

import (
	"github.com/monochromegane/the_platinum_searcher/search/file"
	"github.com/monochromegane/the_platinum_searcher/search/option"
	"github.com/monochromegane/the_platinum_searcher/search/print"
	"testing"
)

type Assert struct {
	path, pattern, fileType, match string
}

var Asserts = []Assert{
	Assert{"ascii.txt", "go", file.ASCII, "go test"},
	Assert{"ja/euc-jp.txt", "go", file.EUCJP, "go テスト"},
	Assert{"ja/shift_jis.txt", "go", file.SHIFTJIS, "go テスト"},
	Assert{"ja/utf8.txt", "go", file.UTF8, "go テスト"},
	Assert{"ja/broken_euc-jp.txt", "go", file.EUCJP, "go テスト"},
	Assert{"ja/broken_shift_jis.txt", "go", file.SHIFTJIS, "go テスト"},
	Assert{"ja/broken_utf8.txt", "go", file.UTF8, "go テスト"},
}

func TestGrep(t *testing.T) {

	for _, g := range Asserts {
		in := make(chan *Params)
		out := make(chan *print.Params)
		grepper := Grepper{in, out, &option.Option{Proc: 1}}

		sem := make(chan bool, 1)
		sem <- true
		go grepper.Grep("../../files/"+g.path, g.fileType, g.pattern, sem)
		o := <-out
		if o.Path != "../../files/"+g.path {
			t.Errorf("It should be equal ../../files/%s.", g.path)
		}
		if o.Matches[0].Match != g.match {
			t.Errorf("%s should be equal %s", g.path, g.match)
		}
	}
}

func receive(in chan *Params, params *Params) {
	in <- params
	close(in)
}
<commit_msg>Fixed wrong test.<commit_after>package grep

import (
	"github.com/monochromegane/the_platinum_searcher/search/file"
	"github.com/monochromegane/the_platinum_searcher/search/option"
	"github.com/monochromegane/the_platinum_searcher/search/print"
	"testing"
)

type Assert struct {
	path, pattern, fileType, match string
}

var Asserts = []Assert{
	Assert{"ascii.txt", "go", file.ASCII, "go test"},
	Assert{"ja/euc-jp.txt", "go", file.EUCJP, "go テスト"},
	Assert{"ja/shift_jis.txt", "go", file.SHIFTJIS, "go テスト"},
	Assert{"ja/utf8.txt", "go", file.UTF8, "go テスト"},
	Assert{"ja/broken_euc-jp.txt", "go", file.EUCJP, "go テスト"},
	Assert{"ja/broken_shift_jis.txt", "go", file.SHIFTJIS, "go テスト"},
	Assert{"ja/broken_utf8.txt", "go", file.UTF8, "go テスト"},
}

func TestGrep(t *testing.T) {

	for _, g := range Asserts {
		in := make(chan *Params)
		out := make(chan *print.Params)
		grepper := Grepper{in, out, &option.Option{Proc: 1}}

		go grepper.Grep("../../files/"+g.path, g.fileType, g.pattern)
		o := <-out
		if o.Path != "../../files/"+g.path {
			t.Errorf("It should be equal ../../files/%s.", g.path)
		}
		if o.Matches[0].Match != g.match {
			t.Errorf("%s should be equal %s", g.path, g.match)
		}
	}
}

func receive(in chan *Params, params *Params) {
	in <- params
	close(in)
}
<|endoftext|>


<commit_before>package interfaces

import (
	"log"
	"net/http"
	"time"

	"github.com/Tinker-Ware/gh-service/domain"
)

type Adapter func(http.Handler) http.Handler
type repository interface {
	SetToken(token string)
}

func Notify() Adapter {
	return func(h http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			start := time.Now()
			defer log.Printf("%s on %s took %s\n", r.Method, r.URL.Path, time.Since(start))
			h.ServeHTTP(w, r)
		})
	}
}

func Adapt(h http.Handler, adapters ...Adapter) http.Handler {
	for _, adapter := range adapters {
		h = adapter(h)
	}
	return h
}

func SetToken(repo repository) Adapter {
	return func(h http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			token := r.Header.Get(domain.TokenHeader)
			repo.SetToken(token)
			h.ServeHTTP(w, r)
		})
	}
}
<commit_msg>Add middleware to get the provider token<commit_after>package interfaces

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/Tinker-Ware/gh-service/domain"
	"github.com/dvsekhvalnov/jose2go"
)

type Adapter func(http.Handler) http.Handler
type repository interface {
	SetToken(token string)
}

func Notify() Adapter {
	return func(h http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			start := time.Now()
			defer log.Printf("%s on %s took %s\n", r.Method, r.URL.Path, time.Since(start))
			h.ServeHTTP(w, r)
		})
	}
}

func Adapt(h http.Handler, adapters ...Adapter) http.Handler {
	for _, adapter := range adapters {
		h = adapter(h)
	}
	return h
}

func SetToken(repo repository) Adapter {
	return func(h http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			token := r.Header.Get(domain.TokenHeader)
			repo.SetToken(token)
			h.ServeHTTP(w, r)
		})
	}
}

type integration struct {
	Token    string `json:"token"`
	Provider string `json:"provider"`
}

type integrationWrapper struct {
	Integrations []integration `json:"integrations"`
}

const integrationsURL string = "/api/v1/users/%s/integrations"

// GetToken gets the token from the users microservice
func GetToken(repo repository, apiURL string, salt string) Adapter {
	return func(h http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			userToken := r.Header.Get("authorization")

			payload, _, _ := jose.Decode(userToken, []byte(salt))

			var objmap map[string]*json.RawMessage
			json.Unmarshal([]byte(payload), &objmap)

			var aud string
			json.Unmarshal(*objmap["aud"], &aud)

			vals := strings.Split(aud, ":")

			path := fmt.Sprintf(integrationsURL, vals[1])

			request, _ := http.NewRequest(http.MethodGet, apiURL+path, nil)
			request.Header.Set("authorization", userToken)

			client := &http.Client{}
			resp, _ := client.Do(request)
			defer resp.Body.Close()

			integrations := integrationWrapper{}
			decoder := json.NewDecoder(resp.Body)
			decoder.Decode(&integrations)
			var token string

			for _, integ := range integrations.Integrations {
				if integ.Provider == "github" {
					token = integ.Token
				}
			}

			repo.SetToken(token)

			h.ServeHTTP(w, r)
		})
	}
}
<|endoftext|>


<commit_before>package exec

import (
	"reflect"
	"strings"

	"github.com/neelance/graphql-go/internal/query"
	"github.com/neelance/graphql-go/internal/schema"
)

type Exec struct {
	iExec
	resolver reflect.Value
}

func Make(s *schema.Schema, resolver interface{}) *Exec {
	t := s.Types[s.EntryPoints["query"]]
	return &Exec{
		iExec:    makeExec(s, t, reflect.TypeOf(resolver), make(map[typeRefMapKey]*typeRefExec)),
		resolver: reflect.ValueOf(resolver),
	}
}

func (e *Exec) Exec(document *query.Document, variables map[string]interface{}, selSet *query.SelectionSet) interface{} {
	return e.exec(&request{document, variables}, selSet, e.resolver)
}

func makeExec(s *schema.Schema, t schema.Type, resolverType reflect.Type, typeRefMap map[typeRefMapKey]*typeRefExec) iExec {
	switch t := t.(type) {
	case *schema.Scalar:
		return &scalarExec{}

	case *schema.Object:
		fields := make(map[string]*fieldExec)

		for name, f := range t.Fields {
			methodIndex := -1
			for i := 0; i < resolverType.NumMethod(); i++ {
				if strings.EqualFold(name, resolverType.Method(i).Name) {
					methodIndex = i
					break
				}
			}
			if methodIndex == -1 {
				continue // TODO error
			}

			fields[name] = &fieldExec{
				field:       f,
				methodIndex: methodIndex,
				valueExec:   makeExec(s, f.Type, resolverType.Method(methodIndex).Type.Out(0), typeRefMap),
			}
		}

		return &objectExec{
			fields: fields,
		}

	case *schema.Enum:
		return &scalarExec{}

	case *schema.List:
		return &listExec{
			elem: makeExec(s, t.Elem, resolverType.Elem(), typeRefMap),
		}

	case *schema.TypeReference:
		refT := s.Types[t.Name]
		k := typeRefMapKey{refT, resolverType}
		e, ok := typeRefMap[k]
		if !ok {
			e = &typeRefExec{}
			typeRefMap[k] = e
			e.iExec = makeExec(s, refT, resolverType, typeRefMap)
		}
		return e

	default:
		panic("invalid type")
	}
}

type request struct {
	*query.Document
	Variables map[string]interface{}
}

type iExec interface {
	exec(r *request, selSet *query.SelectionSet, resolver reflect.Value) interface{}
}

type scalarExec struct{}

func (e *scalarExec) exec(r *request, selSet *query.SelectionSet, resolver reflect.Value) interface{} {
	return resolver.Interface()
}

type listExec struct {
	elem iExec
}

func (e *listExec) exec(r *request, selSet *query.SelectionSet, resolver reflect.Value) interface{} {
	l := make([]interface{}, resolver.Len())
	for i := range l {
		l[i] = e.elem.exec(r, selSet, resolver.Index(i))
	}
	return l
}

type typeRefExec struct {
	iExec
}

type typeRefMapKey struct {
	s schema.Type
	r reflect.Type
}

type objectExec struct {
	fields map[string]*fieldExec
}

func (e *objectExec) exec(r *request, selSet *query.SelectionSet, resolver reflect.Value) interface{} {
	result := make(map[string]interface{})
	e.execFragment(r, selSet, resolver, result)
	return result
}

func (e *objectExec) execFragment(r *request, selSet *query.SelectionSet, resolver reflect.Value, result map[string]interface{}) {
	for _, sel := range selSet.Selections {
		switch sel := sel.(type) {
		case *query.Field:
			if skipByDirective(r, sel.Directives) {
				continue
			}
			e.fields[sel.Name].exec(r, sel, resolver, result)
		case *query.FragmentSpread:
			if skipByDirective(r, sel.Directives) {
				continue
			}
			e.execFragment(r, r.Fragments[sel.Name].SelSet, resolver, result)
		default:
			panic("invalid type")
		}
	}
}

type fieldExec struct {
	field       *schema.Field
	methodIndex int
	valueExec   iExec
}

func (e *fieldExec) exec(r *request, f *query.Field, resolver reflect.Value, result map[string]interface{}) {
	m := resolver.Method(e.methodIndex)
	var in []reflect.Value
	if len(e.field.Parameters) != 0 {
		args := reflect.New(m.Type().In(0))
		for name, param := range e.field.Parameters {
			value, ok := f.Arguments[name]
			if !ok {
				value = &query.Literal{Value: param.Default}
			}
			rf := args.Elem().FieldByNameFunc(func(n string) bool { return strings.EqualFold(n, name) })
			rf.Set(reflect.ValueOf(execValue(r, value)))
		}
		in = []reflect.Value{args.Elem()}
	}
	result[f.Alias] = e.valueExec.exec(r, f.SelSet, m.Call(in)[0])
}

func skipByDirective(r *request, d map[string]*query.Directive) bool {
	if skip, ok := d["skip"]; ok {
		if execValue(r, skip.Arguments["if"]).(bool) {
			return true
		}
	}
	if include, ok := d["include"]; ok {
		if !execValue(r, include.Arguments["if"]).(bool) {
			return true
		}
	}
	return false
}

func execValue(r *request, v query.Value) interface{} {
	switch v := v.(type) {
	case *query.Variable:
		return r.Variables[v.Name]
	case *query.Literal:
		return v.Value
	default:
		panic("invalid value")
	}
}
<commit_msg>collect fields<commit_after>package exec

import (
	"reflect"
	"strings"

	"github.com/neelance/graphql-go/internal/query"
	"github.com/neelance/graphql-go/internal/schema"
)

type Exec struct {
	iExec
	resolver reflect.Value
}

func Make(s *schema.Schema, resolver interface{}) *Exec {
	t := s.Types[s.EntryPoints["query"]]
	return &Exec{
		iExec:    makeExec(s, t, reflect.TypeOf(resolver), make(map[typeRefMapKey]*typeRefExec)),
		resolver: reflect.ValueOf(resolver),
	}
}

func (e *Exec) Exec(document *query.Document, variables map[string]interface{}, selSet *query.SelectionSet) interface{} {
	return e.exec(&request{document, variables}, selSet, e.resolver)
}

func makeExec(s *schema.Schema, t schema.Type, resolverType reflect.Type, typeRefMap map[typeRefMapKey]*typeRefExec) iExec {
	switch t := t.(type) {
	case *schema.Scalar:
		return &scalarExec{}

	case *schema.Object:
		fields := make(map[string]*fieldExec)

		for name, f := range t.Fields {
			methodIndex := -1
			for i := 0; i < resolverType.NumMethod(); i++ {
				if strings.EqualFold(name, resolverType.Method(i).Name) {
					methodIndex = i
					break
				}
			}
			if methodIndex == -1 {
				continue // TODO error
			}

			fields[name] = &fieldExec{
				field:       f,
				methodIndex: methodIndex,
				valueExec:   makeExec(s, f.Type, resolverType.Method(methodIndex).Type.Out(0), typeRefMap),
			}
		}

		return &objectExec{
			fields: fields,
		}

	case *schema.Enum:
		return &scalarExec{}

	case *schema.List:
		return &listExec{
			elem: makeExec(s, t.Elem, resolverType.Elem(), typeRefMap),
		}

	case *schema.TypeReference:
		refT := s.Types[t.Name]
		k := typeRefMapKey{refT, resolverType}
		e, ok := typeRefMap[k]
		if !ok {
			e = &typeRefExec{}
			typeRefMap[k] = e
			e.iExec = makeExec(s, refT, resolverType, typeRefMap)
		}
		return e

	default:
		panic("invalid type")
	}
}

type request struct {
	*query.Document
	Variables map[string]interface{}
}

type iExec interface {
	exec(r *request, selSet *query.SelectionSet, resolver reflect.Value) interface{}
}

type scalarExec struct{}

func (e *scalarExec) exec(r *request, selSet *query.SelectionSet, resolver reflect.Value) interface{} {
	return resolver.Interface()
}

type listExec struct {
	elem iExec
}

func (e *listExec) exec(r *request, selSet *query.SelectionSet, resolver reflect.Value) interface{} {
	l := make([]interface{}, resolver.Len())
	for i := range l {
		l[i] = e.elem.exec(r, selSet, resolver.Index(i))
	}
	return l
}

type typeRefExec struct {
	iExec
}

type typeRefMapKey struct {
	s schema.Type
	r reflect.Type
}

type objectExec struct {
	fields map[string]*fieldExec
}

func (e *objectExec) exec(r *request, selSet *query.SelectionSet, resolver reflect.Value) interface{} {
	result := make(map[string]interface{})
	var allFields []*query.Field
	collectFields(r, selSet, &allFields)
	for _, f := range allFields {
		result[f.Alias] = e.fields[f.Name].exec(r, f, resolver)
	}
	return result
}

func collectFields(r *request, selSet *query.SelectionSet, allFields *[]*query.Field) {
	for _, sel := range selSet.Selections {
		switch sel := sel.(type) {
		case *query.Field:
			if !skipByDirective(r, sel.Directives) {
				*allFields = append(*allFields, sel)
			}
		case *query.FragmentSpread:
			if !skipByDirective(r, sel.Directives) {
				collectFields(r, r.Fragments[sel.Name].SelSet, allFields)
			}
		default:
			panic("invalid type")
		}
	}
}

type fieldExec struct {
	field       *schema.Field
	methodIndex int
	valueExec   iExec
}

func (e *fieldExec) exec(r *request, f *query.Field, resolver reflect.Value) interface{} {
	m := resolver.Method(e.methodIndex)
	var in []reflect.Value
	if len(e.field.Parameters) != 0 {
		args := reflect.New(m.Type().In(0))
		for name, param := range e.field.Parameters {
			value, ok := f.Arguments[name]
			if !ok {
				value = &query.Literal{Value: param.Default}
			}
			rf := args.Elem().FieldByNameFunc(func(n string) bool { return strings.EqualFold(n, name) })
			rf.Set(reflect.ValueOf(execValue(r, value)))
		}
		in = []reflect.Value{args.Elem()}
	}
	return e.valueExec.exec(r, f.SelSet, m.Call(in)[0])
}

func skipByDirective(r *request, d map[string]*query.Directive) bool {
	if skip, ok := d["skip"]; ok {
		if execValue(r, skip.Arguments["if"]).(bool) {
			return true
		}
	}
	if include, ok := d["include"]; ok {
		if !execValue(r, include.Arguments["if"]).(bool) {
			return true
		}
	}
	return false
}

func execValue(r *request, v query.Value) interface{} {
	switch v := v.(type) {
	case *query.Variable:
		return r.Variables[v.Name]
	case *query.Literal:
		return v.Value
	default:
		panic("invalid value")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"net/url"
	"time"

	"github.com/elastic/libbeat/beat"
	"github.com/elastic/libbeat/cfgfile"
	"github.com/elastic/libbeat/logp"
)

// Nginxbeat implements Beater interface and sends Nginx status using libbeat.
type Nginxbeat struct {
	// NbConfig holds configurations of Nginxbeat parsed by libbeat.
	NbConfig ConfigSettings

	url    *url.URL
	period time.Duration
}

// Config Nginxbeat according to nginxbeat.yml.
func (nb *Nginxbeat) Config(b *beat.Beat) error {
	err := cfgfile.Read(&nb.NbConfig, "")
	if err != nil {
		logp.Err("Error reading configuration file: %v", err)
		return err
	}

	var u string
	if nb.NbConfig.Input.URL != "" {
		u = nb.NbConfig.Input.URL
	} else {
		u = "http://127.0.0.1/status"
	}
	nb.url, err = url.Parse(u)
	if err != nil {
		logp.Err("Invalid Nginx status page: %v", err)
		return err
	}

	if nb.NbConfig.Input.Period != nil {
		nb.period = time.Duration(*nb.NbConfig.Input.Period) * time.Second
	} else {
		nb.period = 1 * time.Second
	}

	logp.Debug("nginxbeat", "Init nginxbeat")
	logp.Debug("nginxbeat", "Watch %v\n", nb.url)
	logp.Debug("nginxbeat", "Period %v\n", nb.period)

	return nil
}

// Setup Nginxbeat.
func (nb *Nginxbeat) Setup(b *beat.Beat) error {
	return nil
}

// Run Nginxbeat.
func (nb *Nginxbeat) Run(b *beat.Beat) error {
	return nil
}

// Cleanup Nginxbeat.
func (nb *Nginxbeat) Cleanup(b *beat.Beat) error {
	return nil
}

// Stop Nginxbeat.
func (nb *Nginxbeat) Stop() {
}
<commit_msg>Support exporting Nginx stub status<commit_after>package main

import (
	"bufio"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"time"

	"github.com/elastic/libbeat/beat"
	"github.com/elastic/libbeat/cfgfile"
	"github.com/elastic/libbeat/common"
	"github.com/elastic/libbeat/logp"
	"github.com/elastic/libbeat/publisher"
)

// Nginxbeat implements Beater interface and sends Nginx status using libbeat.
type Nginxbeat struct {
	// NbConfig holds configurations of Nginxbeat parsed by libbeat.
	NbConfig ConfigSettings

	isAlive bool
	events  publisher.Client

	url    *url.URL
	period time.Duration
}

// Config Nginxbeat according to nginxbeat.yml.
func (nb *Nginxbeat) Config(b *beat.Beat) error {
	err := cfgfile.Read(&nb.NbConfig, "")
	if err != nil {
		logp.Err("Error reading configuration file: %v", err)
		return err
	}

	var u string
	if nb.NbConfig.Input.URL != "" {
		u = nb.NbConfig.Input.URL
	} else {
		u = "http://127.0.0.1/status"
	}
	nb.url, err = url.Parse(u)
	if err != nil {
		logp.Err("Invalid Nginx status page: %v", err)
		return err
	}

	if nb.NbConfig.Input.Period != nil {
		nb.period = time.Duration(*nb.NbConfig.Input.Period) * time.Second
	} else {
		nb.period = 1 * time.Second
	}

	logp.Debug("nginxbeat", "Init nginxbeat")
	logp.Debug("nginxbeat", "Watch %v\n", nb.url)
	logp.Debug("nginxbeat", "Period %v\n", nb.period)

	return nil
}

// Setup Nginxbeat.
func (nb *Nginxbeat) Setup(b *beat.Beat) error {
	nb.events = b.Events
	return nil
}

// Run Nginxbeat.
func (nb *Nginxbeat) Run(b *beat.Beat) error {
	nb.isAlive = true

	for nb.isAlive {
		nb.exportStubStatus()

		time.Sleep(nb.period)
	}

	return nil
}

// Cleanup Nginxbeat.
func (nb *Nginxbeat) Cleanup(b *beat.Beat) error {
	return nil
}

// Stop Nginxbeat.
func (nb *Nginxbeat) Stop() {
	nb.isAlive = false
}

func (nb Nginxbeat) exportStubStatus() {
	res, err := http.Get(nb.url.String())
	if err != nil {
		logp.Err("Error reading Nginx stub status: %v", err)
		return
	}

	if res.StatusCode != 200 {
		logp.Err("Error reading Nginx stub status: HTTP%v", res.StatusCode)
		return
	}

	// Nginx stub status sample:
	// Active connections: 1
	// server accepts handled requests
	//  7 7 19
	// Reading: 0 Writing: 1 Waiting: 0
	var re *regexp.Regexp
	scanner := bufio.NewScanner(res.Body)
	defer res.Body.Close()

	// Parse active connections.
	scanner.Scan()
	re = regexp.MustCompile("Active connections: (\\d+)")
	var active int
	if matches := re.FindStringSubmatch(scanner.Text()); matches == nil {
		logp.Err("Fail to parse active connections from Nginx stub status")
		active = -1
	} else {
		active, _ = strconv.Atoi(matches[1])
	}

	// Skip request status headers.
	scanner.Scan()

	// Parse request status.
	scanner.Scan()
	re = regexp.MustCompile("\\s(\\d+)\\s+(\\d+)\\s+(\\d+)")
	var (
		accepts  int
		handled  int
		requests int
	)
	if matches := re.FindStringSubmatch(scanner.Text()); matches == nil {
		logp.Err("Fail to parse request status from Nginx stub status")
		accepts = -1
		handled = -1
		requests = -1
	} else {
		accepts, _ = strconv.Atoi(matches[1])
		handled, _ = strconv.Atoi(matches[2])
		requests, _ = strconv.Atoi(matches[3])
	}

	// Parse connection status.
	scanner.Scan()
	re = regexp.MustCompile("Reading: (\\d+) Writing: (\\d+) Waiting: (\\d+)")
	var (
		reading int
		writing int
		waiting int
	)
	if matches := re.FindStringSubmatch(scanner.Text()); matches == nil {
		logp.Err("Fail to parse connection status from Nginx stub status")
		reading = -1
		writing = -1
		waiting = -1
	} else {
		reading, _ = strconv.Atoi(matches[1])
		writing, _ = strconv.Atoi(matches[2])
		waiting, _ = strconv.Atoi(matches[3])
	}

	event := common.MapStr{
		"timestamp": common.Time(time.Now()),
		"type":      "nginx",
		"nginx": common.MapStr{
			"active":   active,
			"accepts":  accepts,
			"handled":  handled,
			"requests": requests,
			"reading":  reading,
			"writing":  writing,
			"waiting":  waiting,
		},
	}
	nb.events.PublishEvent(event)
}
<|endoftext|>