<commit_before>package main

import (
	"flag"
	"fmt"

	"github.com/sipt/Gotling/common"
	"github.com/sipt/Gotling/encoding"
	"github.com/sipt/Gotling/exec"
	"github.com/sipt/Gotling/network"
	"github.com/sipt/Gotling/room"
	"github.com/sipt/Gotling/transport"
	"github.com/sipt/Gotling/utils"
)

func main() {
	var cport = flag.Int("cport", 20011, "udp listen port")
	var sport = flag.Int("sport", 20010, "udp listen port")
	var ip = flag.String("ip", "127.0.0.1", "udp server ip")
	flag.Parse()
	encoder := encoding.NewJSONEncoder()
	conn := network.NewUDPConn(*cport)
	config := transport.NewServerConfig("udp", *ip, *sport)
	transporter := transport.NewTransporter(conn, encoder, config)
	building := room.NewBuilding()
	executor := exec.NewExecutor(exec.ClientMode, transporter, building)
	result := executor.LoopExec()
	go func() {
		for {
			msg := <-result
			fmt.Printf("[%d]:%s\n", msg.UserID, string(msg.Data))
		}
	}()
	var commond string
	var id int64
	var user = &common.User{
		ID: utils.UniqueID(),
	}
	var roomID int64 = -1
	fmt.Print("Gotaling:\n请输入昵称：\n➜ ")
	fmt.Scanf("%s", &user.Nick)
	for {
		if roomID < 0 {
			fmt.Print("\n➜ ")
		} else {
			fmt.Printf("\n[%d]➜ ", roomID)
		}
		fmt.Scanf("%s %d", &commond, &id)
		switch commond {
		case "into":
			msg := &common.Message{
				RoomID: id,
				UserID: user.ID,
				Type:   common.MsgTypeUserIntoRoom,
			}
			err := executor.ToServer(msg)
			if err != nil {
				fmt.Println("err:", err)
			} else {
				roomID = id
			}
		case "out":
			msg := &common.Message{
				RoomID: roomID,
				UserID: user.ID,
				Type:   common.MsgTypeUserAwayRoom,
			}
			err := executor.ToServer(msg)
			if err != nil {
				fmt.Println("err:", err)
			} else {
				roomID = -1
			}
		default:
			msg := &common.Message{
				Data:   []byte(commond),
				RoomID: roomID,
				UserID: user.ID,
				Type:   common.MsgType,
			}
			err := executor.ToServer(msg)
			if err != nil {
				fmt.Println("err:", err)
			}
		}
	}
}
<commit_msg>show userid<commit_after>package main

import (
	"flag"
	"fmt"

	"github.com/sipt/Gotling/common"
	"github.com/sipt/Gotling/encoding"
	"github.com/sipt/Gotling/exec"
	"github.com/sipt/Gotling/network"
	"github.com/sipt/Gotling/room"
	"github.com/sipt/Gotling/transport"
	"github.com/sipt/Gotling/utils"
)

func main() {
	var cport = flag.Int("cport", 20011, "udp listen port")
	var sport = flag.Int("sport", 20010, "udp listen port")
	var ip = flag.String("ip", "127.0.0.1", "udp server ip")
	flag.Parse()
	encoder := encoding.NewJSONEncoder()
	conn := network.NewUDPConn(*cport)
	config := transport.NewServerConfig("udp", *ip, *sport)
	transporter := transport.NewTransporter(conn, encoder, config)
	building := room.NewBuilding()
	executor := exec.NewExecutor(exec.ClientMode, transporter, building)
	result := executor.LoopExec()
	go func() {
		for {
			msg := <-result
			fmt.Printf("[%d]:%s\n", msg.UserID, string(msg.Data))
		}
	}()
	var commond string
	var id int64
	var user = &common.User{
		ID: utils.UniqueID(),
	}
	var roomID int64 = -1
	fmt.Printf("Gotaling [%d]:\n请输入昵称：\n➜ ", user.ID)
	fmt.Scanf("%s", &user.Nick)
	for {
		if roomID < 0 {
			fmt.Print("\n➜ ")
		} else {
			fmt.Printf("\n[%d]➜ ", roomID)
		}
		fmt.Scanf("%s %d", &commond, &id)
		switch commond {
		case "into":
			msg := &common.Message{
				RoomID: id,
				UserID: user.ID,
				Type:   common.MsgTypeUserIntoRoom,
			}
			err := executor.ToServer(msg)
			if err != nil {
				fmt.Println("err:", err)
			} else {
				roomID = id
			}
		case "out":
			msg := &common.Message{
				RoomID: roomID,
				UserID: user.ID,
				Type:   common.MsgTypeUserAwayRoom,
			}
			err := executor.ToServer(msg)
			if err != nil {
				fmt.Println("err:", err)
			} else {
				roomID = -1
			}
		default:
			msg := &common.Message{
				Data:   []byte(commond),
				RoomID: roomID,
				UserID: user.ID,
				Type:   common.MsgType,
			}
			err := executor.ToServer(msg)
			if err != nil {
				fmt.Println("err:", err)
			}
		}
	}
}
<|endoftext|>


<commit_before>package log

import (
	"fmt"
	"github.com/viant/endly"
	"github.com/viant/endly/model/msg"
	"github.com/viant/endly/workflow"
	"github.com/viant/toolbox"
	"github.com/viant/toolbox/storage"
	"io"
	"io/ioutil"
	"strings"
	"sync"
	"time"
)

//File represents a log file
type File struct {
	URL     string
	Content string
	Name    string
	*Type
	ProcessingState *ProcessingState
	LastModified    time.Time
	Size            int
	Records         []*Record
	IndexedRecords  map[string]*Record
	Mutex           *sync.RWMutex
	context         *endly.Context
}

//ShiftLogRecord returns and remove the first log record if present
func (f *File) ShiftLogRecord() *Record {
	f.Mutex.Lock()
	defer f.Mutex.Unlock()
	if len(f.Records) == 0 {
		return nil
	}
	result := f.Records[0]
	f.Records = f.Records[1:]
	if f.Type.Debug {
		info, _ := toolbox.AsJSONText(result)
		_ = endly.Run(f.context, &workflow.PrintRequest{
			Style:   msg.MessageStyleOutput,
			Message: fmt.Sprintf("shift [%v] -> %v", f.Type.Name, info),
		}, nil)
	}
	return result
}

//ShiftLogRecordByIndex returns and remove the first log record if present
func (f *File) ShiftLogRecordByIndex(value string) *Record {
	f.Mutex.Lock()
	defer f.Mutex.Unlock()
	if len(f.Records) == 0 {
		return nil
	}
	result, has := f.IndexedRecords[value]
	if !has {
		result = f.Records[0]
		f.Records = f.Records[1:]
	} else {
		var records = make([]*Record, 0)
		for _, candidate := range f.Records {
			if candidate == result {
				continue
			}
			records = append(records, candidate)
		}
		f.Records = records
	}

	if f.Type.Debug {
		info, _ := toolbox.AsJSONText(result)
		_ = endly.Run(f.context, &workflow.PrintRequest{
			Style:   msg.MessageStyleOutput,
			Message: fmt.Sprintf("shifted [%v:idx:%s]-> %v", f.Type.Name, value, info),
		}, nil)
	}

	return result
}

//PushLogRecord appends provided log record to the records.
func (f *File) PushLogRecord(record *Record) {
	f.Mutex.Lock()
	defer f.Mutex.Unlock()
	if len(f.Records) == 0 {
		f.Records = make([]*Record, 0)
	}

	if f.Type.Debug {
		info, _ := toolbox.AsJSONText(record)
		_ = endly.Run(f.context, &workflow.PrintRequest{
			Style:   msg.MessageStyleInput,
			Message: fmt.Sprintf("push [%v] <- %v", f.Type.Name, info),
		}, nil)
	}

	f.Records = append(f.Records, record)
	if f.UseIndex() {
		if expr, err := f.GetIndexExpr(); err == nil {
			var indexValue = matchLogIndex(expr, record.Line)
			if indexValue != "" {
				f.IndexedRecords[indexValue] = record
			}
		}
	}
}

//Reset resets processing state
func (f *File) Reset(object storage.Object) {
	f.Mutex.Lock()
	defer f.Mutex.Unlock()
	f.Size = int(object.FileInfo().Size())
	f.LastModified = object.FileInfo().ModTime()
	f.ProcessingState.Reset()
}

//HasPendingLogs returns true if file has pending validation records
func (f *File) HasPendingLogs() bool {
	f.Mutex.Lock()
	defer f.Mutex.Unlock()
	return len(f.Records) > 0
}

func (f *File) readLogRecords(reader io.Reader) error {
	data, err := ioutil.ReadAll(reader)
	if err != nil {
		return err
	}
	if f.ProcessingState.Position > len(data) {
		return nil
	}
	var line = ""
	var startPosition = f.ProcessingState.Position
	var startLine = f.ProcessingState.Line
	var lineIndex = startLine
	var dataProcessed = 0
	for i := startPosition; i < len(data); i++ {
		dataProcessed++
		aChar := string(data[i])
		if aChar != "\n" && aChar != "\r" {
			line += aChar
			continue
		}

		line = strings.Trim(line, " \r\t")
		lineIndex++
		if f.Exclusion != "" {
			if strings.Contains(line, f.Exclusion) {
				line, dataProcessed = f.ProcessingState.Update(dataProcessed, lineIndex)
				continue
			}
		}
		if f.Inclusion != "" {
			if !strings.Contains(line, f.Inclusion) {
				line, dataProcessed = f.ProcessingState.Update(dataProcessed, lineIndex)
				continue
			}
		}

		if len(line) > 0 {
			f.PushLogRecord(&Record{
				URL:    f.URL,
				Line:   line,
				Number: lineIndex,
			})
		}
		if err != nil {
			return err
		}
		line, dataProcessed = f.ProcessingState.Update(dataProcessed, lineIndex)
	}
	return nil
}
<commit_msg>added debug index details<commit_after>package log

import (
	"fmt"
	"github.com/viant/endly"
	"github.com/viant/endly/model/msg"
	"github.com/viant/endly/workflow"
	"github.com/viant/toolbox"
	"github.com/viant/toolbox/storage"
	"io"
	"io/ioutil"
	"strings"
	"sync"
	"time"
)

//File represents a log file
type File struct {
	URL     string
	Content string
	Name    string
	*Type
	ProcessingState *ProcessingState
	LastModified    time.Time
	Size            int
	Records         []*Record
	IndexedRecords  map[string]*Record
	Mutex           *sync.RWMutex
	context         *endly.Context
}

//ShiftLogRecord returns and remove the first log record if present
func (f *File) ShiftLogRecord() *Record {
	f.Mutex.Lock()
	defer f.Mutex.Unlock()
	if len(f.Records) == 0 {
		return nil
	}
	result := f.Records[0]
	f.Records = f.Records[1:]
	if f.Type.Debug {
		info, _ := toolbox.AsJSONText(result)
		_ = endly.Run(f.context, &workflow.PrintRequest{
			Style:   msg.MessageStyleOutput,
			Message: fmt.Sprintf("shift [%v] -> %v", f.Type.Name, info),
		}, nil)
	}
	return result
}

//ShiftLogRecordByIndex returns and remove the first log record if present
func (f *File) ShiftLogRecordByIndex(value string) *Record {
	f.Mutex.Lock()
	defer f.Mutex.Unlock()
	if len(f.Records) == 0 {
		return nil
	}
	result, has := f.IndexedRecords[value]
	if !has {
		result = f.Records[0]
		f.Records = f.Records[1:]
	} else {
		var records = make([]*Record, 0)
		for _, candidate := range f.Records {
			if candidate == result {
				continue
			}
			records = append(records, candidate)
		}
		f.Records = records
	}

	if f.Type.Debug {
		info, _ := toolbox.AsJSONText(result)
		_ = endly.Run(f.context, &workflow.PrintRequest{
			Style:   msg.MessageStyleOutput,
			Message: fmt.Sprintf("shifted [%v:idx:%s]-> %v", f.Type.Name, value, info),
		}, nil)
	}

	return result
}

//PushLogRecord appends provided log record to the records.
func (f *File) PushLogRecord(record *Record) {
	f.Mutex.Lock()
	defer f.Mutex.Unlock()
	if len(f.Records) == 0 {
		f.Records = make([]*Record, 0)
	}

	indexValue := ""
	f.Records = append(f.Records, record)
	if f.UseIndex() {
		if expr, err := f.GetIndexExpr(); err == nil {
			indexValue = matchLogIndex(expr, record.Line)
			if indexValue != "" {
				f.IndexedRecords[indexValue] = record
			}
		}
	}
	if f.Type.Debug {
		if indexValue != "" {
			indexValue = " idx:" + indexValue
		}
		info, _ := toolbox.AsJSONText(record)
		_ = endly.Run(f.context, &workflow.PrintRequest{
			Style:   msg.MessageStyleInput,
			Message: fmt.Sprintf("push [%v%v] <- %v", f.Type.Name, indexValue, info),
		}, nil)
	}

}

//Reset resets processing state
func (f *File) Reset(object storage.Object) {
	f.Mutex.Lock()
	defer f.Mutex.Unlock()
	f.Size = int(object.FileInfo().Size())
	f.LastModified = object.FileInfo().ModTime()
	f.ProcessingState.Reset()
}

//HasPendingLogs returns true if file has pending validation records
func (f *File) HasPendingLogs() bool {
	f.Mutex.Lock()
	defer f.Mutex.Unlock()
	return len(f.Records) > 0
}

func (f *File) readLogRecords(reader io.Reader) error {
	data, err := ioutil.ReadAll(reader)
	if err != nil {
		return err
	}
	if f.ProcessingState.Position > len(data) {
		return nil
	}
	var line = ""
	var startPosition = f.ProcessingState.Position
	var startLine = f.ProcessingState.Line
	var lineIndex = startLine
	var dataProcessed = 0
	for i := startPosition; i < len(data); i++ {
		dataProcessed++
		aChar := string(data[i])
		if aChar != "\n" && aChar != "\r" {
			line += aChar
			continue
		}

		line = strings.Trim(line, " \r\t")
		lineIndex++
		if f.Exclusion != "" {
			if strings.Contains(line, f.Exclusion) {
				line, dataProcessed = f.ProcessingState.Update(dataProcessed, lineIndex)
				continue
			}
		}
		if f.Inclusion != "" {
			if !strings.Contains(line, f.Inclusion) {
				line, dataProcessed = f.ProcessingState.Update(dataProcessed, lineIndex)
				continue
			}
		}

		if len(line) > 0 {
			f.PushLogRecord(&Record{
				URL:    f.URL,
				Line:   line,
				Number: lineIndex,
			})
		}
		if err != nil {
			return err
		}
		line, dataProcessed = f.ProcessingState.Update(dataProcessed, lineIndex)
	}
	return nil
}
<|endoftext|>


<commit_before>// File: ./blockfreight/bft/common/common.go
// Summary: Application code for Blockfreight™ | The blockchain of global freight.
// License: MIT License
// Company: Blockfreight, Inc.
// Author: Julian Nunez, Neil Tran, Julian Smith & contributors
// Site: https://blockfreight.com
// Support: <support@blockfreight.com>

// Copyright 2017 Blockfreight, Inc.

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// =================================================================================================================================================
// =================================================================================================================================================
//
// BBBBBBBBBBBb     lll                                kkk             ffff                         iii                  hhh            ttt
// BBBB``````BBBB   lll                                kkk            fff                           ```                  hhh            ttt
// BBBB      BBBB   lll      oooooo        ccccccc     kkk    kkkk  fffffff  rrr  rrr    eeeee      iii     gggggg ggg   hhh  hhhhh   tttttttt
// BBBBBBBBBBBB     lll    ooo    oooo    ccc    ccc   kkk   kkk    fffffff  rrrrrrrr eee    eeee   iii   gggg   ggggg   hhhh   hhhh  tttttttt
// BBBBBBBBBBBBBB   lll   ooo      ooo   ccc           kkkkkkk        fff    rrrr    eeeeeeeeeeeee  iii  gggg      ggg   hhh     hhh    ttt
// BBBB       BBB   lll   ooo      ooo   ccc           kkkk kkkk      fff    rrr     eeeeeeeeeeeee  iii   ggg      ggg   hhh     hhh    ttt
// BBBB      BBBB   lll   oooo    oooo   cccc    ccc   kkk   kkkk     fff    rrr      eee      eee  iii    ggg    gggg   hhh     hhh    tttt    ....
// BBBBBBBBBBBBB    lll     oooooooo       ccccccc     kkk     kkkk   fff    rrr       eeeeeeeee    iii     gggggg ggg   hhh     hhh     ttttt  ....
//                                                                                ggg      ggg
//   Blockfreight™ | The blockchain of global freight.                                                      ggggggggg
//
// =================================================================================================================================================
// =================================================================================================================================================

// Package common provides some useful functions to work with the Blockfreight project.
package common

import (
    // =======================
    // Golang Standard library
    // =======================
    "errors"    // Implements functions to manipulate errors.
    "fmt"       // Implements formatted I/O with functions analogous to C's printf and scanf.
    "io/ioutil" // Implements some I/O utility functions.
    "log"       // Implements a simple logging package.
)

// ReadJSON is a function that receives the path of a file encapsulates the native Golang process of reading a file.
func ReadJSON(path string) ([]byte, error) {
    fmt.Println("\nReading " + path + "\n")
    file, e := ioutil.ReadFile(path)
    if e != nil {
        return file, errors.New("File error: "+e.Error())
    }
    return file, nil
}

// HandleError is a function that receives an error and a name of the procedure where that error ocurred, and print a clear error message.
func HandleError(err error) {   //, place string) {
    if err != nil {
        log.Fatal(err)
    }
}

// =================================================
// Blockfreight™ | The blockchain of global freight.
// =================================================

// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBB                    BBBBBBBBBBBBBBBBBBB
// BBBBBBB                       BBBBBBBBBBBBBBBB
// BBBBBBB                        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBB         BBBBBBBBBBBBBBBB
// BBBBBBB                     BBBBBBBBBBBBBBBBBB
// BBBBBBB                        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBB        BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBBB       BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBB        BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBB       BBBBB
// BBBBBBB                       BBBB       BBBBB
// BBBBBBB                    BBBBBBB       BBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

// ==================================================
// Blockfreight™ | The blockchain for global freight.
// ==================================================
<commit_msg>Remove HanfleError function, due to is not used anymore.<commit_after>// File: ./blockfreight/bft/common/common.go
// Summary: Application code for Blockfreight™ | The blockchain of global freight.
// License: MIT License
// Company: Blockfreight, Inc.
// Author: Julian Nunez, Neil Tran, Julian Smith & contributors
// Site: https://blockfreight.com
// Support: <support@blockfreight.com>

// Copyright 2017 Blockfreight, Inc.

// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// =================================================================================================================================================
// =================================================================================================================================================
//
// BBBBBBBBBBBb     lll                                kkk             ffff                         iii                  hhh            ttt
// BBBB``````BBBB   lll                                kkk            fff                           ```                  hhh            ttt
// BBBB      BBBB   lll      oooooo        ccccccc     kkk    kkkk  fffffff  rrr  rrr    eeeee      iii     gggggg ggg   hhh  hhhhh   tttttttt
// BBBBBBBBBBBB     lll    ooo    oooo    ccc    ccc   kkk   kkk    fffffff  rrrrrrrr eee    eeee   iii   gggg   ggggg   hhhh   hhhh  tttttttt
// BBBBBBBBBBBBBB   lll   ooo      ooo   ccc           kkkkkkk        fff    rrrr    eeeeeeeeeeeee  iii  gggg      ggg   hhh     hhh    ttt
// BBBB       BBB   lll   ooo      ooo   ccc           kkkk kkkk      fff    rrr     eeeeeeeeeeeee  iii   ggg      ggg   hhh     hhh    ttt
// BBBB      BBBB   lll   oooo    oooo   cccc    ccc   kkk   kkkk     fff    rrr      eee      eee  iii    ggg    gggg   hhh     hhh    tttt    ....
// BBBBBBBBBBBBB    lll     oooooooo       ccccccc     kkk     kkkk   fff    rrr       eeeeeeeee    iii     gggggg ggg   hhh     hhh     ttttt  ....
//                                                                                ggg      ggg
//   Blockfreight™ | The blockchain of global freight.                                                      ggggggggg
//
// =================================================================================================================================================
// =================================================================================================================================================

// Package common provides some useful functions to work with the Blockfreight project.
package common

import (
    // =======================
    // Golang Standard library
    // =======================
    "errors"    // Implements functions to manipulate errors.
    "fmt"       // Implements formatted I/O with functions analogous to C's printf and scanf.
    "io/ioutil" // Implements some I/O utility functions.
)

// ReadJSON is a function that receives the path of a file encapsulates the native Golang process of reading a file.
func ReadJSON(path string) ([]byte, error) {
    fmt.Println("\nReading " + path + "\n")
    file, e := ioutil.ReadFile(path)
    if e != nil {
        return file, errors.New("File error: "+e.Error())
    }
    return file, nil
}

// =================================================
// Blockfreight™ | The blockchain of global freight.
// =================================================

// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBB                    BBBBBBBBBBBBBBBBBBB
// BBBBBBB                       BBBBBBBBBBBBBBBB
// BBBBBBB                        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBB         BBBBBBBBBBBBBBBB
// BBBBBBB                     BBBBBBBBBBBBBBBBBB
// BBBBBBB                        BBBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBB        BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBBB       BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBBB        BBBBBBBBBBBBBB
// BBBBBBB       BBBBBBBBB        BBB       BBBBB
// BBBBBBB                       BBBB       BBBBB
// BBBBBBB                    BBBBBBB       BBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

// ==================================================
// Blockfreight™ | The blockchain for global freight.
// ==================================================
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"mime"
	"log"
	"net/http"
	"path"

	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/s3"
)

type Proxy struct {
	Bucket string
	Svc    *s3.S3
}

func (p *Proxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	key := req.URL.Path
	if key == "/" {
		key = "/index.html"
	}

	input := &s3.GetObjectInput{
		Bucket: aws.String(p.Bucket),
		Key:    aws.String(key),
	}
	if v := req.Header.Get("If-None-Match"); v != "" {
		input.IfNoneMatch = aws.String(v)
	}

	// awsReq, resp := p.Svc.GetObjectRequest(input)
	// log.Printf("request: %#v", awsReq)
	// err := awsReq.Send()
	// log.Printf("response: %#v", )

	resp, err := p.Svc.GetObject(input)
	if awsErr, ok := err.(awserr.Error); ok {
		if awsErr.Code() == "NoSuchKey" {
			http.Error(rw, "Page Not Found", 404)
		} else {
			// A service error occurred.
			log.Printf("Error: %v %v", awsErr.Code(), awsErr.Message())
			http.Error(rw, "Internal Error", 500)
		}
		return
	} else if err != nil {
		log.Printf("not aws error %v %s", err, err)
		http.Error(rw, "Internal Error", 500)
		return
	}

	var contentType string
	if resp.ContentType != nil {
		contentType = *resp.ContentType
	}

	if contentType == "" {
		ext := path.Ext(req.URL.Path)
		contentType = mime.TypeByExtension(ext)
	}

	if resp.ETag != nil && *resp.ETag != "" {
		fmt.Sprintf("etag %q", resp.ETag)
		// see https://github.com/aws/aws-sdk-go/issues/304
		// rw.Header().Set("Etag", *resp.ETag)
	}

	if contentType != "" {
		rw.Header().Set("Content-Type", contentType)
	}
	if resp.ContentLength != nil && *resp.ContentLength > 0 {
		rw.Header().Set("Content-Length", fmt.Sprintf("%d", *resp.ContentLength))
	}

	io.Copy(rw, resp.Body)
	resp.Body.Close()
}

// resp, err := svc.ListObjects(&s3.ListObjectsInput{
// 	Bucket:  aws.String(settings.GetString("s3_bucket")),
// 	Prefix:  aws.String("data/"),
// 	MaxKeys: aws.Long(1000),
// })
// if awsErr, ok := err.(awserr.Error); ok {
// 	// A service error occurred.
// 	log.Fatalf("Error: %v %v", awsErr.Code, awsErr.Message)
// } else if err != nil {
// 	// A non-service error occurred.
// 	log.Fatalf("%v", err)
// }
<commit_msg>gofmt<commit_after>package main

import (
	"fmt"
	"io"
	"log"
	"mime"
	"net/http"
	"path"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/s3"
)

type Proxy struct {
	Bucket string
	Svc    *s3.S3
}

func (p *Proxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	key := req.URL.Path
	if key == "/" {
		key = "/index.html"
	}

	input := &s3.GetObjectInput{
		Bucket: aws.String(p.Bucket),
		Key:    aws.String(key),
	}
	if v := req.Header.Get("If-None-Match"); v != "" {
		input.IfNoneMatch = aws.String(v)
	}

	// awsReq, resp := p.Svc.GetObjectRequest(input)
	// log.Printf("request: %#v", awsReq)
	// err := awsReq.Send()
	// log.Printf("response: %#v", )

	resp, err := p.Svc.GetObject(input)
	if awsErr, ok := err.(awserr.Error); ok {
		if awsErr.Code() == "NoSuchKey" {
			http.Error(rw, "Page Not Found", 404)
		} else {
			// A service error occurred.
			log.Printf("Error: %v %v", awsErr.Code(), awsErr.Message())
			http.Error(rw, "Internal Error", 500)
		}
		return
	} else if err != nil {
		log.Printf("not aws error %v %s", err, err)
		http.Error(rw, "Internal Error", 500)
		return
	}

	var contentType string
	if resp.ContentType != nil {
		contentType = *resp.ContentType
	}

	if contentType == "" {
		ext := path.Ext(req.URL.Path)
		contentType = mime.TypeByExtension(ext)
	}

	if resp.ETag != nil && *resp.ETag != "" {
		fmt.Sprintf("etag %q", resp.ETag)
		// see https://github.com/aws/aws-sdk-go/issues/304
		// rw.Header().Set("Etag", *resp.ETag)
	}

	if contentType != "" {
		rw.Header().Set("Content-Type", contentType)
	}
	if resp.ContentLength != nil && *resp.ContentLength > 0 {
		rw.Header().Set("Content-Length", fmt.Sprintf("%d", *resp.ContentLength))
	}

	io.Copy(rw, resp.Body)
	resp.Body.Close()
}

// resp, err := svc.ListObjects(&s3.ListObjectsInput{
// 	Bucket:  aws.String(settings.GetString("s3_bucket")),
// 	Prefix:  aws.String("data/"),
// 	MaxKeys: aws.Long(1000),
// })
// if awsErr, ok := err.(awserr.Error); ok {
// 	// A service error occurred.
// 	log.Fatalf("Error: %v %v", awsErr.Code, awsErr.Message)
// } else if err != nil {
// 	// A non-service error occurred.
// 	log.Fatalf("%v", err)
// }
<|endoftext|>


<commit_before>package xingapi

import (
	"fmt"
)

// User interface defines methods to call on a user entity
type User interface {
	Name() string
	DisplayName() string
	ID() string
	ActiveEmail() string
	Birthdate() Birthdate
	BusinessAddress() Address
	fmt.Stringer
}

// XINGUser is the concrete implementation of a User
type XINGUser struct {
	InternalName            string    `json:"name"`
	InternalDisplayName     string    `json:"display_name"`
	InternalID              string    `json:"id"`
	InternalActiveEmail     string    `json:"active_email"`
	InternalBirthdate       Birthdate `json:"birth_date"`
	InternalBusinessAddress Address   `json:"business_address"`
}

func (user XINGUser) String() string {
	return " " + user.ID() + " " + user.ActiveEmail() + " - " + user.Birthdate().String() + user.BusinessAddress().String()
}

// Name return the user's full name
func (user XINGUser) Name() string {
	return user.InternalName
}

// DisplayName returns the users display name
func (user XINGUser) DisplayName() string {
	return user.InternalDisplayName
}

// ID returns the user's user ID
func (user XINGUser) ID() string {
	return user.InternalID
}

// ActiveEmail returns the user's email address
func (user XINGUser) ActiveEmail() string {
	return user.InternalActiveEmail
}

// Birthdate represents the user's birthdate
func (user XINGUser) Birthdate() Birthdate {
	return user.InternalBirthdate
}

// BusinessAddress returns the user's business address
func (user XINGUser) BusinessAddress() Address {
	return user.InternalBusinessAddress
}
<commit_msg>Updates json key for name<commit_after>package xingapi

import (
	"fmt"
)

// User interface defines methods to call on a user entity
type User interface {
	Name() string
	DisplayName() string
	ID() string
	ActiveEmail() string
	Birthdate() Birthdate
	BusinessAddress() Address
	fmt.Stringer
}

// XINGUser is the concrete implementation of a User
type XINGUser struct {
	InternalName            string    `json:"first_name"`
	InternalDisplayName     string    `json:"display_name"`
	InternalID              string    `json:"id"`
	InternalActiveEmail     string    `json:"active_email"`
	InternalBirthdate       Birthdate `json:"birth_date"`
	InternalBusinessAddress Address   `json:"business_address"`
}

func (user XINGUser) String() string {
	return " " + user.ID() + " " + user.ActiveEmail() + " - " + user.Birthdate().String() + user.BusinessAddress().String()
}

// Name return the user's full name
func (user XINGUser) Name() string {
	return user.InternalName
}

// DisplayName returns the users display name
func (user XINGUser) DisplayName() string {
	return user.InternalDisplayName
}

// ID returns the user's user ID
func (user XINGUser) ID() string {
	return user.InternalID
}

// ActiveEmail returns the user's email address
func (user XINGUser) ActiveEmail() string {
	return user.InternalActiveEmail
}

// Birthdate represents the user's birthdate
func (user XINGUser) Birthdate() Birthdate {
	return user.InternalBirthdate
}

// BusinessAddress returns the user's business address
func (user XINGUser) BusinessAddress() Address {
	return user.InternalBusinessAddress
}
<|endoftext|>


<commit_before>// Copyright 2017 Corey Scott http://www.sage42.org/
//
// 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 generator

import (
	"bufio"
	"fmt"
	"go/parser"
	"go/token"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/corsc/go-commons/iocloser"
	"github.com/corsc/go-tools/package-coverage/utils"
)

const coverageFilename = "profile.cov"

var fakeTestFilename = "fake_test.go"

func processAllDirs(basePath string, exclusionsMatcher *regexp.Regexp, logTag string, actionFunc func(string)) {
	paths, err := utils.FindAllGoDirs(basePath)
	if err != nil {
		return
	}

	for _, path := range paths {
		if exclusionsMatcher.FindString(path) != "" {
			utils.LogWhenVerbose("[%s] path '%s' skipped due to skipDir regex '%s'",
				logTag, path, exclusionsMatcher.String())
			continue
		}

		utils.LogWhenVerbose("[%s] processing path '%s'", logTag, path)
		actionFunc(path)
	}
}

// this function will generate the test coverage for the supplied directory
func generateCoverage(path string, exclusions *regexp.Regexp, quietMode bool, tags string) {
	packageName := findPackageName(path)

	fakeTestFile := addFakeTest(path, packageName)
	defer removeFakeTest(fakeTestFile)

	err := execCoverage(path, quietMode, tags)
	if err != nil {
		utils.LogWhenVerbose("[coverage] error generating coverage %s", err)
	}

	if exclusions == nil {
		return
	}

	err = filterCoverage(filepath.Join(path, coverageFilename), exclusions)
	if err != nil {
		utils.LogWhenVerbose("[coverage] error filtering files: %s", err)
	}
}

// add a fake test to ensure that there is at least 1 test in this directory
func addFakeTest(path string, packageName string) string {
	testFilename := createTestFilename(path)

	createTestFile(packageName, testFilename)

	return testFilename
}

func createTestFilename(path string) string {
	return path + fakeTestFilename
}

// find the package name by using the go AST
func findPackageName(path string) string {
	fileSet := token.NewFileSet()
	pkgs, err := parser.ParseDir(fileSet, path, nil, 0)
	if err != nil {
		utils.LogWhenVerbose("[coverage] err while parsing the '%s' into Go AST Err: '%s", path, err)
		return UnknownPackage
	}

	for pkgName := range pkgs {
		return pkgName
	}
	return UnknownPackage
}

// create a fake test so that all directories are guaranteed to contain tests (and therefore coverage will be generated)
func createTestFile(packageName string, testFilename string) {
	utils.LogWhenVerbose("[coverage] created test for package %s file @ %s", packageName, testFilename)

	if _, err := os.Stat(testFilename); err == nil {
		utils.LogWhenVerbose("[coverage] file already exists @ %s cowardly refusing to overwrite", testFilename)
		return
	}

	file, err := os.OpenFile(testFilename, os.O_RDWR|os.O_CREATE, 0600)
	if err != nil {
		utils.LogWhenVerbose("[coverage] error while creating test file %s", err)
		return
	}

	_, err = file.WriteString(`package ` + packageName + `

import "testing"

func TestThisTestDoesntReallyTestAnything(t *testing.T) {}
`)
	if err != nil {
		utils.LogWhenVerbose("[coverage] error while writing test file %s", err)
		return
	}

	err = file.Close()
	if err != nil {
		utils.LogWhenVerbose("[coverage] error while closing file '%s", err)
	}
}

// remove the previously added fake test (i.e. clean up)
func removeFakeTest(filename string) {
	utils.LogWhenVerbose("[coverage] remove test file @ %s", filename)

	err := os.Remove(filename)
	if err != nil {
		utils.LogWhenVerbose("[coverage] error while removing test file @ %s, err: %s", filename, err)
	}
}

// essentially call `go test` to generate the coverage
func execCoverage(dir string, quiet bool, tags string) error {
	arguments := []string{
		"test",
		"-coverprofile=" + coverageFilename,
	}

	if len(tags) > 0 {
		arguments = append(arguments, `-tags="`+tags+`"`)
	}

	cmd := exec.Command("go", arguments...)
	cmd.Dir = dir

	if !quiet {
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
	}

	err := cmd.Run()
	if err != nil {
		utils.LogWhenVerbose("[coverage] error while running go test. err: %s", err)
		utils.LogWhenVerbose("[coverage] test output.\n%s", cmd.Stdout)
		utils.LogWhenVerbose("[coverage] test output error\n%s", cmd.Stderr)
		return err
	}

	utils.LogWhenVerbose("[coverage] created coverage file @ %s%s", dir, coverageFilename)
	utils.LogWhenVerbose("[coverage] test output.\n%s", cmd.Stdout)
	return nil
}

func filterCoverage(coverageFilename string, exclusionsMatcher *regexp.Regexp) error {
	coverageTempFilename := coverageFilename + "~"

	coverageTempFile, err := os.OpenFile(coverageTempFilename, os.O_RDWR|os.O_CREATE, 0600)
	if err != nil {
		utils.LogWhenVerbose("[coverage] error while opening file %s, err: %s", coverageTempFilename, err)
		return err
	}

	defer iocloser.Close(coverageTempFile)

	coverageFile, err := os.OpenFile(coverageFilename, os.O_RDWR, 0)
	if err != nil {
		utils.LogWhenVerbose("[coverage] error while opening file %s, err: %s", coverageFilename, err)
		return err
	}

	defer func() {
		if err := coverageFile.Close(); err != nil {
			utils.LogWhenVerbose("[coverage] Cannot close coverage file %s: %s", coverageFilename, err)
		}
	}()

	if err := filterCoverageContents(exclusionsMatcher, coverageFile, coverageTempFile); err != nil {
		utils.LogWhenVerbose("[coverage] error while filtering coverage file %s: %s", coverageFilename, err)
		return err
	}

	if err := os.Remove(coverageFilename); err != nil {
		utils.LogWhenVerbose("[coverage] cannot remove old coverage file %s: %s", coverageFilename, err)
	}

	if err := os.Rename(coverageTempFilename, coverageFilename); err != nil {
		utils.LogWhenVerbose("[coverage] cannot rename filtered coverage file %s: %s", coverageTempFilename, err)
	}

	return nil
}

func filterCoverageContents(exclusionsMatcher *regexp.Regexp, in io.Reader, out io.Writer) error {
	coverageFileScanner := bufio.NewScanner(in)
	for coverageFileScanner.Scan() {
		line := coverageFileScanner.Text()

		fileNameEndIndex := strings.LastIndex(line, ":")
		if fileNameEndIndex == -1 {
			utils.LogWhenVerbose("[coverage] error in line '%s'", line)
			continue
		}

		fileName := line[:fileNameEndIndex]

		if exclusionsMatcher.MatchString(fileName) {
			utils.LogWhenVerbose("[coverage] skipped file %s", fileName)
			continue
		}

		if _, err := fmt.Fprintln(out, line); err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>Turn on Go modules and add more debugging to test failures<commit_after>// Copyright 2017 Corey Scott http://www.sage42.org/
//
// 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 generator

import (
	"bufio"
	"fmt"
	"go/parser"
	"go/token"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/corsc/go-commons/iocloser"
	"github.com/corsc/go-tools/package-coverage/utils"
)

const coverageFilename = "profile.cov"

var fakeTestFilename = "fake_test.go"

func processAllDirs(basePath string, exclusionsMatcher *regexp.Regexp, logTag string, actionFunc func(string)) {
	paths, err := utils.FindAllGoDirs(basePath)
	if err != nil {
		return
	}

	for _, path := range paths {
		if exclusionsMatcher.FindString(path) != "" {
			utils.LogWhenVerbose("[%s] path '%s' skipped due to skipDir regex '%s'",
				logTag, path, exclusionsMatcher.String())
			continue
		}

		utils.LogWhenVerbose("[%s] processing path '%s'", logTag, path)
		actionFunc(path)
	}
}

// this function will generate the test coverage for the supplied directory
func generateCoverage(path string, exclusions *regexp.Regexp, quietMode bool, tags string) {
	packageName := findPackageName(path)

	fakeTestFile := addFakeTest(path, packageName)
	defer removeFakeTest(fakeTestFile)

	err := execCoverage(path, quietMode, tags)
	if err != nil {
		utils.LogWhenVerbose("[coverage] error generating coverage %s", err)
	}

	if exclusions == nil {
		return
	}

	err = filterCoverage(filepath.Join(path, coverageFilename), exclusions)
	if err != nil {
		utils.LogWhenVerbose("[coverage] error filtering files: %s", err)
	}
}

// add a fake test to ensure that there is at least 1 test in this directory
func addFakeTest(path string, packageName string) string {
	testFilename := createTestFilename(path)

	createTestFile(packageName, testFilename)

	return testFilename
}

func createTestFilename(path string) string {
	return path + fakeTestFilename
}

// find the package name by using the go AST
func findPackageName(path string) string {
	fileSet := token.NewFileSet()
	pkgs, err := parser.ParseDir(fileSet, path, nil, 0)
	if err != nil {
		utils.LogWhenVerbose("[coverage] err while parsing the '%s' into Go AST Err: '%s", path, err)
		return UnknownPackage
	}

	for pkgName := range pkgs {
		return pkgName
	}
	return UnknownPackage
}

// create a fake test so that all directories are guaranteed to contain tests (and therefore coverage will be generated)
func createTestFile(packageName string, testFilename string) {
	utils.LogWhenVerbose("[coverage] created test for package %s file @ %s", packageName, testFilename)

	if _, err := os.Stat(testFilename); err == nil {
		utils.LogWhenVerbose("[coverage] file already exists @ %s cowardly refusing to overwrite", testFilename)
		return
	}

	file, err := os.OpenFile(testFilename, os.O_RDWR|os.O_CREATE, 0600)
	if err != nil {
		utils.LogWhenVerbose("[coverage] error while creating test file %s", err)
		return
	}

	_, err = file.WriteString(`package ` + packageName + `

import "testing"

func TestThisTestDoesntReallyTestAnything(t *testing.T) {}
`)
	if err != nil {
		utils.LogWhenVerbose("[coverage] error while writing test file %s", err)
		return
	}

	err = file.Close()
	if err != nil {
		utils.LogWhenVerbose("[coverage] error while closing file '%s", err)
	}
}

// remove the previously added fake test (i.e. clean up)
func removeFakeTest(filename string) {
	utils.LogWhenVerbose("[coverage] remove test file @ %s", filename)

	err := os.Remove(filename)
	if err != nil {
		utils.LogWhenVerbose("[coverage] error while removing test file @ %s, err: %s", filename, err)
	}
}

// essentially call `go test` to generate the coverage
func execCoverage(dir string, quiet bool, tags string) error {
	arguments := []string{
		"test",
		"-coverprofile=" + coverageFilename,
	}

	if len(tags) > 0 {
		arguments = append(arguments, `-tags="`+tags+`"`)
	}

	cmd := exec.Command("go", arguments...)
	cmd.Dir = dir

	if !quiet {
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
	}

	err := cmd.Run()

	payload, _ := cmd.CombinedOutput()
	utils.LogWhenVerbose("[coverage] test output:\n%s", payload)

	if err != nil {
		utils.LogWhenVerbose("[coverage] error while running go test. err: %s", err)
		return err
	}

	utils.LogWhenVerbose("[coverage] created coverage file @ %s%s", dir, coverageFilename)
	return nil
}

func filterCoverage(coverageFilename string, exclusionsMatcher *regexp.Regexp) error {
	coverageTempFilename := coverageFilename + "~"

	coverageTempFile, err := os.OpenFile(coverageTempFilename, os.O_RDWR|os.O_CREATE, 0600)
	if err != nil {
		utils.LogWhenVerbose("[coverage] error while opening file %s, err: %s", coverageTempFilename, err)
		return err
	}

	defer iocloser.Close(coverageTempFile)

	coverageFile, err := os.OpenFile(coverageFilename, os.O_RDWR, 0)
	if err != nil {
		utils.LogWhenVerbose("[coverage] error while opening file %s, err: %s", coverageFilename, err)
		return err
	}

	defer func() {
		if err := coverageFile.Close(); err != nil {
			utils.LogWhenVerbose("[coverage] Cannot close coverage file %s: %s", coverageFilename, err)
		}
	}()

	if err := filterCoverageContents(exclusionsMatcher, coverageFile, coverageTempFile); err != nil {
		utils.LogWhenVerbose("[coverage] error while filtering coverage file %s: %s", coverageFilename, err)
		return err
	}

	if err := os.Remove(coverageFilename); err != nil {
		utils.LogWhenVerbose("[coverage] cannot remove old coverage file %s: %s", coverageFilename, err)
	}

	if err := os.Rename(coverageTempFilename, coverageFilename); err != nil {
		utils.LogWhenVerbose("[coverage] cannot rename filtered coverage file %s: %s", coverageTempFilename, err)
	}

	return nil
}

func filterCoverageContents(exclusionsMatcher *regexp.Regexp, in io.Reader, out io.Writer) error {
	coverageFileScanner := bufio.NewScanner(in)
	for coverageFileScanner.Scan() {
		line := coverageFileScanner.Text()

		fileNameEndIndex := strings.LastIndex(line, ":")
		if fileNameEndIndex == -1 {
			utils.LogWhenVerbose("[coverage] error in line '%s'", line)
			continue
		}

		fileName := line[:fileNameEndIndex]

		if exclusionsMatcher.MatchString(fileName) {
			utils.LogWhenVerbose("[coverage] skipped file %s", fileName)
			continue
		}

		if _, err := fmt.Fprintln(out, line); err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
//
// Note:
// 1. It needs manually import: _ "github.com/denisenkom/go-mssqldb"
// 2. It does not support Save/Replace features.
// 3. It does not support LastInsertId.

package gdb

import (
	"database/sql"
	"errors"
	"fmt"
	"strconv"
	"strings"

	"github.com/gogf/gf/internal/intlog"
	"github.com/gogf/gf/text/gstr"

	"github.com/gogf/gf/text/gregex"
)

// DriverMssql is the driver for SQL server database.
type DriverMssql struct {
	*Core
}

// New creates and returns a database object for SQL server.
// It implements the interface of gdb.Driver for extra database driver installation.
func (d *DriverMssql) New(core *Core, node *ConfigNode) (DB, error) {
	return &DriverMssql{
		Core: core,
	}, nil
}

// Open creates and returns a underlying sql.DB object for mssql.
func (d *DriverMssql) Open(config *ConfigNode) (*sql.DB, error) {
	source := ""
	if config.LinkInfo != "" {
		source = config.LinkInfo
	} else {
		source = fmt.Sprintf(
			"user id=%s;password=%s;server=%s;port=%s;database=%s;encrypt=disable",
			config.User, config.Pass, config.Host, config.Port, config.Name,
		)
	}
	intlog.Printf("Open: %s", source)
	if db, err := sql.Open("sqlserver", source); err == nil {
		return db, nil
	} else {
		return nil, err
	}
}

// GetChars returns the security char for this type of database.
func (d *DriverMssql) GetChars() (charLeft string, charRight string) {
	return "\"", "\""
}

// HandleSqlBeforeCommit deals with the sql string before commits it to underlying sql driver.
func (d *DriverMssql) HandleSqlBeforeCommit(link Link, sql string, args []interface{}) (string, []interface{}) {
	var index int
	// Convert place holder char '?' to string "@px".
	str, _ := gregex.ReplaceStringFunc("\\?", sql, func(s string) string {
		index++
		return fmt.Sprintf("@p%d", index)
	})
	str, _ = gregex.ReplaceString("\"", "", str)
	return d.parseSql(str), args
}

// parseSql does some replacement of the sql before commits it to underlying driver,
// for support of microsoft sql server.
func (d *DriverMssql) parseSql(sql string) string {
	// SELECT * FROM USER WHERE ID=1 LIMIT 1
	if m, _ := gregex.MatchString(`^SELECT(.+)LIMIT 1$`, sql); len(m) > 1 {
		return fmt.Sprintf(`SELECT TOP 1 %s`, m[1])
	}
	// SELECT * FROM USER WHERE AGE>18 ORDER BY ID DESC LIMIT 100, 200
	patten := `^\s*(?i)(SELECT)|(LIMIT\s*(\d+)\s*,\s*(\d+))`
	if gregex.IsMatchString(patten, sql) == false {
		return sql
	}
	res, err := gregex.MatchAllString(patten, sql)
	if err != nil {
		return ""
	}
	index := 0
	keyword := strings.TrimSpace(res[index][0])
	keyword = strings.ToUpper(keyword)
	index++
	switch keyword {
	case "SELECT":
		// LIMIT statement checks.
		if len(res) < 2 ||
			(strings.HasPrefix(res[index][0], "LIMIT") == false &&
				strings.HasPrefix(res[index][0], "limit") == false) {
			break
		}
		if gregex.IsMatchString("((?i)SELECT)(.+)((?i)LIMIT)", sql) == false {
			break
		}
		// ORDER BY statement checks.
		selectStr := ""
		orderStr := ""
		haveOrder := gregex.IsMatchString("((?i)SELECT)(.+)((?i)ORDER BY)", sql)
		if haveOrder {
			queryExpr, _ := gregex.MatchString("((?i)SELECT)(.+)((?i)ORDER BY)", sql)
			if len(queryExpr) != 4 ||
				strings.EqualFold(queryExpr[1], "SELECT") == false ||
				strings.EqualFold(queryExpr[3], "ORDER BY") == false {
				break
			}
			selectStr = queryExpr[2]
			orderExpr, _ := gregex.MatchString("((?i)ORDER BY)(.+)((?i)LIMIT)", sql)
			if len(orderExpr) != 4 ||
				strings.EqualFold(orderExpr[1], "ORDER BY") == false ||
				strings.EqualFold(orderExpr[3], "LIMIT") == false {
				break
			}
			orderStr = orderExpr[2]
		} else {
			queryExpr, _ := gregex.MatchString("((?i)SELECT)(.+)((?i)LIMIT)", sql)
			if len(queryExpr) != 4 ||
				strings.EqualFold(queryExpr[1], "SELECT") == false ||
				strings.EqualFold(queryExpr[3], "LIMIT") == false {
				break
			}
			selectStr = queryExpr[2]
		}
		first, limit := 0, 0
		for i := 1; i < len(res[index]); i++ {
			if len(strings.TrimSpace(res[index][i])) == 0 {
				continue
			}

			if strings.HasPrefix(res[index][i], "LIMIT") ||
				strings.HasPrefix(res[index][i], "limit") {
				first, _ = strconv.Atoi(res[index][i+1])
				limit, _ = strconv.Atoi(res[index][i+2])
				break
			}
		}
		if haveOrder {
			sql = fmt.Sprintf(
				"SELECT * FROM "+
					"(SELECT ROW_NUMBER() OVER (ORDER BY %s) as ROWNUMBER_, %s ) as TMP_ "+
					"WHERE TMP_.ROWNUMBER_ > %d AND TMP_.ROWNUMBER_ <= %d",
				orderStr, selectStr, first, first+limit,
			)
		} else {
			if first == 0 {
				first = limit
			}
			sql = fmt.Sprintf(
				"SELECT * FROM (SELECT TOP %d * FROM (SELECT TOP %d %s) as TMP1_ ) as TMP2_ ",
				limit, first+limit, selectStr,
			)
		}
	default:
	}
	return sql
}

// Tables retrieves and returns the tables of current schema.
// It's mainly used in cli tool chain for automatically generating the models.
func (d *DriverMssql) Tables(schema ...string) (tables []string, err error) {
	var result Result
	link, err := d.DB.GetSlave(schema...)
	if err != nil {
		return nil, err
	}

	result, err = d.DB.DoGetAll(link, `SELECT NAME FROM SYSOBJECTS WHERE XTYPE='U' AND STATUS >= 0 ORDER BY NAME`)
	if err != nil {
		return
	}
	for _, m := range result {
		for _, v := range m {
			tables = append(tables, v.String())
		}
	}
	return
}

// TableFields retrieves and returns the fields information of specified table of current schema.
func (d *DriverMssql) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) {
	charL, charR := d.GetChars()
	table = gstr.Trim(table, charL+charR)
	if gstr.Contains(table, " ") {
		return nil, errors.New("function TableFields supports only single table operations")
	}
	checkSchema := d.DB.GetSchema()
	if len(schema) > 0 && schema[0] != "" {
		checkSchema = schema[0]
	}
	v := d.DB.GetCache().GetOrSetFunc(
		fmt.Sprintf(`mssql_table_fields_%s_%s`, table, checkSchema), func() interface{} {
			var result Result
			var link *sql.DB
			link, err = d.DB.GetSlave(checkSchema)
			if err != nil {
				return nil
			}
			result, err = d.DB.DoGetAll(link, fmt.Sprintf(`
			SELECT a.name Field,
	CASE b.name
		WHEN 'datetime' THEN 'datetime'
		WHEN 'numeric' THEN b.name + '(' + convert(varchar(20),a.xprec) + ',' + convert(varchar(20),a.xscale) + ')'
		WHEN 'char' THEN b.name + '(' + convert(varchar(20),a.length)+ ')'
		WHEN 'varchar' THEN b.name + '(' + convert(varchar(20),a.length)+ ')'
		ELSE b.name + '(' + convert(varchar(20),a.length)+ ')' END as TYPE,
	case when a.isnullable=1 then 'YES'else 'NO' end as [Null],
	case when exists(SELECT 1 FROM sysobjects where xtype='PK' and name in (
	  SELECT name FROM sysindexes WHERE indid in(
	   SELECT indid FROM sysindexkeys WHERE id = a.id AND colid=a.colid
	   ))) then 'PRI' else '' end AS [Key],
	case when COLUMNPROPERTY(a.id,a.name,'IsIdentity')=1 then 'auto_increment'else '' end Extra,
	isnull(e.text,'') as [Default],
	isnull(g.[value],'') AS [Comment]
	FROM syscolumns a
	left join systypes b on a.xtype=b.xusertype
	inner join sysobjects d on a.id=d.id and d.xtype='U' and d.name<>'dtproperties'
	left join syscomments e on a.cdefault=e.id
	left join sys.extended_properties g on a.id=g.major_id and a.colid=g.minor_id
	left join sys.extended_properties f on d.id=f.major_id and f.minor_id =0
	where d.name='%s'
	order by a.id,a.colorder`, strings.ToUpper(table)))
			if err != nil {
				return nil
			}
			fields = make(map[string]*TableField)
			for i, m := range result {
				fields[strings.ToLower(m["FIELD"].String())] = &TableField{
					Index:   i,
					Name:    strings.ToLower(m["FIELD"].String()),
					Type:    strings.ToLower(m["TYPE"].String()),
					Null:    m["Null"].Bool(),
					Key:     m["Key"].String(),
					Default: m["Default"].Val(),
					Extra:   m["Extra"].String(),
					Comment: m["Comment"].String(),
				}
			}
			return fields
		}, 0)
	if err == nil {
		fields = v.(map[string]*TableField)
	}
	return
}
<commit_msg>Update gdb_driver_mssql.go<commit_after>// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
//
// Note:
// 1. It needs manually import: _ "github.com/denisenkom/go-mssqldb"
// 2. It does not support Save/Replace features.
// 3. It does not support LastInsertId.

package gdb

import (
	"database/sql"
	"errors"
	"fmt"
	"strconv"
	"strings"

	"github.com/gogf/gf/internal/intlog"
	"github.com/gogf/gf/text/gstr"

	"github.com/gogf/gf/text/gregex"
)

// DriverMssql is the driver for SQL server database.
type DriverMssql struct {
	*Core
}

// New creates and returns a database object for SQL server.
// It implements the interface of gdb.Driver for extra database driver installation.
func (d *DriverMssql) New(core *Core, node *ConfigNode) (DB, error) {
	return &DriverMssql{
		Core: core,
	}, nil
}

// Open creates and returns a underlying sql.DB object for mssql.
func (d *DriverMssql) Open(config *ConfigNode) (*sql.DB, error) {
	source := ""
	if config.LinkInfo != "" {
		source = config.LinkInfo
	} else {
		source = fmt.Sprintf(
			"user id=%s;password=%s;server=%s;port=%s;database=%s;encrypt=disable",
			config.User, config.Pass, config.Host, config.Port, config.Name,
		)
	}
	intlog.Printf("Open: %s", source)
	if db, err := sql.Open("sqlserver", source); err == nil {
		return db, nil
	} else {
		return nil, err
	}
}

// GetChars returns the security char for this type of database.
func (d *DriverMssql) GetChars() (charLeft string, charRight string) {
	return "\"", "\""
}

// HandleSqlBeforeCommit deals with the sql string before commits it to underlying sql driver.
func (d *DriverMssql) HandleSqlBeforeCommit(link Link, sql string, args []interface{}) (string, []interface{}) {
	var index int
	// Convert place holder char '?' to string "@px".
	str, _ := gregex.ReplaceStringFunc("\\?", sql, func(s string) string {
		index++
		return fmt.Sprintf("@p%d", index)
	})
	str, _ = gregex.ReplaceString("\"", "", str)
	return d.parseSql(str), args
}

// parseSql does some replacement of the sql before commits it to underlying driver,
// for support of microsoft sql server.
func (d *DriverMssql) parseSql(sql string) string {
	// SELECT * FROM USER WHERE ID=1 LIMIT 1
	if m, _ := gregex.MatchString(`^SELECT(.+)LIMIT 1$`, sql); len(m) > 1 {
		return fmt.Sprintf(`SELECT TOP 1 %s`, m[1])
	}
	// SELECT * FROM USER WHERE AGE>18 ORDER BY ID DESC LIMIT 100, 200
	patten := `^\s*(?i)(SELECT)|(LIMIT\s*(\d+)\s*,\s*(\d+))`
	if gregex.IsMatchString(patten, sql) == false {
		return sql
	}
	res, err := gregex.MatchAllString(patten, sql)
	if err != nil {
		return ""
	}
	index := 0
	keyword := strings.TrimSpace(res[index][0])
	keyword = strings.ToUpper(keyword)
	index++
	switch keyword {
	case "SELECT":
		// LIMIT statement checks.
		if len(res) < 2 ||
			(strings.HasPrefix(res[index][0], "LIMIT") == false &&
				strings.HasPrefix(res[index][0], "limit") == false) {
			break
		}
		if gregex.IsMatchString("((?i)SELECT)(.+)((?i)LIMIT)", sql) == false {
			break
		}
		// ORDER BY statement checks.
		selectStr := ""
		orderStr := ""
		haveOrder := gregex.IsMatchString("((?i)SELECT)(.+)((?i)ORDER BY)", sql)
		if haveOrder {
			queryExpr, _ := gregex.MatchString("((?i)SELECT)(.+)((?i)ORDER BY)", sql)
			if len(queryExpr) != 4 ||
				strings.EqualFold(queryExpr[1], "SELECT") == false ||
				strings.EqualFold(queryExpr[3], "ORDER BY") == false {
				break
			}
			selectStr = queryExpr[2]
			orderExpr, _ := gregex.MatchString("((?i)ORDER BY)(.+)((?i)LIMIT)", sql)
			if len(orderExpr) != 4 ||
				strings.EqualFold(orderExpr[1], "ORDER BY") == false ||
				strings.EqualFold(orderExpr[3], "LIMIT") == false {
				break
			}
			orderStr = orderExpr[2]
		} else {
			queryExpr, _ := gregex.MatchString("((?i)SELECT)(.+)((?i)LIMIT)", sql)
			if len(queryExpr) != 4 ||
				strings.EqualFold(queryExpr[1], "SELECT") == false ||
				strings.EqualFold(queryExpr[3], "LIMIT") == false {
				break
			}
			selectStr = queryExpr[2]
		}
		first, limit := 0, 0
		for i := 1; i < len(res[index]); i++ {
			if len(strings.TrimSpace(res[index][i])) == 0 {
				continue
			}

			if strings.HasPrefix(res[index][i], "LIMIT") ||
				strings.HasPrefix(res[index][i], "limit") {
				first, _ = strconv.Atoi(res[index][i+1])
				limit, _ = strconv.Atoi(res[index][i+2])
				break
			}
		}
		if haveOrder {
			sql = fmt.Sprintf(
				"SELECT * FROM "+
					"(SELECT ROW_NUMBER() OVER (ORDER BY %s) as ROWNUMBER_, %s ) as TMP_ "+
					"WHERE TMP_.ROWNUMBER_ > %d AND TMP_.ROWNUMBER_ <= %d",
				orderStr, selectStr, first, first+limit,
			)
		} else {
			if first == 0 {
				first = limit
			}
			sql = fmt.Sprintf(
				"SELECT * FROM (SELECT TOP %d * FROM (SELECT TOP %d %s) as TMP1_ ) as TMP2_ ",
				limit, first+limit, selectStr,
			)
		}
	default:
	}
	return sql
}

// Tables retrieves and returns the tables of current schema.
// It's mainly used in cli tool chain for automatically generating the models.
func (d *DriverMssql) Tables(schema ...string) (tables []string, err error) {
	var result Result
	link, err := d.DB.GetSlave(schema...)
	if err != nil {
		return nil, err
	}

	result, err = d.DB.DoGetAll(link, `SELECT NAME FROM SYSOBJECTS WHERE XTYPE='U' AND STATUS >= 0 ORDER BY NAME`)
	if err != nil {
		return
	}
	for _, m := range result {
		for _, v := range m {
			tables = append(tables, v.String())
		}
	}
	return
}

// TableFields retrieves and returns the fields information of specified table of current schema.
func (d *DriverMssql) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) {
	charL, charR := d.GetChars()
	table = gstr.Trim(table, charL+charR)
	if gstr.Contains(table, " ") {
		return nil, errors.New("function TableFields supports only single table operations")
	}
	checkSchema := d.DB.GetSchema()
	if len(schema) > 0 && schema[0] != "" {
		checkSchema = schema[0]
	}
	v := d.DB.GetCache().GetOrSetFunc(
		fmt.Sprintf(`mssql_table_fields_%s_%s`, table, checkSchema), func() interface{} {
			var result Result
			var link *sql.DB
			link, err = d.DB.GetSlave(checkSchema)
			if err != nil {
				return nil
			}
			result, err = d.DB.DoGetAll(link, fmt.Sprintf(`
			SELECT a.name Field,
	CASE b.name
		WHEN 'datetime' THEN 'datetime'
		WHEN 'numeric' THEN b.name + '(' + convert(varchar(20),a.xprec) + ',' + convert(varchar(20),a.xscale) + ')'
		WHEN 'char' THEN b.name + '(' + convert(varchar(20),a.length)+ ')'
		WHEN 'varchar' THEN b.name + '(' + convert(varchar(20),a.length)+ ')'
		ELSE b.name + '(' + convert(varchar(20),a.length)+ ')' END as TYPE,
	case when a.isnullable=1 then 'YES'else 'NO' end as [Null],
	case when exists(SELECT 1 FROM sysobjects where xtype='PK' and name in (
	  SELECT name FROM sysindexes WHERE indid in(
	   SELECT indid FROM sysindexkeys WHERE id = a.id AND colid=a.colid
	   ))) then 'PRI' else '' end AS [Key],
	case when COLUMNPROPERTY(a.id,a.name,'IsIdentity')=1 then 'auto_increment'else '' end Extra,
	isnull(e.text,'') as [Default],
	isnull(g.[value],'') AS [Comment]
	FROM syscolumns a
	left join systypes b on a.xtype=b.xtype and a.xusertype=b.xusertype
	inner join sysobjects d on a.id=d.id and d.xtype='U' and d.name<>'dtproperties'
	left join syscomments e on a.cdefault=e.id
	left join sys.extended_properties g on a.id=g.major_id and a.colid=g.minor_id
	left join sys.extended_properties f on d.id=f.major_id and f.minor_id =0
	where d.name='%s'
	order by a.id,a.colorder`, strings.ToUpper(table)))
			if err != nil {
				return nil
			}
			fields = make(map[string]*TableField)
			for i, m := range result {
				fields[strings.ToLower(m["FIELD"].String())] = &TableField{
					Index:   i,
					Name:    strings.ToLower(m["FIELD"].String()),
					Type:    strings.ToLower(m["TYPE"].String()),
					Null:    m["Null"].Bool(),
					Key:     m["Key"].String(),
					Default: m["Default"].Val(),
					Extra:   m["Extra"].String(),
					Comment: m["Comment"].String(),
				}
			}
			return fields
		}, 0)
	if err == nil {
		fields = v.(map[string]*TableField)
	}
	return
}
<|endoftext|>


<commit_before>package abstract_sql

import (
	"context"
	"database/sql"
	"fmt"
	"github.com/chrislusf/seaweedfs/weed/filer"
	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/util"
)

type AbstractSqlStore struct {
	DB                      *sql.DB
	SqlInsert               string
	SqlUpdate               string
	SqlFind                 string
	SqlDelete               string
	SqlDeleteFolderChildren string
	SqlListExclusive        string
	SqlListInclusive        string
}

type TxOrDB interface {
	ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
	QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
	QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
}

func (store *AbstractSqlStore) BeginTransaction(ctx context.Context) (context.Context, error) {
	tx, err := store.DB.BeginTx(ctx, &sql.TxOptions{
		Isolation: sql.LevelReadCommitted,
		ReadOnly:  false,
	})
	if err != nil {
		return ctx, err
	}

	return context.WithValue(ctx, "tx", tx), nil
}
func (store *AbstractSqlStore) CommitTransaction(ctx context.Context) error {
	if tx, ok := ctx.Value("tx").(*sql.Tx); ok {
		return tx.Commit()
	}
	return nil
}
func (store *AbstractSqlStore) RollbackTransaction(ctx context.Context) error {
	if tx, ok := ctx.Value("tx").(*sql.Tx); ok {
		return tx.Rollback()
	}
	return nil
}

func (store *AbstractSqlStore) getTxOrDB(ctx context.Context) TxOrDB {
	if tx, ok := ctx.Value("tx").(*sql.Tx); ok {
		return tx
	}
	return store.DB
}

func (store *AbstractSqlStore) InsertEntry(ctx context.Context, entry *filer.Entry) (err error) {

	dir, name := entry.FullPath.DirAndName()
	meta, err := entry.EncodeAttributesAndChunks()
	if err != nil {
		return fmt.Errorf("encode %s: %s", entry.FullPath, err)
	}

	res, err := store.getTxOrDB(ctx).ExecContext(ctx, store.SqlInsert, util.HashStringToLong(dir), name, dir, meta)
	if err != nil {
		return fmt.Errorf("insert %s: %s", entry.FullPath, err)
	}

	affectedRows, err := res.RowsAffected()
	if err == nil && affectedRows > 0 {
		return nil
	}

	// now the insert failed possibly due to duplication constraints
	glog.V(1).Infof("insert %s falls back to update: %s", entry.FullPath, err)

	res, err = store.getTxOrDB(ctx).ExecContext(ctx, store.SqlUpdate, meta, util.HashStringToLong(dir), name, dir)
	if err != nil {
		return fmt.Errorf("upsert %s: %s", entry.FullPath, err)
	}

	_, err = res.RowsAffected()
	if err != nil {
		return fmt.Errorf("upsert %s but no rows affected: %s", entry.FullPath, err)
	}
	return nil

}

func (store *AbstractSqlStore) UpdateEntry(ctx context.Context, entry *filer.Entry) (err error) {

	dir, name := entry.FullPath.DirAndName()
	meta, err := entry.EncodeAttributesAndChunks()
	if err != nil {
		return fmt.Errorf("encode %s: %s", entry.FullPath, err)
	}

	res, err := store.getTxOrDB(ctx).ExecContext(ctx, store.SqlUpdate, meta, util.HashStringToLong(dir), name, dir)
	if err != nil {
		return fmt.Errorf("update %s: %s", entry.FullPath, err)
	}

	_, err = res.RowsAffected()
	if err != nil {
		return fmt.Errorf("update %s but no rows affected: %s", entry.FullPath, err)
	}
	return nil
}

func (store *AbstractSqlStore) FindEntry(ctx context.Context, fullpath util.FullPath) (*filer.Entry, error) {

	dir, name := fullpath.DirAndName()
	row := store.getTxOrDB(ctx).QueryRowContext(ctx, store.SqlFind, util.HashStringToLong(dir), name, dir)

	var data []byte
	if err := row.Scan(&data); err != nil {
		if err == sql.ErrNoRows {
			return nil, filer_pb.ErrNotFound
		}
		return nil, fmt.Errorf("find %s: %v", fullpath, err)
	}

	entry := &filer.Entry{
		FullPath: fullpath,
	}
	if err := entry.DecodeAttributesAndChunks(data); err != nil {
		return entry, fmt.Errorf("decode %s : %v", entry.FullPath, err)
	}

	return entry, nil
}

func (store *AbstractSqlStore) DeleteEntry(ctx context.Context, fullpath util.FullPath) error {

	dir, name := fullpath.DirAndName()

	res, err := store.getTxOrDB(ctx).ExecContext(ctx, store.SqlDelete, util.HashStringToLong(dir), name, dir)
	if err != nil {
		return fmt.Errorf("delete %s: %s", fullpath, err)
	}

	_, err = res.RowsAffected()
	if err != nil {
		return fmt.Errorf("delete %s but no rows affected: %s", fullpath, err)
	}

	return nil
}

func (store *AbstractSqlStore) DeleteFolderChildren(ctx context.Context, fullpath util.FullPath) error {

	res, err := store.getTxOrDB(ctx).ExecContext(ctx, store.SqlDeleteFolderChildren, util.HashStringToLong(string(fullpath)), fullpath)
	if err != nil {
		return fmt.Errorf("deleteFolderChildren %s: %s", fullpath, err)
	}

	_, err = res.RowsAffected()
	if err != nil {
		return fmt.Errorf("deleteFolderChildren %s but no rows affected: %s", fullpath, err)
	}

	return nil
}

func (store *AbstractSqlStore) ListDirectoryPrefixedEntries(ctx context.Context, fullpath util.FullPath, startFileName string, inclusive bool, limit int, prefix string) (entries []*filer.Entry, err error) {
	sqlText := store.SqlListExclusive
	if inclusive {
		sqlText = store.SqlListInclusive
	}

	rows, err := store.getTxOrDB(ctx).QueryContext(ctx, sqlText, util.HashStringToLong(string(fullpath)), startFileName, string(fullpath), prefix, limit)
	if err != nil {
		return nil, fmt.Errorf("list %s : %v", fullpath, err)
	}
	defer rows.Close()

	for rows.Next() {
		var name string
		var data []byte
		if err = rows.Scan(&name, &data); err != nil {
			glog.V(0).Infof("scan %s : %v", fullpath, err)
			return nil, fmt.Errorf("scan %s: %v", fullpath, err)
		}

		entry := &filer.Entry{
			FullPath: util.NewFullPath(string(fullpath), name),
		}
		if err = entry.DecodeAttributesAndChunks(data); err != nil {
			glog.V(0).Infof("scan decode %s : %v", entry.FullPath, err)
			return nil, fmt.Errorf("scan decode %s : %v", entry.FullPath, err)
		}

		entries = append(entries, entry)
	}

	return entries, nil
}

func (store *AbstractSqlStore) ListDirectoryEntries(ctx context.Context, fullpath util.FullPath, startFileName string, inclusive bool, limit int) (entries []*filer.Entry, err error) {
	return store.ListDirectoryPrefixedEntries(ctx, fullpath, startFileName, inclusive, limit, "")
}

func (store *AbstractSqlStore) Shutdown() {
	store.DB.Close()
}
<commit_msg>fix sql insert with duplicated primary key<commit_after>package abstract_sql

import (
	"context"
	"database/sql"
	"fmt"
	"github.com/chrislusf/seaweedfs/weed/filer"
	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/util"
	"strings"
)

type AbstractSqlStore struct {
	DB                      *sql.DB
	SqlInsert               string
	SqlUpdate               string
	SqlFind                 string
	SqlDelete               string
	SqlDeleteFolderChildren string
	SqlListExclusive        string
	SqlListInclusive        string
}

type TxOrDB interface {
	ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
	QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
	QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
}

func (store *AbstractSqlStore) BeginTransaction(ctx context.Context) (context.Context, error) {
	tx, err := store.DB.BeginTx(ctx, &sql.TxOptions{
		Isolation: sql.LevelReadCommitted,
		ReadOnly:  false,
	})
	if err != nil {
		return ctx, err
	}

	return context.WithValue(ctx, "tx", tx), nil
}
func (store *AbstractSqlStore) CommitTransaction(ctx context.Context) error {
	if tx, ok := ctx.Value("tx").(*sql.Tx); ok {
		return tx.Commit()
	}
	return nil
}
func (store *AbstractSqlStore) RollbackTransaction(ctx context.Context) error {
	if tx, ok := ctx.Value("tx").(*sql.Tx); ok {
		return tx.Rollback()
	}
	return nil
}

func (store *AbstractSqlStore) getTxOrDB(ctx context.Context) TxOrDB {
	if tx, ok := ctx.Value("tx").(*sql.Tx); ok {
		return tx
	}
	return store.DB
}

func (store *AbstractSqlStore) InsertEntry(ctx context.Context, entry *filer.Entry) (err error) {

	dir, name := entry.FullPath.DirAndName()
	meta, err := entry.EncodeAttributesAndChunks()
	if err != nil {
		return fmt.Errorf("encode %s: %s", entry.FullPath, err)
	}

	res, err := store.getTxOrDB(ctx).ExecContext(ctx, store.SqlInsert, util.HashStringToLong(dir), name, dir, meta)
	if err != nil {
		if !strings.Contains(strings.ToLower(err.Error()), "duplicate") {
			return fmt.Errorf("kv insert: %s", err)
		}
	}

	// now the insert failed possibly due to duplication constraints
	glog.V(1).Infof("insert %s falls back to update: %s", entry.FullPath, err)

	res, err = store.getTxOrDB(ctx).ExecContext(ctx, store.SqlUpdate, meta, util.HashStringToLong(dir), name, dir)
	if err != nil {
		return fmt.Errorf("upsert %s: %s", entry.FullPath, err)
	}

	_, err = res.RowsAffected()
	if err != nil {
		return fmt.Errorf("upsert %s but no rows affected: %s", entry.FullPath, err)
	}
	return nil

}

func (store *AbstractSqlStore) UpdateEntry(ctx context.Context, entry *filer.Entry) (err error) {

	dir, name := entry.FullPath.DirAndName()
	meta, err := entry.EncodeAttributesAndChunks()
	if err != nil {
		return fmt.Errorf("encode %s: %s", entry.FullPath, err)
	}

	res, err := store.getTxOrDB(ctx).ExecContext(ctx, store.SqlUpdate, meta, util.HashStringToLong(dir), name, dir)
	if err != nil {
		return fmt.Errorf("update %s: %s", entry.FullPath, err)
	}

	_, err = res.RowsAffected()
	if err != nil {
		return fmt.Errorf("update %s but no rows affected: %s", entry.FullPath, err)
	}
	return nil
}

func (store *AbstractSqlStore) FindEntry(ctx context.Context, fullpath util.FullPath) (*filer.Entry, error) {

	dir, name := fullpath.DirAndName()
	row := store.getTxOrDB(ctx).QueryRowContext(ctx, store.SqlFind, util.HashStringToLong(dir), name, dir)

	var data []byte
	if err := row.Scan(&data); err != nil {
		if err == sql.ErrNoRows {
			return nil, filer_pb.ErrNotFound
		}
		return nil, fmt.Errorf("find %s: %v", fullpath, err)
	}

	entry := &filer.Entry{
		FullPath: fullpath,
	}
	if err := entry.DecodeAttributesAndChunks(data); err != nil {
		return entry, fmt.Errorf("decode %s : %v", entry.FullPath, err)
	}

	return entry, nil
}

func (store *AbstractSqlStore) DeleteEntry(ctx context.Context, fullpath util.FullPath) error {

	dir, name := fullpath.DirAndName()

	res, err := store.getTxOrDB(ctx).ExecContext(ctx, store.SqlDelete, util.HashStringToLong(dir), name, dir)
	if err != nil {
		return fmt.Errorf("delete %s: %s", fullpath, err)
	}

	_, err = res.RowsAffected()
	if err != nil {
		return fmt.Errorf("delete %s but no rows affected: %s", fullpath, err)
	}

	return nil
}

func (store *AbstractSqlStore) DeleteFolderChildren(ctx context.Context, fullpath util.FullPath) error {

	res, err := store.getTxOrDB(ctx).ExecContext(ctx, store.SqlDeleteFolderChildren, util.HashStringToLong(string(fullpath)), fullpath)
	if err != nil {
		return fmt.Errorf("deleteFolderChildren %s: %s", fullpath, err)
	}

	_, err = res.RowsAffected()
	if err != nil {
		return fmt.Errorf("deleteFolderChildren %s but no rows affected: %s", fullpath, err)
	}

	return nil
}

func (store *AbstractSqlStore) ListDirectoryPrefixedEntries(ctx context.Context, fullpath util.FullPath, startFileName string, inclusive bool, limit int, prefix string) (entries []*filer.Entry, err error) {
	sqlText := store.SqlListExclusive
	if inclusive {
		sqlText = store.SqlListInclusive
	}

	rows, err := store.getTxOrDB(ctx).QueryContext(ctx, sqlText, util.HashStringToLong(string(fullpath)), startFileName, string(fullpath), prefix, limit)
	if err != nil {
		return nil, fmt.Errorf("list %s : %v", fullpath, err)
	}
	defer rows.Close()

	for rows.Next() {
		var name string
		var data []byte
		if err = rows.Scan(&name, &data); err != nil {
			glog.V(0).Infof("scan %s : %v", fullpath, err)
			return nil, fmt.Errorf("scan %s: %v", fullpath, err)
		}

		entry := &filer.Entry{
			FullPath: util.NewFullPath(string(fullpath), name),
		}
		if err = entry.DecodeAttributesAndChunks(data); err != nil {
			glog.V(0).Infof("scan decode %s : %v", entry.FullPath, err)
			return nil, fmt.Errorf("scan decode %s : %v", entry.FullPath, err)
		}

		entries = append(entries, entry)
	}

	return entries, nil
}

func (store *AbstractSqlStore) ListDirectoryEntries(ctx context.Context, fullpath util.FullPath, startFileName string, inclusive bool, limit int) (entries []*filer.Entry, err error) {
	return store.ListDirectoryPrefixedEntries(ctx, fullpath, startFileName, inclusive, limit, "")
}

func (store *AbstractSqlStore) Shutdown() {
	store.DB.Close()
}
<|endoftext|>


<commit_before>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package krusty_test

import (
	"testing"

	kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)

func TestNamePrefixSuffixPatch(t *testing.T) {
	th := kusttest_test.MakeHarness(t)

	th.WriteK("bottom", `
configMapGenerator:
- name: bottom
  literals:
  - KEY=value
`)

	th.WriteK("left-service", `
resources:
- deployment.yaml
`)

	th.WriteF("left-service/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: left-deploy
  labels:
    app.kubernetes.io/name: left-deploy
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: left-pod
  template:
    metadata:
      labels:
        app.kubernetes.io/name: left-pod
    spec:
      containers:
      - image: left-image:v1.0
        name: service
`)

	th.WriteK("right-service", `
resources:
- deployment.yaml
`)

	th.WriteF("right-service/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: right-deploy
  labels:
    app.kubernetes.io/name: right-deploy
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: right-pod
  template:
    metadata:
      labels:
        app.kubernetes.io/name: right-pod
    spec:
      containers:
      - image: right-image:v1.0
        name: service
`)

	th.WriteK("top", `
resources:
- ./left
- ./right
`)

	th.WriteK("top/left", `
resources:
- ../../left-service
- ./bottom

patches:
- target:
    kind: Deployment
    name: left-deploy
  patch: |-
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ignored-by-kustomize
    spec:
      template:
        spec:
          containers:
          - name: service
            env:
            - name: MAPPED_CONFIG_ITEM
              valueFrom:
                configMapKeyRef:
                  name: left-bottom
                  key: KEY
`)

	th.WriteK("top/left/bottom", `
namePrefix: left-

resources:
- ../../../bottom
`)

	th.WriteK("top/right", `
resources:
- ../../right-service
- ./bottom

patches:
- target:
    kind: Deployment
    name: right-deploy
  patch: |-
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ignored-by-kustomize
    spec:
      template:
        spec:
          containers:
          - name: service
            env:
            - name: MAPPED_CONFIG_ITEM
              valueFrom:
                configMapKeyRef:
                  name: right-bottom
                  key: KEY
`)

	th.WriteK("top/right/bottom", `
namePrefix: right-

resources:
- ../../../bottom
`)

	m := th.Run("top", th.MakeDefaultOptions())
	// Desired behaviour: configMapKeyRef should reference ConfigMap names.
	th.AssertActualEqualsExpected(m, `apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: left-deploy
  name: left-deploy
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: left-pod
  template:
    metadata:
      labels:
        app.kubernetes.io/name: left-pod
    spec:
      containers:
      - env:
        - name: MAPPED_CONFIG_ITEM
          valueFrom:
            configMapKeyRef:
              key: KEY
              name: left-bottom
        image: left-image:v1.0
        name: service
---
apiVersion: v1
data:
  KEY: value
kind: ConfigMap
metadata:
  name: left-bottom-9f2t6f5h6d
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: right-deploy
  name: right-deploy
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: right-pod
  template:
    metadata:
      labels:
        app.kubernetes.io/name: right-pod
    spec:
      containers:
      - env:
        - name: MAPPED_CONFIG_ITEM
          valueFrom:
            configMapKeyRef:
              key: KEY
              name: right-bottom
        image: right-image:v1.0
        name: service
---
apiVersion: v1
data:
  KEY: value
kind: ConfigMap
metadata:
  name: right-bottom-9f2t6f5h6d
`)
}
<commit_msg>Modified test name per PR feedback<commit_after>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package krusty_test

import (
	"testing"

	kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
)

func TestConfMapNameResolutionInDiamondWithPatches(t *testing.T) {
	th := kusttest_test.MakeHarness(t)

	th.WriteK("bottom", `
configMapGenerator:
- name: bottom
  literals:
  - KEY=value
`)

	th.WriteK("left-service", `
resources:
- deployment.yaml
`)

	th.WriteF("left-service/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: left-deploy
  labels:
    app.kubernetes.io/name: left-deploy
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: left-pod
  template:
    metadata:
      labels:
        app.kubernetes.io/name: left-pod
    spec:
      containers:
      - image: left-image:v1.0
        name: service
`)

	th.WriteK("right-service", `
resources:
- deployment.yaml
`)

	th.WriteF("right-service/deployment.yaml", `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: right-deploy
  labels:
    app.kubernetes.io/name: right-deploy
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: right-pod
  template:
    metadata:
      labels:
        app.kubernetes.io/name: right-pod
    spec:
      containers:
      - image: right-image:v1.0
        name: service
`)

	th.WriteK("top", `
resources:
- ./left
- ./right
`)

	th.WriteK("top/left", `
resources:
- ../../left-service
- ./bottom

patches:
- target:
    kind: Deployment
    name: left-deploy
  patch: |-
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ignored-by-kustomize
    spec:
      template:
        spec:
          containers:
          - name: service
            env:
            - name: MAPPED_CONFIG_ITEM
              valueFrom:
                configMapKeyRef:
                  name: left-bottom
                  key: KEY
`)

	th.WriteK("top/left/bottom", `
namePrefix: left-

resources:
- ../../../bottom
`)

	th.WriteK("top/right", `
resources:
- ../../right-service
- ./bottom

patches:
- target:
    kind: Deployment
    name: right-deploy
  patch: |-
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ignored-by-kustomize
    spec:
      template:
        spec:
          containers:
          - name: service
            env:
            - name: MAPPED_CONFIG_ITEM
              valueFrom:
                configMapKeyRef:
                  name: right-bottom
                  key: KEY
`)

	th.WriteK("top/right/bottom", `
namePrefix: right-

resources:
- ../../../bottom
`)

	m := th.Run("top", th.MakeDefaultOptions())
	// Desired behaviour: configMapKeyRef should reference ConfigMap names.
	th.AssertActualEqualsExpected(m, `apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: left-deploy
  name: left-deploy
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: left-pod
  template:
    metadata:
      labels:
        app.kubernetes.io/name: left-pod
    spec:
      containers:
      - env:
        - name: MAPPED_CONFIG_ITEM
          valueFrom:
            configMapKeyRef:
              key: KEY
              name: left-bottom
        image: left-image:v1.0
        name: service
---
apiVersion: v1
data:
  KEY: value
kind: ConfigMap
metadata:
  name: left-bottom-9f2t6f5h6d
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: right-deploy
  name: right-deploy
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: right-pod
  template:
    metadata:
      labels:
        app.kubernetes.io/name: right-pod
    spec:
      containers:
      - env:
        - name: MAPPED_CONFIG_ITEM
          valueFrom:
            configMapKeyRef:
              key: KEY
              name: right-bottom
        image: right-image:v1.0
        name: service
---
apiVersion: v1
data:
  KEY: value
kind: ConfigMap
metadata:
  name: right-bottom-9f2t6f5h6d
`)
}
<|endoftext|>


<commit_before>// Copyright 2013 Alex Browne.  All rights reserved.
// Use of this source code is governed by the MIT
// license, which can be found in the LICENSE file.

// File util.go contains miscellaneous utility functions used throughout
// the zoom library. They are not intended for external use.

package zoom

import (
	"encoding/json"
	"errors"
	"fmt"
	"math/rand"
	"reflect"
)

func reverseString(s string) string {
	runes := []rune(s)
	for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
		runes[i], runes[j] = runes[j], runes[i]
	}
	return string(runes)
}

func indexOfStringSlice(a string, list []string) int {
	for i, b := range list {
		if b == a {
			return i
		}
	}
	return -1
}

func indexOfSlice(a interface{}, list interface{}) int {
	lVal := reflect.ValueOf(list)
	size := lVal.Len()
	for i := 0; i < size; i++ {
		elem := lVal.Index(i)
		if reflect.DeepEqual(a, elem.Interface()) {
			return i
		}
	}
	return -1
}

func stringSliceContains(a string, list []string) bool {
	return indexOfStringSlice(a, list) != -1
}

func sliceContains(a interface{}, list interface{}) bool {
	return indexOfSlice(a, list) != -1
}

func removeFromStringSlice(list []string, i int) []string {
	return append(list[:i], list[i+1:]...)
}

func removeElementFromStringSlice(list []string, elem string) []string {
	for i, e := range list {
		if e == elem {
			return append(list[:i], list[i+1:]...)
		}
	}
	return list
}

func compareAsStringSet(expecteds, gots []string) (bool, string) {
	// make sure everything in expecteds is also in gots
	for _, e := range expecteds {
		index := indexOfStringSlice(e, gots)
		if index == -1 {
			msg := fmt.Sprintf("Missing expected element: %v", e)
			return false, msg
		}
	}

	// make sure everything in gots is also in expecteds
	for _, g := range gots {
		index := indexOfStringSlice(g, expecteds)
		if index == -1 {
			msg := fmt.Sprintf("Found extra element: %v", g)
			return false, msg
		}
	}

	return true, "ok"
}

func compareAsSet(expecteds, gots interface{}) (bool, string) {
	eVal := reflect.ValueOf(expecteds)
	gVal := reflect.ValueOf(gots)

	if !eVal.IsValid() {
		return false, "expecteds was nil"
	} else if !gVal.IsValid() {
		return false, "gots was nil"
	}

	// make sure everything in expecteds is also in gots
	for i := 0; i < eVal.Len(); i++ {
		expected := eVal.Index(i).Interface()
		index := indexOfSlice(expected, gots)
		if index == -1 {
			msg := fmt.Sprintf("Missing expected element: %v", expected)
			return false, msg
		}
	}

	// make sure everything in gots is also in expecteds
	for i := 0; i < gVal.Len(); i++ {
		got := gVal.Index(i).Interface()
		index := indexOfSlice(got, expecteds)
		if index == -1 {
			msg := fmt.Sprintf("Found unexpected element: %v", got)
			return false, msg
		}
	}
	return true, "ok"
}

func typeIsSliceOrArray(typ reflect.Type) bool {
	k := typ.Kind()
	return (k == reflect.Slice || k == reflect.Array) && typ.Elem().Kind() != reflect.Uint8
}

func typeIsPointerToStruct(typ reflect.Type) bool {
	return typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct
}

func typeIsString(typ reflect.Type) bool {
	k := typ.Kind()
	return k == reflect.String || ((k == reflect.Slice || k == reflect.Array) && typ.Elem().Kind() == reflect.Uint8)
}

func typeIsNumeric(typ reflect.Type) bool {
	k := typ.Kind()
	switch k {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
		return true
	default:
		return false
	}
}

func typeIsBool(typ reflect.Type) bool {
	k := typ.Kind()
	return k == reflect.Bool
}

func typeIsPrimative(typ reflect.Type) bool {
	return typeIsString(typ) || typeIsNumeric(typ) || typeIsBool(typ)
}

// generate a random int from min to max (inclusively).
// I.e. to get either 1 or 0, use randInt(0,1)
func randInt(min int, max int) int {
	if !(max-min >= 1) {
		panic("invalid args. max must be at least one more than min")
	}
	return min + rand.Intn(max-min+1)
}

// looseEquals returns true if the two things are equal.
// equality is based on underlying value, so if the pointer addresses
// are different it doesn't matter. We use gob encoding for simplicity,
// assuming that if the gob representation of two things is the same,
// those two things can be considered equal. Differs from reflect.DeepEqual
// because of the indifference concerning pointer addresses.
func looseEquals(one, two interface{}) (bool, error) {
	oneBytes, err := json.Marshal(one)
	if err != nil {
		return false, err
	}
	twoBytes, err := json.Marshal(two)
	if err != nil {
		return false, err
	}

	return (string(oneBytes) == string(twoBytes)), nil
}

func convertNumericToFloat64(val reflect.Value) (float64, error) {
	switch val.Type().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		integer := val.Int()
		return float64(integer), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		uinteger := val.Uint()
		return float64(uinteger), nil
	case reflect.Float32, reflect.Float64:
		return val.Float(), nil
	default:
		msg := fmt.Sprintf("zoom: attempt to call convertNumericToFloat64 on non-numeric type %s", val.Type().String())
		return 0.0, errors.New(msg)
	}
}

func modelIds(ms []Model) []string {
	results := make([]string, len(ms))
	for i, m := range ms {
		results[i] = m.getId()
	}
	return results
}

// converts a bool to an int using the following rule:
// false = 0
// true = 1
func boolToInt(b bool) int {
	if b {
		return 1
	} else {
		return 0
	}
}
<commit_msg>Add an orderedIntersect method in util.go<commit_after>// Copyright 2013 Alex Browne.  All rights reserved.
// Use of this source code is governed by the MIT
// license, which can be found in the LICENSE file.

// File util.go contains miscellaneous utility functions used throughout
// the zoom library. They are not intended for external use.

package zoom

import (
	"encoding/json"
	"errors"
	"fmt"
	"math/rand"
	"reflect"
)

func reverseString(s string) string {
	runes := []rune(s)
	for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
		runes[i], runes[j] = runes[j], runes[i]
	}
	return string(runes)
}

func indexOfStringSlice(a string, list []string) int {
	for i, b := range list {
		if b == a {
			return i
		}
	}
	return -1
}

func indexOfSlice(a interface{}, list interface{}) int {
	lVal := reflect.ValueOf(list)
	size := lVal.Len()
	for i := 0; i < size; i++ {
		elem := lVal.Index(i)
		if reflect.DeepEqual(a, elem.Interface()) {
			return i
		}
	}
	return -1
}

func stringSliceContains(a string, list []string) bool {
	return indexOfStringSlice(a, list) != -1
}

func sliceContains(a interface{}, list interface{}) bool {
	return indexOfSlice(a, list) != -1
}

func removeFromStringSlice(list []string, i int) []string {
	return append(list[:i], list[i+1:]...)
}

func removeElementFromStringSlice(list []string, elem string) []string {
	for i, e := range list {
		if e == elem {
			return append(list[:i], list[i+1:]...)
		}
	}
	return list
}

func compareAsStringSet(expecteds, gots []string) (bool, string) {
	// make sure everything in expecteds is also in gots
	for _, e := range expecteds {
		index := indexOfStringSlice(e, gots)
		if index == -1 {
			msg := fmt.Sprintf("Missing expected element: %v", e)
			return false, msg
		}
	}

	// make sure everything in gots is also in expecteds
	for _, g := range gots {
		index := indexOfStringSlice(g, expecteds)
		if index == -1 {
			msg := fmt.Sprintf("Found extra element: %v", g)
			return false, msg
		}
	}

	return true, "ok"
}

func compareAsSet(expecteds, gots interface{}) (bool, string) {
	eVal := reflect.ValueOf(expecteds)
	gVal := reflect.ValueOf(gots)

	if !eVal.IsValid() {
		return false, "expecteds was nil"
	} else if !gVal.IsValid() {
		return false, "gots was nil"
	}

	// make sure everything in expecteds is also in gots
	for i := 0; i < eVal.Len(); i++ {
		expected := eVal.Index(i).Interface()
		index := indexOfSlice(expected, gots)
		if index == -1 {
			msg := fmt.Sprintf("Missing expected element: %v", expected)
			return false, msg
		}
	}

	// make sure everything in gots is also in expecteds
	for i := 0; i < gVal.Len(); i++ {
		got := gVal.Index(i).Interface()
		index := indexOfSlice(got, expecteds)
		if index == -1 {
			msg := fmt.Sprintf("Found unexpected element: %v", got)
			return false, msg
		}
	}
	return true, "ok"
}

func typeIsSliceOrArray(typ reflect.Type) bool {
	k := typ.Kind()
	return (k == reflect.Slice || k == reflect.Array) && typ.Elem().Kind() != reflect.Uint8
}

func typeIsPointerToStruct(typ reflect.Type) bool {
	return typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct
}

func typeIsString(typ reflect.Type) bool {
	k := typ.Kind()
	return k == reflect.String || ((k == reflect.Slice || k == reflect.Array) && typ.Elem().Kind() == reflect.Uint8)
}

func typeIsNumeric(typ reflect.Type) bool {
	k := typ.Kind()
	switch k {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
		return true
	default:
		return false
	}
}

func typeIsBool(typ reflect.Type) bool {
	k := typ.Kind()
	return k == reflect.Bool
}

func typeIsPrimative(typ reflect.Type) bool {
	return typeIsString(typ) || typeIsNumeric(typ) || typeIsBool(typ)
}

// generate a random int from min to max (inclusively).
// I.e. to get either 1 or 0, use randInt(0,1)
func randInt(min int, max int) int {
	if !(max-min >= 1) {
		panic("invalid args. max must be at least one more than min")
	}
	return min + rand.Intn(max-min+1)
}

// looseEquals returns true if the two things are equal.
// equality is based on underlying value, so if the pointer addresses
// are different it doesn't matter. We use gob encoding for simplicity,
// assuming that if the gob representation of two things is the same,
// those two things can be considered equal. Differs from reflect.DeepEqual
// because of the indifference concerning pointer addresses.
func looseEquals(one, two interface{}) (bool, error) {
	oneBytes, err := json.Marshal(one)
	if err != nil {
		return false, err
	}
	twoBytes, err := json.Marshal(two)
	if err != nil {
		return false, err
	}

	return (string(oneBytes) == string(twoBytes)), nil
}

func convertNumericToFloat64(val reflect.Value) (float64, error) {
	switch val.Type().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		integer := val.Int()
		return float64(integer), nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		uinteger := val.Uint()
		return float64(uinteger), nil
	case reflect.Float32, reflect.Float64:
		return val.Float(), nil
	default:
		msg := fmt.Sprintf("zoom: attempt to call convertNumericToFloat64 on non-numeric type %s", val.Type().String())
		return 0.0, errors.New(msg)
	}
}

func modelIds(ms []Model) []string {
	results := make([]string, len(ms))
	for i, m := range ms {
		results[i] = m.getId()
	}
	return results
}

// converts a bool to an int using the following rule:
// false = 0
// true = 1
func boolToInt(b bool) int {
	if b {
		return 1
	} else {
		return 0
	}
}

// intersects two string slices. The order will be preserved
// with respect to the first slice. (The first slice is used
// in the outer loop). The return value is a copy, so neither
// the first or second slice will be mutated.
func orderedIntersectString(first []string, second []string) []string {
	results := make([]string, 0)
	lastIndex := 0
	l2 := len(second)
	for _, a := range first {
		var b string
		for i := lastIndex; i < l2 && b <= a; i++ {
			b = second[i]
			if a == b {
				results = append(results, a)
				lastIndex = i
				break
			}
		}
	}
	return results
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"reflect"
	"time"
)

func metricsFileName(series_name string) string {
	return metrics_dir + "/" + series_name + ".log"
}

func getDateStamp(format string) string {

	t := time.Now().UTC()

	if format == "RFC822Z" {

		return t.Format(time.RFC822Z)

	} else if format == "ISO8601" { // 2011-04-19T03:44:01.103Z

		return fmt.Sprintf("%d-%02d-%02dT%02d:%02d:%02d.%03dZ",
			t.Year(), t.Month(), t.Day(),
			t.Hour(), t.Minute(), t.Second(), (t.Nanosecond() / 10000000))

	} else if format == "RFC3339" {

		return t.Format(time.RFC3339)

	} else if format == "SYSLOG" { // 28/Sep/2015:03:26:25.532

		return fmt.Sprintf("%02d/%s/%d:%02d:%02d:%02d.%03d",
			t.Day(), t.Month().String()[0:3], t.Year(),
			t.Hour(), t.Minute(), t.Second(), (t.Nanosecond() / 10000000))

	}
	return t.Format(time.RFC822Z)
}

func Call(m map[string]interface{}, name string, params ...interface{}) (result []reflect.Value, err error) {
	f := reflect.ValueOf(m[name])
	if len(params) != f.Type().NumIn() {
		err = errors.New("Wrong number of parameters!")
		return
	}
	in := make([]reflect.Value, len(params))
	for k, param := range params {
		in[k] = reflect.ValueOf(param)
	}
	result = f.Call(in)
	return
}
<commit_msg>Fixed syslog date prefix format<commit_after>package main

import (
	"errors"
	"fmt"
	"reflect"
	"time"
)

func metricsFileName(series_name string) string {
	return metrics_dir + "/" + series_name + ".log"
}

func getDateStamp(format string) string {

	t := time.Now().UTC()

	if format == "RFC822Z" {

		return t.Format(time.RFC822Z)

	} else if format == "ISO8601" { // 2011-04-19T03:44:01.103Z

		return fmt.Sprintf("%d-%02d-%02dT%02d:%02d:%02d.%03dZ",
			t.Year(), t.Month(), t.Day(),
			t.Hour(), t.Minute(), t.Second(), (t.Nanosecond() / 10000000))

	} else if format == "RFC3339" {

		return t.Format(time.RFC3339)

	} else if format == "SYSLOG" { // 28/Sep/2015:03:26:25.532

		return fmt.Sprintf("%s %d %02d:%02d:%02d",
			t.Month().String()[0:3], t.Day(),
			t.Hour(), t.Minute(), t.Second())
	}
	return t.Format(time.RFC822Z)
}

func Call(m map[string]interface{}, name string, params ...interface{}) (result []reflect.Value, err error) {
	f := reflect.ValueOf(m[name])
	if len(params) != f.Type().NumIn() {
		err = errors.New("Wrong number of parameters!")
		return
	}
	in := make([]reflect.Value, len(params))
	for k, param := range params {
		in[k] = reflect.ValueOf(param)
	}
	result = f.Call(in)
	return
}
<|endoftext|>