<commit_before>package repo

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"

	log "github.com/sirupsen/logrus"
	"github.com/xshellinc/tools/lib/help"
	"gopkg.in/cheggaaa/pb.v1"
)

// S3Bucket stores default S3 bucket path
const S3Bucket = "https://cdn.isaax.io/isaax-distro/versions.json"

// IoTItRepo stores default iotit repo path
const IoTItRepo = "https://cdn.isaax.io/iotit/version.json"

// Releases
const (
	Latest = "latest"
	Stable = "stable"
)

// baseDir is a directory of iotit related files and configurations
var baseDir = filepath.Join(help.UserHomeDir(), ".iotit")

// VboxDir is a directory of virtualboxes
var VboxDir = filepath.Join(baseDir, "virtualbox")

// ImageDir is a directory of the flashing images
var ImageDir = filepath.Join(baseDir, "images")

func init() {
	help.CreateDir(baseDir)
	help.CreateDir(ImageDir)
	help.CreateDir(VboxDir)
	help.CreateDir(filepath.Join(help.UserHomeDir(), "VirtualBox VMs"))
}

// Repository represents image repo
type Repository interface {
	//version of latest distro
	GetVersion() string
	//url of distro
	GetURL() string
	//name of the latest distro file
	Name() string
	//base dir of repository
	Dir() string
}

// GenericRepository is so generic
type GenericRepository struct {
	Version   string
	URL       string
	Directory string
}

// GetVersion of generic repo
func (g *GenericRepository) GetVersion() string {
	return g.Version
}

// GetURL of generic repo
func (g *GenericRepository) GetURL() string {
	return g.URL
}

// Dir of generic repo
func (g *GenericRepository) Dir() string {
	return g.Directory
}

// Name of generic repo
func (g *GenericRepository) Name() string {
	tokens := strings.Split(g.URL, "/")
	return tokens[len(tokens)-1]
}

// VMRepo is a configuration entry for VM
type VMRepo struct {
	VMs struct {
		VM struct {
			Version string `json:"version"`
			URL     string `json:"url"`
			MD5Sum  string `json:"md5sum"`
		} `json:"vm-iotit"`
	} `json:"vms"`
}

// GetVersion of VM
func (v VMRepo) GetVersion() string {
	return v.VMs.VM.Version
}

// GetURL of VM
func (v VMRepo) GetURL() string {
	return v.VMs.VM.URL
}

// Dir of VM
func (VMRepo) Dir() string {
	return VboxDir
}

// Name of VM
func (v VMRepo) Name() string {
	tokens := strings.Split(v.VMs.VM.URL, "/")
	return tokens[len(tokens)-1]
}

// NewRepositoryVM creates new repository for specified VM type
func NewRepositoryVM() (Repository, error) {
	var (
		client http.Client
		repo   VMRepo
	)
	resp, err := client.Get(S3Bucket)
	if err != nil {
		log.Error("Could not make GET request to url:", S3Bucket, " error msg:", err.Error())
		fmt.Println("[-] Could not connect to S3 bucket")
		return nil, err
	}
	defer resp.Body.Close()

	decoder := json.NewDecoder(resp.Body)
	if err = decoder.Decode(&repo); err != nil {
		log.Error("Could not unmarshall json struct ", "error msg:", err.Error())
		return nil, err
	}

	return repo, nil
}

// DownloadAsync starts async download
func DownloadAsync(repo Repository, wg *sync.WaitGroup) (string, *pb.ProgressBar, error) {
	dst := filepath.Join(repo.Dir(), repo.GetVersion())
	return help.DownloadFromUrlWithAttemptsAsync(repo.GetURL(), dst, 3, wg)
}

// NewGenericRepository creates new generic repo
func NewGenericRepository(url, version string, dir string) Repository {
	help.CreateDir(dir)
	return &GenericRepository{
		URL:       url,
		Version:   version,
		Directory: dir,
	}
}

// DownloadNewVersion downloads the latest version based on the current release and skips this step if up to date
func DownloadNewVersion(name, version, dst string) (string, error) {
	zipMethod := "zip"
	if runtime.GOOS == "linux" {
		zipMethod = "tar.gz"
	}

	fileName := fmt.Sprintf("%s_%s_%s_%s", name, version, runtime.GOOS, runtime.GOARCH)

	_, version, err := GetIoTItVersionMD5(runtime.GOOS, runtime.GOARCH, version)
	if err != nil || version == "" {
		return "", err
	}

	url := fmt.Sprintf("https://cdn.isaax.io/%s/%s/%s/%s.%s", name, currentRelease(version), runtime.GOOS, fileName, zipMethod)
	log.WithField("url", url).Debug("DownloadNewVersion")
	wg := &sync.WaitGroup{}
	imgName, bar, err := help.DownloadFromUrlWithAttemptsAsync(url, dst, 5, wg)
	if err != nil {
		return fileName, err
	}
	bar.Prefix(fmt.Sprintf("[+] Download %-15s", imgName))
	bar.Start()
	wg.Wait()
	bar.Finish()
	time.Sleep(time.Second)

	fmt.Println("[+] Extracting into ", dst)
	if runtime.GOOS == "linux" {
		if err := exec.Command("tar", "xvf", dst+help.Separator()+fileName, "-C", dst).Run(); err != nil {
			fmt.Println("[-] ", err)
			return fileName, err
		}
	} else if err := exec.Command("unzip", "-o", dst+help.Separator()+fileName, "-d", dst).Run(); err != nil {
		fmt.Println("[-] ", err)
		return fileName, err
	}

	return fileName, nil
}

// currentRelease detects whether release is stable or latest
func currentRelease(version string) (release string) {
	r := Latest
	match, _ := regexp.Compile(`^[\d|_]+\.[\d|_]+\.[\d|_]+$`)
	if match.MatchString(version) {
		r = Stable
	}

	return r
}

// getVersionLexem parses string lexems into comparable parts
func getVersionLexem(token string, seps ...string) []string {
	var lexs []string
	for i, sep := range seps {
		if i == 0 {
			lexs = strings.Split(token, sep)
			continue
		}

		var tmp []string
		for _, lex := range lexs {
			tmp = append(tmp, strings.Split(lex, sep)...)
		}

		lexs = tmp
	}

	return lexs
}

// IsVersionUpToDate checks if version is up to date
func IsVersionUpToDate(v1, v2 string) (bool, error) {
	vlex1 := getVersionLexem(v1, ".", "_", "-")
	vlex2 := getVersionLexem(v2, ".", "_", "-")

	for i := 0; i < len(vlex1) && i < len(vlex2); i++ {
		n1, err := strconv.Atoi(vlex1[i])
		if err != nil {
			return false, err
		}

		n2, err := strconv.Atoi(vlex2[i])
		if err != nil {
			return false, err
		}

		if n1 == n2 {
			continue
		}

		return n1 > n2, nil
	}

	// not reachable
	return false, nil
}

// GetIoTItVersionMD5 gets the latest version from the repo and checks if the new version is available
func GetIoTItVersionMD5(oss, arch, version string) (hash string, repoVersion string, err error) {
	log.WithField("url", IoTItRepo).WithField("ver", version).Debug("GetIoTItVersionMD5")
	var checkMethKey = "md5sums"
	var versionKey = "version"

	var client http.Client
	resp, err := client.Get(IoTItRepo)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	r := make(map[string]*json.RawMessage)
	if err = json.NewDecoder(resp.Body).Decode(&r); err != nil {
		return
	}
	if err = json.Unmarshal(*r[currentRelease(version)], &r); err != nil {
		return
	}
	if err = json.Unmarshal(*r[checkMethKey], &r); err != nil {
		return
	}
	if err = json.Unmarshal(*r[oss], &r); err != nil {
		return
	}
	if err = json.Unmarshal(*r[arch], &hash); err != nil {
		return
	}
	if err = json.Unmarshal(*r[versionKey], &repoVersion); err != nil {
		return
	}
	log.WithField("registry", r).Debug("parsed")

	if result := help.CompareVersions(version, repoVersion); result <= 0 {
		repoVersion = ""
		return
	}

	return
}
<commit_msg>Fix cdn links<commit_after>package repo

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"time"

	log "github.com/sirupsen/logrus"
	"github.com/xshellinc/tools/lib/help"
	"gopkg.in/cheggaaa/pb.v1"
)

// S3Bucket stores default S3 bucket path
const S3Bucket = "http://cdn.isaax.io/iotit/versions.json"

// IoTItRepo stores default iotit repo path
const IoTItRepo = "https://cdn.isaax.io/iotit/versions.json"

// Releases
const (
	Latest = "latest"
	Stable = "stable"
)

// baseDir is a directory of iotit related files and configurations
var baseDir = filepath.Join(help.UserHomeDir(), ".iotit")

// VboxDir is a directory of virtualboxes
var VboxDir = filepath.Join(baseDir, "virtualbox")

// ImageDir is a directory of the flashing images
var ImageDir = filepath.Join(baseDir, "images")

func init() {
	help.CreateDir(baseDir)
	help.CreateDir(ImageDir)
	help.CreateDir(VboxDir)
	help.CreateDir(filepath.Join(help.UserHomeDir(), "VirtualBox VMs"))
}

// Repository represents image repo
type Repository interface {
	//version of latest distro
	GetVersion() string
	//url of distro
	GetURL() string
	//name of the latest distro file
	Name() string
	//base dir of repository
	Dir() string
}

// GenericRepository is so generic
type GenericRepository struct {
	Version   string
	URL       string
	Directory string
}

// GetVersion of generic repo
func (g *GenericRepository) GetVersion() string {
	return g.Version
}

// GetURL of generic repo
func (g *GenericRepository) GetURL() string {
	return g.URL
}

// Dir of generic repo
func (g *GenericRepository) Dir() string {
	return g.Directory
}

// Name of generic repo
func (g *GenericRepository) Name() string {
	tokens := strings.Split(g.URL, "/")
	return tokens[len(tokens)-1]
}

// VMRepo is a configuration entry for VM
type VMRepo struct {
	VMs struct {
		VM struct {
			Version string `json:"version"`
			URL     string `json:"url"`
			MD5Sum  string `json:"md5sum"`
		} `json:"vm-iotit"`
	} `json:"vms"`
}

// GetVersion of VM
func (v VMRepo) GetVersion() string {
	return v.VMs.VM.Version
}

// GetURL of VM
func (v VMRepo) GetURL() string {
	return v.VMs.VM.URL
}

// Dir of VM
func (VMRepo) Dir() string {
	return VboxDir
}

// Name of VM
func (v VMRepo) Name() string {
	tokens := strings.Split(v.VMs.VM.URL, "/")
	return tokens[len(tokens)-1]
}

// NewRepositoryVM creates new repository for specified VM type
func NewRepositoryVM() (Repository, error) {
	var (
		client http.Client
		repo   VMRepo
	)
	resp, err := client.Get(S3Bucket)
	if err != nil {
		log.Error("Could not make GET request to url:", S3Bucket, " error msg:", err.Error())
		fmt.Println("[-] Could not connect to S3 bucket")
		return nil, err
	}
	defer resp.Body.Close()

	decoder := json.NewDecoder(resp.Body)
	if err = decoder.Decode(&repo); err != nil {
		log.Error("Could not unmarshall json struct ", "error msg:", err.Error())
		return nil, err
	}

	return repo, nil
}

// DownloadAsync starts async download
func DownloadAsync(repo Repository, wg *sync.WaitGroup) (string, *pb.ProgressBar, error) {
	dst := filepath.Join(repo.Dir(), repo.GetVersion())
	return help.DownloadFromUrlWithAttemptsAsync(repo.GetURL(), dst, 3, wg)
}

// NewGenericRepository creates new generic repo
func NewGenericRepository(url, version string, dir string) Repository {
	help.CreateDir(dir)
	return &GenericRepository{
		URL:       url,
		Version:   version,
		Directory: dir,
	}
}

// DownloadNewVersion downloads the latest version based on the current release and skips this step if up to date
func DownloadNewVersion(name, version, dst string) (string, error) {
	zipMethod := "zip"
	if runtime.GOOS == "linux" {
		zipMethod = "tar.gz"
	}

	fileName := fmt.Sprintf("%s_%s_%s_%s", name, version, runtime.GOOS, runtime.GOARCH)

	_, version, err := GetIoTItVersionMD5(runtime.GOOS, runtime.GOARCH, version)
	if err != nil || version == "" {
		return "", err
	}

	url := fmt.Sprintf("https://cdn.isaax.io/%s/%s/%s/%s.%s", name, currentRelease(version), runtime.GOOS, fileName, zipMethod)
	log.WithField("url", url).Debug("DownloadNewVersion")
	wg := &sync.WaitGroup{}
	imgName, bar, err := help.DownloadFromUrlWithAttemptsAsync(url, dst, 5, wg)
	if err != nil {
		return fileName, err
	}
	bar.Prefix(fmt.Sprintf("[+] Download %-15s", imgName))
	bar.Start()
	wg.Wait()
	bar.Finish()
	time.Sleep(time.Second)

	fmt.Println("[+] Extracting into ", dst)
	if runtime.GOOS == "linux" {
		if err := exec.Command("tar", "xvf", dst+help.Separator()+fileName, "-C", dst).Run(); err != nil {
			fmt.Println("[-] ", err)
			return fileName, err
		}
	} else if err := exec.Command("unzip", "-o", dst+help.Separator()+fileName, "-d", dst).Run(); err != nil {
		fmt.Println("[-] ", err)
		return fileName, err
	}

	return fileName, nil
}

// currentRelease detects whether release is stable or latest
func currentRelease(version string) (release string) {
	r := Latest
	match, _ := regexp.Compile(`^[\d|_]+\.[\d|_]+\.[\d|_]+$`)
	if match.MatchString(version) {
		r = Stable
	}

	return r
}

// getVersionLexem parses string lexems into comparable parts
func getVersionLexem(token string, seps ...string) []string {
	var lexs []string
	for i, sep := range seps {
		if i == 0 {
			lexs = strings.Split(token, sep)
			continue
		}

		var tmp []string
		for _, lex := range lexs {
			tmp = append(tmp, strings.Split(lex, sep)...)
		}

		lexs = tmp
	}

	return lexs
}

// IsVersionUpToDate checks if version is up to date
func IsVersionUpToDate(v1, v2 string) (bool, error) {
	vlex1 := getVersionLexem(v1, ".", "_", "-")
	vlex2 := getVersionLexem(v2, ".", "_", "-")

	for i := 0; i < len(vlex1) && i < len(vlex2); i++ {
		n1, err := strconv.Atoi(vlex1[i])
		if err != nil {
			return false, err
		}

		n2, err := strconv.Atoi(vlex2[i])
		if err != nil {
			return false, err
		}

		if n1 == n2 {
			continue
		}

		return n1 > n2, nil
	}

	// not reachable
	return false, nil
}

// GetIoTItVersionMD5 gets the latest version from the repo and checks if the new version is available
func GetIoTItVersionMD5(oss, arch, version string) (hash string, repoVersion string, err error) {
	log.WithField("url", IoTItRepo).WithField("ver", version).Debug("GetIoTItVersionMD5")
	var checkMethKey = "md5sums"
	var versionKey = "version"

	var client http.Client
	resp, err := client.Get(IoTItRepo)
	if err != nil {
		return
	}
	defer resp.Body.Close()

	r := make(map[string]*json.RawMessage)
	if err = json.NewDecoder(resp.Body).Decode(&r); err != nil {
		return
	}
	if err = json.Unmarshal(*r[currentRelease(version)], &r); err != nil {
		return
	}
	if err = json.Unmarshal(*r[checkMethKey], &r); err != nil {
		return
	}
	if err = json.Unmarshal(*r[oss], &r); err != nil {
		return
	}
	if err = json.Unmarshal(*r[arch], &hash); err != nil {
		return
	}
	if err = json.Unmarshal(*r[versionKey], &repoVersion); err != nil {
		return
	}
	log.WithField("registry", r).Debug("parsed")

	if result := help.CompareVersions(version, repoVersion); result <= 0 {
		repoVersion = ""
		return
	}

	return
}
<|endoftext|>


<commit_before>package aws

import (
	"encoding/base64"
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/kms"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func dataSourceAwsKmsSecrets() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceAwsKmsSecretsRead,

		Schema: map[string]*schema.Schema{
			"secret": {
				Type:     schema.TypeSet,
				Required: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"name": {
							Type:     schema.TypeString,
							Required: true,
						},
						"payload": {
							Type:     schema.TypeString,
							Required: true,
						},
						"context": {
							Type:     schema.TypeMap,
							Optional: true,
							Elem:     &schema.Schema{Type: schema.TypeString},
						},
						"grant_tokens": {
							Type:     schema.TypeList,
							Optional: true,
							Elem:     &schema.Schema{Type: schema.TypeString},
						},
					},
				},
			},
			"plaintext": {
				Type:      schema.TypeMap,
				Computed:  true,
				Sensitive: true
				Elem:      &schema.Schema{Type: schema.TypeString},
			},
		},
	}
}

func dataSourceAwsKmsSecretsRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).kmsconn

	secrets := d.Get("secret").(*schema.Set)
	plaintext := make(map[string]string, len(secrets.List()))

	for _, v := range secrets.List() {
		secret := v.(map[string]interface{})

		// base64 decode the payload
		payload, err := base64.StdEncoding.DecodeString(secret["payload"].(string))
		if err != nil {
			return fmt.Errorf("Invalid base64 value for secret '%s': %v", secret["name"].(string), err)
		}

		// build the kms decrypt params
		params := &kms.DecryptInput{
			CiphertextBlob: payload,
		}
		if context, exists := secret["context"]; exists {
			params.EncryptionContext = make(map[string]*string)
			for k, v := range context.(map[string]interface{}) {
				params.EncryptionContext[k] = aws.String(v.(string))
			}
		}
		if grant_tokens, exists := secret["grant_tokens"]; exists {
			params.GrantTokens = make([]*string, 0)
			for _, v := range grant_tokens.([]interface{}) {
				params.GrantTokens = append(params.GrantTokens, aws.String(v.(string)))
			}
		}

		// decrypt
		resp, err := conn.Decrypt(params)
		if err != nil {
			return fmt.Errorf("Failed to decrypt '%s': %s", secret["name"].(string), err)
		}

		// Set the secret via the name
		log.Printf("[DEBUG] aws_kms_secret - successfully decrypted secret: %s", secret["name"].(string))
		plaintext[secret["name"].(string)] = string(resp.Plaintext)
	}

	if err := d.Set("plaintext", plaintext); err != nil {
		return fmt.Errorf("error setting plaintext: %s", err)
	}

	d.SetId(time.Now().UTC().String())

	return nil
}
<commit_msg>Update data_source_aws_kms_secrets.go<commit_after>package aws

import (
	"encoding/base64"
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/kms"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func dataSourceAwsKmsSecrets() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceAwsKmsSecretsRead,

		Schema: map[string]*schema.Schema{
			"secret": {
				Type:     schema.TypeSet,
				Required: true,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"name": {
							Type:     schema.TypeString,
							Required: true,
						},
						"payload": {
							Type:     schema.TypeString,
							Required: true,
						},
						"context": {
							Type:     schema.TypeMap,
							Optional: true,
							Elem:     &schema.Schema{Type: schema.TypeString},
						},
						"grant_tokens": {
							Type:     schema.TypeList,
							Optional: true,
							Elem:     &schema.Schema{Type: schema.TypeString},
						},
					},
				},
			},
			"plaintext": {
				Type:      schema.TypeMap,
				Computed:  true,
				Sensitive: true,
				Elem:      &schema.Schema{Type: schema.TypeString},
			},
		},
	}
}

func dataSourceAwsKmsSecretsRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).kmsconn

	secrets := d.Get("secret").(*schema.Set)
	plaintext := make(map[string]string, len(secrets.List()))

	for _, v := range secrets.List() {
		secret := v.(map[string]interface{})

		// base64 decode the payload
		payload, err := base64.StdEncoding.DecodeString(secret["payload"].(string))
		if err != nil {
			return fmt.Errorf("Invalid base64 value for secret '%s': %v", secret["name"].(string), err)
		}

		// build the kms decrypt params
		params := &kms.DecryptInput{
			CiphertextBlob: payload,
		}
		if context, exists := secret["context"]; exists {
			params.EncryptionContext = make(map[string]*string)
			for k, v := range context.(map[string]interface{}) {
				params.EncryptionContext[k] = aws.String(v.(string))
			}
		}
		if grant_tokens, exists := secret["grant_tokens"]; exists {
			params.GrantTokens = make([]*string, 0)
			for _, v := range grant_tokens.([]interface{}) {
				params.GrantTokens = append(params.GrantTokens, aws.String(v.(string)))
			}
		}

		// decrypt
		resp, err := conn.Decrypt(params)
		if err != nil {
			return fmt.Errorf("Failed to decrypt '%s': %s", secret["name"].(string), err)
		}

		// Set the secret via the name
		log.Printf("[DEBUG] aws_kms_secret - successfully decrypted secret: %s", secret["name"].(string))
		plaintext[secret["name"].(string)] = string(resp.Plaintext)
	}

	if err := d.Set("plaintext", plaintext); err != nil {
		return fmt.Errorf("error setting plaintext: %s", err)
	}

	d.SetId(time.Now().UTC().String())

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/hashicorp/terraform/helper/schema"
)

func resourceClient() *schema.Resource {
	return &schema.Resource{
		Create: resourceClientCreate,
		Read:   resourceClientRead,
		Update: resourceClientUpdate,
		Delete: resourceClientDelete,

		Schema: map[string]*schema.Schema{
			"client_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"client_secret": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"description": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},
			"is_token_endpoint_ip_header_trusted": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},
			"is_first_party": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},
			"cross_origin_auth": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},
			"sso": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},
			"token_endpoint_auth_method": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},
			"grant_types": &schema.Schema{
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Optional: true,
			},
			"custom_login_page_on": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},
			"app_type": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},
			"callbacks": &schema.Schema{
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Optional: true,
			},
		},
	}
}

type Client struct {
	Client_id                           string        `json:"client_id,omitempty"`
	Client_secret                       string        `json:"client_secret,omitempty"`
	Name                                string        `json:"name"`
	Is_token_endpoint_ip_header_trusted bool          `json:"is_token_endpoint_ip_header_trusted"`
	Is_first_party                      bool          `json:"is_first_party"`
	Description                         string        `json:"description"`
	Cross_origin_auth                   bool          `json:"cross_origin_auth"`
	Sso                                 bool          `json:"sso"`
	Token_endpoint_auth_method          string        `json:"token_endpoint_auth_method"`
	Grant_types                         []interface{} `json:"grant_types"`
	App_type                            string        `json:"app_type"`
	Custom_login_page_on                bool          `json:"custom_login_page_on"`
}

func resourceClientCreate(d *schema.ResourceData, m interface{}) error {
	reqClient := Client{
		Name: d.Get("name").(string),
		Is_token_endpoint_ip_header_trusted: d.Get("is_token_endpoint_ip_header_trusted").(bool),
		Is_first_party:                      d.Get("is_first_party").(bool),
		Description:                         d.Get("description").(string),
		Cross_origin_auth:                   d.Get("cross_origin_auth").(bool),
		Sso:                                 d.Get("sso").(bool),
		Token_endpoint_auth_method: d.Get("token_endpoint_auth_method").(string),
		Grant_types:                d.Get("grant_types").([]interface{}),
		App_type:                   d.Get("app_type").(string),
		Custom_login_page_on:       d.Get("custom_login_page_on").(bool),
	}

	jsonValue, err := json.Marshal(reqClient)
	if err != nil {
		return err
	}
	log.Println("Request JSON: " + string(jsonValue))

	config := m.(Config)
	client := http.Client{}
	req, err := http.NewRequest("POST", "https://"+config.domain+"/api/v2/clients", bytes.NewBuffer(jsonValue))
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", "Bearer "+config.accessToken)
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	log.Println("Response JSON:" + string(data))

	if resp.StatusCode != 201 {
		return errors.New("Error: Invalid status code during create: " + string(data))
	}

	var respClient Client
	err = json.Unmarshal(data, &respClient)
	if err != nil {
		return err
	}

	log.Println("New client_id:" + respClient.Client_id)
	d.Set("client_id", respClient.Client_id)
	d.Set("client_secret", respClient.Client_secret)
	d.SetId(respClient.Client_id)
	return nil
}

func resourceClientRead(d *schema.ResourceData, m interface{}) error {
	config := m.(Config)
	client := http.Client{}
	req, err := http.NewRequest("GET", "https://"+config.domain+"/api/v2/clients/"+d.Id(), nil)
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", "Bearer "+config.accessToken)

	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	log.Println("Response JSON:" + string(data))

	if resp.StatusCode != 200 {
		if resp.StatusCode == 404 {
			// Client was deleted
			d.SetId("")
			return nil
		} else {
			return errors.New("Error: Invalid status code during read: " + string(data))
		}
	}

	var respClient Client
	err = json.Unmarshal(data, &respClient)
	if err != nil {
		return err
	}

	return nil
}

func resourceClientUpdate(d *schema.ResourceData, m interface{}) error {
	reqClient := Client{
		Name: d.Get("name").(string),
		Is_token_endpoint_ip_header_trusted: d.Get("is_token_endpoint_ip_header_trusted").(bool),
		Is_first_party:                      d.Get("is_first_party").(bool),
		Description:                         d.Get("description").(string),
		Cross_origin_auth:                   d.Get("cross_origin_auth").(bool),
		Sso:                                 d.Get("sso").(bool),
		Token_endpoint_auth_method: d.Get("token_endpoint_auth_method").(string),
		Grant_types:                d.Get("grant_types").([]interface{}),
		App_type:                   d.Get("app_type").(string),
		Custom_login_page_on:       d.Get("custom_login_page_on").(bool),
	}

	jsonValue, err := json.Marshal(reqClient)
	if err != nil {
		return err
	}
	log.Println("Request JSON: " + string(jsonValue))

	config := m.(Config)
	client := http.Client{}
	req, err := http.NewRequest("PATCH", "https://"+config.domain+"/api/v2/clients/"+d.Id(), bytes.NewBuffer(jsonValue))
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", "Bearer "+config.accessToken)
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	log.Println("Response JSON:" + string(data))

	if resp.StatusCode != 200 {
		return errors.New("Error: Invalid status code during update: " + string(data))
	}

	var respClient Client
	err = json.Unmarshal(data, &respClient)
	if err != nil {
		return err
	}

	return nil
}

func resourceClientDelete(d *schema.ResourceData, m interface{}) error {
	config := m.(Config)
	client := http.Client{}
	req, err := http.NewRequest("DELETE", "https://"+config.domain+"/api/v2/clients/"+d.Id(), nil)
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", "Bearer "+config.accessToken)

	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	log.Println("Response Status Code:" + string(resp.StatusCode))

	if resp.StatusCode != 204 {
		return errors.New("Error: Invalid status code during delete")
	}

	return nil
}
<commit_msg>Mark client secret as sensitive<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/hashicorp/terraform/helper/schema"
)

func resourceClient() *schema.Resource {
	return &schema.Resource{
		Create: resourceClientCreate,
		Read:   resourceClientRead,
		Update: resourceClientUpdate,
		Delete: resourceClientDelete,

		Schema: map[string]*schema.Schema{
			"client_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
			"client_secret": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
				Sensitive: true,
			},
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},
			"description": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},
			"is_token_endpoint_ip_header_trusted": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},
			"is_first_party": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},
			"cross_origin_auth": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},
			"sso": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},
			"token_endpoint_auth_method": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},
			"grant_types": &schema.Schema{
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Optional: true,
			},
			"custom_login_page_on": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
			},
			"app_type": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},
			"callbacks": &schema.Schema{
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Optional: true,
			},
		},
	}
}

type Client struct {
	Client_id                           string        `json:"client_id,omitempty"`
	Client_secret                       string        `json:"client_secret,omitempty"`
	Name                                string        `json:"name"`
	Is_token_endpoint_ip_header_trusted bool          `json:"is_token_endpoint_ip_header_trusted"`
	Is_first_party                      bool          `json:"is_first_party"`
	Description                         string        `json:"description"`
	Cross_origin_auth                   bool          `json:"cross_origin_auth"`
	Sso                                 bool          `json:"sso"`
	Token_endpoint_auth_method          string        `json:"token_endpoint_auth_method"`
	Grant_types                         []interface{} `json:"grant_types"`
	App_type                            string        `json:"app_type"`
	Custom_login_page_on                bool          `json:"custom_login_page_on"`
}

func resourceClientCreate(d *schema.ResourceData, m interface{}) error {
	reqClient := Client{
		Name: d.Get("name").(string),
		Is_token_endpoint_ip_header_trusted: d.Get("is_token_endpoint_ip_header_trusted").(bool),
		Is_first_party:                      d.Get("is_first_party").(bool),
		Description:                         d.Get("description").(string),
		Cross_origin_auth:                   d.Get("cross_origin_auth").(bool),
		Sso:                                 d.Get("sso").(bool),
		Token_endpoint_auth_method: d.Get("token_endpoint_auth_method").(string),
		Grant_types:                d.Get("grant_types").([]interface{}),
		App_type:                   d.Get("app_type").(string),
		Custom_login_page_on:       d.Get("custom_login_page_on").(bool),
	}

	jsonValue, err := json.Marshal(reqClient)
	if err != nil {
		return err
	}
	log.Println("Request JSON: " + string(jsonValue))

	config := m.(Config)
	client := http.Client{}
	req, err := http.NewRequest("POST", "https://"+config.domain+"/api/v2/clients", bytes.NewBuffer(jsonValue))
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", "Bearer "+config.accessToken)
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	log.Println("Response JSON:" + string(data))

	if resp.StatusCode != 201 {
		return errors.New("Error: Invalid status code during create: " + string(data))
	}

	var respClient Client
	err = json.Unmarshal(data, &respClient)
	if err != nil {
		return err
	}

	log.Println("New client_id:" + respClient.Client_id)
	d.Set("client_id", respClient.Client_id)
	d.Set("client_secret", respClient.Client_secret)
	d.SetId(respClient.Client_id)
	return nil
}

func resourceClientRead(d *schema.ResourceData, m interface{}) error {
	config := m.(Config)
	client := http.Client{}
	req, err := http.NewRequest("GET", "https://"+config.domain+"/api/v2/clients/"+d.Id(), nil)
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", "Bearer "+config.accessToken)

	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	log.Println("Response JSON:" + string(data))

	if resp.StatusCode != 200 {
		if resp.StatusCode == 404 {
			// Client was deleted
			d.SetId("")
			return nil
		} else {
			return errors.New("Error: Invalid status code during read: " + string(data))
		}
	}

	var respClient Client
	err = json.Unmarshal(data, &respClient)
	if err != nil {
		return err
	}

	return nil
}

func resourceClientUpdate(d *schema.ResourceData, m interface{}) error {
	reqClient := Client{
		Name: d.Get("name").(string),
		Is_token_endpoint_ip_header_trusted: d.Get("is_token_endpoint_ip_header_trusted").(bool),
		Is_first_party:                      d.Get("is_first_party").(bool),
		Description:                         d.Get("description").(string),
		Cross_origin_auth:                   d.Get("cross_origin_auth").(bool),
		Sso:                                 d.Get("sso").(bool),
		Token_endpoint_auth_method: d.Get("token_endpoint_auth_method").(string),
		Grant_types:                d.Get("grant_types").([]interface{}),
		App_type:                   d.Get("app_type").(string),
		Custom_login_page_on:       d.Get("custom_login_page_on").(bool),
	}

	jsonValue, err := json.Marshal(reqClient)
	if err != nil {
		return err
	}
	log.Println("Request JSON: " + string(jsonValue))

	config := m.(Config)
	client := http.Client{}
	req, err := http.NewRequest("PATCH", "https://"+config.domain+"/api/v2/clients/"+d.Id(), bytes.NewBuffer(jsonValue))
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", "Bearer "+config.accessToken)
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	log.Println("Response JSON:" + string(data))

	if resp.StatusCode != 200 {
		return errors.New("Error: Invalid status code during update: " + string(data))
	}

	var respClient Client
	err = json.Unmarshal(data, &respClient)
	if err != nil {
		return err
	}

	return nil
}

func resourceClientDelete(d *schema.ResourceData, m interface{}) error {
	config := m.(Config)
	client := http.Client{}
	req, err := http.NewRequest("DELETE", "https://"+config.domain+"/api/v2/clients/"+d.Id(), nil)
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", "Bearer "+config.accessToken)

	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	log.Println("Response Status Code:" + string(resp.StatusCode))

	if resp.StatusCode != 204 {
		return errors.New("Error: Invalid status code during delete")
	}

	return nil
}
<|endoftext|>


<commit_before>package bytecode

import (
	"bytes"
	"strings"

	"github.com/goby-lang/goby/compiler/ast"
	"github.com/looplab/fsm"
)

type scope struct {
	self       ast.Statement
	program    *ast.Program
	localTable *localTable
	line       int
	anchors    map[string]*anchor
}

func newScope(stmt ast.Statement) *scope {
	return &scope{localTable: newLocalTable(0), self: stmt, line: 0, anchors: make(map[string]*anchor)}
}

// Generator contains program's AST and will store generated instruction sets
type Generator struct {
	REPL            bool
	instructionSets []*InstructionSet
	blockCounter    int
	scope           *scope
	fsm             *fsm.FSM
}

const (
	removeExp = "removeExp"
	keepExp   = "keepExp"
)

// NewGenerator initializes new Generator with complete AST tree.
func NewGenerator() *Generator {
	return &Generator{
		fsm: fsm.NewFSM(
			keepExp,

			/*
				This is for deciding if we should remove the expression.
				For example, these expression should be ignored when show up alone like:

				```
				a
				```

				```
				1 + a
				```

				```
				Foo
				```

				Because in these cases they are useless and will keep stack growing unnecessarily.

				Following expressions should be removed when declared but not used

				- Variable expressions like identifier, instance variable or constant
				- Data type expressions like string, integer, array...etc.
				- Self expression
				- Prefix expression like !true or -5
				- Not assignment infix expressions like: 1 + a * 5

				But only when those they are inside following places:
				- block argument
				- method definition
				- if expression's consequence or alternative block
				- while statement

				So if we know we are having those expressions in above places,
				we should switch the state to removeExp and compile function will ignore them.
			*/

			fsm.Events{
				{Name: removeExp, Src: []string{keepExp}, Dst: removeExp},
				{Name: keepExp, Src: []string{removeExp, keepExp}, Dst: keepExp},
			},
			fsm.Callbacks{},
		),
	}
}

// ResetInstructionSets clears generator's instruction sets
func (g *Generator) ResetInstructionSets() {
	g.instructionSets = []*InstructionSet{}
}

// InitTopLevelScope sets generator's scope with program node, which means it's the top level scope
func (g *Generator) InitTopLevelScope(program *ast.Program) {
	g.scope = &scope{program: program, localTable: newLocalTable(0), anchors: make(map[string]*anchor)}
}

// GenerateByteCode returns compiled instructions in string format
func (g *Generator) GenerateByteCode(stmts []ast.Statement) string {
	g.compileStatements(stmts, g.scope, g.scope.localTable)
	var out bytes.Buffer

	for _, is := range g.instructionSets {
		out.WriteString(is.compile())
	}

	return strings.TrimSpace(strings.Replace(out.String(), "\n\n", "\n", -1))
}

// GenerateInstructions returns compiled instructions
func (g *Generator) GenerateInstructions(stmts []ast.Statement) []*InstructionSet {
	g.compileStatements(stmts, g.scope, g.scope.localTable)
	return g.instructionSets
}

func (g *Generator) compileCodeBlock(is *InstructionSet, stmt *ast.BlockStatement, scope *scope, table *localTable) {
	for i, s := range stmt.Statements {
		/*
			We shouldn't remove last expression since it would be the method's return value. Example:

			```
			def foo
			  10 <- should be removed
			  100 <- shouldn't be removed
			end
			```
		*/
		if i == len(stmt.Statements)-1 && g.fsm.Is(removeExp) {
			g.fsm.Event(keepExp)
			g.compileStatement(is, s, scope, table)
			g.fsm.Event(removeExp)
			continue
		}

		g.compileStatement(is, s, scope, table)
	}
}

func (g *Generator) endInstructions(is *InstructionSet) {
	if g.REPL && is.name == Program {
		return
	}
	is.define(Leave)
}
<commit_msg>Make inspecting instructions more easier.<commit_after>package bytecode

import (
	"bytes"
	"strings"

	"github.com/goby-lang/goby/compiler/ast"
	"github.com/looplab/fsm"
)

type scope struct {
	self       ast.Statement
	program    *ast.Program
	localTable *localTable
	line       int
	anchors    map[string]*anchor
}

func newScope(stmt ast.Statement) *scope {
	return &scope{localTable: newLocalTable(0), self: stmt, line: 0, anchors: make(map[string]*anchor)}
}

// Generator contains program's AST and will store generated instruction sets
type Generator struct {
	REPL            bool
	instructionSets []*InstructionSet
	blockCounter    int
	scope           *scope
	fsm             *fsm.FSM
}

const (
	removeExp = "removeExp"
	keepExp   = "keepExp"
)

// NewGenerator initializes new Generator with complete AST tree.
func NewGenerator() *Generator {
	return &Generator{
		fsm: fsm.NewFSM(
			keepExp,

			/*
				This is for deciding if we should remove the expression.
				For example, these expression should be ignored when show up alone like:

				```
				a
				```

				```
				1 + a
				```

				```
				Foo
				```

				Because in these cases they are useless and will keep stack growing unnecessarily.

				Following expressions should be removed when declared but not used

				- Variable expressions like identifier, instance variable or constant
				- Data type expressions like string, integer, array...etc.
				- Self expression
				- Prefix expression like !true or -5
				- Not assignment infix expressions like: 1 + a * 5

				But only when those they are inside following places:
				- block argument
				- method definition
				- if expression's consequence or alternative block
				- while statement

				So if we know we are having those expressions in above places,
				we should switch the state to removeExp and compile function will ignore them.
			*/

			fsm.Events{
				{Name: removeExp, Src: []string{keepExp}, Dst: removeExp},
				{Name: keepExp, Src: []string{removeExp, keepExp}, Dst: keepExp},
			},
			fsm.Callbacks{},
		),
	}
}

// ResetInstructionSets clears generator's instruction sets
func (g *Generator) ResetInstructionSets() {
	g.instructionSets = []*InstructionSet{}
}

// InitTopLevelScope sets generator's scope with program node, which means it's the top level scope
func (g *Generator) InitTopLevelScope(program *ast.Program) {
	g.scope = &scope{program: program, localTable: newLocalTable(0), anchors: make(map[string]*anchor)}
}

// GenerateByteCode returns compiled instructions in string format
func (g *Generator) GenerateByteCode(stmts []ast.Statement) string {
	g.compileStatements(stmts, g.scope, g.scope.localTable)

	return strings.TrimSpace(strings.Replace(g.instructionsToString(), "\n\n", "\n", -1))
}

// GenerateInstructions returns compiled instructions
func (g *Generator) GenerateInstructions(stmts []ast.Statement) []*InstructionSet {
	g.compileStatements(stmts, g.scope, g.scope.localTable)

	//fmt.Println(g.instructionsToString())
	//fmt.Print()
	return g.instructionSets
}

func (g *Generator) instructionsToString() string {
	var out bytes.Buffer

	for _, is := range g.instructionSets {
		out.WriteString(is.compile())
	}

	return out.String()
}

func (g *Generator) compileCodeBlock(is *InstructionSet, stmt *ast.BlockStatement, scope *scope, table *localTable) {
	for i, s := range stmt.Statements {
		/*
			We shouldn't remove last expression since it would be the method's return value. Example:

			```
			def foo
			  10 <- should be removed
			  100 <- shouldn't be removed
			end
			```
		*/
		if i == len(stmt.Statements)-1 && g.fsm.Is(removeExp) {
			g.fsm.Event(keepExp)
			g.compileStatement(is, s, scope, table)
			g.fsm.Event(removeExp)
			continue
		}

		g.compileStatement(is, s, scope, table)
	}
}

func (g *Generator) endInstructions(is *InstructionSet) {
	if g.REPL && is.name == Program {
		return
	}
	is.define(Leave)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"log"
	"net"
	"runtime"
	"sync"
	"sync/atomic"
	"time"

	"github.com/absolute8511/go-nsq"
)

var (
	runfor     = flag.Duration("runfor", 10*time.Second, "duration of time to run")
	sleepfor   = flag.Duration("sleepfor", 1*time.Second, " time to sleep between pub")
	keepAlive  = flag.Bool("keepalive", true, "keep alive for connection")
	tcpAddress = flag.String("nsqd-tcp-address", "127.0.0.1:4150", "<addr>:<port> to connect to nsqd")
	topic      = flag.String("topic", "sub_bench", "topic to receive messages on")
	size       = flag.Int("size", 200, "size of messages")
	batchSize  = flag.Int("batch-size", 20, "batch size of messages")
	deadline   = flag.String("deadline", "", "deadline to start the benchmark run")
)

var totalMsgCount int64

func main() {
	flag.Parse()
	var wg sync.WaitGroup

	log.SetPrefix("[bench_writer] ")

	msg := make([]byte, *size)
	batch := make([][]byte, *batchSize)
	for i := range batch {
		batch[i] = msg
	}
	conn, err := net.DialTimeout("tcp", *tcpAddress, time.Second)
	if err != nil {
		log.Println(err.Error())
	} else {
		conn.Write(nsq.MagicV2)
		nsq.CreateTopic(*topic, 0).WriteTo(conn)
		resp, err := nsq.ReadResponse(conn)
		if err != nil {
			log.Println(err.Error())
		} else {
			frameType, data, err := nsq.UnpackResponse(resp)
			if err != nil {
				log.Println(err.Error())
			} else if frameType == nsq.FrameTypeError {
				log.Println(string(data))
			}
		}
		conn.Close()
	}

	goChan := make(chan int)
	rdyChan := make(chan int)
	for j := 0; j < runtime.GOMAXPROCS(0); j++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			pubWorker(*runfor, *tcpAddress, *batchSize, batch, *topic, rdyChan, goChan)
		}()
		<-rdyChan
	}

	if *deadline != "" {
		t, err := time.Parse("2006-01-02 15:04:05", *deadline)
		if err != nil {
			log.Fatal(err)
		}
		d := t.Sub(time.Now())
		log.Printf("sleeping until %s (%s)", t, d)
		time.Sleep(d)
	}

	start := time.Now()
	close(goChan)
	wg.Wait()
	end := time.Now()
	duration := end.Sub(start)
	tmc := atomic.LoadInt64(&totalMsgCount)
	log.Printf("duration: %s - %.03fmb/s - %.03fops/s - %.03fus/op",
		duration,
		float64(tmc*int64(*size))/duration.Seconds()/1024/1024,
		float64(tmc)/duration.Seconds(),
		float64(duration/time.Microsecond)/(float64(tmc)+0.01))
}

func checkShouldClose(err error) bool {
	if err != nil {
		log.Printf("err: %v\n", err)
		return true
	}
	return false
}

func pubWorker(td time.Duration, tcpAddr string, batchSize int, batch [][]byte, topic string, rdyChan chan int, goChan chan int) {
	shouldClose := !*keepAlive
	conn, err := net.DialTimeout("tcp", tcpAddr, time.Second)
	if err != nil {
		log.Println(err.Error())
		shouldClose = true
	} else {
		conn.Write(nsq.MagicV2)
	}
	rdyChan <- 1
	<-goChan
	var msgCount int64
	endTime := time.Now().Add(td)
	rw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
	for {
		if time.Now().After(endTime) {
			break
		}
		if (*sleepfor).Nanoseconds() > int64(10000) {
			time.Sleep(*sleepfor)
		}
		if shouldClose || !*keepAlive {
			if conn != nil {
				conn.Close()
			}
			conn, err = net.DialTimeout("tcp", tcpAddr, time.Second)
			shouldClose = checkShouldClose(err)
			if shouldClose {
				continue
			}
			_, err = conn.Write(nsq.MagicV2)
			shouldClose = checkShouldClose(err)
			if shouldClose {
				continue
			}
			rw = bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
		}
		conn.SetReadDeadline(time.Now().Add(5 * time.Second))
		cmd, _ := nsq.MultiPublish(topic, batch)
		_, err := cmd.WriteTo(rw)
		shouldClose = checkShouldClose(err)
		if shouldClose {
			continue
		}
		err = rw.Flush()
		shouldClose = checkShouldClose(err)
		if shouldClose {
			continue
		}
		resp, err := nsq.ReadResponse(rw)
		shouldClose = checkShouldClose(err)
		if shouldClose {
			continue
		}
		frameType, data, err := nsq.UnpackResponse(resp)
		shouldClose = checkShouldClose(err)
		if shouldClose {
			continue
		}
		conn.SetReadDeadline(time.Time{})
		if frameType == nsq.FrameTypeError {
			log.Println("frame unexpected:" + string(data))
			shouldClose = true
		}
		msgCount += int64(len(batch))
		if time.Now().After(endTime) {
			break
		}
	}
	atomic.AddInt64(&totalMsgCount, msgCount)
}
<commit_msg>print tps periodally<commit_after>package main

import (
	"bufio"
	"flag"
	"log"
	"net"
	"runtime"
	"sync"
	"sync/atomic"
	"time"

	"github.com/absolute8511/go-nsq"
)

var (
	runfor     = flag.Duration("runfor", 10*time.Second, "duration of time to run")
	sleepfor   = flag.Duration("sleepfor", 1*time.Second, " time to sleep between pub")
	keepAlive  = flag.Bool("keepalive", true, "keep alive for connection")
	tcpAddress = flag.String("nsqd-tcp-address", "127.0.0.1:4150", "<addr>:<port> to connect to nsqd")
	topic      = flag.String("topic", "sub_bench", "topic to receive messages on")
	size       = flag.Int("size", 200, "size of messages")
	batchSize  = flag.Int("batch-size", 20, "batch size of messages")
	deadline   = flag.String("deadline", "", "deadline to start the benchmark run")
)

var totalMsgCount int64
var currentMsgCount int64

func main() {
	flag.Parse()
	var wg sync.WaitGroup

	log.SetPrefix("[bench_writer] ")

	msg := make([]byte, *size)
	batch := make([][]byte, *batchSize)
	for i := range batch {
		batch[i] = msg
	}
	conn, err := net.DialTimeout("tcp", *tcpAddress, time.Second)
	if err != nil {
		log.Println(err.Error())
	} else {
		conn.Write(nsq.MagicV2)
		nsq.CreateTopic(*topic, 0).WriteTo(conn)
		resp, err := nsq.ReadResponse(conn)
		if err != nil {
			log.Println(err.Error())
		} else {
			frameType, data, err := nsq.UnpackResponse(resp)
			if err != nil {
				log.Println(err.Error())
			} else if frameType == nsq.FrameTypeError {
				log.Println(string(data))
			}
		}
		conn.Close()
	}

	goChan := make(chan int)
	rdyChan := make(chan int)
	for j := 0; j < runtime.GOMAXPROCS(0); j++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			pubWorker(*runfor, *tcpAddress, *batchSize, batch, *topic, rdyChan, goChan)
		}()
		<-rdyChan
	}

	if *deadline != "" {
		t, err := time.Parse("2006-01-02 15:04:05", *deadline)
		if err != nil {
			log.Fatal(err)
		}
		d := t.Sub(time.Now())
		log.Printf("sleeping until %s (%s)", t, d)
		time.Sleep(d)
	}

	start := time.Now()
	close(goChan)
	go func() {
		prevMsgCount := int64(0)
		prevStart := start
		for {
			time.Sleep(time.Second * 5)
			end := time.Now()
			duration := end.Sub(prevStart)
			currentTmc := atomic.LoadInt64(&currentMsgCount)
			tmc := currentTmc - prevMsgCount
			prevMsgCount = currentTmc
			prevStart = time.Now()
			log.Printf("duration: %s - %.03fmb/s - %.03fops/s - %.03fus/op",
				duration,
				float64(tmc*int64(*size))/duration.Seconds()/1024/1024,
				float64(tmc)/duration.Seconds(),
				float64(duration/time.Microsecond)/(float64(tmc)+0.01))

		}

	}()
	wg.Wait()
	end := time.Now()
	duration := end.Sub(start)
	tmc := atomic.LoadInt64(&totalMsgCount)
	log.Printf("duration: %s - %.03fmb/s - %.03fops/s - %.03fus/op",
		duration,
		float64(tmc*int64(*size))/duration.Seconds()/1024/1024,
		float64(tmc)/duration.Seconds(),
		float64(duration/time.Microsecond)/(float64(tmc)+0.01))
}

func checkShouldClose(err error) bool {
	if err != nil {
		log.Printf("err: %v\n", err)
		return true
	}
	return false
}

func pubWorker(td time.Duration, tcpAddr string, batchSize int, batch [][]byte, topic string, rdyChan chan int, goChan chan int) {
	shouldClose := !*keepAlive
	conn, err := net.DialTimeout("tcp", tcpAddr, time.Second)
	if err != nil {
		log.Println(err.Error())
		shouldClose = true
	} else {
		conn.Write(nsq.MagicV2)
	}
	rdyChan <- 1
	<-goChan
	var msgCount int64
	endTime := time.Now().Add(td)
	rw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
	for {
		if time.Now().After(endTime) {
			break
		}
		if (*sleepfor).Nanoseconds() > int64(10000) {
			time.Sleep(*sleepfor)
		}
		if shouldClose || !*keepAlive {
			if conn != nil {
				conn.Close()
			}
			conn, err = net.DialTimeout("tcp", tcpAddr, time.Second)
			shouldClose = checkShouldClose(err)
			if shouldClose {
				continue
			}
			_, err = conn.Write(nsq.MagicV2)
			shouldClose = checkShouldClose(err)
			if shouldClose {
				continue
			}
			rw = bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
		}
		conn.SetReadDeadline(time.Now().Add(time.Second))
		cmd, _ := nsq.MultiPublish(topic, batch)
		_, err := cmd.WriteTo(rw)
		shouldClose = checkShouldClose(err)
		if shouldClose {
			continue
		}
		err = rw.Flush()
		shouldClose = checkShouldClose(err)
		if shouldClose {
			continue
		}
		resp, err := nsq.ReadResponse(rw)
		shouldClose = checkShouldClose(err)
		if shouldClose {
			continue
		}
		frameType, data, err := nsq.UnpackResponse(resp)
		shouldClose = checkShouldClose(err)
		if shouldClose {
			continue
		}
		conn.SetReadDeadline(time.Time{})
		if frameType == nsq.FrameTypeError {
			log.Println("frame unexpected:" + string(data))
			shouldClose = true
		}
		msgCount += int64(len(batch))
		if time.Now().After(endTime) {
			break
		}
		atomic.AddInt64(&currentMsgCount, int64(len(batch)))
	}
	atomic.AddInt64(&totalMsgCount, msgCount)
}
<|endoftext|>


<commit_before>package surveys

import (
	"encoding/json"
	"log"
	"net/http"
	"regexp"

	"github.com/AreaHQ/jsonhal"
	"github.com/ONSdigital/go-launch-a-survey/settings"
)

// LauncherSchema is a representation of a schema in the Launcher
type LauncherSchema struct {
	Name     string
	EqID     string
	FormType string
	URL      string
}

// RegisterResponse is the response from the eq-survey-register request
type RegisterResponse struct {
	jsonhal.Hal
}

// Schemas is a list of Schema
type Schemas []Schema

// Schema is an available schema
type Schema struct {
	jsonhal.Hal
	Name string `json:"name"`
}

var eqIDFormTypeRegex = regexp.MustCompile(`^(?P<eq_id>[a-z0-9]+)_(?P<form_type>\w+)`)

func extractEqIDFormType(schema string) (EqID, formType string) {
	match := eqIDFormTypeRegex.FindStringSubmatch(schema)
	if match != nil {
		EqID = match[1]
		formType = match[2]
	}
	return
}

// LauncherSchemaFromFilename creates a LauncherSchema record from a schema filename
func LauncherSchemaFromFilename(filename string) LauncherSchema {
	EqID, formType := extractEqIDFormType(filename)
	return LauncherSchema{
		Name:     filename,
		EqID:     EqID,
		FormType: formType,
	}
}

// GetAvailableSchemas Gets the list of static schemas an joins them with any schemas from the eq-survey-register if defined
func GetAvailableSchemas() []LauncherSchema {
	schemaList := []LauncherSchema{
		LauncherSchemaFromFilename("0_star_wars.json"),
		LauncherSchemaFromFilename("1_0005.json"),
		LauncherSchemaFromFilename("1_0102.json"),
		LauncherSchemaFromFilename("1_0112.json"),
		LauncherSchemaFromFilename("1_0203.json"),
		LauncherSchemaFromFilename("1_0205.json"),
		LauncherSchemaFromFilename("1_0213.json"),
		LauncherSchemaFromFilename("1_0215.json"),
		LauncherSchemaFromFilename("2_0001.json"),
		LauncherSchemaFromFilename("census_communal.json"),
		LauncherSchemaFromFilename("census_household.json"),
		LauncherSchemaFromFilename("census_individual.json"),
		LauncherSchemaFromFilename("e_commerce.json"),
		LauncherSchemaFromFilename("labour_force.json"),
		LauncherSchemaFromFilename("mbs_0106.json"),
		LauncherSchemaFromFilename("mbs_0111.json"),
		LauncherSchemaFromFilename("mbs_0117.json"),
		LauncherSchemaFromFilename("mbs_0123.json"),
		LauncherSchemaFromFilename("mbs_0158.json"),
		LauncherSchemaFromFilename("mbs_0161.json"),
		LauncherSchemaFromFilename("mbs_0167.json"),
		LauncherSchemaFromFilename("mbs_0173.json"),
		LauncherSchemaFromFilename("mbs_0201.json"),
		LauncherSchemaFromFilename("mbs_0202.json"),
		LauncherSchemaFromFilename("mbs_0203.json"),
		LauncherSchemaFromFilename("mbs_0204.json"),
		LauncherSchemaFromFilename("mbs_0205.json"),
		LauncherSchemaFromFilename("mbs_0216.json"),
		LauncherSchemaFromFilename("mbs_0251.json"),
		LauncherSchemaFromFilename("mbs_0253.json"),
		LauncherSchemaFromFilename("mbs_0255.json"),
		LauncherSchemaFromFilename("mbs_0817.json"),
		LauncherSchemaFromFilename("mbs_0867.json"),
		LauncherSchemaFromFilename("multiple_answers.json"),
		LauncherSchemaFromFilename("test_big_list_naughty_strings.json"),
		LauncherSchemaFromFilename("test_checkbox.json"),
		LauncherSchemaFromFilename("test_conditional_dates.json"),
		LauncherSchemaFromFilename("test_conditional_routing.json"),
		LauncherSchemaFromFilename("test_confirmation_question.json"),
		LauncherSchemaFromFilename("test_currency.json"),
		LauncherSchemaFromFilename("test_date_range_period_validation.json"),
		LauncherSchemaFromFilename("test_dates.json"),
		LauncherSchemaFromFilename("test_default.json"),
		LauncherSchemaFromFilename("test_dependencies_calculation.json"),
		LauncherSchemaFromFilename("test_dependencies_max_value.json"),
		LauncherSchemaFromFilename("test_dependencies_min_value.json"),
		LauncherSchemaFromFilename("test_difference_in_years.json"),
		LauncherSchemaFromFilename("test_difference_in_years_month_year.json"),
		LauncherSchemaFromFilename("test_difference_in_years_month_year_range.json"),
		LauncherSchemaFromFilename("test_difference_in_years_range.json"),
		LauncherSchemaFromFilename("test_dropdown_mandatory.json"),
		LauncherSchemaFromFilename("test_dropdown_mandatory_with_overridden_error.json"),
		LauncherSchemaFromFilename("test_dropdown_optional.json"),
		LauncherSchemaFromFilename("test_error_messages.json"),
		LauncherSchemaFromFilename("test_final_confirmation.json"),
		LauncherSchemaFromFilename("test_household_question.json"),
		LauncherSchemaFromFilename("test_interstitial_page.json"),
		LauncherSchemaFromFilename("test_introduction.json"),
		LauncherSchemaFromFilename("test_language.json"),
		LauncherSchemaFromFilename("test_language_cy.json"),
		LauncherSchemaFromFilename("test_markup.json"),
		LauncherSchemaFromFilename("test_metadata_routing.json"),
		LauncherSchemaFromFilename("test_multiple_piping.json"),
		LauncherSchemaFromFilename("test_navigation.json"),
		LauncherSchemaFromFilename("test_navigation_completeness.json"),
		LauncherSchemaFromFilename("test_navigation_confirmation.json"),
		LauncherSchemaFromFilename("test_navigation_routing.json"),
		LauncherSchemaFromFilename("test_numbers.json"),
		LauncherSchemaFromFilename("test_percentage.json"),
		LauncherSchemaFromFilename("test_question_guidance.json"),
		LauncherSchemaFromFilename("test_radio_checkbox_descriptions.json"),
		LauncherSchemaFromFilename("test_radio_mandatory.json"),
		LauncherSchemaFromFilename("test_radio_mandatory_with_mandatory_other.json"),
		LauncherSchemaFromFilename("test_radio_mandatory_with_mandatory_other_overridden_error.json"),
		LauncherSchemaFromFilename("test_radio_mandatory_with_optional_other.json"),
		LauncherSchemaFromFilename("test_radio_mandatory_with_overridden_error.json"),
		LauncherSchemaFromFilename("test_radio_optional.json"),
		LauncherSchemaFromFilename("test_radio_optional_with_mandatory_other.json"),
		LauncherSchemaFromFilename("test_radio_optional_with_mandatory_other_overridden_error.json"),
		LauncherSchemaFromFilename("test_radio_optional_with_optional_other.json"),
		LauncherSchemaFromFilename("test_relationship_household.json"),
		LauncherSchemaFromFilename("test_repeating_and_conditional_routing.json"),
		LauncherSchemaFromFilename("test_repeating_household.json"),
		LauncherSchemaFromFilename("test_routing_date_equals.json"),
		LauncherSchemaFromFilename("test_routing_date_greater_than.json"),
		LauncherSchemaFromFilename("test_routing_date_less_than.json"),
		LauncherSchemaFromFilename("test_routing_date_not_equals.json"),
		LauncherSchemaFromFilename("test_routing_group.json"),
		LauncherSchemaFromFilename("test_routing_number_equals.json"),
		LauncherSchemaFromFilename("test_routing_number_greater_than.json"),
		LauncherSchemaFromFilename("test_routing_number_greater_than_or_equal.json"),
		LauncherSchemaFromFilename("test_routing_number_less_than.json"),
		LauncherSchemaFromFilename("test_routing_number_less_than_or_equal.json"),
		LauncherSchemaFromFilename("test_routing_number_not_equals.json"),
		LauncherSchemaFromFilename("test_routing_on_multiple_select.json"),
		LauncherSchemaFromFilename("test_single_date_period_validation.json"),
		LauncherSchemaFromFilename("test_skip_condition.json"),
		LauncherSchemaFromFilename("test_skip_condition_block.json"),
		LauncherSchemaFromFilename("test_skip_condition_group.json"),
		LauncherSchemaFromFilename("test_summary.json"),
		LauncherSchemaFromFilename("test_section_summary.json"),
		LauncherSchemaFromFilename("test_sum_equal_validation_against_total.json"),
		LauncherSchemaFromFilename("test_sum_equal_or_less_validation_against_total.json"),
		LauncherSchemaFromFilename("test_sum_less_validation_against_total.json"),
		LauncherSchemaFromFilename("test_sum_multi_validation_against_total.json"),
		LauncherSchemaFromFilename("test_view_submitted_response.json"),
		LauncherSchemaFromFilename("test_textarea.json"),
		LauncherSchemaFromFilename("test_textfield.json"),
		LauncherSchemaFromFilename("test_timeout.json"),
		LauncherSchemaFromFilename("test_total_breakdown.json"),
		LauncherSchemaFromFilename("test_unit_patterns.json"),
	}

	return append(schemaList, getAvailableSchemasFromRegister()...)
}

func getAvailableSchemasFromRegister() []LauncherSchema {

	schemaList := []LauncherSchema{}

	if settings.Get("SURVEY_REGISTER_URL") != "" {
		req, err := http.NewRequest("GET", settings.Get("SURVEY_REGISTER_URL"), nil)
		if err != nil {
			log.Fatal("NewRequest: ", err)
			return []LauncherSchema{}
		}
		client := &http.Client{}

		resp, err := client.Do(req)
		if err != nil {
			log.Fatal("Do: ", err)
			return []LauncherSchema{}
		}

		defer resp.Body.Close()

		var registerResponse RegisterResponse

		if err := json.NewDecoder(resp.Body).Decode(&registerResponse); err != nil {
			log.Println(err)
		}

		var schemas Schemas

		schemasJSON, _ := json.Marshal(registerResponse.Embedded["schemas"])

		if err := json.Unmarshal(schemasJSON, &schemas); err != nil {
			log.Println(err)
		}

		for _, schema := range schemas {
			url := schema.Links["self"]
			EqID, formType := extractEqIDFormType(schema.Name)
			schemaList = append(schemaList, LauncherSchema{
				Name:     schema.Name,
				URL:      url.Href,
				EqID:     EqID,
				FormType: formType,
			})
		}
	}

	return schemaList
}

// FindSurveyByName Finds the schema in the list of available schemas
func FindSurveyByName(name string) LauncherSchema {
	for _, survey := range GetAvailableSchemas() {
		if survey.Name == name {
			return survey
		}
	}
	panic("Survey not found")
}
<commit_msg>Add MBS Surveys<commit_after>package surveys

import (
	"encoding/json"
	"log"
	"net/http"
	"regexp"

	"github.com/AreaHQ/jsonhal"
	"github.com/ONSdigital/go-launch-a-survey/settings"
)

// LauncherSchema is a representation of a schema in the Launcher
type LauncherSchema struct {
	Name     string
	EqID     string
	FormType string
	URL      string
}

// RegisterResponse is the response from the eq-survey-register request
type RegisterResponse struct {
	jsonhal.Hal
}

// Schemas is a list of Schema
type Schemas []Schema

// Schema is an available schema
type Schema struct {
	jsonhal.Hal
	Name string `json:"name"`
}

var eqIDFormTypeRegex = regexp.MustCompile(`^(?P<eq_id>[a-z0-9]+)_(?P<form_type>\w+)`)

func extractEqIDFormType(schema string) (EqID, formType string) {
	match := eqIDFormTypeRegex.FindStringSubmatch(schema)
	if match != nil {
		EqID = match[1]
		formType = match[2]
	}
	return
}

// LauncherSchemaFromFilename creates a LauncherSchema record from a schema filename
func LauncherSchemaFromFilename(filename string) LauncherSchema {
	EqID, formType := extractEqIDFormType(filename)
	return LauncherSchema{
		Name:     filename,
		EqID:     EqID,
		FormType: formType,
	}
}

// GetAvailableSchemas Gets the list of static schemas an joins them with any schemas from the eq-survey-register if defined
func GetAvailableSchemas() []LauncherSchema {
	schemaList := []LauncherSchema{
		LauncherSchemaFromFilename("0_star_wars.json"),
		LauncherSchemaFromFilename("1_0005.json"),
		LauncherSchemaFromFilename("1_0102.json"),
		LauncherSchemaFromFilename("1_0112.json"),
		LauncherSchemaFromFilename("1_0203.json"),
		LauncherSchemaFromFilename("1_0205.json"),
		LauncherSchemaFromFilename("1_0213.json"),
		LauncherSchemaFromFilename("1_0215.json"),
		LauncherSchemaFromFilename("2_0001.json"),
		LauncherSchemaFromFilename("census_communal.json"),
		LauncherSchemaFromFilename("census_household.json"),
		LauncherSchemaFromFilename("census_individual.json"),
		LauncherSchemaFromFilename("e_commerce.json"),
		LauncherSchemaFromFilename("labour_force.json"),
		LauncherSchemaFromFilename("mbs_0106.json"),
		LauncherSchemaFromFilename("mbs_0111.json"),
		LauncherSchemaFromFilename("mbs_0117.json"),
		LauncherSchemaFromFilename("mbs_0123.json"),
		LauncherSchemaFromFilename("mbs_0158.json"),
		LauncherSchemaFromFilename("mbs_0161.json"),
		LauncherSchemaFromFilename("mbs_0167.json"),
		LauncherSchemaFromFilename("mbs_0173.json"),
		LauncherSchemaFromFilename("mbs_0201.json"),
		LauncherSchemaFromFilename("mbs_0202.json"),
		LauncherSchemaFromFilename("mbs_0203.json"),
		LauncherSchemaFromFilename("mbs_0204.json"),
		LauncherSchemaFromFilename("mbs_0205.json"),
		LauncherSchemaFromFilename("mbs_0216.json"),
		LauncherSchemaFromFilename("mbs_0251.json"),
		LauncherSchemaFromFilename("mbs_0253.json"),
		LauncherSchemaFromFilename("mbs_0255.json"),
		LauncherSchemaFromFilename("mbs_0817.json"),
		LauncherSchemaFromFilename("mbs_0823.json"),
		LauncherSchemaFromFilename("mbs_0867.json"),
		LauncherSchemaFromFilename("mbs_0873.json"),
		LauncherSchemaFromFilename("multiple_answers.json"),
		LauncherSchemaFromFilename("test_big_list_naughty_strings.json"),
		LauncherSchemaFromFilename("test_checkbox.json"),
		LauncherSchemaFromFilename("test_conditional_dates.json"),
		LauncherSchemaFromFilename("test_conditional_routing.json"),
		LauncherSchemaFromFilename("test_confirmation_question.json"),
		LauncherSchemaFromFilename("test_currency.json"),
		LauncherSchemaFromFilename("test_date_range_period_validation.json"),
		LauncherSchemaFromFilename("test_dates.json"),
		LauncherSchemaFromFilename("test_default.json"),
		LauncherSchemaFromFilename("test_dependencies_calculation.json"),
		LauncherSchemaFromFilename("test_dependencies_max_value.json"),
		LauncherSchemaFromFilename("test_dependencies_min_value.json"),
		LauncherSchemaFromFilename("test_difference_in_years.json"),
		LauncherSchemaFromFilename("test_difference_in_years_month_year.json"),
		LauncherSchemaFromFilename("test_difference_in_years_month_year_range.json"),
		LauncherSchemaFromFilename("test_difference_in_years_range.json"),
		LauncherSchemaFromFilename("test_dropdown_mandatory.json"),
		LauncherSchemaFromFilename("test_dropdown_mandatory_with_overridden_error.json"),
		LauncherSchemaFromFilename("test_dropdown_optional.json"),
		LauncherSchemaFromFilename("test_error_messages.json"),
		LauncherSchemaFromFilename("test_final_confirmation.json"),
		LauncherSchemaFromFilename("test_household_question.json"),
		LauncherSchemaFromFilename("test_interstitial_page.json"),
		LauncherSchemaFromFilename("test_introduction.json"),
		LauncherSchemaFromFilename("test_language.json"),
		LauncherSchemaFromFilename("test_language_cy.json"),
		LauncherSchemaFromFilename("test_markup.json"),
		LauncherSchemaFromFilename("test_metadata_routing.json"),
		LauncherSchemaFromFilename("test_multiple_piping.json"),
		LauncherSchemaFromFilename("test_navigation.json"),
		LauncherSchemaFromFilename("test_navigation_completeness.json"),
		LauncherSchemaFromFilename("test_navigation_confirmation.json"),
		LauncherSchemaFromFilename("test_navigation_routing.json"),
		LauncherSchemaFromFilename("test_numbers.json"),
		LauncherSchemaFromFilename("test_percentage.json"),
		LauncherSchemaFromFilename("test_question_guidance.json"),
		LauncherSchemaFromFilename("test_radio_checkbox_descriptions.json"),
		LauncherSchemaFromFilename("test_radio_mandatory.json"),
		LauncherSchemaFromFilename("test_radio_mandatory_with_mandatory_other.json"),
		LauncherSchemaFromFilename("test_radio_mandatory_with_mandatory_other_overridden_error.json"),
		LauncherSchemaFromFilename("test_radio_mandatory_with_optional_other.json"),
		LauncherSchemaFromFilename("test_radio_mandatory_with_overridden_error.json"),
		LauncherSchemaFromFilename("test_radio_optional.json"),
		LauncherSchemaFromFilename("test_radio_optional_with_mandatory_other.json"),
		LauncherSchemaFromFilename("test_radio_optional_with_mandatory_other_overridden_error.json"),
		LauncherSchemaFromFilename("test_radio_optional_with_optional_other.json"),
		LauncherSchemaFromFilename("test_relationship_household.json"),
		LauncherSchemaFromFilename("test_repeating_and_conditional_routing.json"),
		LauncherSchemaFromFilename("test_repeating_household.json"),
		LauncherSchemaFromFilename("test_routing_date_equals.json"),
		LauncherSchemaFromFilename("test_routing_date_greater_than.json"),
		LauncherSchemaFromFilename("test_routing_date_less_than.json"),
		LauncherSchemaFromFilename("test_routing_date_not_equals.json"),
		LauncherSchemaFromFilename("test_routing_group.json"),
		LauncherSchemaFromFilename("test_routing_number_equals.json"),
		LauncherSchemaFromFilename("test_routing_number_greater_than.json"),
		LauncherSchemaFromFilename("test_routing_number_greater_than_or_equal.json"),
		LauncherSchemaFromFilename("test_routing_number_less_than.json"),
		LauncherSchemaFromFilename("test_routing_number_less_than_or_equal.json"),
		LauncherSchemaFromFilename("test_routing_number_not_equals.json"),
		LauncherSchemaFromFilename("test_routing_on_multiple_select.json"),
		LauncherSchemaFromFilename("test_single_date_period_validation.json"),
		LauncherSchemaFromFilename("test_skip_condition.json"),
		LauncherSchemaFromFilename("test_skip_condition_block.json"),
		LauncherSchemaFromFilename("test_skip_condition_group.json"),
		LauncherSchemaFromFilename("test_summary.json"),
		LauncherSchemaFromFilename("test_section_summary.json"),
		LauncherSchemaFromFilename("test_sum_equal_validation_against_total.json"),
		LauncherSchemaFromFilename("test_sum_equal_or_less_validation_against_total.json"),
		LauncherSchemaFromFilename("test_sum_less_validation_against_total.json"),
		LauncherSchemaFromFilename("test_sum_multi_validation_against_total.json"),
		LauncherSchemaFromFilename("test_view_submitted_response.json"),
		LauncherSchemaFromFilename("test_textarea.json"),
		LauncherSchemaFromFilename("test_textfield.json"),
		LauncherSchemaFromFilename("test_timeout.json"),
		LauncherSchemaFromFilename("test_total_breakdown.json"),
		LauncherSchemaFromFilename("test_unit_patterns.json"),
	}

	return append(schemaList, getAvailableSchemasFromRegister()...)
}

func getAvailableSchemasFromRegister() []LauncherSchema {

	schemaList := []LauncherSchema{}

	if settings.Get("SURVEY_REGISTER_URL") != "" {
		req, err := http.NewRequest("GET", settings.Get("SURVEY_REGISTER_URL"), nil)
		if err != nil {
			log.Fatal("NewRequest: ", err)
			return []LauncherSchema{}
		}
		client := &http.Client{}

		resp, err := client.Do(req)
		if err != nil {
			log.Fatal("Do: ", err)
			return []LauncherSchema{}
		}

		defer resp.Body.Close()

		var registerResponse RegisterResponse

		if err := json.NewDecoder(resp.Body).Decode(&registerResponse); err != nil {
			log.Println(err)
		}

		var schemas Schemas

		schemasJSON, _ := json.Marshal(registerResponse.Embedded["schemas"])

		if err := json.Unmarshal(schemasJSON, &schemas); err != nil {
			log.Println(err)
		}

		for _, schema := range schemas {
			url := schema.Links["self"]
			EqID, formType := extractEqIDFormType(schema.Name)
			schemaList = append(schemaList, LauncherSchema{
				Name:     schema.Name,
				URL:      url.Href,
				EqID:     EqID,
				FormType: formType,
			})
		}
	}

	return schemaList
}

// FindSurveyByName Finds the schema in the list of available schemas
func FindSurveyByName(name string) LauncherSchema {
	for _, survey := range GetAvailableSchemas() {
		if survey.Name == name {
			return survey
		}
	}
	panic("Survey not found")
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"github.com/GeertJohan/go.rice/embedded"
	"github.com/akavel/rsrc/coff"
	"go/build"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"text/template"
	"time"
)

type sizedBytes []byte

func (s sizedBytes) Size() int64 {
	return int64(len(s))
}

var tmplEmbeddedSysoHelper *template.Template

func init() {
	var err error
	tmplEmbeddedSysoHelper, err = template.New("embeddedSysoHelper").Parse(`package {{.Package}}

// extern char _bricebox_{{.Symname}}[], _ericebox_{{.Symname}};
// int get_{{.Symname}}_length() {
// 	return &_ericebox_{{.Symname}} - _bricebox_{{.Symname}};
// }
import "C"
import (
	"bytes"
	"encoding/gob"
	"github.com/GeertJohan/go.rice/embedded"
	"unsafe"
)

// func get_{{.Symname}}() []byte {
// 	ptr := unsafe.Pointer(&C._bricebox_{{.Symname}})
// 	bts := C.GoBytes(ptr, C.get_{{.Symname}}_length())
// 	return bts
// }

func init() {
	ptr := unsafe.Pointer(&C._bricebox_{{.Symname}})
	bts := C.GoBytes(ptr, C.get_{{.Symname}}_length())
	embeddedBox := &embedded.EmbeddedBox{}
	err := gob.NewDecoder(bytes.NewReader(bts)).Decode(embeddedBox)
	if err != nil {
		panic("error decoding embedded box: "+err.Error())
	}
	embeddedBox.Link()
	embedded.RegisterEmbeddedBox(embeddedBox.Name, embeddedBox)
}`)
	if err != nil {
		panic("could not parse template embeddedSysoHelper: " + err.Error())
	}
}

type embeddedSysoHelperData struct {
	Package string
	Symname string
}

func operationEmbedSyso(pkg *build.Package) {

	regexpSynameReplacer := regexp.MustCompile(`[^a-z0-9_]`)

	boxMap := findBoxes(pkg)

	// notify user when no calls to rice.FindBox are made (is this an error and therefore os.Exit(1) ?
	if len(boxMap) == 0 {
		fmt.Println("no calls to rice.FindBox() found")
		return
	}

	verbosef("\n")

	for boxname := range boxMap {
		// find path and filename for this box
		boxPath := filepath.Join(pkg.Dir, boxname)
		boxFilename := strings.Replace(boxname, "/", "-", -1)
		boxFilename = strings.Replace(boxFilename, "..", "back", -1)

		// verbose info
		verbosef("embedding box '%s'\n", boxname)
		verbosef("\tto file %s\n", boxFilename)

		// create box datastructure (used by template)
		box := &embedded.EmbeddedBox{
			Name:      boxname,
			Time:      time.Now(),
			EmbedType: embedded.EmbedTypeSyso,
			Files:     make(map[string]*embedded.EmbeddedFile),
			Dirs:      make(map[string]*embedded.EmbeddedDir),
		}

		// fill box datastructure with file data
		filepath.Walk(boxPath, func(path string, info os.FileInfo, err error) error {
			if err != nil {
				fmt.Printf("error walking box: %s\n", err)
				os.Exit(1)
			}

			filename := strings.TrimPrefix(path, boxPath)
			filename = strings.Replace(filename, "\\", "/", -1)
			filename = strings.TrimPrefix(filename, "/")
			if info.IsDir() {
				embeddedDir := &embedded.EmbeddedDir{
					Filename:   filename,
					DirModTime: info.ModTime(),
				}
				verbosef("\tincludes dir: '%s'\n", embeddedDir.Filename)
				box.Dirs[embeddedDir.Filename] = embeddedDir

				// add tree entry (skip for root, it'll create a recursion)
				if embeddedDir.Filename != "" {
					pathParts := strings.Split(embeddedDir.Filename, "/")
					parentDir := box.Dirs[strings.Join(pathParts[:len(pathParts)-1], "/")]
					parentDir.ChildDirs = append(parentDir.ChildDirs, embeddedDir)
				}
			} else {
				embeddedFile := &embedded.EmbeddedFile{
					Filename:    filename,
					FileModTime: info.ModTime(),
					Content:     "",
				}
				verbosef("\tincludes file: '%s'\n", embeddedFile.Filename)
				contentBytes, err := ioutil.ReadFile(path)
				if err != nil {
					fmt.Printf("error reading file content while walking box: %s\n", err)
					os.Exit(1)
				}
				embeddedFile.Content = string(contentBytes)
				box.Files[embeddedFile.Filename] = embeddedFile
			}
			return nil
		})

		// encode embedded box to gob file
		boxGobBuf := &bytes.Buffer{}
		err := gob.NewEncoder(boxGobBuf).Encode(box)
		if err != nil {
			fmt.Printf("error encoding box to gob: %v\n", err)
			os.Exit(1)
		}

		// write coff
		symname := regexpSynameReplacer.ReplaceAllString(boxname, "_")
		createCoffSyso(boxname, symname, "386", boxGobBuf.Bytes())
		createCoffSyso(boxname, symname, "amd64", boxGobBuf.Bytes())

		// write go
		sysoHelperData := embeddedSysoHelperData{
			Package: pkg.Name,
			Symname: symname,
		}
		fileSysoHelper, err := os.Create(boxFilename + ".rice-box.go")
		if err != nil {
			fmt.Printf("error creating syso helper: %v\n", err)
			os.Exit(1)
		}
		err = tmplEmbeddedSysoHelper.Execute(fileSysoHelper, sysoHelperData)
		if err != nil {
			fmt.Printf("error executing tmplEmbeddedSysoHelper: %v\n", err)
			os.Exit(1)
		}
	}
}

func createCoffSyso(boxFilename string, symname string, arch string, data []byte) {
	boxCoff := coff.NewRDATA()
	switch arch {
	case "386":
	case "amd64":
		boxCoff.FileHeader.Machine = 0x8664
	default:
		panic("invalid arch")
	}
	boxCoff.AddData("_bricebox_"+symname, sizedBytes(data))
	boxCoff.AddData("_ericebox_"+symname, io.NewSectionReader(strings.NewReader("\000\000"), 0, 2)) // TODO: why? copied from rsrc, which copied it from as-generated
	boxCoff.Freeze()
	err := writeCoff(boxCoff, boxFilename+"_"+arch+".rice-box.syso")
	if err != nil {
		fmt.Printf("error writing %s coff/.syso: %v\n", arch, err)
		os.Exit(1)
	}
}
<commit_msg>Cleanup commented code<commit_after>package main

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"github.com/GeertJohan/go.rice/embedded"
	"github.com/akavel/rsrc/coff"
	"go/build"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"text/template"
	"time"
)

type sizedBytes []byte

func (s sizedBytes) Size() int64 {
	return int64(len(s))
}

var tmplEmbeddedSysoHelper *template.Template

func init() {
	var err error
	tmplEmbeddedSysoHelper, err = template.New("embeddedSysoHelper").Parse(`package {{.Package}}

// extern char _bricebox_{{.Symname}}[], _ericebox_{{.Symname}};
// int get_{{.Symname}}_length() {
// 	return &_ericebox_{{.Symname}} - _bricebox_{{.Symname}};
// }
import "C"
import (
	"bytes"
	"encoding/gob"
	"github.com/GeertJohan/go.rice/embedded"
	"unsafe"
)

func init() {
	ptr := unsafe.Pointer(&C._bricebox_{{.Symname}})
	bts := C.GoBytes(ptr, C.get_{{.Symname}}_length())
	embeddedBox := &embedded.EmbeddedBox{}
	err := gob.NewDecoder(bytes.NewReader(bts)).Decode(embeddedBox)
	if err != nil {
		panic("error decoding embedded box: "+err.Error())
	}
	embeddedBox.Link()
	embedded.RegisterEmbeddedBox(embeddedBox.Name, embeddedBox)
}`)
	if err != nil {
		panic("could not parse template embeddedSysoHelper: " + err.Error())
	}
}

type embeddedSysoHelperData struct {
	Package string
	Symname string
}

func operationEmbedSyso(pkg *build.Package) {

	regexpSynameReplacer := regexp.MustCompile(`[^a-z0-9_]`)

	boxMap := findBoxes(pkg)

	// notify user when no calls to rice.FindBox are made (is this an error and therefore os.Exit(1) ?
	if len(boxMap) == 0 {
		fmt.Println("no calls to rice.FindBox() found")
		return
	}

	verbosef("\n")

	for boxname := range boxMap {
		// find path and filename for this box
		boxPath := filepath.Join(pkg.Dir, boxname)
		boxFilename := strings.Replace(boxname, "/", "-", -1)
		boxFilename = strings.Replace(boxFilename, "..", "back", -1)

		// verbose info
		verbosef("embedding box '%s'\n", boxname)
		verbosef("\tto file %s\n", boxFilename)

		// create box datastructure (used by template)
		box := &embedded.EmbeddedBox{
			Name:      boxname,
			Time:      time.Now(),
			EmbedType: embedded.EmbedTypeSyso,
			Files:     make(map[string]*embedded.EmbeddedFile),
			Dirs:      make(map[string]*embedded.EmbeddedDir),
		}

		// fill box datastructure with file data
		filepath.Walk(boxPath, func(path string, info os.FileInfo, err error) error {
			if err != nil {
				fmt.Printf("error walking box: %s\n", err)
				os.Exit(1)
			}

			filename := strings.TrimPrefix(path, boxPath)
			filename = strings.Replace(filename, "\\", "/", -1)
			filename = strings.TrimPrefix(filename, "/")
			if info.IsDir() {
				embeddedDir := &embedded.EmbeddedDir{
					Filename:   filename,
					DirModTime: info.ModTime(),
				}
				verbosef("\tincludes dir: '%s'\n", embeddedDir.Filename)
				box.Dirs[embeddedDir.Filename] = embeddedDir

				// add tree entry (skip for root, it'll create a recursion)
				if embeddedDir.Filename != "" {
					pathParts := strings.Split(embeddedDir.Filename, "/")
					parentDir := box.Dirs[strings.Join(pathParts[:len(pathParts)-1], "/")]
					parentDir.ChildDirs = append(parentDir.ChildDirs, embeddedDir)
				}
			} else {
				embeddedFile := &embedded.EmbeddedFile{
					Filename:    filename,
					FileModTime: info.ModTime(),
					Content:     "",
				}
				verbosef("\tincludes file: '%s'\n", embeddedFile.Filename)
				contentBytes, err := ioutil.ReadFile(path)
				if err != nil {
					fmt.Printf("error reading file content while walking box: %s\n", err)
					os.Exit(1)
				}
				embeddedFile.Content = string(contentBytes)
				box.Files[embeddedFile.Filename] = embeddedFile
			}
			return nil
		})

		// encode embedded box to gob file
		boxGobBuf := &bytes.Buffer{}
		err := gob.NewEncoder(boxGobBuf).Encode(box)
		if err != nil {
			fmt.Printf("error encoding box to gob: %v\n", err)
			os.Exit(1)
		}

		// write coff
		symname := regexpSynameReplacer.ReplaceAllString(boxname, "_")
		createCoffSyso(boxname, symname, "386", boxGobBuf.Bytes())
		createCoffSyso(boxname, symname, "amd64", boxGobBuf.Bytes())

		// write go
		sysoHelperData := embeddedSysoHelperData{
			Package: pkg.Name,
			Symname: symname,
		}
		fileSysoHelper, err := os.Create(boxFilename + ".rice-box.go")
		if err != nil {
			fmt.Printf("error creating syso helper: %v\n", err)
			os.Exit(1)
		}
		err = tmplEmbeddedSysoHelper.Execute(fileSysoHelper, sysoHelperData)
		if err != nil {
			fmt.Printf("error executing tmplEmbeddedSysoHelper: %v\n", err)
			os.Exit(1)
		}
	}
}

func createCoffSyso(boxFilename string, symname string, arch string, data []byte) {
	boxCoff := coff.NewRDATA()
	switch arch {
	case "386":
	case "amd64":
		boxCoff.FileHeader.Machine = 0x8664
	default:
		panic("invalid arch")
	}
	boxCoff.AddData("_bricebox_"+symname, sizedBytes(data))
	boxCoff.AddData("_ericebox_"+symname, io.NewSectionReader(strings.NewReader("\000\000"), 0, 2)) // TODO: why? copied from rsrc, which copied it from as-generated
	boxCoff.Freeze()
	err := writeCoff(boxCoff, boxFilename+"_"+arch+".rice-box.syso")
	if err != nil {
		fmt.Printf("error writing %s coff/.syso: %v\n", arch, err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>//package syncmap is a map with sync.RWMutex.
package syncmap

import (
	"errors"
	. "github.com/yanjinzh6/flowkey/tools"
	"sync"
	"time"
)

const (
	DEFAULT_DURATION_TIME = time.Minute * 30
)

var (
	NilKeyError = errors.New("nil key error")
	NilError    = errors.New("text")
)

type syncMap struct {
	m      map[interface{}]interface{}
	rwlock sync.RWMutex
}

type SyncMap interface {
	Get(key interface{}) (val interface{}, err error)
	Put(key, value interface{}) (val interface{}, err error)
	PutIfAbsent(key, value interface{}) (b bool, err error)
	PutAll(child map[interface{}]interface{}) (err error)
	Remove(key interface{}) (val interface{}, err error)
	RemoveEntry(key, value interface{}) (b bool, err error)
	IsEmpty() (b bool)
	Clear() (err error)
	Size() (size int)
}

func NewSyncMap() SyncMap {
	return &syncMap{
		m: make(map[interface{}]interface{}),
	}
}

func (s *syncMap) Get(key interface{}) (val interface{}, err error) {
	if !ChKey(key) {
		return nil, NilKeyError
	}
	s.rwlock.RLock()
	val = s.m[key]
	if ok, ent := chTimeEntity(val); ok {
		val, err = ent.Value()
	}
	s.rwlock.RUnlock()
	return
}

func (s *syncMap) Put(key, value interface{}, d time.Duration) (val interface{}, err error) {
	if !ChKey(key) {
		return nil, NilKeyError
	}
	s.rwlock.Lock()
	val = s.m[key]
	if val == nil {
		ent := NewTimeEntity(value, d)
		s.m[key] = ent
	} else {
		if ok, ent := chTimeEntity(val); ok {
			val, err = ent.Value()
		} else {
			s.m[key] = value
		}
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMap) PutSimple(key, value interface{}) (val interface{}, err error) {
	Put(key, value, DEFAULT_DURATION_TIME)
}

func (s *syncMap) PutNormal(key, value interface{}) (val interface{}, err error) {
	Put(key, value, DEFAULT_DURATION_TIME)
}

func (s *syncMap) PutIfAbsent(key, value interface{}) (b bool, err error) {
	if !ChKey(key) {
		return false, NilKeyError
	}
	s.rwlock.Lock()
	if s.m[key] == nil {
		b = true
		s.m[key] = value
	} else {
		b = false
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMap) PutAll(child map[interface{}]interface{}) (err error) {
	if child != nil {
		s.rwlock.Lock()
		for k, v := range child {
			s.m[k] = v
		}
		s.rwlock.Unlock()
	}
	return
}

func (s *syncMap) Remove(key interface{}) (val interface{}, err error) {
	if !ChKey(key) {
		return nil, NilKeyError
	}
	s.rwlock.Lock()
	val = s.m[key]
	if val != nil {
		delete(s.m, key)
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMap) RemoveEntry(key, value interface{}) (b bool, err error) {
	if !ChKey(key) {
		return false, NilKeyError
	}
	s.rwlock.Lock()
	val := s.m[key]
	if val != nil && val == value {
		b = true
		delete(s.m, key)
	} else {
		b = false
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMap) IsEmpty() (b bool) {
	s.rwlock.RLock()
	if s.m == nil || len(s.m) == 0 {
		b = true
	} else {
		b = false
	}
	s.rwlock.RUnlock()
	return
}

func (s *syncMap) Clear() (err error) {
	s.rwlock.Lock()
	for k := range s.m {
		delete(s.m, k)
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMap) Size() (size int) {
	s.rwlock.RLock()
	size = len(s.m)
	s.rwlock.RUnlock()
	return
}

func chTimeEntity(val interface{}) (ok bool, ent TimeEntity) {
	if val == nil {
		return false
	}
	switch value := val.(type) {
	case TimeEntity:
		return true, value
	default:
		return false, nil
	}
}
<commit_msg>syncMap.go add new type and implement the interface, add update function.<commit_after>//package syncmap is a map with sync.RWMutex.
package syncmap

import (
	"errors"
	. "github.com/yanjinzh6/flowkey/tools"
	"sync"
	"time"
)

const (
	DEFAULT_DURATION_TIME = time.Minute * 30
)

var (
	NilKeyError = errors.New("nil key error")
	NilError    = errors.New("text")
)

type syncMap struct {
	m      map[interface{}]interface{}
	rwlock sync.RWMutex
}

type SyncMap interface {
	Get(key interface{}) (val interface{}, err error)
	Put(key, value interface{}, d time.Duration) (val interface{}, err error)
	PutSimple(key, value interface{}) (val interface{}, err error)
	PutNormal(key, value interface{}) (val interface{}, err error)
	PutIfAbsent(key, value interface{}, d time.Duration) (b bool, err error)
	PutAll(child map[interface{}]interface{}, d time.Duration) (err error)
	Remove(key interface{}) (val interface{}, err error)
	RemoveEntry(key, value interface{}) (b bool, err error)
	Update(key, value interface{}) (b bool, err error)
	IsEmpty() (b bool)
	Clear() (err error)
	Size() (size int)
}

func NewSyncMap() SyncMap {
	return &syncMap{
		m: make(map[interface{}]interface{}),
	}
}

func (s *syncMap) Get(key interface{}) (val interface{}, err error) {
	if !ChKey(key) {
		return nil, NilKeyError
	}
	s.rwlock.RLock()
	val = s.m[key]
	if ok, ent := chTimeEntity(val); ok {
		val, err = ent.Value()
	}
	s.rwlock.RUnlock()
	return
}

func (s *syncMap) Put(key, value interface{}, d time.Duration) (val interface{}, err error) {
	if !ChKey(key) {
		return nil, NilKeyError
	}
	s.rwlock.Lock()
	val = s.m[key]
	if val == nil {
		ent := NewTimeEntity(value, d)
		s.m[key] = ent
	} else {
		if ok, ent := chTimeEntity(val); ok {
			val, err = ent.Value()
		} else {
			s.m[key] = value
		}
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMap) PutSimple(key, value interface{}) (val interface{}, err error) {
	val, err = s.Put(key, value, DEFAULT_DURATION_TIME)
	return
}

func (s *syncMap) PutNormal(key, value interface{}) (val interface{}, err error) {
	val, err = s.Put(key, value, 0)
	return
}

func (s *syncMap) PutIfAbsent(key, value interface{}, d time.Duration) (b bool, err error) {
	if !ChKey(key) {
		return false, NilKeyError
	}
	s.rwlock.Lock()
	if s.m[key] == nil {
		b = true
		s.m[key] = value
	} else {
		b = false
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMap) PutAll(child map[interface{}]interface{}, d time.Duration) (err error) {
	if child != nil {
		s.rwlock.Lock()
		for k, v := range child {
			s.m[k] = v
		}
		s.rwlock.Unlock()
	}
	return
}

func (s *syncMap) Remove(key interface{}) (val interface{}, err error) {
	if !ChKey(key) {
		return nil, NilKeyError
	}
	s.rwlock.Lock()
	val = s.m[key]
	if val != nil {
		delete(s.m, key)
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMap) RemoveEntry(key, value interface{}) (b bool, err error) {
	if !ChKey(key) {
		return false, NilKeyError
	}
	s.rwlock.Lock()
	val := s.m[key]
	if val != nil && val == value {
		b = true
		delete(s.m, key)
	} else {
		b = false
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMap) Update(key, value interface{}) (b bool, err error) {
	if !ChKey(key) {
		return false, NilKeyError
	}
	return
}

func (s *syncMap) IsEmpty() (b bool) {
	s.rwlock.RLock()
	if s.m == nil || len(s.m) == 0 {
		b = true
	} else {
		b = false
	}
	s.rwlock.RUnlock()
	return
}

func (s *syncMap) Clear() (err error) {
	s.rwlock.Lock()
	for k := range s.m {
		delete(s.m, k)
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMap) Size() (size int) {
	s.rwlock.RLock()
	size = len(s.m)
	s.rwlock.RUnlock()
	return
}

func chTimeEntity(val interface{}) (ok bool, ent TimeEntity) {
	if val == nil {
		return false, nil
	}
	switch value := val.(type) {
	case TimeEntity:
		return true, value
	default:
		return false, nil
	}
}

type syncMapEnt struct {
	m      map[interface{}]TimeEntity
	rwlock sync.RWMutex
}

func NewSyncMapEnt() SyncMap {
	return &syncMapEnt{
		m: make(map[interface{}]TimeEntity),
	}
}

func (s *syncMapEnt) Get(key interface{}) (val interface{}, err error) {
	if !ChKey(key) {
		return nil, NilKeyError
	}
	if s.m[key].IsDie() {
		s.rwlock.Lock()
		s.m[key] = nil
		delete(s.m, key)
		val = nil
		s.rwlock.Unlock()
	} else {
		s.rwlock.RLock()
		val, err = s.m[key].Value()
		s.rwlock.RUnlock()
	}
	return
}

func (s *syncMapEnt) Put(key, value interface{}, d time.Duration) (val interface{}, err error) {
	if !ChKey(key) {
		return nil, NilKeyError
	}
	s.rwlock.Lock()
	oldEnt := s.m[key]
	if oldEnt == nil {
		ent := NewTimeEntity(value, d)
		s.m[key] = ent
	} else {
		if val, _ := oldEnt.Value(); val != value {
			s.m[key].Update(value)
		}
		if oldEnt.Dtime() != d {
			s.m[key].ChangeDur(d)
		}
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMapEnt) PutSimple(key, value interface{}) (val interface{}, err error) {
	val, err = s.Put(key, value, DEFAULT_DURATION_TIME)
	return
}

func (s *syncMapEnt) PutNormal(key, value interface{}) (val interface{}, err error) {
	val, err = s.Put(key, value, 0)
	return
}

func (s *syncMapEnt) PutIfAbsent(key, value interface{}, d time.Duration) (b bool, err error) {
	if !ChKey(key) {
		return false, NilKeyError
	}
	s.rwlock.Lock()
	if s.m[key] == nil {
		b = true
		ent := NewTimeEntity(value, d)
		s.m[key] = ent
	} else {
		b = false
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMapEnt) PutAll(child map[interface{}]interface{}, d time.Duration) (err error) {
	if child != nil {
		s.rwlock.Lock()
		for k, v := range child {
			if s.m[k] != nil {
				s.m[k] = nil
			}
			ent := NewTimeEntity(v, d)
			s.m[k] = ent
		}
		s.rwlock.Unlock()
	}
	return
}

func (s *syncMapEnt) Remove(key interface{}) (val interface{}, err error) {
	if !ChKey(key) {
		return nil, NilKeyError
	}
	s.rwlock.Lock()
	val = s.m[key]
	if val != nil {
		s.m[key] = nil
		delete(s.m, key)
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMapEnt) RemoveEntry(key, value interface{}) (b bool, err error) {
	if !ChKey(key) {
		return false, NilKeyError
	}
	s.rwlock.Lock()
	val := s.m[key]
	if val != nil {
		if v, _ := val.Value(); v == value {
			b = true
			s.m[key] = nil
			delete(s.m, key)
		}
	} else {
		b = false
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMapEnt) Update(key, value interface{}) (b bool, err error) {
	if !ChKey(key) {
		return false, NilKeyError
	}
	s.rwlock.Lock()
	val := s.m[key]
	if val != nil {
		b = true
		val.Update(value)
	} else {
		b = false
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMapEnt) IsEmpty() (b bool) {
	s.rwlock.RLock()
	if s.m == nil || len(s.m) == 0 {
		b = true
	} else {
		b = false
	}
	s.rwlock.RUnlock()
	return
}

func (s *syncMapEnt) Clear() (err error) {
	s.rwlock.Lock()
	for k := range s.m {
		delete(s.m, k)
	}
	s.rwlock.Unlock()
	return
}

func (s *syncMapEnt) Size() (size int) {
	s.rwlock.RLock()
	size = len(s.m)
	s.rwlock.RUnlock()
	return
}
<|endoftext|>