<commit_before>// Package proctl provides functions for attaching to and manipulating
// a process during the debug session.
package proctl

import (
	"bytes"
	"debug/gosym"
	"encoding/binary"
	"fmt"
	"os"
	"os/exec"
	"sync"
	"syscall"

	"github.com/derekparker/delve/dwarf/frame"
	"github.com/derekparker/delve/vendor/elf"
)

// Struct representing a debugged process. Holds onto pid, register values,
// process struct and process state.
type DebuggedProcess struct {
	Pid           int
	Process       *os.Process
	Executable    *elf.File
	Symbols       []elf.Symbol
	GoSymTable    *gosym.Table
	FrameEntries  *frame.FrameDescriptionEntries
	BreakPoints   map[uint64]*BreakPoint
	Threads       map[int]*ThreadContext
	CurrentThread *ThreadContext
}

// Represents a single breakpoint. Stores information on the break
// point including the byte of data that originally was stored at that
// address.
type BreakPoint struct {
	FunctionName string
	File         string
	Line         int
	Addr         uint64
	OriginalData []byte
}

type BreakPointExistsError struct {
	file string
	line int
	addr uintptr
}

func (bpe BreakPointExistsError) Error() string {
	return fmt.Sprintf("Breakpoint exists at %s:%d at %x", bpe.file, bpe.line, bpe.addr)
}

func AttachBinary(name string) (*DebuggedProcess, error) {
	proc := exec.Command(name)
	proc.Stdout = os.Stdout

	err := proc.Start()
	if err != nil {
		return nil, err
	}

	dbgproc, err := NewDebugProcess(proc.Process.Pid)
	if err != nil {
		return nil, err
	}

	return dbgproc, nil
}

// Returns a new DebuggedProcess struct with sensible defaults.
func NewDebugProcess(pid int) (*DebuggedProcess, error) {
	debuggedProc := DebuggedProcess{
		Pid:         pid,
		Threads:     make(map[int]*ThreadContext),
		BreakPoints: make(map[uint64]*BreakPoint),
	}

	_, err := debuggedProc.AttachThread(pid)
	if err != nil {
		return nil, err
	}

	proc, err := os.FindProcess(pid)
	if err != nil {
		return nil, err
	}

	debuggedProc.Process = proc
	err = debuggedProc.LoadInformation()
	if err != nil {
		return nil, err
	}

	// TODO: for some reason this isn't grabbing all threads, and
	// neither is the subsequent ptrace clone op. Maybe when
	// we attach the process is right in the middle of a clone syscall?
	for _, tid := range threadIds(pid) {
		if !debuggedProc.hasthread(tid) {
			_, err := debuggedProc.AttachThread(tid)
			if err != nil {
				return nil, err
			}
		}
	}

	return &debuggedProc, nil
}

func (dbp *DebuggedProcess) hasthread(tid int) bool {
	for _, t := range dbp.Threads {
		if tid == t.Id {
			return true
		}
	}

	return false
}

func (dbp *DebuggedProcess) AttachThread(tid int) (*ThreadContext, error) {
	var (
		status syscall.WaitStatus
	)
	if thread, ok := dbp.Threads[tid]; ok {
		return thread, nil
	}

	err := syscall.PtraceAttach(tid)
	if err != nil {
		if err != syscall.EPERM {
			// Do not return err if err == EPERM,
			// we may already be tracing this thread due to
			// PTRACE_O_TRACECLONE. We will surely blow up later
			// if we truly don't have permissions.
			return nil, fmt.Errorf("could not attach to new thread %d %s", tid, err)
		}
	} else {
		pid, e := syscall.Wait4(tid, &status, syscall.WALL, nil)
		if e != nil {
			return nil, err
		}
		// pid, status, err = wait(dbp, tid, 0)
		if err != nil && err != syscall.ECHILD {
			return nil, err
		}

		if pid != 0 && status.Exited() {
			return nil, fmt.Errorf("thread already exited %d", tid)
		}
	}

	return dbp.addThread(tid)
}

func (dbp *DebuggedProcess) addThread(tid int) (*ThreadContext, error) {
	err := syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE)
	if err != nil {
		var status syscall.WaitStatus
		pid, e := syscall.Wait4(tid, &status, syscall.WALL, nil)
		if e != nil {
			if status.Exited() {
				return nil, ProcessExitedError{tid}
			}
			return nil, fmt.Errorf("error while waiting after adding thread: %d %s %v %d", tid, e, status.Exited(), status.TrapCause())
		}

		if pid != 0 {
			err := syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE)
			if err != nil {
				return nil, fmt.Errorf("could not set options for new traced thread %d %s", tid, err)
			}
		}
	}

	tctxt := &ThreadContext{
		Id:      tid,
		Process: dbp,
		Regs:    new(syscall.PtraceRegs),
	}

	if tid == dbp.Pid {
		dbp.CurrentThread = tctxt
	}

	dbp.Threads[tid] = tctxt

	return tctxt, nil
}

// Sets a breakpoint in the running process.
func (dbp *DebuggedProcess) Break(addr uintptr) (*BreakPoint, error) {
	var (
		int3         = []byte{0xCC}
		f, l, fn     = dbp.GoSymTable.PCToLine(uint64(addr))
		originalData = make([]byte, 1)
	)

	if fn == nil {
		return nil, InvalidAddressError{address: addr}
	}

	_, err := syscall.PtracePeekData(dbp.CurrentThread.Id, addr, originalData)
	if err != nil {
		return nil, err
	}

	if bytes.Equal(originalData, int3) {
		return nil, BreakPointExistsError{f, l, addr}
	}

	_, err = syscall.PtracePokeData(dbp.CurrentThread.Id, addr, int3)
	if err != nil {
		return nil, err
	}

	breakpoint := &BreakPoint{
		FunctionName: fn.Name,
		File:         f,
		Line:         l,
		Addr:         uint64(addr),
		OriginalData: originalData,
	}

	dbp.BreakPoints[uint64(addr)] = breakpoint

	return breakpoint, nil
}

// Clears a breakpoint.
func (dbp *DebuggedProcess) Clear(pc uint64) (*BreakPoint, error) {
	bp, ok := dbp.BreakPoints[pc]
	if !ok {
		return nil, fmt.Errorf("No breakpoint currently set for %#v", pc)
	}

	_, err := syscall.PtracePokeData(dbp.CurrentThread.Id, uintptr(bp.Addr), bp.OriginalData)
	if err != nil {
		return nil, err
	}

	delete(dbp.BreakPoints, pc)

	return bp, nil
}

// Returns the status of the current main thread context.
func (dbp *DebuggedProcess) Status() *syscall.WaitStatus {
	return dbp.CurrentThread.Status
}

// Finds the executable from /proc/<pid>/exe and then
// uses that to parse the following information:
// * Dwarf .debug_frame section
// * Dwarf .debug_line section
// * Go symbol table.
func (dbp *DebuggedProcess) LoadInformation() error {
	var (
		wg  sync.WaitGroup
		err error
	)

	err = dbp.findExecutable()
	if err != nil {
		return err
	}

	wg.Add(2)
	go dbp.parseDebugFrame(&wg)
	go dbp.obtainGoSymbols(&wg)

	wg.Wait()

	return nil
}

// Steps through process.
func (dbp *DebuggedProcess) Step() (err error) {
	for _, thread := range dbp.Threads {
		err := thread.Step()
		if err != nil {
			if _, ok := err.(ProcessExitedError); !ok {
				return err
			}
		}
	}

	return nil
}

// Step over function calls.
func (dbp *DebuggedProcess) Next() error {
	for _, thread := range dbp.Threads {
		err := thread.Next()
		if _, ok := err.(ProcessExitedError); !ok {
			return err
		}
	}

	return nil
}

// Continue process until next breakpoint.
func (dbp *DebuggedProcess) Continue() error {
	for _, thread := range dbp.Threads {
		err := thread.Continue()
		if err != nil {
			return err
		}
	}

	_, _, err := wait(dbp, -1, 0)
	if err != nil {
		if _, ok := err.(ProcessExitedError); !ok {
			return err
		}
	}

	return nil
}

// Obtains register values from the debugged process.
func (dbp *DebuggedProcess) Registers() (*syscall.PtraceRegs, error) {
	return dbp.CurrentThread.Registers()
}

type InvalidAddressError struct {
	address uintptr
}

func (iae InvalidAddressError) Error() string {
	return fmt.Sprintf("Invalid address %#v\n", iae.address)
}

func (dbp *DebuggedProcess) CurrentPC() (uint64, error) {
	return dbp.CurrentThread.CurrentPC()
}

// Returns the value of the named symbol.
func (dbp *DebuggedProcess) EvalSymbol(name string) (*Variable, error) {
	return dbp.CurrentThread.EvalSymbol(name)
}

func (dbp *DebuggedProcess) findExecutable() error {
	procpath := fmt.Sprintf("/proc/%d/exe", dbp.Pid)

	f, err := os.OpenFile(procpath, 0, os.ModePerm)
	if err != nil {
		return err
	}

	elffile, err := elf.NewFile(f)
	if err != nil {
		return err
	}

	dbp.Executable = elffile

	return nil
}

func (dbp *DebuggedProcess) parseDebugFrame(wg *sync.WaitGroup) {
	defer wg.Done()

	debugFrame, err := dbp.Executable.Section(".debug_frame").Data()
	if err != nil {
		fmt.Println("could not get .debug_frame section", err)
		os.Exit(1)
	}

	dbp.FrameEntries = frame.Parse(debugFrame)
}

func (dbp *DebuggedProcess) obtainGoSymbols(wg *sync.WaitGroup) {
	defer wg.Done()

	var (
		symdat  []byte
		pclndat []byte
		err     error
	)

	if sec := dbp.Executable.Section(".gosymtab"); sec != nil {
		symdat, err = sec.Data()
		if err != nil {
			fmt.Println("could not get .gosymtab section", err)
			os.Exit(1)
		}
	}

	if sec := dbp.Executable.Section(".gopclntab"); sec != nil {
		pclndat, err = sec.Data()
		if err != nil {
			fmt.Println("could not get .gopclntab section", err)
			os.Exit(1)
		}
	}

	pcln := gosym.NewLineTable(pclndat, dbp.Executable.Section(".text").Addr)
	tab, err := gosym.NewTable(symdat, pcln)
	if err != nil {
		fmt.Println("could not get initialize line table", err)
		os.Exit(1)
	}

	dbp.GoSymTable = tab
}

// Takes an offset from RSP and returns the address of the
// instruction the currect function is going to return to.
func (dbp *DebuggedProcess) ReturnAddressFromOffset(offset int64) uint64 {
	regs, err := dbp.Registers()
	if err != nil {
		panic("Could not obtain register values")
	}

	retaddr := int64(regs.Rsp) + offset
	data := make([]byte, 8)
	syscall.PtracePeekText(dbp.Pid, uintptr(retaddr), data)
	return binary.LittleEndian.Uint64(data)
}

type ProcessExitedError struct {
	pid int
}

func (pe ProcessExitedError) Error() string {
	return fmt.Sprintf("process %d has exited", pe.pid)
}

func wait(dbp *DebuggedProcess, pid int, options int) (int, *syscall.WaitStatus, error) {
	var status syscall.WaitStatus

	for {
		pid, e := syscall.Wait4(-1, &status, syscall.WALL|options, nil)
		if e != nil {
			return -1, nil, fmt.Errorf("wait err %s %d", e, pid)
		}

		thread, threadtraced := dbp.Threads[pid]
		if threadtraced {
			thread.Status = &status
		}

		if status.Exited() {
			if pid == dbp.Pid {
				return 0, nil, ProcessExitedError{pid}
			}

			delete(dbp.Threads, pid)
		}

		if status.StopSignal() == syscall.SIGTRAP {
			if status.TrapCause() == syscall.PTRACE_EVENT_CLONE {
				// A traced thread has cloned a new thread, grab the pid and
				// add it to our list of traced threads.
				msg, err := syscall.PtraceGetEventMsg(pid)
				if err != nil {
					return 0, nil, fmt.Errorf("could not get event message: %s", err)
				}

				_, err = dbp.addThread(int(msg))
				if err != nil {
					if _, ok := err.(ProcessExitedError); ok {
						continue
					}
					return 0, nil, err
				}

				err = syscall.PtraceCont(int(msg), 0)
				if err != nil {
					return 0, nil, fmt.Errorf("could not continue new thread %d %s", msg, err)
				}

				err = syscall.PtraceCont(pid, 0)
				if err != nil {
					return 0, nil, fmt.Errorf("could not continue stopped thread %d %s", pid, err)
				}

				continue
			}

			if pid != dbp.CurrentThread.Id {
				fmt.Printf("changed thread context from %d to %d\n", dbp.CurrentThread.Id, pid)
				dbp.CurrentThread = thread
			}

			pc, _ := thread.CurrentPC()
			if _, ok := dbp.BreakPoints[pc-1]; ok {
				return pid, &status, nil
			}
		}

		if status.Stopped() {
			if pid == dbp.Pid {
				return pid, &status, nil
			}
		}
	}
}
<commit_msg>remove silly function<commit_after>// Package proctl provides functions for attaching to and manipulating
// a process during the debug session.
package proctl

import (
	"bytes"
	"debug/gosym"
	"encoding/binary"
	"fmt"
	"os"
	"os/exec"
	"sync"
	"syscall"

	"github.com/derekparker/delve/dwarf/frame"
	"github.com/derekparker/delve/vendor/elf"
)

// Struct representing a debugged process. Holds onto pid, register values,
// process struct and process state.
type DebuggedProcess struct {
	Pid           int
	Process       *os.Process
	Executable    *elf.File
	Symbols       []elf.Symbol
	GoSymTable    *gosym.Table
	FrameEntries  *frame.FrameDescriptionEntries
	BreakPoints   map[uint64]*BreakPoint
	Threads       map[int]*ThreadContext
	CurrentThread *ThreadContext
}

// Represents a single breakpoint. Stores information on the break
// point including the byte of data that originally was stored at that
// address.
type BreakPoint struct {
	FunctionName string
	File         string
	Line         int
	Addr         uint64
	OriginalData []byte
}

type BreakPointExistsError struct {
	file string
	line int
	addr uintptr
}

func (bpe BreakPointExistsError) Error() string {
	return fmt.Sprintf("Breakpoint exists at %s:%d at %x", bpe.file, bpe.line, bpe.addr)
}

func AttachBinary(name string) (*DebuggedProcess, error) {
	proc := exec.Command(name)
	proc.Stdout = os.Stdout

	err := proc.Start()
	if err != nil {
		return nil, err
	}

	dbgproc, err := NewDebugProcess(proc.Process.Pid)
	if err != nil {
		return nil, err
	}

	return dbgproc, nil
}

// Returns a new DebuggedProcess struct with sensible defaults.
func NewDebugProcess(pid int) (*DebuggedProcess, error) {
	debuggedProc := DebuggedProcess{
		Pid:         pid,
		Threads:     make(map[int]*ThreadContext),
		BreakPoints: make(map[uint64]*BreakPoint),
	}

	_, err := debuggedProc.AttachThread(pid)
	if err != nil {
		return nil, err
	}

	proc, err := os.FindProcess(pid)
	if err != nil {
		return nil, err
	}

	debuggedProc.Process = proc
	err = debuggedProc.LoadInformation()
	if err != nil {
		return nil, err
	}

	// TODO: for some reason this isn't grabbing all threads, and
	// neither is the subsequent ptrace clone op. Maybe when
	// we attach the process is right in the middle of a clone syscall?
	for _, tid := range threadIds(pid) {
		if _, ok := debuggedProc.Threads[tid]; !ok {
			_, err := debuggedProc.AttachThread(tid)
			if err != nil {
				return nil, err
			}
		}
	}

	return &debuggedProc, nil
}

func (dbp *DebuggedProcess) AttachThread(tid int) (*ThreadContext, error) {
	var (
		status syscall.WaitStatus
	)
	if thread, ok := dbp.Threads[tid]; ok {
		return thread, nil
	}

	err := syscall.PtraceAttach(tid)
	if err != nil {
		if err != syscall.EPERM {
			// Do not return err if err == EPERM,
			// we may already be tracing this thread due to
			// PTRACE_O_TRACECLONE. We will surely blow up later
			// if we truly don't have permissions.
			return nil, fmt.Errorf("could not attach to new thread %d %s", tid, err)
		}
	} else {
		pid, e := syscall.Wait4(tid, &status, syscall.WALL, nil)
		if e != nil {
			return nil, err
		}
		// pid, status, err = wait(dbp, tid, 0)
		if err != nil && err != syscall.ECHILD {
			return nil, err
		}

		if pid != 0 && status.Exited() {
			return nil, fmt.Errorf("thread already exited %d", tid)
		}
	}

	return dbp.addThread(tid)
}

func (dbp *DebuggedProcess) addThread(tid int) (*ThreadContext, error) {
	err := syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE)
	if err != nil {
		var status syscall.WaitStatus
		pid, e := syscall.Wait4(tid, &status, syscall.WALL, nil)
		if e != nil {
			if status.Exited() {
				return nil, ProcessExitedError{tid}
			}
			return nil, fmt.Errorf("error while waiting after adding thread: %d %s %v %d", tid, e, status.Exited(), status.TrapCause())
		}

		if pid != 0 {
			err := syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE)
			if err != nil {
				return nil, fmt.Errorf("could not set options for new traced thread %d %s", tid, err)
			}
		}
	}

	tctxt := &ThreadContext{
		Id:      tid,
		Process: dbp,
		Regs:    new(syscall.PtraceRegs),
	}

	if tid == dbp.Pid {
		dbp.CurrentThread = tctxt
	}

	dbp.Threads[tid] = tctxt

	return tctxt, nil
}

// Sets a breakpoint in the running process.
func (dbp *DebuggedProcess) Break(addr uintptr) (*BreakPoint, error) {
	var (
		int3         = []byte{0xCC}
		f, l, fn     = dbp.GoSymTable.PCToLine(uint64(addr))
		originalData = make([]byte, 1)
	)

	if fn == nil {
		return nil, InvalidAddressError{address: addr}
	}

	_, err := syscall.PtracePeekData(dbp.CurrentThread.Id, addr, originalData)
	if err != nil {
		return nil, err
	}

	if bytes.Equal(originalData, int3) {
		return nil, BreakPointExistsError{f, l, addr}
	}

	_, err = syscall.PtracePokeData(dbp.CurrentThread.Id, addr, int3)
	if err != nil {
		return nil, err
	}

	breakpoint := &BreakPoint{
		FunctionName: fn.Name,
		File:         f,
		Line:         l,
		Addr:         uint64(addr),
		OriginalData: originalData,
	}

	dbp.BreakPoints[uint64(addr)] = breakpoint

	return breakpoint, nil
}

// Clears a breakpoint.
func (dbp *DebuggedProcess) Clear(pc uint64) (*BreakPoint, error) {
	bp, ok := dbp.BreakPoints[pc]
	if !ok {
		return nil, fmt.Errorf("No breakpoint currently set for %#v", pc)
	}

	_, err := syscall.PtracePokeData(dbp.CurrentThread.Id, uintptr(bp.Addr), bp.OriginalData)
	if err != nil {
		return nil, err
	}

	delete(dbp.BreakPoints, pc)

	return bp, nil
}

// Returns the status of the current main thread context.
func (dbp *DebuggedProcess) Status() *syscall.WaitStatus {
	return dbp.CurrentThread.Status
}

// Finds the executable from /proc/<pid>/exe and then
// uses that to parse the following information:
// * Dwarf .debug_frame section
// * Dwarf .debug_line section
// * Go symbol table.
func (dbp *DebuggedProcess) LoadInformation() error {
	var (
		wg  sync.WaitGroup
		err error
	)

	err = dbp.findExecutable()
	if err != nil {
		return err
	}

	wg.Add(2)
	go dbp.parseDebugFrame(&wg)
	go dbp.obtainGoSymbols(&wg)

	wg.Wait()

	return nil
}

// Steps through process.
func (dbp *DebuggedProcess) Step() (err error) {
	for _, thread := range dbp.Threads {
		err := thread.Step()
		if err != nil {
			if _, ok := err.(ProcessExitedError); !ok {
				return err
			}
		}
	}

	return nil
}

// Step over function calls.
func (dbp *DebuggedProcess) Next() error {
	for _, thread := range dbp.Threads {
		err := thread.Next()
		if _, ok := err.(ProcessExitedError); !ok {
			return err
		}
	}

	return nil
}

// Continue process until next breakpoint.
func (dbp *DebuggedProcess) Continue() error {
	for _, thread := range dbp.Threads {
		err := thread.Continue()
		if err != nil {
			return err
		}
	}

	_, _, err := wait(dbp, -1, 0)
	if err != nil {
		if _, ok := err.(ProcessExitedError); !ok {
			return err
		}
	}

	return nil
}

// Obtains register values from the debugged process.
func (dbp *DebuggedProcess) Registers() (*syscall.PtraceRegs, error) {
	return dbp.CurrentThread.Registers()
}

type InvalidAddressError struct {
	address uintptr
}

func (iae InvalidAddressError) Error() string {
	return fmt.Sprintf("Invalid address %#v\n", iae.address)
}

func (dbp *DebuggedProcess) CurrentPC() (uint64, error) {
	return dbp.CurrentThread.CurrentPC()
}

// Returns the value of the named symbol.
func (dbp *DebuggedProcess) EvalSymbol(name string) (*Variable, error) {
	return dbp.CurrentThread.EvalSymbol(name)
}

func (dbp *DebuggedProcess) findExecutable() error {
	procpath := fmt.Sprintf("/proc/%d/exe", dbp.Pid)

	f, err := os.OpenFile(procpath, 0, os.ModePerm)
	if err != nil {
		return err
	}

	elffile, err := elf.NewFile(f)
	if err != nil {
		return err
	}

	dbp.Executable = elffile

	return nil
}

func (dbp *DebuggedProcess) parseDebugFrame(wg *sync.WaitGroup) {
	defer wg.Done()

	debugFrame, err := dbp.Executable.Section(".debug_frame").Data()
	if err != nil {
		fmt.Println("could not get .debug_frame section", err)
		os.Exit(1)
	}

	dbp.FrameEntries = frame.Parse(debugFrame)
}

func (dbp *DebuggedProcess) obtainGoSymbols(wg *sync.WaitGroup) {
	defer wg.Done()

	var (
		symdat  []byte
		pclndat []byte
		err     error
	)

	if sec := dbp.Executable.Section(".gosymtab"); sec != nil {
		symdat, err = sec.Data()
		if err != nil {
			fmt.Println("could not get .gosymtab section", err)
			os.Exit(1)
		}
	}

	if sec := dbp.Executable.Section(".gopclntab"); sec != nil {
		pclndat, err = sec.Data()
		if err != nil {
			fmt.Println("could not get .gopclntab section", err)
			os.Exit(1)
		}
	}

	pcln := gosym.NewLineTable(pclndat, dbp.Executable.Section(".text").Addr)
	tab, err := gosym.NewTable(symdat, pcln)
	if err != nil {
		fmt.Println("could not get initialize line table", err)
		os.Exit(1)
	}

	dbp.GoSymTable = tab
}

// Takes an offset from RSP and returns the address of the
// instruction the currect function is going to return to.
func (dbp *DebuggedProcess) ReturnAddressFromOffset(offset int64) uint64 {
	regs, err := dbp.Registers()
	if err != nil {
		panic("Could not obtain register values")
	}

	retaddr := int64(regs.Rsp) + offset
	data := make([]byte, 8)
	syscall.PtracePeekText(dbp.Pid, uintptr(retaddr), data)
	return binary.LittleEndian.Uint64(data)
}

type ProcessExitedError struct {
	pid int
}

func (pe ProcessExitedError) Error() string {
	return fmt.Sprintf("process %d has exited", pe.pid)
}

func wait(dbp *DebuggedProcess, pid int, options int) (int, *syscall.WaitStatus, error) {
	var status syscall.WaitStatus

	for {
		pid, e := syscall.Wait4(-1, &status, syscall.WALL|options, nil)
		if e != nil {
			return -1, nil, fmt.Errorf("wait err %s %d", e, pid)
		}

		thread, threadtraced := dbp.Threads[pid]
		if threadtraced {
			thread.Status = &status
		}

		if status.Exited() {
			if pid == dbp.Pid {
				return 0, nil, ProcessExitedError{pid}
			}

			delete(dbp.Threads, pid)
		}

		if status.StopSignal() == syscall.SIGTRAP {
			if status.TrapCause() == syscall.PTRACE_EVENT_CLONE {
				// A traced thread has cloned a new thread, grab the pid and
				// add it to our list of traced threads.
				msg, err := syscall.PtraceGetEventMsg(pid)
				if err != nil {
					return 0, nil, fmt.Errorf("could not get event message: %s", err)
				}

				_, err = dbp.addThread(int(msg))
				if err != nil {
					if _, ok := err.(ProcessExitedError); ok {
						continue
					}
					return 0, nil, err
				}

				err = syscall.PtraceCont(int(msg), 0)
				if err != nil {
					return 0, nil, fmt.Errorf("could not continue new thread %d %s", msg, err)
				}

				err = syscall.PtraceCont(pid, 0)
				if err != nil {
					return 0, nil, fmt.Errorf("could not continue stopped thread %d %s", pid, err)
				}

				continue
			}

			if pid != dbp.CurrentThread.Id {
				fmt.Printf("changed thread context from %d to %d\n", dbp.CurrentThread.Id, pid)
				dbp.CurrentThread = thread
			}

			pc, _ := thread.CurrentPC()
			if _, ok := dbp.BreakPoints[pc-1]; ok {
				return pid, &status, nil
			}
		}

		if status.Stopped() {
			if pid == dbp.Pid {
				return pid, &status, nil
			}
		}
	}
}
<|endoftext|>


<commit_before>package board

import (
	"color"
	"errors"
	"matrix"
	"piece"
)

type Board struct {
	matrix.Matrix
	first [8][8]bool
}

func NewBoard() *Board {
	board := new(Board)
	board.Matrix = matrix.Starting()
	for i := 0; i < 8; i++ {
		board.first[0][i] = true
		board.first[1][i] = true
		board.first[6][i] = true
		board.first[7][i] = true
	}
	return board
}

func (board Board) IsFirst(p matrix.Point) bool {
	return board.first[p.Y][p.X]
}

func (board *Board) CanCastling(from, to matrix.Point) bool {
	diff := from.Diff(to)
	rfrom := from
	rto := to

	if diff.X == 2 {
		rfrom.X = 7
		rto.X = to.X - 1
	} else {
		rfrom.X = 0
		rto.X = to.X + 1
	}
	fsymbol := board.Matrix[rfrom.Y][rfrom.X]
	if piece.Rook.IsSymbol(fsymbol) == false {
		return false
	} else if board.first[rfrom.Y][rfrom.X] == false {
		return false
	} else if board.Matrix.ExistBarrier(rfrom, rto) {
		return false
	}
	return true
}

func (board *Board) Castling(from, to matrix.Point) {
	diff := from.Diff(to)
	rfrom := from
	rto := to
	if diff.X == 2 {
		rfrom.X = 7
		rto.X = to.X - 1
	} else {
		rfrom.X = 0
		rto.X = to.X + 1
	}

	board.Matrix[to.Y][to.X] = board.Matrix[from.Y][from.X]
	board.Matrix[from.Y][from.X] = ' '
	board.first[from.Y][from.X] = false
	board.first[to.Y][to.X] = false
	board.Matrix[rto.Y][rto.X] = board.Matrix[rfrom.Y][rfrom.X]
	board.Matrix[rfrom.Y][rfrom.X] = ' '
	board.first[rfrom.Y][rfrom.X] = false
	board.first[rto.Y][rto.X] = false
}

func (board *Board) Move(from, to matrix.Point, c color.Color) error {
	if matrix.InMatrix(from) == false || matrix.InMatrix(to) == false {
		return errors.New("out of board")
	}

	fsymbol := board.Matrix[from.Y][from.X]
	tsymbol := board.Matrix[to.Y][to.X]

	fcolor := color.WhichColor(board.Matrix[from.Y][from.X])
	tcolor := color.WhichColor(board.Matrix[to.Y][to.X])
	diff := matrix.Point{0, 0}
	if fcolor == color.White {
		diff = from.Diff(to)
	} else if fcolor == color.Black {
		diff = to.Diff(from)
	}
	if fcolor != c || tcolor == c {
		return errors.New("cannot move pieces that is not yours")
	}

	fpiece := piece.WhichPiece(fsymbol)
	toEnemy := color.WhichColor(board.Matrix[to.Y][to.X]) == c.Enemy()
	canMove := fpiece.CanMove(diff, board.first[from.Y][from.X], toEnemy)
	existBarrier := board.Matrix.ExistBarrier(from, to)
	if canMove == false || (existBarrier && piece.Knight.IsSymbol(fsymbol) == false) {
		return errors.New("cannot move this piece to there")
	}

	ffirst := board.first[from.Y][from.X]
	tfirst := board.first[to.Y][to.X]

	isCastling := piece.King.IsSymbol(fsymbol) && (diff.X == -2 || diff.X == 2)
	canCastling := isCastling && board.CanCastling(from, to)
	if isCastling && canCastling == false {
		return errors.New("cannnot castle to that point")
	} else if canCastling == true {
		board.Castling(from, to)
	} else {
		board.Matrix[to.Y][to.X] = board.Matrix[from.Y][from.X]
		board.Matrix[from.Y][from.X] = ' '
		board.first[from.Y][from.X] = false
		board.first[to.Y][to.X] = false
	}
	if board.IsChecked(c) {
		board.Matrix[from.Y][from.X] = fsymbol
		board.Matrix[to.Y][to.X] = tsymbol
		board.first[from.Y][from.X] = ffirst
		board.first[to.Y][to.X] = tfirst
		return errors.New("cannot move that piece there: your king will be checked")
	}

	return nil
}
<commit_msg>Implement checks the moving is castling or not<commit_after>package board

import (
	"color"
	"errors"
	"matrix"
	"piece"
)

type Board struct {
	matrix.Matrix
	first [8][8]bool
}

func NewBoard() *Board {
	board := new(Board)
	board.Matrix = matrix.Starting()
	for i := 0; i < 8; i++ {
		board.first[0][i] = true
		board.first[1][i] = true
		board.first[6][i] = true
		board.first[7][i] = true
	}
	return board
}

func (board Board) IsFirst(p matrix.Point) bool {
	return board.first[p.Y][p.X]
}

func (board *Board) IsCastling(from, to matrix.Point) bool {
	isKing := piece.King.IsSymbol(board.Matrix[from.Y][from.X])
	diff := from.Diff(to)
	return isKing && (diff == matrix.Point{0, 2} || diff == matrix.Point{0, -2})
}

func (board *Board) CanCastling(from, to matrix.Point) bool {
	diff := from.Diff(to)
	rfrom := from
	rto := to

	if diff.X == 2 {
		rfrom.X = 7
		rto.X = to.X - 1
	} else {
		rfrom.X = 0
		rto.X = to.X + 1
	}
	fsymbol := board.Matrix[rfrom.Y][rfrom.X]
	if piece.Rook.IsSymbol(fsymbol) == false {
		return false
	} else if board.first[rfrom.Y][rfrom.X] == false {
		return false
	} else if board.Matrix.ExistBarrier(rfrom, rto) {
		return false
	}
	return true
}

func (board *Board) Castling(from, to matrix.Point) {
	diff := from.Diff(to)
	rfrom := from
	rto := to
	if diff.X == 2 {
		rfrom.X = 7
		rto.X = to.X - 1
	} else {
		rfrom.X = 0
		rto.X = to.X + 1
	}

	board.Matrix[to.Y][to.X] = board.Matrix[from.Y][from.X]
	board.Matrix[from.Y][from.X] = ' '
	board.first[from.Y][from.X] = false
	board.first[to.Y][to.X] = false
	board.Matrix[rto.Y][rto.X] = board.Matrix[rfrom.Y][rfrom.X]
	board.Matrix[rfrom.Y][rfrom.X] = ' '
	board.first[rfrom.Y][rfrom.X] = false
	board.first[rto.Y][rto.X] = false
}

func (board *Board) Move(from, to matrix.Point, c color.Color) error {
	if matrix.InMatrix(from) == false || matrix.InMatrix(to) == false {
		return errors.New("out of board")
	}

	fsymbol := board.Matrix[from.Y][from.X]
	tsymbol := board.Matrix[to.Y][to.X]

	fcolor := color.WhichColor(board.Matrix[from.Y][from.X])
	tcolor := color.WhichColor(board.Matrix[to.Y][to.X])
	diff := matrix.Point{0, 0}
	if fcolor == color.White {
		diff = from.Diff(to)
	} else if fcolor == color.Black {
		diff = to.Diff(from)
	}
	if fcolor != c || tcolor == c {
		return errors.New("cannot move pieces that is not yours")
	}

	fpiece := piece.WhichPiece(fsymbol)
	toEnemy := color.WhichColor(board.Matrix[to.Y][to.X]) == c.Enemy()
	canMove := fpiece.CanMove(diff, board.first[from.Y][from.X], toEnemy)
	existBarrier := board.Matrix.ExistBarrier(from, to)
	if canMove == false || (existBarrier && piece.Knight.IsSymbol(fsymbol) == false) {
		return errors.New("cannot move this piece to there")
	}

	ffirst := board.first[from.Y][from.X]
	tfirst := board.first[to.Y][to.X]

	isCastling := board.IsCastling(from, to)
	canCastling := isCastling && board.CanCastling(from, to)
	if isCastling && canCastling == false {
		return errors.New("cannnot castle to that point")
	} else if canCastling == true {
		board.Castling(from, to)
	} else {
		board.Matrix[to.Y][to.X] = board.Matrix[from.Y][from.X]
		board.Matrix[from.Y][from.X] = ' '
		board.first[from.Y][from.X] = false
		board.first[to.Y][to.X] = false
	}
	if board.IsChecked(c) {
		board.Matrix[from.Y][from.X] = fsymbol
		board.Matrix[to.Y][to.X] = tsymbol
		board.first[from.Y][from.X] = ffirst
		board.first[to.Y][to.X] = tfirst
		return errors.New("cannot move that piece there: your king will be checked")
	}

	return nil
}
<|endoftext|>


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

package span

import (
	"context"
	"fmt"
	"time"

	"cloud.google.com/go/spanner"
	"github.com/golang/protobuf/ptypes"
	durpb "github.com/golang/protobuf/ptypes/duration"
	"google.golang.org/grpc/codes"

	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/grpc/grpcutil"

	"go.chromium.org/luci/resultdb/internal/pagination"
	"go.chromium.org/luci/resultdb/pbutil"
	pb "go.chromium.org/luci/resultdb/proto/rpc/v1"
)

// MustParseTestResultName retrieves the invocation ID, unescaped test id, and
// result ID.
// Panics if the name is invalid. Useful for situations when name was already
// validated.
func MustParseTestResultName(name string) (invID InvocationID, testID, resultID string) {
	invIDStr, testID, resultID, err := pbutil.ParseTestResultName(name)
	if err != nil {
		panic(err)
	}
	invID = InvocationID(invIDStr)
	return
}

// ReadTestResult reads specified TestResult within the transaction.
// If the TestResult does not exist, the returned error is annotated with
// NotFound GRPC code.
func ReadTestResult(ctx context.Context, txn Txn, name string) (*pb.TestResult, error) {
	invID, testID, resultID := MustParseTestResultName(name)
	tr := &pb.TestResult{
		Name:     name,
		TestId:   testID,
		ResultId: resultID,
		Expected: true,
	}

	var maybeUnexpected spanner.NullBool
	var micros int64
	var summaryHTML Compressed
	err := ReadRow(ctx, txn, "TestResults", invID.Key(testID, resultID), map[string]interface{}{
		"Variant":         &tr.Variant,
		"IsUnexpected":    &maybeUnexpected,
		"Status":          &tr.Status,
		"SummaryHTML":     &summaryHTML,
		"StartTime":       &tr.StartTime,
		"RunDurationUsec": &micros,
		"Tags":            &tr.Tags,
		"InputArtifacts":  &tr.InputArtifacts,
		"OutputArtifacts": &tr.OutputArtifacts,
	})
	switch {
	case spanner.ErrCode(err) == codes.NotFound:
		return nil, errors.Reason("%q not found", name).
			InternalReason("%s", err).
			Tag(grpcutil.NotFoundTag).
			Err()
	case err != nil:
		return nil, errors.Annotate(err, "failed to fetch %q", name).Err()
	}

	tr.SummaryHtml = string(summaryHTML)
	populateExpectedField(tr, maybeUnexpected)
	populateDurationField(tr, micros)
	return tr, nil
}

// TestResultQuery specifies test results to fetch.
type TestResultQuery struct {
	InvocationIDs InvocationIDSet
	Predicate     *pb.TestResultPredicate // Predicate.Invocation must be nil.
	PageSize      int                     // must be positive
	PageToken     string
}

func queryTestResults(ctx context.Context, txn *spanner.ReadOnlyTransaction, q TestResultQuery, f func(tr *pb.TestResult) error) (err error) {
	switch {
	case q.PageSize < 0:
		panic("PageSize < 0")
	}

	from := "TestResults tr"
	if q.Predicate.GetExpectancy() == pb.TestResultPredicate_VARIANTS_WITH_UNEXPECTED_RESULTS {
		// We must return only test results of test variants that have unexpected results.
		//
		// The following query ensures that we first select test variants with
		// unexpected results, and then for each variant do a lookup in TestResults
		// table.
		from = `
			VariantsWithUnexpectedResults vur
			JOIN@{FORCE_JOIN_ORDER=TRUE} TestResults tr
				ON vur.TestId = tr.TestId AND vur.VariantHash = tr.VariantHash
		`
	}

	limit := ""
	if q.PageSize > 0 {
		limit = `LIMIT @limit`
	}

	st := spanner.NewStatement(fmt.Sprintf(`
		WITH VariantsWithUnexpectedResults AS (
			# Note: this query is not executed if it ends up not used in the top-level
			# query.
			SELECT DISTINCT TestId, VariantHash
			FROM TestResults@{FORCE_INDEX=UnexpectedTestResults}
			WHERE IsUnexpected AND InvocationId IN UNNEST(@invIDs)
		)
		SELECT
			tr.InvocationId,
			tr.TestId,
			tr.ResultId,
			tr.Variant,
			tr.IsUnexpected,
			tr.Status,
			tr.SummaryHtml,
			tr.StartTime,
			tr.RunDurationUsec,
			tr.Tags,
			tr.InputArtifacts,
			tr.OutputArtifacts
		FROM %s
		WHERE InvocationId IN UNNEST(@invIDs)
			# Skip test results after the one specified in the page token.
			AND (
				(tr.InvocationId > @afterInvocationId) OR
				(tr.InvocationId = @afterInvocationId AND tr.TestId > @afterTestId) OR
				(tr.InvocationId = @afterInvocationId AND tr.TestId = @afterTestId AND tr.ResultId > @afterResultId)
			)
			AND REGEXP_CONTAINS(tr.TestId, @TestIdRegexp)
		ORDER BY tr.InvocationId, tr.TestId, tr.ResultId
		%s
	`, from, limit))
	st.Params["invIDs"] = q.InvocationIDs
	st.Params["limit"] = q.PageSize

	testIDRegexp := q.Predicate.GetTestIdRegexp()
	if testIDRegexp == "" {
		testIDRegexp = ".*"
	}
	st.Params["TestIdRegexp"] = fmt.Sprintf("^%s$", testIDRegexp)

	st.Params["afterInvocationId"],
		st.Params["afterTestId"],
		st.Params["afterResultId"],
		err = parseTestObjectPageToken(q.PageToken)
	if err != nil {
		return
	}

	if q.Predicate.GetVariant() != nil {
		// TODO(nodir): add support for q.Predicate.Variant.
		return grpcutil.Unimplemented
	}

	var summaryHTML Compressed
	var b Buffer
	return query(ctx, txn, st, func(row *spanner.Row) error {
		var invID InvocationID
		var maybeUnexpected spanner.NullBool
		var micros int64
		tr := &pb.TestResult{}
		err = b.FromSpanner(row,
			&invID,
			&tr.TestId,
			&tr.ResultId,
			&tr.Variant,
			&maybeUnexpected,
			&tr.Status,
			&summaryHTML,
			&tr.StartTime,
			&micros,
			&tr.Tags,
			&tr.InputArtifacts,
			&tr.OutputArtifacts,
		)
		if err != nil {
			return err
		}

		tr.Name = pbutil.TestResultName(string(invID), tr.TestId, tr.ResultId)
		tr.SummaryHtml = string(summaryHTML)
		populateExpectedField(tr, maybeUnexpected)
		populateDurationField(tr, micros)

		return f(tr)
	})
}

// QueryTestResults reads test results matching the predicate.
// Returned test results from the same invocation are contiguous.
func QueryTestResults(ctx context.Context, txn *spanner.ReadOnlyTransaction, q TestResultQuery) (trs []*pb.TestResult, nextPageToken string, err error) {
	switch {
	case q.PageSize <= 0:
		panic("PageSize <= 0")
	}

	trs = make([]*pb.TestResult, 0, q.PageSize)
	err = queryTestResults(ctx, txn, q, func(tr *pb.TestResult) error {
		trs = append(trs, tr)
		return nil
	})
	if err != nil {
		trs = nil
		return
	}

	// If we got pageSize results, then we haven't exhausted the collection and
	// need to return the next page token.
	if len(trs) == q.PageSize {
		last := trs[q.PageSize-1]
		invID, testID, resultID := MustParseTestResultName(last.Name)
		nextPageToken = pagination.Token(string(invID), testID, resultID)
	}
	return
}

func populateDurationField(tr *pb.TestResult, micros int64) {
	tr.Duration = FromMicros(micros)
}

func populateExpectedField(tr *pb.TestResult, maybeUnexpected spanner.NullBool) {
	tr.Expected = !maybeUnexpected.Valid || !maybeUnexpected.Bool
}

// ToMicros converts a duration.Duration proto to microseconds.
func ToMicros(d *durpb.Duration) int64 {
	if d == nil {
		return 0
	}
	return 1e6*d.Seconds + int64(1e-3*float64(d.Nanos))
}

// FromMicros converts microseconds to a duration.Duration proto.
func FromMicros(micros int64) *durpb.Duration {
	return ptypes.DurationProto(time.Duration(1e3 * micros))
}

// parseTestObjectPageToken parses the page token into invocation ID, test id
// and a test object id.
func parseTestObjectPageToken(pageToken string) (inv InvocationID, testID, objID string, err error) {
	switch pos, tokErr := pagination.ParseToken(pageToken); {
	case tokErr != nil:
		err = encapsulatePageTokenError(tokErr)

	case pos == nil:

	case len(pos) != 3:
		err = encapsulatePageTokenError(errors.Reason("expected 3 position strings, got %q", pos).Err())

	default:
		inv = InvocationID(pos[0])
		testID = pos[1]
		objID = pos[2]
	}

	return
}

// encapsulatePageTokenError returns a generic error message that a page token
// is invalid and records err as an internal error.
// The returned error is anontated with INVALID_ARUGMENT code.
func encapsulatePageTokenError(err error) error {
	return errors.Reason("invalid page_token").InternalReason("%s", err).Tag(grpcutil.InvalidArgumentTag).Err()
}
<commit_msg>[resultdb] BigQuery Export: Add QueryTestResultsStreaming<commit_after>// Copyright 2019 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package span

import (
	"context"
	"fmt"
	"time"

	"cloud.google.com/go/spanner"
	"github.com/golang/protobuf/ptypes"
	durpb "github.com/golang/protobuf/ptypes/duration"
	"google.golang.org/grpc/codes"

	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/grpc/grpcutil"

	"go.chromium.org/luci/resultdb/internal/pagination"
	"go.chromium.org/luci/resultdb/pbutil"
	pb "go.chromium.org/luci/resultdb/proto/rpc/v1"
)

// MustParseTestResultName retrieves the invocation ID, unescaped test id, and
// result ID.
// Panics if the name is invalid. Useful for situations when name was already
// validated.
func MustParseTestResultName(name string) (invID InvocationID, testID, resultID string) {
	invIDStr, testID, resultID, err := pbutil.ParseTestResultName(name)
	if err != nil {
		panic(err)
	}
	invID = InvocationID(invIDStr)
	return
}

// ReadTestResult reads specified TestResult within the transaction.
// If the TestResult does not exist, the returned error is annotated with
// NotFound GRPC code.
func ReadTestResult(ctx context.Context, txn Txn, name string) (*pb.TestResult, error) {
	invID, testID, resultID := MustParseTestResultName(name)
	tr := &pb.TestResult{
		Name:     name,
		TestId:   testID,
		ResultId: resultID,
		Expected: true,
	}

	var maybeUnexpected spanner.NullBool
	var micros int64
	var summaryHTML Compressed
	err := ReadRow(ctx, txn, "TestResults", invID.Key(testID, resultID), map[string]interface{}{
		"Variant":         &tr.Variant,
		"IsUnexpected":    &maybeUnexpected,
		"Status":          &tr.Status,
		"SummaryHTML":     &summaryHTML,
		"StartTime":       &tr.StartTime,
		"RunDurationUsec": &micros,
		"Tags":            &tr.Tags,
		"InputArtifacts":  &tr.InputArtifacts,
		"OutputArtifacts": &tr.OutputArtifacts,
	})
	switch {
	case spanner.ErrCode(err) == codes.NotFound:
		return nil, errors.Reason("%q not found", name).
			InternalReason("%s", err).
			Tag(grpcutil.NotFoundTag).
			Err()
	case err != nil:
		return nil, errors.Annotate(err, "failed to fetch %q", name).Err()
	}

	tr.SummaryHtml = string(summaryHTML)
	populateExpectedField(tr, maybeUnexpected)
	populateDurationField(tr, micros)
	return tr, nil
}

// TestResultQuery specifies test results to fetch.
type TestResultQuery struct {
	InvocationIDs InvocationIDSet
	Predicate     *pb.TestResultPredicate // Predicate.Invocation must be nil.
	PageSize      int                     // must be positive
	PageToken     string
}

func queryTestResults(ctx context.Context, txn *spanner.ReadOnlyTransaction, q TestResultQuery, f func(tr *pb.TestResult) error) (err error) {
	if q.PageSize < 0 {
		panic("PageSize < 0")
	}

	from := "TestResults tr"
	if q.Predicate.GetExpectancy() == pb.TestResultPredicate_VARIANTS_WITH_UNEXPECTED_RESULTS {
		// We must return only test results of test variants that have unexpected results.
		//
		// The following query ensures that we first select test variants with
		// unexpected results, and then for each variant do a lookup in TestResults
		// table.
		from = `
			VariantsWithUnexpectedResults vur
			JOIN@{FORCE_JOIN_ORDER=TRUE} TestResults tr
				ON vur.TestId = tr.TestId AND vur.VariantHash = tr.VariantHash
		`
	}

	limit := ""
	if q.PageSize > 0 {
		limit = `LIMIT @limit`
	}

	st := spanner.NewStatement(fmt.Sprintf(`
		WITH VariantsWithUnexpectedResults AS (
			# Note: this query is not executed if it ends up not used in the top-level
			# query.
			SELECT DISTINCT TestId, VariantHash
			FROM TestResults@{FORCE_INDEX=UnexpectedTestResults}
			WHERE IsUnexpected AND InvocationId IN UNNEST(@invIDs)
		)
		SELECT
			tr.InvocationId,
			tr.TestId,
			tr.ResultId,
			tr.Variant,
			tr.IsUnexpected,
			tr.Status,
			tr.SummaryHtml,
			tr.StartTime,
			tr.RunDurationUsec,
			tr.Tags,
			tr.InputArtifacts,
			tr.OutputArtifacts
		FROM %s
		WHERE InvocationId IN UNNEST(@invIDs)
			# Skip test results after the one specified in the page token.
			AND (
				(tr.InvocationId > @afterInvocationId) OR
				(tr.InvocationId = @afterInvocationId AND tr.TestId > @afterTestId) OR
				(tr.InvocationId = @afterInvocationId AND tr.TestId = @afterTestId AND tr.ResultId > @afterResultId)
			)
			AND REGEXP_CONTAINS(tr.TestId, @TestIdRegexp)
		ORDER BY tr.InvocationId, tr.TestId, tr.ResultId
		%s
	`, from, limit))
	st.Params["invIDs"] = q.InvocationIDs
	st.Params["limit"] = q.PageSize

	testIDRegexp := q.Predicate.GetTestIdRegexp()
	if testIDRegexp == "" {
		testIDRegexp = ".*"
	}
	st.Params["TestIdRegexp"] = fmt.Sprintf("^%s$", testIDRegexp)

	st.Params["afterInvocationId"],
		st.Params["afterTestId"],
		st.Params["afterResultId"],
		err = parseTestObjectPageToken(q.PageToken)
	if err != nil {
		return
	}

	if q.Predicate.GetVariant() != nil {
		// TODO(nodir): add support for q.Predicate.Variant.
		return grpcutil.Unimplemented
	}

	var summaryHTML Compressed
	var b Buffer
	return query(ctx, txn, st, func(row *spanner.Row) error {
		var invID InvocationID
		var maybeUnexpected spanner.NullBool
		var micros int64
		tr := &pb.TestResult{}
		err = b.FromSpanner(row,
			&invID,
			&tr.TestId,
			&tr.ResultId,
			&tr.Variant,
			&maybeUnexpected,
			&tr.Status,
			&summaryHTML,
			&tr.StartTime,
			&micros,
			&tr.Tags,
			&tr.InputArtifacts,
			&tr.OutputArtifacts,
		)
		if err != nil {
			return err
		}

		tr.Name = pbutil.TestResultName(string(invID), tr.TestId, tr.ResultId)
		tr.SummaryHtml = string(summaryHTML)
		populateExpectedField(tr, maybeUnexpected)
		populateDurationField(tr, micros)

		return f(tr)
	})
}

// QueryTestResults reads test results matching the predicate.
// Returned test results from the same invocation are contiguous.
func QueryTestResults(ctx context.Context, txn *spanner.ReadOnlyTransaction, q TestResultQuery) (trs []*pb.TestResult, nextPageToken string, err error) {
	if q.PageSize <= 0 {
		panic("PageSize <= 0")
	}

	trs = make([]*pb.TestResult, 0, q.PageSize)
	err = queryTestResults(ctx, txn, q, func(tr *pb.TestResult) error {
		trs = append(trs, tr)
		return nil
	})
	if err != nil {
		trs = nil
		return
	}

	// If we got pageSize results, then we haven't exhausted the collection and
	// need to return the next page token.
	if len(trs) == q.PageSize {
		last := trs[q.PageSize-1]
		invID, testID, resultID := MustParseTestResultName(last.Name)
		nextPageToken = pagination.Token(string(invID), testID, resultID)
	}
	return
}

func QueryTestResultsStreaming(ctx context.Context, txn *spanner.ReadOnlyTransaction, q TestResultQuery, f func(tr *pb.TestResult) error) error {
	if q.PageSize > 0 {
		panic("PageSize is specified when QueryTestResultsStreaming")
	}
	return queryTestResults(ctx, txn, q, f)
}

func populateDurationField(tr *pb.TestResult, micros int64) {
	tr.Duration = FromMicros(micros)
}

func populateExpectedField(tr *pb.TestResult, maybeUnexpected spanner.NullBool) {
	tr.Expected = !maybeUnexpected.Valid || !maybeUnexpected.Bool
}

// ToMicros converts a duration.Duration proto to microseconds.
func ToMicros(d *durpb.Duration) int64 {
	if d == nil {
		return 0
	}
	return 1e6*d.Seconds + int64(1e-3*float64(d.Nanos))
}

// FromMicros converts microseconds to a duration.Duration proto.
func FromMicros(micros int64) *durpb.Duration {
	return ptypes.DurationProto(time.Duration(1e3 * micros))
}

// parseTestObjectPageToken parses the page token into invocation ID, test id
// and a test object id.
func parseTestObjectPageToken(pageToken string) (inv InvocationID, testID, objID string, err error) {
	switch pos, tokErr := pagination.ParseToken(pageToken); {
	case tokErr != nil:
		err = encapsulatePageTokenError(tokErr)

	case pos == nil:

	case len(pos) != 3:
		err = encapsulatePageTokenError(errors.Reason("expected 3 position strings, got %q", pos).Err())

	default:
		inv = InvocationID(pos[0])
		testID = pos[1]
		objID = pos[2]
	}

	return
}

// encapsulatePageTokenError returns a generic error message that a page token
// is invalid and records err as an internal error.
// The returned error is anontated with INVALID_ARUGMENT code.
func encapsulatePageTokenError(err error) error {
	return errors.Reason("invalid page_token").InternalReason("%s", err).Tag(grpcutil.InvalidArgumentTag).Err()
}
<|endoftext|>


<commit_before>package bigfft

import (
	"math/big"
)

// Arithmetic modulo 2^n+1.

// A fermat of length w+1 represents a number modulo 2^(w*_W) + 1. The last
// word is zero or one. A number has at most two representatives satisfying the
// 0-1 last word constraint.
type fermat nat

func (n fermat) String() string { return nat(n).String() }

func (z fermat) norm() {
	n := len(z) - 1
	c := z[n]
	if c == 0 {
		return
	}
	if z[0] >= c {
		z[n] = 0
		z[0] -= c
		return
	}
	// z[0] < z[n].
	subVW(z, z, c) // Substract c
	if c > 1 {
		z[n] -= c - 1
		c = 1
	}
	// Add back c.
	if z[n] == 1 {
		z[n] = 0
		return
	} else {
		addVW(z, z, 1)
	}
}

// Shift computes (x << k) mod (2^n+1).
func (z fermat) Shift(x fermat, k int) {
	if len(z) != len(x) {
		println(len(z), len(x))
		panic("len(z) != len(x) in Shift")
	}
	n := len(x) - 1
	// Shift by n*_W is taking the opposite.
	k %= 2 * n * _W
	if k < 0 {
		k += 2 * n * _W
	}
	neg := false
	if k >= n*_W {
		k -= n * _W
		neg = true
	}

	kw, kb := k/_W, k%_W

	z[n] = 1 // Add (-1)
	if !neg {
		for i := 0; i < kw; i++ {
			z[i] = 0
		}
		// Shift left by kw words.
		// x = a·2^(n-k) + b
		// x<<k = (b<<k) - a
		copy(z[kw:], x[:n-kw])
		b := subVV(z[:kw+1], z[:kw+1], x[n-kw:])
		if z[kw+1] > 0 {
			z[kw+1] -= b
		} else {
			subVW(z[kw+1:], z[kw+1:], b)
		}
	} else {
		for i := kw + 1; i < n; i++ {
			z[i] = 0
		}
		// Shift left and negate, by kw words.
		copy(z[:kw+1], x[n-kw:n+1])            // z_low = x_high
		b := subVV(z[kw:n], z[kw:n], x[:n-kw]) // z_high -= x_low
		z[n] -= b
	}
	// Add back 1.
	if z[0] < ^big.Word(0) {
		z[0]++
	} else {
		addVW(z, z, 1)
	}
	// Shift left by kb bits
	shlVU(z, z, uint(kb))
	z.norm()
}

// ShiftHalf shifts x by k/2 bits the left. Shifting by 1/2 bit
// is multiplication by sqrt(2) mod 2^n+1 which is 2^(3n/4) - 2^(n/4).
// A temporary buffer must be provided in tmp.
func (z fermat) ShiftHalf(x fermat, k int, tmp fermat) {
	n := len(z) - 1
	if k%2 == 0 {
		z.Shift(x, k/2)
		return
	}
	u := (k - 1) / 2
	a := u + (3*_W/4)*n
	b := u + (_W/4)*n
	z.Shift(x, a)
	tmp.Shift(x, b)
	z.Sub(z, tmp)
}

// Add computes addition mod 2^n+1.
func (z fermat) Add(x, y fermat) fermat {
	if len(z) != len(x) {
		panic("Add: len(z) != len(x)")
	}
	addVV(z, x, y) // there cannot be a carry here.
	z.norm()
	return z
}

// Sub computes substraction mod 2^n+1.
func (z fermat) Sub(x, y fermat) fermat {
	if len(z) != len(x) {
		panic("Add: len(z) != len(x)")
	}
	n := len(y) - 1
	b := subVV(z[:n], x[:n], y[:n])
	b += y[n]
	// If b > 0, we need to subtract b<<n, which is the same as adding b.
	z[n] = x[n]
	if z[0] <= ^big.Word(0)-b {
		z[0] += b
	} else {
		addVW(z, z, b)
	}
	z.norm()
	return z
}

func (z fermat) Mul(x, y fermat) fermat {
	var xi, yi, zi big.Int
	xi.SetBits(x)
	yi.SetBits(y)
	zi.SetBits(z)
	zb := zi.Mul(&xi, &yi).Bits()
	n := len(x) - 1
	if len(zb) <= n {
		// Short product.
		copy(z, zb)
		for i := len(zb); i < len(z); i++ {
			z[i] = 0
		}
		return z
	}
	z = zb
	// len(z) is at most 2n+1.
	if len(z) > 2*n+1 {
		panic("len(z) > 2n+1")
	}
	i := len(z) - (n + 1) // i <= n
	c := subVV(z[1:i+1], z[1:i+1], z[n+1:])
	z = z[:n+1]
	z[n]++ // Add -1.
	subVW(z[i+1:], z[i+1:], c)
	// Add 1.
	if z[n] == 1 {
		z[n] = 0
	} else {
		addVW(z, z, 1)
	}
	z.norm()
	return z
}
<commit_msg>Inline basicMul from math/big for small products.<commit_after>package bigfft

import (
	"math/big"
)

// Arithmetic modulo 2^n+1.

// A fermat of length w+1 represents a number modulo 2^(w*_W) + 1. The last
// word is zero or one. A number has at most two representatives satisfying the
// 0-1 last word constraint.
type fermat nat

func (n fermat) String() string { return nat(n).String() }

func (z fermat) norm() {
	n := len(z) - 1
	c := z[n]
	if c == 0 {
		return
	}
	if z[0] >= c {
		z[n] = 0
		z[0] -= c
		return
	}
	// z[0] < z[n].
	subVW(z, z, c) // Substract c
	if c > 1 {
		z[n] -= c - 1
		c = 1
	}
	// Add back c.
	if z[n] == 1 {
		z[n] = 0
		return
	} else {
		addVW(z, z, 1)
	}
}

// Shift computes (x << k) mod (2^n+1).
func (z fermat) Shift(x fermat, k int) {
	if len(z) != len(x) {
		println(len(z), len(x))
		panic("len(z) != len(x) in Shift")
	}
	n := len(x) - 1
	// Shift by n*_W is taking the opposite.
	k %= 2 * n * _W
	if k < 0 {
		k += 2 * n * _W
	}
	neg := false
	if k >= n*_W {
		k -= n * _W
		neg = true
	}

	kw, kb := k/_W, k%_W

	z[n] = 1 // Add (-1)
	if !neg {
		for i := 0; i < kw; i++ {
			z[i] = 0
		}
		// Shift left by kw words.
		// x = a·2^(n-k) + b
		// x<<k = (b<<k) - a
		copy(z[kw:], x[:n-kw])
		b := subVV(z[:kw+1], z[:kw+1], x[n-kw:])
		if z[kw+1] > 0 {
			z[kw+1] -= b
		} else {
			subVW(z[kw+1:], z[kw+1:], b)
		}
	} else {
		for i := kw + 1; i < n; i++ {
			z[i] = 0
		}
		// Shift left and negate, by kw words.
		copy(z[:kw+1], x[n-kw:n+1])            // z_low = x_high
		b := subVV(z[kw:n], z[kw:n], x[:n-kw]) // z_high -= x_low
		z[n] -= b
	}
	// Add back 1.
	if z[0] < ^big.Word(0) {
		z[0]++
	} else {
		addVW(z, z, 1)
	}
	// Shift left by kb bits
	shlVU(z, z, uint(kb))
	z.norm()
}

// ShiftHalf shifts x by k/2 bits the left. Shifting by 1/2 bit
// is multiplication by sqrt(2) mod 2^n+1 which is 2^(3n/4) - 2^(n/4).
// A temporary buffer must be provided in tmp.
func (z fermat) ShiftHalf(x fermat, k int, tmp fermat) {
	n := len(z) - 1
	if k%2 == 0 {
		z.Shift(x, k/2)
		return
	}
	u := (k - 1) / 2
	a := u + (3*_W/4)*n
	b := u + (_W/4)*n
	z.Shift(x, a)
	tmp.Shift(x, b)
	z.Sub(z, tmp)
}

// Add computes addition mod 2^n+1.
func (z fermat) Add(x, y fermat) fermat {
	if len(z) != len(x) {
		panic("Add: len(z) != len(x)")
	}
	addVV(z, x, y) // there cannot be a carry here.
	z.norm()
	return z
}

// Sub computes substraction mod 2^n+1.
func (z fermat) Sub(x, y fermat) fermat {
	if len(z) != len(x) {
		panic("Add: len(z) != len(x)")
	}
	n := len(y) - 1
	b := subVV(z[:n], x[:n], y[:n])
	b += y[n]
	// If b > 0, we need to subtract b<<n, which is the same as adding b.
	z[n] = x[n]
	if z[0] <= ^big.Word(0)-b {
		z[0] += b
	} else {
		addVW(z, z, b)
	}
	z.norm()
	return z
}

func (z fermat) Mul(x, y fermat) fermat {
	n := len(x) - 1
	if n < 30 {
		z = z[:2*n+2]
		basicMul(z, x, y)
		z = z[:2*n+1]
	} else {
		var xi, yi, zi big.Int
		xi.SetBits(x)
		yi.SetBits(y)
		zi.SetBits(z)
		zb := zi.Mul(&xi, &yi).Bits()
		if len(zb) <= n {
			// Short product.
			copy(z, zb)
			for i := len(zb); i < len(z); i++ {
				z[i] = 0
			}
			return z
		}
		z = zb
	}
	// len(z) is at most 2n+1.
	if len(z) > 2*n+1 {
		panic("len(z) > 2n+1")
	}
	i := len(z) - (n + 1) // i <= n
	c := subVV(z[1:i+1], z[1:i+1], z[n+1:])
	z = z[:n+1]
	z[n]++ // Add -1.
	subVW(z[i+1:], z[i+1:], c)
	// Add 1.
	if z[n] == 1 {
		z[n] = 0
	} else {
		addVW(z, z, 1)
	}
	z.norm()
	return z
}

// copied from math/big
//
// basicMul multiplies x and y and leaves the result in z.
// The (non-normalized) result is placed in z[0 : len(x) + len(y)].
func basicMul(z, x, y fermat) {
	// initialize z
	for i := 0; i < len(z); i++ {
		z[i] = 0
	}
	for i, d := range y {
		if d != 0 {
			z[len(x)+i] = addMulVVW(z[i:i+len(x)], x, d)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/go-sqlite/go1/sqlite3"
	"github.com/SlyMarbo/rss"
	"time"
)

/* RSS feed's */
var RSS = map[string]string {
	"miau":    "http://www.lets-hack.it/feed/",
	"marmaro": "http://marmaro.de/lue/feed.rss",
	"kuchen":  "https://kuchen.io/feed",
	"g0tmi1k": "https://blog.g0tmi1k.com/atom.xml",
}

var cursor *sqlite3.Conn

func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}

func initSQL() {
	cursor, _ = sqlite3.Open("feedme.db")

	query := "CREATE TABLE IF NOT EXISTS feed(" +
		"id        INTEGER PRIMARY KEY," +
		"site      VARCHAR(50)," +
		"title     VARCHAR(50) UNIQUE," +
		"link      VARCHAR(100)," +
		"date      INTEGER," +
		"read      INTEGER);"

	cursor.Exec(query)
}

func insertSQL(site string, title string, link string, date time.Time, read bool) {
	query := "INSERT INTO feed (site, title, link, date, read) " +
		"VALUES ($site, $title, $link, $date, $read);"

	sql := sqlite3.NamedArgs{
		"$site":  site,
		"$title": title,
		"$link":  link,
		"$date":  date,
		"$read":  read,
	}

	cursor.Exec(query, sql)
}

func main() {
	// initialize SQL database
	initSQL()

	for _, url := range RSS {
		feed, err := rss.Fetch(url)
		check_err(err)

		err = feed.Update()
		check_err(err)

		for _, element := range feed.Items {
			insertSQL(feed.Title, element.Title, element.Link,
				element.Date, element.Read)
		}
	}
}

/* vim: set noet sw=4 sts=4: */
<commit_msg>Fix mistake<commit_after>package main

import (
	"code.google.com/p/go-sqlite/go1/sqlite3"
	"github.com/SlyMarbo/rss"
	"time"
)

/* RSS feed's */
var RSS = map[string]string {
	"miau":    "http://www.lets-hack.it/feed/",
	"marmaro": "http://marmaro.de/lue/feed.rss",
	"kuchen":  "https://kuchen.io/feed",
	"g0tmi1k": "https://blog.g0tmi1k.com/atom.xml",
}

var cursor *sqlite3.Conn

func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}

func initSQL() {
	cursor, _ = sqlite3.Open("feedme.db")

	query := "CREATE TABLE IF NOT EXISTS feed(" +
		"id        INTEGER PRIMARY KEY," +
		"site      VARCHAR(50)," +
		"title     VARCHAR(50) UNIQUE," +
		"link      VARCHAR(100)," +
		"date      INTEGER," +
		"read      INTEGER);"

	cursor.Exec(query)
}

func insertSQL(site string, title string, link string, date time.Time, read bool) {
	query := "INSERT INTO feed (site, title, link, date, read) " +
		"VALUES ($site, $title, $link, $date, $read);"

	sql := sqlite3.NamedArgs{
		"$site":  site,
		"$title": title,
		"$link":  link,
		"$date":  date,
		"$read":  read,
	}

	cursor.Exec(query, sql)
}

func main() {
	// initialize SQL database
	initSQL()

	for _, url := range RSS {
		feed, err := rss.Fetch(url)
		checkErr(err)

		err = feed.Update()
		checkErr(err)

		for _, element := range feed.Items {
			insertSQL(feed.Title, element.Title, element.Link,
				element.Date, element.Read)
		}
	}
}

/* vim: set noet sw=4 sts=4: */
<|endoftext|>


<commit_before>package plugins

import (
	"errors"
	"log"
	"net/http"

	"github.com/adam-hanna/go-oauth2-server/config"
	"github.com/adam-hanna/go-oauth2-server/health"
	"github.com/adam-hanna/go-oauth2-server/oauth"
	"github.com/adam-hanna/go-oauth2-server/session"
	"github.com/adam-hanna/go-oauth2-server/web"
	"github.com/gorilla/sessions"
	"github.com/jinzhu/gorm"
	redisStore "gopkg.in/boj/redistore.v1"
)

// CustomHealthService extends health.ServiceInterface
type CustomHealthService struct {
	health.ServiceInterface
}

// NewHealthService defines a custom health service if the developer so chooses to implement one
func NewHealthService(db *gorm.DB) *CustomHealthService {
	// YOUR CODE, HERE
	return nil
}

// CustomAuthService extends health.ServiceInterface
type CustomAuthService struct {
	oauth.ServiceInterface
}

// NewOauthService defines a custom auth service if the developer so chooses to implement one
func NewOauthService(cnf *config.Config, db *gorm.DB) *CustomAuthService {
	// YOUR CODE, HERE
	return nil
}

// CustomSessionService extends health.ServiceInterface
type CustomSessionService struct {
	session.ServiceInterface
	sessionStore   sessions.Store
	sessionOptions *sessions.Options
	session        *sessions.Session
	r              *http.Request
	w              http.ResponseWriter
}

func (c *CustomSessionService) SetSessionService(r *http.Request, w http.ResponseWriter) {
	c.r = r
	c.w = w
}

func (c *CustomSessionService) StartSession() error {
	// Get a session.
	session, err := store.Get(c.r, session.UserSessionKey)
	if err != nil {
		return err
	}

	c.session = session
	return nil
}

func (c *CustomSessionService) GetUserSession() (*session.UserSession, error) {
	// Make sure StartSession has been called
	if c.session == nil {
		return nil, session.ErrSessonNotStarted
	}

	// Retrieve our user session struct and type-assert it
	userSession, ok := c.session.Values[session.UserSessionKey].(*session.UserSession)
	if !ok {
		return nil, errors.New("User session type assertion error")
	}

	return userSession, nil
}

func (c *CustomSessionService) SetUserSession(userSession *session.UserSession) error {
	// Make sure StartSession has been called
	if c.session == nil {
		return ErrSessonNotStarted
	}

	// Set a new user session
	c.session.Values[session.UserSessionKey] = userSession
	return c.session.Save(s.r, s.w)
}

func (c *CustomSessionService) ClearUserSession() error {
	c.session.Options.MaxAge = -1
	return c.sessions.Save(s.r, s.w)
}

func (c *CustomSessionService) SetFlashMessage(msg string) error {

}

func (c *CustomSessionService) GetFlashMessage() (interface{}, error) {

}

// NewSessionService defines a custom session service if the developer so chooses to implement one
func NewSessionService(cnf *config.Config) *CustomSessionService {
	store, err := redisStore.NewRediStore(10, "tcp", ":6379", "", []byte("secret-key"))
	if err != nil {
		log.Fatal(err)
	}
	// note @adam-hanna: how to handle this?
	// defer store.Close()

	return &CustomSessionService{
		// Session cookie storage
		sessionStore: store,
		// Session options
		sessionOptions: &sessions.Options{
			Path:     cnf.Session.Path,
			MaxAge:   cnf.Session.MaxAge,
			HttpOnly: cnf.Session.HTTPOnly,
		},
	}
}

// CustomWebService extends health.ServiceInterface
type CustomWebService struct {
	web.ServiceInterface
}

// NewWebService defines a custom web service if the developer so chooses to implement one
func NewWebService(cnf *config.Config, oauthService oauth.ServiceInterface, sessionService session.ServiceInterface) *CustomWebService {
	// YOUR CODE, HERE
	return nil
}
<commit_msg>no build errs<commit_after>package plugins

import (
	"errors"
	"log"
	"net/http"

	"github.com/adam-hanna/go-oauth2-server/config"
	"github.com/adam-hanna/go-oauth2-server/health"
	"github.com/adam-hanna/go-oauth2-server/oauth"
	"github.com/adam-hanna/go-oauth2-server/session"
	"github.com/adam-hanna/go-oauth2-server/web"
	"github.com/gorilla/sessions"
	"github.com/jinzhu/gorm"
	redisStore "gopkg.in/boj/redistore.v1"
)

// CustomHealthService extends health.ServiceInterface
type CustomHealthService struct {
	health.ServiceInterface
}

// NewHealthService defines a custom health service if the developer so chooses to implement one
func NewHealthService(db *gorm.DB) *CustomHealthService {
	// YOUR CODE, HERE
	return nil
}

// CustomAuthService extends health.ServiceInterface
type CustomAuthService struct {
	oauth.ServiceInterface
}

// NewOauthService defines a custom auth service if the developer so chooses to implement one
func NewOauthService(cnf *config.Config, db *gorm.DB) *CustomAuthService {
	// YOUR CODE, HERE
	return nil
}

// CustomSessionService extends health.ServiceInterface
type CustomSessionService struct {
	session.ServiceInterface
	sessionStore   sessions.Store
	sessionOptions *sessions.Options
	session        *sessions.Session
	r              *http.Request
	w              http.ResponseWriter
}

// SetSessionService custom SetSessionStore
func (c *CustomSessionService) SetSessionService(r *http.Request, w http.ResponseWriter) {
	c.r = r
	c.w = w
}

// StartSession custom StartSession
func (c *CustomSessionService) StartSession() error {
	// Get a session.
	session, err := c.sessionStore.Get(c.r, session.UserSessionKey)
	if err != nil {
		return err
	}

	c.session = session
	return nil
}

// GetUserSession custom GetUserSession
func (c *CustomSessionService) GetUserSession() (*session.UserSession, error) {
	// Make sure StartSession has been called
	if c.session == nil {
		return nil, session.ErrSessonNotStarted
	}

	// Retrieve our user session struct and type-assert it
	userSession, ok := c.session.Values[session.UserSessionKey].(*session.UserSession)
	if !ok {
		return nil, errors.New("User session type assertion error")
	}

	return userSession, nil
}

// SetUserSession custom SetUserSession
func (c *CustomSessionService) SetUserSession(userSession *session.UserSession) error {
	// Make sure StartSession has been called
	if c.session == nil {
		return session.ErrSessonNotStarted
	}

	// Set a new user session
	c.session.Values[session.UserSessionKey] = userSession
	return c.session.Save(c.r, c.w)
}

// ClearUserSession custom ClearUserSession
func (c *CustomSessionService) ClearUserSession() error {
	c.session.Options.MaxAge = -1
	return c.session.Save(c.r, c.w)
}

// SetFlashMessage custom SetFlashMessage
func (c *CustomSessionService) SetFlashMessage(msg string) error {
	// Make sure StartSession has been called
	if c.session == nil {
		return session.ErrSessonNotStarted
	}

	// Add the flash message
	c.session.AddFlash(msg)
	return c.session.Save(c.r, c.w)
}

// GetFlashMessage custom GetFlashMessage
func (c *CustomSessionService) GetFlashMessage() (interface{}, error) {
	// Make sure StartSession has been called
	if c.session == nil {
		return nil, session.ErrSessonNotStarted
	}

	// Get the last flash message from the stack
	if flashes := c.session.Flashes(); len(flashes) > 0 {
		// We need to save the session, otherwise the flash message won't be removed
		c.session.Save(c.r, c.w)
		return flashes[0], nil
	}

	// No flash messages in the stack
	return nil, nil
}

// NewSessionService defines a custom session service if the developer so chooses to implement one
func NewSessionService(cnf *config.Config) *CustomSessionService {
	store, err := redisStore.NewRediStore(10, "tcp", ":6379", "", []byte("secret-key"))
	if err != nil {
		log.Fatal(err)
	}
	// note @adam-hanna: how to handle this?
	// defer store.Close()

	return &CustomSessionService{
		// Session cookie storage
		sessionStore: store,
		// Session options
		sessionOptions: &sessions.Options{
			Path:     cnf.Session.Path,
			MaxAge:   cnf.Session.MaxAge,
			HttpOnly: cnf.Session.HTTPOnly,
		},
	}
}

// CustomWebService extends health.ServiceInterface
type CustomWebService struct {
	web.ServiceInterface
}

// NewWebService defines a custom web service if the developer so chooses to implement one
func NewWebService(cnf *config.Config, oauthService oauth.ServiceInterface, sessionService session.ServiceInterface) *CustomWebService {
	// YOUR CODE, HERE
	return nil
}
<|endoftext|>


<commit_before>package fixity

import (
	"io"

	"github.com/leeola/errors"
	"github.com/leeola/fixity/q"
)

// Fixity implements user focused writing and reading of data.
//
// This interface will be implemented for multiple stores, such as a local on
// disk store and a remote over network store.
type Fixity interface {
	// Blob returns a raw blob of the given hash.
	//
	// Mainly useful for inspecting the underlying data structure.
	//
	// TODO(leeola): change the name of this to something that does not conflict
	// with the Blob type. Since the Blob type is used to fetch the full rolled
	// contents of all the chunks, this method's name has an implication, which
	// is incorrect.
	Blob(hash string) (io.ReadCloser, error)

	// Blockchain allows one to manage and inspect the Fixity Blockchain.
	//
	// The blockchain is low level and should be used with care. See Blockchain
	// docstring for further details.
	Blockchain() Blockchain

	// Close shuts down any connections that may need to be closed.
	Close() error

	// Delete the given id's content from the fixity store.
	//
	// Each Content, Blob and Chunk will be deleted if no other block in the
	// blockchain depends on it. Verifying this is done by the garbage
	// collector and is a slow process.
	//
	// All blocks for the given id will be removed from the blockchain.
	Delete(id string) error

	// Read the latest Content with the given id.
	Read(id string) (Content, error)

	// Read the Content with the given hash.
	ReadHash(hash string) (Content, error)

	// Search for documents matching the given query.
	Search(*q.Query) ([]string, error)

	// Write the given reader to the fixity store and index fields.
	//
	// This is a shorthand for manually creating a WriteRequest.
	Write(id string, r io.Reader, f ...Field) (Content, error)

	// WriteRequest writes the given blob to Fixity with the associated settings.
	WriteRequest(*WriteRequest) (Content, error)
}

// Blockchain implements low level block management methods for Fixity.
//
// The fixity blockchain does not contain any traditional proof of work
// and does not have anything related to crypto or crypto currencies.
// The name was chosen in hopes to clearly express the ledger side of
// blockchains. While there will be many similarities in how the Fixity
// blockchain uses immutability and history, there will also be many
// differences from popular blockchains.
//
// A blockchain in Fixity serves as a ledger for what content exists
// on a distributed Fixity network. If a hash address cannot be found
// within one of the Blocks on the blockchain, such as the hash of
// a Content, Blob or Chunk, then it is considered available for
// garbage collection and will be removed.
//
// The Fixity blockchain consists of three main parts: The Block number,
// the PreviousBlockHash and some data effectively giving the Block a
// "type".
//
// The Block number is an ever incrementing value and with the help of
// PreviousBlockHash it provides a way for distributed nodes to achieve
// eventual consensus.
//
// The PreviousBlockHash provides a way to track the entire blockchain
// from the Head() Block. It also provides a way for the blockchain itself
// to be mutable, in an immutable environment. More on mutability soon.
//
// The Block type is the reason why the block exists. It may have added
// Content, removed Content, mutated the chain, etc.
//
// Mutability of the blockchain is achieved by appending new blocks that
// skip one or more blocks in their PreviousBlockHash. For example, with
// a blockchain of 5 blocks, Block 6 could be written with a
// PreviousBlockHash set to the hash of Block 4. Since Block 6 is the head,
// traversing the blockchain would look like: Block 6 -> Block 4 -> Block 3
// and so on. Note that Blocks start with 0 index, but for these examples
// we're not using zero index.
//
// To achieve mutability on blocks that aren't currently the Head()
// as Block 5 was in the previous example, all Blocks from the target
// Block to the Head() must be rewritten to the blockchain. In order.
// This means that removing old blocks can be costly and slow.
//
// Fixity strives to keep the ledger as a trustable and easy to verify
// chain. An alternative to block skipping would be to write a content
// deletion block, essentially writing to the ledger that content is
// to be garbage collected. However, verifying the ever growing blockchain
// would mean needing to reference these deletion blocks frequently to know
// what content should and shouldn't be looked into. In otherwords,
// content on the blockchain may have a deletion block for it further up
// the chain, so verifying content of the ledger becomes difficult.
//
// The chosen method of content skipping does most of the difficult work
// up front and results in a very clean ledger. It does this at the cost
// of needing to complicate the removal/skipping process.
//
// This interface focuses on all of the above functionality.
type Blockchain interface {
	// // AppendBlocks locks the store and writes the given blocks in order.
	// //
	// // The field PreviousBlockHash's value of all blocks *must* be empty.
	// //
	// // The returned Block array will contain the new hashes of the given
	// // blocks.
	// AppendBlocks(appendTo Block, blocks []Block) ([]Block, error)

	// AppendContent creates a new block with the given content.
	//
	// If the block is the same as the current Head() the blockchain must
	// not be progressed.
	AppendContent(Content) (Block, error)

	// Head returns the latest block in the blockchain.
	Head() (Block, error)

	// // SkipBlock removes the given block from the blockchain.
	// SkipBlock(Block) ([]Block, error)
}

// Block serves as a ledger for mutations of the fixity datastore.
//
// Each block stores an always incrementing Block number and a hash of
// the previous block in the chain. These two fields allow a fixity
// store to be iterated through the always appending history.
//
// While the history is always appending, previous blocks may be skipped,
// effectively removing them from the history of the blockchain. This is
// done by writing a new block whose PreviousBlockHash value skips one or
// more previous blocks in the chain.
type Block struct {
	// Block is the ever incrementing block number for this block.
	//
	// Each block will be incremented from the previous block.
	Block int `json:"block"`

	// PreviousBlockHash is the hash of the block that came before this.
	//
	// Note that the blockchain itself is mutable, such that the
	// PreviousBlockHash isn't guaranteed to have the block number of Block-1.
	// If a block was skipped, the block numbers may differ.
	//
	// See FixityBlockchain.SkipBlock for more information on block skipping
	// and implications of that.
	PreviousBlockHash string `json:"previousBlockHash"`

	// Skip contains Skip data and makes this Block a Skip Block.
	Skip *Skip `json:"skip,omitempty"`

	// ContentHash contains the ContentHash and makes this block a Content block.
	ContentHash string `json:"cotentHash,omitempty"`

	// Hash is the hash of the Block itself, provided by Fixity.
	//
	// This value is not stored.
	Hash string `json:"-"`

	// Store allows block method(s) to load previous blocks and content.
	//
	// This value is not stored.
	Store Store `json:"-"`
}

// Skip blocks provide information about the block that was skipped.
type Skip struct {
	// BlockHash of the block to be skipped.
	BlockHash string `json:"blockHash"`
}

// Content stores blob, index and history information for Fixity content.
type Content struct {
	// Id provides a user friendly way to reference a chain of Contents.
	//
	// History of Content is tracked through the PreviousContentHash chain,
	// however that does not provide a clear single identity for users.
	// The id field allows this, can be indexed and assocoated and is
	// easy to conceptualize.
	Id string `json:"id,omitempty"`

	// PreviousContentHash stores the previous Content for this Content.
	//
	// This allows a single entity, such as a file or a database "record"
	// to be mutated through time. To reference this history of contents,
	// the Id is used.
	PreviousContentHash string `json:"previousContentHash,omitempty"`

	// BlobHash is the hash of the  Blob containing this content's data.
	BlobHash string `json:"blobHash"`

	// IndexedFields contains the indexed metadata for this content.
	//
	// This allows the content to be searched for and can be used to
	// store basic metadata about the content.
	IndexedFields Fields `json:"indexedFields,omitempty"`

	// Hash is the hash of the Content itself, provided by Fixity.
	//
	// This value is not stored.
	Hash string `json:"-"`

	// Store allows block method(s) to load previous content.
	//
	// This value is not stored.
	Store Store `json:"-"`
}

// Blob stores a series of ordered ChunkHashes
type Blob struct {
	ChunkHashes []string `json:"chunkHashes"`
	Size        int64    `json:"size,omitempty"`
	RollSize    int64    `json:"rollSize,omitempty"`

	// NextBlobHash is not currently supported / implemented anywhere, but
	// is required for very large storage. Eg, if there are so many chunks
	// for a given dataset that it cannot be stored in memory during writing
	// and reading, then we will need to split them up via NextBlobHash.
	//
	// // NextBlobHash stores another blob which is to be appended to this blob.
	// //
	// // This serves to allow very large blobs that cannot be loaded entirely
	// // into to memory to be split up into many parts.
	// NextBlobHash string `json:"nextBlobHash,omitempty"`

	// Hash is the hash of the Blob itself, provided by Fixity.
	//
	// This value is not stored.
	Hash string `json:"-"`

	// Store allows block method(s) to load previous content.
	//
	// This value is not stored.
	Store Store `json:"-"`
}

type Chunk struct {
	ChunkBytes []byte `json:"chunkBytes"`
	Size       int64  `json:"size"`
}

func (b *Block) PreviousBlock() (Block, error) {
	if b.Store == nil {
		return Block{}, errors.New("previousblock: Store not set")
	}

	if b.PreviousBlockHash == "" {
		return Block{}, nil
	}

	var previousBlock Block
	err := readAndUnmarshal(b.Store, b.PreviousBlockHash, &previousBlock)
	if err != nil {
		return Block{}, err
	}

	previousBlock.Hash = b.PreviousBlockHash
	previousBlock.Store = b.Store

	return previousBlock, nil
}

func (b *Block) Content() (Content, error) {
	if b.Store == nil {
		return Content{}, errors.New("content: Store not set")
	}

	if b.ContentHash == "" {
		return Content{}, errors.New("content: contentHash is empty")
	}

	var c Content
	err := readAndUnmarshal(b.Store, b.ContentHash, &c)
	if err != nil {
		return Content{}, err
	}

	c.Hash = b.ContentHash
	c.Store = b.Store

	return c, nil
}

func (c *Content) Blob() (Blob, error) {
	if c.Store == nil {
		return Blob{}, errors.New("blob: Store not set")
	}

	if c.BlobHash == "" {
		return Blob{}, errors.New("blob: blobHash is empty")
	}

	var b Blob
	err := readAndUnmarshal(c.Store, c.BlobHash, &b)
	if err != nil {
		return Blob{}, err
	}
	b.Hash = c.BlobHash
	b.Store = c.Store

	return b, nil
}

func (c *Content) Read() (io.ReadCloser, error) {
	b, err := c.Blob()
	if err != nil {
		return nil, err
	}

	return b.Read()
}

func (b *Blob) Read() (io.ReadCloser, error) {
	if b.Store == nil {
		return nil, errors.New("read: Store not set")
	}

	return Reader(b.Store, b.Hash), nil
}
<commit_msg>feat: added optional chunking metadata fields<commit_after>package fixity

import (
	"io"

	"github.com/leeola/errors"
	"github.com/leeola/fixity/q"
)

// Fixity implements user focused writing and reading of data.
//
// This interface will be implemented for multiple stores, such as a local on
// disk store and a remote over network store.
type Fixity interface {
	// Blob returns a raw blob of the given hash.
	//
	// Mainly useful for inspecting the underlying data structure.
	//
	// TODO(leeola): change the name of this to something that does not conflict
	// with the Blob type. Since the Blob type is used to fetch the full rolled
	// contents of all the chunks, this method's name has an implication, which
	// is incorrect.
	Blob(hash string) (io.ReadCloser, error)

	// Blockchain allows one to manage and inspect the Fixity Blockchain.
	//
	// The blockchain is low level and should be used with care. See Blockchain
	// docstring for further details.
	Blockchain() Blockchain

	// Close shuts down any connections that may need to be closed.
	Close() error

	// Delete the given id's content from the fixity store.
	//
	// Each Content, Blob and Chunk will be deleted if no other block in the
	// blockchain depends on it. Verifying this is done by the garbage
	// collector and is a slow process.
	//
	// All blocks for the given id will be removed from the blockchain.
	Delete(id string) error

	// Read the latest Content with the given id.
	Read(id string) (Content, error)

	// Read the Content with the given hash.
	ReadHash(hash string) (Content, error)

	// Search for documents matching the given query.
	Search(*q.Query) ([]string, error)

	// Write the given reader to the fixity store and index fields.
	//
	// This is a shorthand for manually creating a WriteRequest.
	Write(id string, r io.Reader, f ...Field) (Content, error)

	// WriteRequest writes the given blob to Fixity with the associated settings.
	WriteRequest(*WriteRequest) (Content, error)
}

// Blockchain implements low level block management methods for Fixity.
//
// The fixity blockchain does not contain any traditional proof of work
// and does not have anything related to crypto or crypto currencies.
// The name was chosen in hopes to clearly express the ledger side of
// blockchains. While there will be many similarities in how the Fixity
// blockchain uses immutability and history, there will also be many
// differences from popular blockchains.
//
// A blockchain in Fixity serves as a ledger for what content exists
// on a distributed Fixity network. If a hash address cannot be found
// within one of the Blocks on the blockchain, such as the hash of
// a Content, Blob or Chunk, then it is considered available for
// garbage collection and will be removed.
//
// The Fixity blockchain consists of three main parts: The Block number,
// the PreviousBlockHash and some data effectively giving the Block a
// "type".
//
// The Block number is an ever incrementing value and with the help of
// PreviousBlockHash it provides a way for distributed nodes to achieve
// eventual consensus.
//
// The PreviousBlockHash provides a way to track the entire blockchain
// from the Head() Block. It also provides a way for the blockchain itself
// to be mutable, in an immutable environment. More on mutability soon.
//
// The Block type is the reason why the block exists. It may have added
// Content, removed Content, mutated the chain, etc.
//
// Mutability of the blockchain is achieved by appending new blocks that
// skip one or more blocks in their PreviousBlockHash. For example, with
// a blockchain of 5 blocks, Block 6 could be written with a
// PreviousBlockHash set to the hash of Block 4. Since Block 6 is the head,
// traversing the blockchain would look like: Block 6 -> Block 4 -> Block 3
// and so on. Note that Blocks start with 0 index, but for these examples
// we're not using zero index.
//
// To achieve mutability on blocks that aren't currently the Head()
// as Block 5 was in the previous example, all Blocks from the target
// Block to the Head() must be rewritten to the blockchain. In order.
// This means that removing old blocks can be costly and slow.
//
// Fixity strives to keep the ledger as a trustable and easy to verify
// chain. An alternative to block skipping would be to write a content
// deletion block, essentially writing to the ledger that content is
// to be garbage collected. However, verifying the ever growing blockchain
// would mean needing to reference these deletion blocks frequently to know
// what content should and shouldn't be looked into. In otherwords,
// content on the blockchain may have a deletion block for it further up
// the chain, so verifying content of the ledger becomes difficult.
//
// The chosen method of content skipping does most of the difficult work
// up front and results in a very clean ledger. It does this at the cost
// of needing to complicate the removal/skipping process.
//
// This interface focuses on all of the above functionality.
type Blockchain interface {
	// // AppendBlocks locks the store and writes the given blocks in order.
	// //
	// // The field PreviousBlockHash's value of all blocks *must* be empty.
	// //
	// // The returned Block array will contain the new hashes of the given
	// // blocks.
	// AppendBlocks(appendTo Block, blocks []Block) ([]Block, error)

	// AppendContent creates a new block with the given content.
	//
	// If the block is the same as the current Head() the blockchain must
	// not be progressed.
	AppendContent(Content) (Block, error)

	// Head returns the latest block in the blockchain.
	Head() (Block, error)

	// // SkipBlock removes the given block from the blockchain.
	// SkipBlock(Block) ([]Block, error)
}

// Block serves as a ledger for mutations of the fixity datastore.
//
// Each block stores an always incrementing Block number and a hash of
// the previous block in the chain. These two fields allow a fixity
// store to be iterated through the always appending history.
//
// While the history is always appending, previous blocks may be skipped,
// effectively removing them from the history of the blockchain. This is
// done by writing a new block whose PreviousBlockHash value skips one or
// more previous blocks in the chain.
type Block struct {
	// Block is the ever incrementing block number for this block.
	//
	// Each block will be incremented from the previous block.
	Block int `json:"block"`

	// PreviousBlockHash is the hash of the block that came before this.
	//
	// Note that the blockchain itself is mutable, such that the
	// PreviousBlockHash isn't guaranteed to have the block number of Block-1.
	// If a block was skipped, the block numbers may differ.
	//
	// See FixityBlockchain.SkipBlock for more information on block skipping
	// and implications of that.
	PreviousBlockHash string `json:"previousBlockHash"`

	// Skip contains Skip data and makes this Block a Skip Block.
	Skip *Skip `json:"skip,omitempty"`

	// ContentHash contains the ContentHash and makes this block a Content block.
	ContentHash string `json:"cotentHash,omitempty"`

	// Hash is the hash of the Block itself, provided by Fixity.
	//
	// This value is not stored.
	Hash string `json:"-"`

	// Store allows block method(s) to load previous blocks and content.
	//
	// This value is not stored.
	Store Store `json:"-"`
}

// Skip blocks provide information about the block that was skipped.
type Skip struct {
	// BlockHash of the block to be skipped.
	BlockHash string `json:"blockHash"`
}

// Content stores blob, index and history information for Fixity content.
type Content struct {
	// Id provides a user friendly way to reference a chain of Contents.
	//
	// History of Content is tracked through the PreviousContentHash chain,
	// however that does not provide a clear single identity for users.
	// The id field allows this, can be indexed and assocoated and is
	// easy to conceptualize.
	Id string `json:"id,omitempty"`

	// PreviousContentHash stores the previous Content for this Content.
	//
	// This allows a single entity, such as a file or a database "record"
	// to be mutated through time. To reference this history of contents,
	// the Id is used.
	PreviousContentHash string `json:"previousContentHash,omitempty"`

	// BlobHash is the hash of the  Blob containing this content's data.
	BlobHash string `json:"blobHash"`

	// IndexedFields contains the indexed metadata for this content.
	//
	// This allows the content to be searched for and can be used to
	// store basic metadata about the content.
	IndexedFields Fields `json:"indexedFields,omitempty"`

	// Hash is the hash of the Content itself, provided by Fixity.
	//
	// This value is not stored.
	Hash string `json:"-"`

	// Store allows block method(s) to load previous content.
	//
	// This value is not stored.
	Store Store `json:"-"`
}

// Blob stores a series of ordered ChunkHashes
type Blob struct {
	ChunkHashes []string `json:"chunkHashes"`
	Size        int64    `json:"size,omitempty"`
	RollSize    int64    `json:"rollSize,omitempty"`

	// NextBlobHash is not currently supported / implemented anywhere, but
	// is required for very large storage. Eg, if there are so many chunks
	// for a given dataset that it cannot be stored in memory during writing
	// and reading, then we will need to split them up via NextBlobHash.
	//
	// // NextBlobHash stores another blob which is to be appended to this blob.
	// //
	// // This serves to allow very large blobs that cannot be loaded entirely
	// // into to memory to be split up into many parts.
	// NextBlobHash string `json:"nextBlobHash,omitempty"`

	// Hash is the hash of the Blob itself, provided by Fixity.
	//
	// This value is not stored.
	Hash string `json:"-"`

	// Store allows block method(s) to load previous content.
	//
	// This value is not stored.
	Store Store `json:"-"`
}

// Chunk represents a content defined chunk of data in fixity.
type Chunk struct {
	ChunkBytes []byte `json:"chunkBytes"`
	Size       int64  `json:"size"`

	// Start of this chunk within the bounds of the Blob.
	//
	// NOTE: This is not stored in the Fixity Store and is only a means to
	// allow the chunker to return additional data about the created chunk.
	// If this was stored in Fixity, each Chunk would have a different
	// Content Address, defeating the purpose of CDC & Content Addressed
	// storage.
	StartBoundry uint `json:"-"`

	// End of this chunk within the bounds of the Blob.
	//
	// NOTE: This is not stored in the Fixity Store and is only a means to
	// allow the chunker to return additional data about the created chunk.
	// If this was stored in Fixity, each Chunk would have a different
	// Content Address, defeating the purpose of CDC & Content Addressed
	// storage.
	EndBoundry uint `json:"-"`
}

func (b *Block) PreviousBlock() (Block, error) {
	if b.Store == nil {
		return Block{}, errors.New("previousblock: Store not set")
	}

	if b.PreviousBlockHash == "" {
		return Block{}, nil
	}

	var previousBlock Block
	err := readAndUnmarshal(b.Store, b.PreviousBlockHash, &previousBlock)
	if err != nil {
		return Block{}, err
	}

	previousBlock.Hash = b.PreviousBlockHash
	previousBlock.Store = b.Store

	return previousBlock, nil
}

func (b *Block) Content() (Content, error) {
	if b.Store == nil {
		return Content{}, errors.New("content: Store not set")
	}

	if b.ContentHash == "" {
		return Content{}, errors.New("content: contentHash is empty")
	}

	var c Content
	err := readAndUnmarshal(b.Store, b.ContentHash, &c)
	if err != nil {
		return Content{}, err
	}

	c.Hash = b.ContentHash
	c.Store = b.Store

	return c, nil
}

func (c *Content) Blob() (Blob, error) {
	if c.Store == nil {
		return Blob{}, errors.New("blob: Store not set")
	}

	if c.BlobHash == "" {
		return Blob{}, errors.New("blob: blobHash is empty")
	}

	var b Blob
	err := readAndUnmarshal(c.Store, c.BlobHash, &b)
	if err != nil {
		return Blob{}, err
	}
	b.Hash = c.BlobHash
	b.Store = c.Store

	return b, nil
}

func (c *Content) Read() (io.ReadCloser, error) {
	b, err := c.Blob()
	if err != nil {
		return nil, err
	}

	return b.Read()
}

func (b *Blob) Read() (io.ReadCloser, error) {
	if b.Store == nil {
		return nil, errors.New("read: Store not set")
	}

	return Reader(b.Store, b.Hash), nil
}
<|endoftext|>