<commit_before>/*
   Copyright (c) 2016 VMware, Inc. All Rights Reserved.
   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 dao

import (
	"fmt"
	"time"

	"strings"

	"github.com/astaxie/beego/orm"
	"github.com/vmware/harbor/models"
)

// AddRepTarget ...
func AddRepTarget(target models.RepTarget) (int64, error) {
	o := GetOrmer()
	return o.Insert(&target)
}

// GetRepTarget ...
func GetRepTarget(id int64) (*models.RepTarget, error) {
	o := GetOrmer()
	t := models.RepTarget{ID: id}
	err := o.Read(&t)
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return &t, err
}

// GetRepTargetByName ...
func GetRepTargetByName(name string) (*models.RepTarget, error) {
	o := GetOrmer()
	t := models.RepTarget{Name: name}
	err := o.Read(&t, "Name")
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return &t, err
}

// GetRepTargetByConnInfo ...
func GetRepTargetByConnInfo(endpoint, username string) (*models.RepTarget, error) {
	o := GetOrmer()
	t := models.RepTarget{
		URL:      endpoint,
		Username: username,
	}
	err := o.Read(&t, "URL", "Username")
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return &t, err
}

// DeleteRepTarget ...
func DeleteRepTarget(id int64) error {
	o := GetOrmer()
	_, err := o.Delete(&models.RepTarget{ID: id})
	return err
}

// UpdateRepTarget ...
func UpdateRepTarget(target models.RepTarget) error {
	o := GetOrmer()
	_, err := o.Update(&target, "URL", "Name", "Username", "Password")
	return err
}

// FilterRepTargets filters targets by name
func FilterRepTargets(name string) ([]*models.RepTarget, error) {
	o := GetOrmer()

	var args []interface{}

	sql := `select * from replication_target `
	if len(name) != 0 {
		sql += `where name like ? `
		args = append(args, "%"+name+"%")
	}
	sql += `order by creation_time`

	var targets []*models.RepTarget

	if _, err := o.Raw(sql, args).QueryRows(&targets); err != nil {
		return nil, err
	}

	return targets, nil
}

// AddRepPolicy ...
func AddRepPolicy(policy models.RepPolicy) (int64, error) {
	o := GetOrmer()
	sqlTpl := `insert into replication_policy (name, project_id, target_id, enabled, description, cron_str, start_time, creation_time, update_time ) values (?, ?, ?, ?, ?, ?, %s, NOW(), NOW())`
	var sql string
	if policy.Enabled == 1 {
		sql = fmt.Sprintf(sqlTpl, "NOW()")
	} else {
		sql = fmt.Sprintf(sqlTpl, "NULL")
	}
	p, err := o.Raw(sql).Prepare()
	if err != nil {
		return 0, err
	}
	r, err := p.Exec(policy.Name, policy.ProjectID, policy.TargetID, policy.Enabled, policy.Description, policy.CronStr)
	if err != nil {
		return 0, err
	}
	id, err := r.LastInsertId()
	return id, err
}

// GetRepPolicy ...
func GetRepPolicy(id int64) (*models.RepPolicy, error) {
	o := GetOrmer()
	sql := `select * from replication_policy where id = ?`

	var policy models.RepPolicy

	if err := o.Raw(sql, id).QueryRow(&policy); err != nil {
		if err == orm.ErrNoRows {
			return nil, nil
		}
		return nil, err
	}

	return &policy, nil
}

// FilterRepPolicies filters policies by name and project ID
func FilterRepPolicies(name string, projectID int64) ([]*models.RepPolicy, error) {
	o := GetOrmer()

	var args []interface{}

	sql := `select rp.id, rp.project_id, p.name as project_name, rp.target_id,
				rt.name as target_name, rp.name, rp.enabled, rp.description,
				rp.cron_str, rp.start_time, rp.creation_time, rp.update_time,
				count(rj.status) as error_job_count
			from replication_policy rp
			left join project p on rp.project_id=p.project_id
			left join replication_target rt on rp.target_id=rt.id
			left join replication_job rj on rp.id=rj.policy_id and rj.status="error" `

	if len(name) != 0 && projectID != 0 {
		sql += `where rp.name like ? and rp.project_id = ? `
		args = append(args, "%"+name+"%")
		args = append(args, projectID)
	} else if len(name) != 0 {
		sql += `where rp.name like ? `
		args = append(args, "%"+name+"%")
	} else if projectID != 0 {
		sql += `where rp.project_id = ? `
		args = append(args, projectID)
	}

	sql += `order by rp.creation_time`

	var policies []*models.RepPolicy
	if _, err := o.Raw(sql, args).QueryRows(&policies); err != nil {
		return nil, err
	}
	return policies, nil
}

// GetRepPolicyByName ...
func GetRepPolicyByName(name string) (*models.RepPolicy, error) {
	o := GetOrmer()
	sql := `select * from replication_policy where name = ?`

	var policy models.RepPolicy

	if err := o.Raw(sql, name).QueryRow(&policy); err != nil {
		if err == orm.ErrNoRows {
			return nil, nil
		}
		return nil, err
	}

	return &policy, nil
}

// GetRepPolicyByProject ...
func GetRepPolicyByProject(projectID int64) ([]*models.RepPolicy, error) {
	o := GetOrmer()
	sql := `select * from replication_policy where project_id = ?`

	var policies []*models.RepPolicy

	if _, err := o.Raw(sql, projectID).QueryRows(&policies); err != nil {
		return nil, err
	}

	return policies, nil
}

// GetRepPolicyByTarget ...
func GetRepPolicyByTarget(targetID int64) ([]*models.RepPolicy, error) {
	o := GetOrmer()
	sql := `select * from replication_policy where target_id = ?`

	var policies []*models.RepPolicy

	if _, err := o.Raw(sql, targetID).QueryRows(&policies); err != nil {
		return nil, err
	}

	return policies, nil
}

// GetRepPolicyByProjectAndTarget ...
func GetRepPolicyByProjectAndTarget(projectID, targetID int64) ([]*models.RepPolicy, error) {
	o := GetOrmer()
	sql := `select * from replication_policy where project_id = ? and target_id = ?`

	var policies []*models.RepPolicy

	if _, err := o.Raw(sql, projectID, targetID).QueryRows(&policies); err != nil {
		return nil, err
	}

	return policies, nil
}

// UpdateRepPolicy ...
func UpdateRepPolicy(policy *models.RepPolicy) error {
	o := GetOrmer()
	_, err := o.Update(policy, "TargetID", "Name", "Enabled", "Description", "CronStr")
	return err
}

// DeleteRepPolicy ...
func DeleteRepPolicy(id int64) error {
	o := GetOrmer()
	_, err := o.Delete(&models.RepPolicy{ID: id})
	return err
}

// UpdateRepPolicyEnablement ...
func UpdateRepPolicyEnablement(id int64, enabled int) error {
	o := GetOrmer()
	p := models.RepPolicy{
		ID:      id,
		Enabled: enabled,
	}

	var err error
	if enabled == 1 {
		p.StartTime = time.Now()
		_, err = o.Update(&p, "Enabled", "StartTime")
	} else {
		_, err = o.Update(&p, "Enabled")
	}

	return err
}

// EnableRepPolicy ...
func EnableRepPolicy(id int64) error {
	return UpdateRepPolicyEnablement(id, 1)
}

// DisableRepPolicy ...
func DisableRepPolicy(id int64) error {
	return UpdateRepPolicyEnablement(id, 0)
}

// AddRepJob ...
func AddRepJob(job models.RepJob) (int64, error) {
	o := GetOrmer()
	if len(job.Status) == 0 {
		job.Status = models.JobPending
	}
	if len(job.TagList) > 0 {
		job.Tags = strings.Join(job.TagList, ",")
	}
	return o.Insert(&job)
}

// GetRepJob ...
func GetRepJob(id int64) (*models.RepJob, error) {
	o := GetOrmer()
	j := models.RepJob{ID: id}
	err := o.Read(&j)
	if err == orm.ErrNoRows {
		return nil, nil
	}
	genTagListForJob(&j)
	return &j, nil
}

// GetRepJobByPolicy ...
func GetRepJobByPolicy(policyID int64) ([]*models.RepJob, error) {
	var res []*models.RepJob
	_, err := repJobPolicyIDQs(policyID).All(&res)
	genTagListForJob(res...)
	return res, err
}

// FilterRepJobs filters jobs by repo and policy ID
func FilterRepJobs(policyID int64, repository, status string, startTime,
	endTime *time.Time, limit int) ([]*models.RepJob, error) {
	o := GetOrmer()

	qs := o.QueryTable(new(models.RepJob))
	if policyID != 0 {
		qs = qs.Filter("PolicyID", policyID)
	}
	if len(repository) != 0 {
		qs = qs.Filter("Repository__icontains", repository)
	}
	if len(status) != 0 {
		qs = qs.Filter("Status__icontains", status)
	}

	if startTime != nil {
		fmt.Printf("%v\n", startTime)
		qs = qs.Filter("CreationTime__gte", startTime)
	}

	if endTime != nil {
		fmt.Printf("%v\n", endTime)
		qs = qs.Filter("CreationTime__lte", endTime)
	}

	if limit != 0 {
		qs = qs.Limit(limit)
	}

	qs = qs.OrderBy("-CreationTime")

	var jobs []*models.RepJob
	_, err := qs.All(&jobs)
	if err != nil {
		return nil, err
	}

	genTagListForJob(jobs...)

	return jobs, nil
}

// GetRepJobToStop get jobs that are possibly being handled by workers of a certain policy.
func GetRepJobToStop(policyID int64) ([]*models.RepJob, error) {
	var res []*models.RepJob
	_, err := repJobPolicyIDQs(policyID).Filter("status__in", models.JobPending, models.JobRunning).All(&res)
	genTagListForJob(res...)
	return res, err
}

func repJobQs() orm.QuerySeter {
	o := GetOrmer()
	return o.QueryTable("replication_job")
}

func repJobPolicyIDQs(policyID int64) orm.QuerySeter {
	return repJobQs().Filter("policy_id", policyID)
}

// DeleteRepJob ...
func DeleteRepJob(id int64) error {
	o := GetOrmer()
	_, err := o.Delete(&models.RepJob{ID: id})
	return err
}

// UpdateRepJobStatus ...
func UpdateRepJobStatus(id int64, status string) error {
	o := GetOrmer()
	j := models.RepJob{
		ID:     id,
		Status: status,
	}
	num, err := o.Update(&j, "Status")
	if num == 0 {
		err = fmt.Errorf("Failed to update replication job with id: %d %s", id, err.Error())
	}
	return err
}

// ResetRunningJobs update all running jobs status to pending
func ResetRunningJobs() error {
	o := GetOrmer()
	sql := fmt.Sprintf("update replication_job set status = '%s' where status = '%s'", models.JobPending, models.JobRunning)
	_, err := o.Raw(sql).Exec()
	return err
}

// GetRepJobByStatus get jobs of certain statuses
func GetRepJobByStatus(status ...string) ([]*models.RepJob, error) {
	var res []*models.RepJob
	var t []interface{}
	for _, s := range status {
		t = append(t, interface{}(s))
	}
	_, err := repJobQs().Filter("status__in", t...).All(&res)
	genTagListForJob(res...)
	return res, err
}

func genTagListForJob(jobs ...*models.RepJob) {
	for _, j := range jobs {
		if len(j.Tags) > 0 {
			j.TagList = strings.Split(j.Tags, ",")
		}
	}
}
<commit_msg>count status 'retrying'<commit_after>/*
   Copyright (c) 2016 VMware, Inc. All Rights Reserved.
   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 dao

import (
	"fmt"
	"time"

	"strings"

	"github.com/astaxie/beego/orm"
	"github.com/vmware/harbor/models"
)

// AddRepTarget ...
func AddRepTarget(target models.RepTarget) (int64, error) {
	o := GetOrmer()
	return o.Insert(&target)
}

// GetRepTarget ...
func GetRepTarget(id int64) (*models.RepTarget, error) {
	o := GetOrmer()
	t := models.RepTarget{ID: id}
	err := o.Read(&t)
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return &t, err
}

// GetRepTargetByName ...
func GetRepTargetByName(name string) (*models.RepTarget, error) {
	o := GetOrmer()
	t := models.RepTarget{Name: name}
	err := o.Read(&t, "Name")
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return &t, err
}

// GetRepTargetByConnInfo ...
func GetRepTargetByConnInfo(endpoint, username string) (*models.RepTarget, error) {
	o := GetOrmer()
	t := models.RepTarget{
		URL:      endpoint,
		Username: username,
	}
	err := o.Read(&t, "URL", "Username")
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return &t, err
}

// DeleteRepTarget ...
func DeleteRepTarget(id int64) error {
	o := GetOrmer()
	_, err := o.Delete(&models.RepTarget{ID: id})
	return err
}

// UpdateRepTarget ...
func UpdateRepTarget(target models.RepTarget) error {
	o := GetOrmer()
	_, err := o.Update(&target, "URL", "Name", "Username", "Password")
	return err
}

// FilterRepTargets filters targets by name
func FilterRepTargets(name string) ([]*models.RepTarget, error) {
	o := GetOrmer()

	var args []interface{}

	sql := `select * from replication_target `
	if len(name) != 0 {
		sql += `where name like ? `
		args = append(args, "%"+name+"%")
	}
	sql += `order by creation_time`

	var targets []*models.RepTarget

	if _, err := o.Raw(sql, args).QueryRows(&targets); err != nil {
		return nil, err
	}

	return targets, nil
}

// AddRepPolicy ...
func AddRepPolicy(policy models.RepPolicy) (int64, error) {
	o := GetOrmer()
	sqlTpl := `insert into replication_policy (name, project_id, target_id, enabled, description, cron_str, start_time, creation_time, update_time ) values (?, ?, ?, ?, ?, ?, %s, NOW(), NOW())`
	var sql string
	if policy.Enabled == 1 {
		sql = fmt.Sprintf(sqlTpl, "NOW()")
	} else {
		sql = fmt.Sprintf(sqlTpl, "NULL")
	}
	p, err := o.Raw(sql).Prepare()
	if err != nil {
		return 0, err
	}
	r, err := p.Exec(policy.Name, policy.ProjectID, policy.TargetID, policy.Enabled, policy.Description, policy.CronStr)
	if err != nil {
		return 0, err
	}
	id, err := r.LastInsertId()
	return id, err
}

// GetRepPolicy ...
func GetRepPolicy(id int64) (*models.RepPolicy, error) {
	o := GetOrmer()
	sql := `select * from replication_policy where id = ?`

	var policy models.RepPolicy

	if err := o.Raw(sql, id).QueryRow(&policy); err != nil {
		if err == orm.ErrNoRows {
			return nil, nil
		}
		return nil, err
	}

	return &policy, nil
}

// FilterRepPolicies filters policies by name and project ID
func FilterRepPolicies(name string, projectID int64) ([]*models.RepPolicy, error) {
	o := GetOrmer()

	var args []interface{}

	sql := `select rp.id, rp.project_id, p.name as project_name, rp.target_id,
				rt.name as target_name, rp.name, rp.enabled, rp.description,
				rp.cron_str, rp.start_time, rp.creation_time, rp.update_time,
				count(rj.status) as error_job_count
			from replication_policy rp
			left join project p on rp.project_id=p.project_id
			left join replication_target rt on rp.target_id=rt.id
			left join replication_job rj on rp.id=rj.policy_id and (rj.status="error"
				or rj.status="retrying") group by rp.id `

	if len(name) != 0 && projectID != 0 {
		sql += `where rp.name like ? and rp.project_id = ? `
		args = append(args, "%"+name+"%")
		args = append(args, projectID)
	} else if len(name) != 0 {
		sql += `where rp.name like ? `
		args = append(args, "%"+name+"%")
	} else if projectID != 0 {
		sql += `where rp.project_id = ? `
		args = append(args, projectID)
	}

	sql += `order by rp.creation_time`

	var policies []*models.RepPolicy
	if _, err := o.Raw(sql, args).QueryRows(&policies); err != nil {
		return nil, err
	}
	return policies, nil
}

// GetRepPolicyByName ...
func GetRepPolicyByName(name string) (*models.RepPolicy, error) {
	o := GetOrmer()
	sql := `select * from replication_policy where name = ?`

	var policy models.RepPolicy

	if err := o.Raw(sql, name).QueryRow(&policy); err != nil {
		if err == orm.ErrNoRows {
			return nil, nil
		}
		return nil, err
	}

	return &policy, nil
}

// GetRepPolicyByProject ...
func GetRepPolicyByProject(projectID int64) ([]*models.RepPolicy, error) {
	o := GetOrmer()
	sql := `select * from replication_policy where project_id = ?`

	var policies []*models.RepPolicy

	if _, err := o.Raw(sql, projectID).QueryRows(&policies); err != nil {
		return nil, err
	}

	return policies, nil
}

// GetRepPolicyByTarget ...
func GetRepPolicyByTarget(targetID int64) ([]*models.RepPolicy, error) {
	o := GetOrmer()
	sql := `select * from replication_policy where target_id = ?`

	var policies []*models.RepPolicy

	if _, err := o.Raw(sql, targetID).QueryRows(&policies); err != nil {
		return nil, err
	}

	return policies, nil
}

// GetRepPolicyByProjectAndTarget ...
func GetRepPolicyByProjectAndTarget(projectID, targetID int64) ([]*models.RepPolicy, error) {
	o := GetOrmer()
	sql := `select * from replication_policy where project_id = ? and target_id = ?`

	var policies []*models.RepPolicy

	if _, err := o.Raw(sql, projectID, targetID).QueryRows(&policies); err != nil {
		return nil, err
	}

	return policies, nil
}

// UpdateRepPolicy ...
func UpdateRepPolicy(policy *models.RepPolicy) error {
	o := GetOrmer()
	_, err := o.Update(policy, "TargetID", "Name", "Enabled", "Description", "CronStr")
	return err
}

// DeleteRepPolicy ...
func DeleteRepPolicy(id int64) error {
	o := GetOrmer()
	_, err := o.Delete(&models.RepPolicy{ID: id})
	return err
}

// UpdateRepPolicyEnablement ...
func UpdateRepPolicyEnablement(id int64, enabled int) error {
	o := GetOrmer()
	p := models.RepPolicy{
		ID:      id,
		Enabled: enabled,
	}

	var err error
	if enabled == 1 {
		p.StartTime = time.Now()
		_, err = o.Update(&p, "Enabled", "StartTime")
	} else {
		_, err = o.Update(&p, "Enabled")
	}

	return err
}

// EnableRepPolicy ...
func EnableRepPolicy(id int64) error {
	return UpdateRepPolicyEnablement(id, 1)
}

// DisableRepPolicy ...
func DisableRepPolicy(id int64) error {
	return UpdateRepPolicyEnablement(id, 0)
}

// AddRepJob ...
func AddRepJob(job models.RepJob) (int64, error) {
	o := GetOrmer()
	if len(job.Status) == 0 {
		job.Status = models.JobPending
	}
	if len(job.TagList) > 0 {
		job.Tags = strings.Join(job.TagList, ",")
	}
	return o.Insert(&job)
}

// GetRepJob ...
func GetRepJob(id int64) (*models.RepJob, error) {
	o := GetOrmer()
	j := models.RepJob{ID: id}
	err := o.Read(&j)
	if err == orm.ErrNoRows {
		return nil, nil
	}
	genTagListForJob(&j)
	return &j, nil
}

// GetRepJobByPolicy ...
func GetRepJobByPolicy(policyID int64) ([]*models.RepJob, error) {
	var res []*models.RepJob
	_, err := repJobPolicyIDQs(policyID).All(&res)
	genTagListForJob(res...)
	return res, err
}

// FilterRepJobs filters jobs by repo and policy ID
func FilterRepJobs(policyID int64, repository, status string, startTime,
	endTime *time.Time, limit int) ([]*models.RepJob, error) {
	o := GetOrmer()

	qs := o.QueryTable(new(models.RepJob))
	if policyID != 0 {
		qs = qs.Filter("PolicyID", policyID)
	}
	if len(repository) != 0 {
		qs = qs.Filter("Repository__icontains", repository)
	}
	if len(status) != 0 {
		qs = qs.Filter("Status__icontains", status)
	}

	if startTime != nil {
		fmt.Printf("%v\n", startTime)
		qs = qs.Filter("CreationTime__gte", startTime)
	}

	if endTime != nil {
		fmt.Printf("%v\n", endTime)
		qs = qs.Filter("CreationTime__lte", endTime)
	}

	if limit != 0 {
		qs = qs.Limit(limit)
	}

	qs = qs.OrderBy("-CreationTime")

	var jobs []*models.RepJob
	_, err := qs.All(&jobs)
	if err != nil {
		return nil, err
	}

	genTagListForJob(jobs...)

	return jobs, nil
}

// GetRepJobToStop get jobs that are possibly being handled by workers of a certain policy.
func GetRepJobToStop(policyID int64) ([]*models.RepJob, error) {
	var res []*models.RepJob
	_, err := repJobPolicyIDQs(policyID).Filter("status__in", models.JobPending, models.JobRunning).All(&res)
	genTagListForJob(res...)
	return res, err
}

func repJobQs() orm.QuerySeter {
	o := GetOrmer()
	return o.QueryTable("replication_job")
}

func repJobPolicyIDQs(policyID int64) orm.QuerySeter {
	return repJobQs().Filter("policy_id", policyID)
}

// DeleteRepJob ...
func DeleteRepJob(id int64) error {
	o := GetOrmer()
	_, err := o.Delete(&models.RepJob{ID: id})
	return err
}

// UpdateRepJobStatus ...
func UpdateRepJobStatus(id int64, status string) error {
	o := GetOrmer()
	j := models.RepJob{
		ID:     id,
		Status: status,
	}
	num, err := o.Update(&j, "Status")
	if num == 0 {
		err = fmt.Errorf("Failed to update replication job with id: %d %s", id, err.Error())
	}
	return err
}

// ResetRunningJobs update all running jobs status to pending
func ResetRunningJobs() error {
	o := GetOrmer()
	sql := fmt.Sprintf("update replication_job set status = '%s' where status = '%s'", models.JobPending, models.JobRunning)
	_, err := o.Raw(sql).Exec()
	return err
}

// GetRepJobByStatus get jobs of certain statuses
func GetRepJobByStatus(status ...string) ([]*models.RepJob, error) {
	var res []*models.RepJob
	var t []interface{}
	for _, s := range status {
		t = append(t, interface{}(s))
	}
	_, err := repJobQs().Filter("status__in", t...).All(&res)
	genTagListForJob(res...)
	return res, err
}

func genTagListForJob(jobs ...*models.RepJob) {
	for _, j := range jobs {
		if len(j.Tags) > 0 {
			j.TagList = strings.Split(j.Tags, ",")
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
A trivial example of wrapping a C library in Go.
For a more complex example and explanation,
see ../gmp/gmp.go.
*/

package stdio

/*
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>

char* greeting = "hello, world";
*/
import "C"
import "unsafe"

type File C.FILE

var Stdout = (*File)(C.stdout)
var Stderr = (*File)(C.stderr)

// Test reference to library symbol.
// Stdout and stderr are too special to be a reliable test.
var myerr = C.sys_errlist

func (f *File) WriteString(s string) {
	p := C.CString(s)
	C.fputs(p, (*C.FILE)(f))
	C.free(unsafe.Pointer(p))
	f.Flush()
}

func (f *File) Flush() {
	C.fflush((*C.FILE)(f))
}

var Greeting = C.GoString(C.greeting)
<commit_msg>go/build: fix windows build by commenting out references to stdout and stderr in cgotest<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
A trivial example of wrapping a C library in Go.
For a more complex example and explanation,
see ../gmp/gmp.go.
*/

package stdio

/*
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>

char* greeting = "hello, world";
*/
import "C"
import "unsafe"

type File C.FILE

// TODO(brainman): uncomment once stdout and stderr references are working on Windows.
//var Stdout = (*File)(C.stdout)
//var Stderr = (*File)(C.stderr)

// Test reference to library symbol.
// Stdout and stderr are too special to be a reliable test.
var myerr = C.sys_errlist

func (f *File) WriteString(s string) {
	p := C.CString(s)
	C.fputs(p, (*C.FILE)(f))
	C.free(unsafe.Pointer(p))
	f.Flush()
}

func (f *File) Flush() {
	C.fflush((*C.FILE)(f))
}

var Greeting = C.GoString(C.greeting)
<|endoftext|>


<commit_before>package dao

import (
	"fmt"

	"strings"

	"github.com/astaxie/beego/orm"
	"github.com/vmware/harbor/models"
)

// AddRepTarget ...
func AddRepTarget(target models.RepTarget) (int64, error) {
	o := GetOrmer()
	return o.Insert(&target)
}

// GetRepTarget ...
func GetRepTarget(id int64) (*models.RepTarget, error) {
	o := GetOrmer()
	t := models.RepTarget{ID: id}
	err := o.Read(&t)
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return &t, err
}

// GetRepTargetByName ...
func GetRepTargetByName(name string) (*models.RepTarget, error) {
	o := GetOrmer()
	t := models.RepTarget{Name: name}
	err := o.Read(&t, "Name")
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return &t, err
}

// DeleteRepTarget ...
func DeleteRepTarget(id int64) error {
	o := GetOrmer()
	_, err := o.Delete(&models.RepTarget{ID: id})
	return err
}

// UpdateRepTarget ...
func UpdateRepTarget(target models.RepTarget) error {
	o := GetOrmer()
	_, err := o.Update(&target, "URL", "Name", "Username", "Password")
	return err
}

// GetAllRepTargets ...
func GetAllRepTargets() ([]*models.RepTarget, error) {
	o := GetOrmer()

	qs := o.QueryTable(&models.RepTarget{})
	var targets []*models.RepTarget
	_, err := qs.All(&targets)
	return targets, err
}

// FilterRepTargets filters targets by name
func FilterRepTargets(name string) ([]*models.RepTarget, error) {
	if len(name) == 0 {
		return GetAllRepTargets()
	}

	o := GetOrmer()

	var targets []*models.RepTarget
	sql := "select * from replication_target where name like ?"
	if _, err := o.Raw(sql, "%"+name+"%").QueryRows(targets); err != nil {
		return nil, err
	}

	return targets, nil
}

// AddRepPolicy ...
func AddRepPolicy(policy models.RepPolicy) (int64, error) {
	o := GetOrmer()
	sqlTpl := `insert into replication_policy (name, project_id, target_id, enabled, description, cron_str, start_time, creation_time, update_time ) values (?, ?, ?, ?, ?, ?, %s, NOW(), NOW())`
	var sql string
	if policy.Enabled == 1 {
		sql = fmt.Sprintf(sqlTpl, "NOW()")
	} else {
		sql = fmt.Sprintf(sqlTpl, "NULL")
	}
	p, err := o.Raw(sql).Prepare()
	if err != nil {
		return 0, err
	}
	r, err := p.Exec(policy.Name, policy.ProjectID, policy.TargetID, policy.Enabled, policy.Description, policy.CronStr)
	if err != nil {
		return 0, err
	}
	id, err := r.LastInsertId()
	return id, err
}

// GetRepPolicy ...
func GetRepPolicy(id int64) (*models.RepPolicy, error) {
	o := GetOrmer()
	p := models.RepPolicy{ID: id}
	err := o.Read(&p)
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return &p, err
}

// GetRepPolicyByName ...
func GetRepPolicyByName(name string) (*models.RepPolicy, error) {
	o := GetOrmer()
	p := models.RepPolicy{Name: name}
	err := o.Read(&p, "Name")
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return &p, err
}

// GetRepPolicyByProject ...
func GetRepPolicyByProject(projectID int64) ([]*models.RepPolicy, error) {
	var res []*models.RepPolicy
	o := GetOrmer()
	_, err := o.QueryTable("replication_policy").Filter("project_id", projectID).All(&res)
	return res, err
}

// DeleteRepPolicy ...
func DeleteRepPolicy(id int64) error {
	o := GetOrmer()
	_, err := o.Delete(&models.RepPolicy{ID: id})
	return err
}

// UpdateRepPolicyEnablement ...
func UpdateRepPolicyEnablement(id int64, enabled int) error {
	o := GetOrmer()
	p := models.RepPolicy{
		ID:      id,
		Enabled: enabled}
	_, err := o.Update(&p, "Enabled")

	return err
}

// EnableRepPolicy ...
func EnableRepPolicy(id int64) error {
	return UpdateRepPolicyEnablement(id, 1)
}

// DisableRepPolicy ...
func DisableRepPolicy(id int64) error {
	return UpdateRepPolicyEnablement(id, 0)
}

// AddRepJob ...
func AddRepJob(job models.RepJob) (int64, error) {
	o := GetOrmer()
	if len(job.Status) == 0 {
		job.Status = models.JobPending
	}
	if len(job.TagList) > 0 {
		job.Tags = strings.Join(job.TagList, ",")
	}
	return o.Insert(&job)
}

// GetRepJob ...
func GetRepJob(id int64) (*models.RepJob, error) {
	o := GetOrmer()
	j := models.RepJob{ID: id}
	err := o.Read(&j)
	if err == orm.ErrNoRows {
		return nil, nil
	}
	genTagListForJob(&j)
	return &j, nil
}

// GetRepJobByPolicy ...
func GetRepJobByPolicy(policyID int64) ([]*models.RepJob, error) {
	var res []*models.RepJob
	_, err := repJobPolicyIDQs(policyID).All(&res)
	genTagListForJob(res...)
	return res, err
}

// GetRepJobToStop get jobs that are possibly being handled by workers of a certain policy.
func GetRepJobToStop(policyID int64) ([]*models.RepJob, error) {
	var res []*models.RepJob
	_, err := repJobPolicyIDQs(policyID).Filter("status__in", models.JobPending, models.JobRunning).All(&res)
	genTagListForJob(res...)
	return res, err
}

func repJobPolicyIDQs(policyID int64) orm.QuerySeter {
	o := GetOrmer()
	return o.QueryTable("replication_job").Filter("policy_id", policyID)
}

// DeleteRepJob ...
func DeleteRepJob(id int64) error {
	o := GetOrmer()
	_, err := o.Delete(&models.RepJob{ID: id})
	return err
}

// UpdateRepJobStatus ...
func UpdateRepJobStatus(id int64, status string) error {
	o := GetOrmer()
	j := models.RepJob{
		ID:     id,
		Status: status,
	}
	num, err := o.Update(&j, "Status")
	if num == 0 {
		err = fmt.Errorf("Failed to update replication job with id: %d %s", id, err.Error())
	}
	return err
}

func genTagListForJob(jobs ...*models.RepJob) {
	for _, j := range jobs {
		if len(j.Tags) > 0 {
			j.TagList = strings.Split(j.Tags, ",")
		}
	}
}
<commit_msg>update implements of FilterTargets()<commit_after>package dao

import (
	"fmt"

	"strings"

	"github.com/astaxie/beego/orm"
	"github.com/vmware/harbor/models"
)

// AddRepTarget ...
func AddRepTarget(target models.RepTarget) (int64, error) {
	o := GetOrmer()
	return o.Insert(&target)
}

// GetRepTarget ...
func GetRepTarget(id int64) (*models.RepTarget, error) {
	o := GetOrmer()
	t := models.RepTarget{ID: id}
	err := o.Read(&t)
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return &t, err
}

// GetRepTargetByName ...
func GetRepTargetByName(name string) (*models.RepTarget, error) {
	o := GetOrmer()
	t := models.RepTarget{Name: name}
	err := o.Read(&t, "Name")
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return &t, err
}

// DeleteRepTarget ...
func DeleteRepTarget(id int64) error {
	o := GetOrmer()
	_, err := o.Delete(&models.RepTarget{ID: id})
	return err
}

// UpdateRepTarget ...
func UpdateRepTarget(target models.RepTarget) error {
	o := GetOrmer()
	_, err := o.Update(&target, "URL", "Name", "Username", "Password")
	return err
}

// GetAllRepTargets ...
func GetAllRepTargets() ([]*models.RepTarget, error) {
	o := GetOrmer()

	qs := o.QueryTable(&models.RepTarget{})
	var targets []*models.RepTarget
	_, err := qs.All(&targets)
	return targets, err
}

// FilterRepTargets filters targets by name
func FilterRepTargets(name string) ([]*models.RepTarget, error) {
	if len(name) == 0 {
		return GetAllRepTargets()
	}

	o := GetOrmer()
	var args []string
	args = append(args, "%"+name+"%")

	var targets []*models.RepTarget

	sql := "select * from replication_target where name like ?"
	if _, err := o.Raw(sql, args).QueryRows(targets); err != nil {
		return nil, err
	}

	return targets, nil
}

// AddRepPolicy ...
func AddRepPolicy(policy models.RepPolicy) (int64, error) {
	o := GetOrmer()
	sqlTpl := `insert into replication_policy (name, project_id, target_id, enabled, description, cron_str, start_time, creation_time, update_time ) values (?, ?, ?, ?, ?, ?, %s, NOW(), NOW())`
	var sql string
	if policy.Enabled == 1 {
		sql = fmt.Sprintf(sqlTpl, "NOW()")
	} else {
		sql = fmt.Sprintf(sqlTpl, "NULL")
	}
	p, err := o.Raw(sql).Prepare()
	if err != nil {
		return 0, err
	}
	r, err := p.Exec(policy.Name, policy.ProjectID, policy.TargetID, policy.Enabled, policy.Description, policy.CronStr)
	if err != nil {
		return 0, err
	}
	id, err := r.LastInsertId()
	return id, err
}

// GetRepPolicy ...
func GetRepPolicy(id int64) (*models.RepPolicy, error) {
	o := GetOrmer()
	p := models.RepPolicy{ID: id}
	err := o.Read(&p)
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return &p, err
}

// GetRepPolicyByName ...
func GetRepPolicyByName(name string) (*models.RepPolicy, error) {
	o := GetOrmer()
	p := models.RepPolicy{Name: name}
	err := o.Read(&p, "Name")
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return &p, err
}

// GetRepPolicyByProject ...
func GetRepPolicyByProject(projectID int64) ([]*models.RepPolicy, error) {
	var res []*models.RepPolicy
	o := GetOrmer()
	_, err := o.QueryTable("replication_policy").Filter("project_id", projectID).All(&res)
	return res, err
}

// DeleteRepPolicy ...
func DeleteRepPolicy(id int64) error {
	o := GetOrmer()
	_, err := o.Delete(&models.RepPolicy{ID: id})
	return err
}

// UpdateRepPolicyEnablement ...
func UpdateRepPolicyEnablement(id int64, enabled int) error {
	o := GetOrmer()
	p := models.RepPolicy{
		ID:      id,
		Enabled: enabled}
	_, err := o.Update(&p, "Enabled")

	return err
}

// EnableRepPolicy ...
func EnableRepPolicy(id int64) error {
	return UpdateRepPolicyEnablement(id, 1)
}

// DisableRepPolicy ...
func DisableRepPolicy(id int64) error {
	return UpdateRepPolicyEnablement(id, 0)
}

// AddRepJob ...
func AddRepJob(job models.RepJob) (int64, error) {
	o := GetOrmer()
	if len(job.Status) == 0 {
		job.Status = models.JobPending
	}
	if len(job.TagList) > 0 {
		job.Tags = strings.Join(job.TagList, ",")
	}
	return o.Insert(&job)
}

// GetRepJob ...
func GetRepJob(id int64) (*models.RepJob, error) {
	o := GetOrmer()
	j := models.RepJob{ID: id}
	err := o.Read(&j)
	if err == orm.ErrNoRows {
		return nil, nil
	}
	genTagListForJob(&j)
	return &j, nil
}

// GetRepJobByPolicy ...
func GetRepJobByPolicy(policyID int64) ([]*models.RepJob, error) {
	var res []*models.RepJob
	_, err := repJobPolicyIDQs(policyID).All(&res)
	genTagListForJob(res...)
	return res, err
}

// GetRepJobToStop get jobs that are possibly being handled by workers of a certain policy.
func GetRepJobToStop(policyID int64) ([]*models.RepJob, error) {
	var res []*models.RepJob
	_, err := repJobPolicyIDQs(policyID).Filter("status__in", models.JobPending, models.JobRunning).All(&res)
	genTagListForJob(res...)
	return res, err
}

func repJobPolicyIDQs(policyID int64) orm.QuerySeter {
	o := GetOrmer()
	return o.QueryTable("replication_job").Filter("policy_id", policyID)
}

// DeleteRepJob ...
func DeleteRepJob(id int64) error {
	o := GetOrmer()
	_, err := o.Delete(&models.RepJob{ID: id})
	return err
}

// UpdateRepJobStatus ...
func UpdateRepJobStatus(id int64, status string) error {
	o := GetOrmer()
	j := models.RepJob{
		ID:     id,
		Status: status,
	}
	num, err := o.Update(&j, "Status")
	if num == 0 {
		err = fmt.Errorf("Failed to update replication job with id: %d %s", id, err.Error())
	}
	return err
}

func genTagListForJob(jobs ...*models.RepJob) {
	for _, j := range jobs {
		if len(j.Tags) > 0 {
			j.TagList = strings.Split(j.Tags, ",")
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2016, RadiantBlue Technologies, Inc.
//
// 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 elasticsearch

import (
	"encoding/json"
	"errors"
	"fmt"
	"sort"
	"strconv"

	"github.com/venicegeo/pz-gocommon/gocommon"
)

const percolateTypeName = ".percolate"

type MockIndexType struct {
	// maps from id string to document body
	items map[string]*json.RawMessage

	mapping interface{}
}

type MockIndex struct {
	name     string
	types    map[string]*MockIndexType
	exists   bool
	open     bool
	settings interface{}
}

func NewMockIndex(indexName string) *MockIndex {
	var _ IIndex = new(MockIndex)

	esi := MockIndex{
		name:   indexName,
		types:  make(map[string]*MockIndexType),
		exists: false,
		open:   false,
	}
	return &esi
}

func (esi *MockIndex) GetVersion() string {
	return "2.2.0"
}

func (esi *MockIndex) IndexName() string {
	return esi.name
}

func (esi *MockIndex) IndexExists() (bool, error) {
	return esi.exists, nil
}

func (esi *MockIndex) TypeExists(typ string) (bool, error) {

	ok, err := esi.IndexExists()
	if err != nil {
		return false, err
	}
	if !ok {
		return false, nil
	}
	_, ok = esi.types[typ]
	return ok, nil
}

func (esi *MockIndex) ItemExists(typeName string, id string) (bool, error) {
	ok, err := esi.TypeExists(typeName)
	if err != nil {
		return false, err
	}
	if !ok {
		return false, nil
	}
	typ := esi.types[typeName]
	_, ok = (*typ).items[id]
	return ok, nil
}

// if index already exists, does nothing
func (esi *MockIndex) Create(settings string) error {
	if esi.exists {
		return fmt.Errorf("Index already exists")
	}

	esi.exists = true

	if settings == "" {
		esi.settings = nil
		return nil
	}

	obj := map[string]interface{}{}
	err := json.Unmarshal([]byte(settings), &obj)
	if err != nil {
		return err
	}

	esi.settings = obj

	for k, v := range obj["mappings"].(map[string]interface{}) {
		mapping, err := json.Marshal(v)
		if err != nil {
			return err
		}
		err = esi.addType(k, string(mapping))
		if err != nil {
			return err
		}
	}

	return nil
}

// if index doesn't already exist, does nothing
func (esi *MockIndex) Close() error {
	esi.open = false
	return nil
}

// if index doesn't already exist, does nothing
func (esi *MockIndex) Delete() error {
	esi.exists = false
	esi.open = false

	for tk, tv := range esi.types {
		for ik := range tv.items {
			delete(tv.items, ik)
		}
		delete(esi.types, tk)
	}

	return nil
}

func (esi *MockIndex) addType(typeName string, mapping string) error {

	if mapping == "" {
		return fmt.Errorf("addType: mapping may not be null")
	}

	obj := map[string]interface{}{}
	err := json.Unmarshal([]byte(mapping), &obj)
	if err != nil {
		return err
	}

	esi.types[typeName] = &MockIndexType{
		mapping: obj,
		items:   make(map[string]*json.RawMessage),
	}

	return nil
}

func (esi *MockIndex) SetMapping(typeName string, mapping piazza.JsonString) error {
	return esi.addType(typeName, string(mapping))
}

func (esi *MockIndex) PostData(typeName string, id string, obj interface{}) (*IndexResponse, error) {
	ok, err := esi.IndexExists()
	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, fmt.Errorf("Index does not exist")
	}
	ok, err = esi.TypeExists(typeName)
	if err != nil {
		return nil, err
	}

	var typ *MockIndexType
	if !ok {
		typ = &MockIndexType{}
		typ.items = make(map[string]*json.RawMessage)
		esi.types[typeName] = typ
	} else {
		typ = esi.types[typeName]
	}

	byts, err := json.Marshal(obj)
	if err != nil {
		return nil, err
	}

	var raw json.RawMessage
	err = raw.UnmarshalJSON(byts)
	if err != nil {
		return nil, err
	}
	typ.items[id] = &raw

	r := &IndexResponse{Created: true, ID: id, Index: esi.name, Type: typeName}
	return r, nil
}

//TODO
func (esi *MockIndex) PutData(typeName string, id string, obj interface{}) (*IndexResponse, error) {
	return esi.PostData(typeName, id, obj)
}

func (esi *MockIndex) GetByID(typeName string, id string) (*GetResult, error) {
	ok, err := esi.TypeExists(typeName)
	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, fmt.Errorf("GetById: type does not exist: %s", typeName)
	}
	ok, err = esi.ItemExists(typeName, id)
	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, fmt.Errorf("GetById: id does not exist: %s", id)
	}

	typ := esi.types[typeName]
	item := typ.items[id]
	r := &GetResult{ID: id, Source: item, Found: true}
	return r, nil
}

func (esi *MockIndex) DeleteByID(typeName string, id string) (*DeleteResponse, error) {
	ok, err := esi.TypeExists(typeName)
	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, fmt.Errorf("GetById: type does not exist: %s", typeName)
	}
	ok, err = esi.ItemExists(typeName, id)
	if err != nil {
		return nil, err
	}
	if !ok {
		return &DeleteResponse{Found: false}, err
	}

	typ := esi.types[typeName]
	delete(typ.items, id)
	r := &DeleteResponse{Found: true}
	return r, nil

}

type srhByID []*SearchResultHit

func (a srhByID) Len() int {
	return len(a)
}
func (a srhByID) Swap(i, j int) {
	a[i], a[j] = a[j], a[i]
}
func (a srhByID) Less(i, j int) bool {
	return (*a[i]).ID < (*a[j]).ID
}
func srhSortMatches(matches []*SearchResultHit) []*SearchResultHit {
	sort.Sort(srhByID(matches))
	return matches
}

func (esi *MockIndex) FilterByMatchAll(typeName string, realFormat *piazza.JsonPagination) (*SearchResult, error) {
	format := NewQueryFormat(realFormat)

	objs := make(map[string]*json.RawMessage)

	if typeName == "" {
		for tk, tv := range esi.types {
			if tk == percolateTypeName {
				continue
			}
			for ik, iv := range tv.items {
				objs[ik] = iv
			}
		}
	} else {
		for ik, iv := range esi.types[typeName].items {
			objs[ik] = iv
		}
	}

	resp := &SearchResult{
		totalHits: int64(len(objs)),
		hits:      make([]*SearchResultHit, len(objs)),
	}

	i := 0
	for id, obj := range objs {
		tmp := &SearchResultHit{
			ID:     id,
			Source: obj,
		}
		resp.hits[i] = tmp
		i++
	}

	// TODO; sort key not supported
	// TODO: sort order not supported

	from := format.From
	size := format.Size

	resp.hits = srhSortMatches(resp.hits)

	if from >= len(resp.hits) {
		resp.hits = make([]*SearchResultHit, 0)
	}
	if from+size >= len(resp.hits) {
		size = len(resp.hits)
	}
	resp.hits = resp.hits[from : from+size]

	return resp, nil
}

func (esi *MockIndex) GetAllElements(typ string) (*SearchResult, error) {
	return nil, errors.New("GetAllElements not supported under mocking")
}

func (esi *MockIndex) FilterByMatchQuery(typ string, name string, value interface{}, realFormat *piazza.JsonPagination) (*SearchResult, error) {

	return nil, errors.New("FilterByMatchQuery not supported under mocking")
}

func (esi *MockIndex) FilterByTermQuery(typeName string, name string, value interface{}, realFormat *piazza.JsonPagination) (*SearchResult, error) {

	objs := make(map[string]*json.RawMessage)

	for ik, iv := range esi.types[typeName].items {
		objs[ik] = iv
	}

	resp := &SearchResult{
		totalHits: int64(len(objs)),
		hits:      make([]*SearchResultHit, 0),
	}

	i := 0
	for id, obj := range objs {
		var iface interface{}
		err := json.Unmarshal(*obj, &iface)
		if err != nil {
			return nil, err
		}
		actualValue := iface.(map[string]interface{})[name].(string)
		if actualValue != value.(string) {
			continue
		}
		tmp := &SearchResultHit{
			ID:     id,
			Source: obj,
		}
		resp.hits = append(resp.hits, tmp)
		i++
	}

	if len(resp.hits) > 0 {
		resp.Found = true
	}

	resp.hits = srhSortMatches(resp.hits)

	return resp, nil
}

func (esi *MockIndex) SearchByJSON(typ string, jsn string) (*SearchResult, error) {

	/*var obj interface{}
	err := json.Unmarshal([]byte(jsn), &obj)
	if err != nil {
		return nil, err
	}

	searchResult, err := esi.lib.Search().
		Index(esi.index).
		Type(typ).
		Source(obj).Do()

	return searchResult, err*/

	////resp := &SearchResult{}
	////return resp, nil

	return nil, errors.New("SearchByJSON not supported under mocking")
}

func (esi *MockIndex) GetTypes() ([]string, error) {
	var s []string

	for k := range esi.types {
		s = append(s, k)
	}

	return s, nil
}

func (esi *MockIndex) GetMapping(typ string) (interface{}, error) {
	return nil, errors.New("GetMapping not supported under mocking")
}

func (esi *MockIndex) AddPercolationQuery(id string, query piazza.JsonString) (*IndexResponse, error) {
	return esi.PostData(percolateTypeName, id, query)
}

func (esi *MockIndex) DeletePercolationQuery(id string) (*DeleteResponse, error) {
	return esi.DeleteByID(percolateTypeName, id)
}

var percid int

func (esi *MockIndex) AddPercolationDocument(typeName string, doc interface{}) (*PercolateResponse, error) {

	_, err := esi.PostData(percolateTypeName, strconv.Itoa(percid), doc)
	if err != nil {
		return nil, err
	}

	resp := &PercolateResponse{}
	return resp, nil
}

func (esi *MockIndex) DirectAccess(verb string, endpoint string, input interface{}, output interface{}) error {
	return fmt.Errorf("DirectAccess not supported")
}
<commit_msg>Ha -- if we're gonna use a map, we'd better make durned sure we have unique keys<commit_after>// Copyright 2016, RadiantBlue Technologies, Inc.
//
// 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 elasticsearch

import (
	"encoding/json"
	"errors"
	"fmt"
	"sort"
	"strconv"

	"github.com/venicegeo/pz-gocommon/gocommon"
)

const percolateTypeName = ".percolate"

type MockIndexType struct {
	// maps from id string to document body
	items map[string]*json.RawMessage

	mapping interface{}
}

type MockIndex struct {
	name     string
	types    map[string]*MockIndexType
	exists   bool
	open     bool
	settings interface{}
	idSource int
}

func NewMockIndex(indexName string) *MockIndex {
	var _ IIndex = new(MockIndex)

	esi := MockIndex{
		name:   indexName,
		types:  make(map[string]*MockIndexType),
		exists: false,
		open:   false,
	}
	return &esi
}

func (esi *MockIndex) GetVersion() string {
	return "2.2.0"
}

func (esi *MockIndex) IndexName() string {
	return esi.name
}

func (esi *MockIndex) IndexExists() (bool, error) {
	return esi.exists, nil
}

func (esi *MockIndex) TypeExists(typ string) (bool, error) {

	ok, err := esi.IndexExists()
	if err != nil {
		return false, err
	}
	if !ok {
		return false, nil
	}
	_, ok = esi.types[typ]
	return ok, nil
}

func (esi *MockIndex) ItemExists(typeName string, id string) (bool, error) {
	ok, err := esi.TypeExists(typeName)
	if err != nil {
		return false, err
	}
	if !ok {
		return false, nil
	}
	typ := esi.types[typeName]
	_, ok = (*typ).items[id]
	return ok, nil
}

// if index already exists, does nothing
func (esi *MockIndex) Create(settings string) error {
	if esi.exists {
		return fmt.Errorf("Index already exists")
	}

	esi.exists = true

	if settings == "" {
		esi.settings = nil
		return nil
	}

	obj := map[string]interface{}{}
	err := json.Unmarshal([]byte(settings), &obj)
	if err != nil {
		return err
	}

	esi.settings = obj

	for k, v := range obj["mappings"].(map[string]interface{}) {
		mapping, err := json.Marshal(v)
		if err != nil {
			return err
		}
		err = esi.addType(k, string(mapping))
		if err != nil {
			return err
		}
	}

	return nil
}

// if index doesn't already exist, does nothing
func (esi *MockIndex) Close() error {
	esi.open = false
	return nil
}

// if index doesn't already exist, does nothing
func (esi *MockIndex) Delete() error {
	esi.exists = false
	esi.open = false

	for tk, tv := range esi.types {
		for ik := range tv.items {
			delete(tv.items, ik)
		}
		delete(esi.types, tk)
	}

	return nil
}

func (esi *MockIndex) addType(typeName string, mapping string) error {

	if mapping == "" {
		return fmt.Errorf("addType: mapping may not be null")
	}

	obj := map[string]interface{}{}
	err := json.Unmarshal([]byte(mapping), &obj)
	if err != nil {
		return err
	}

	esi.types[typeName] = &MockIndexType{
		mapping: obj,
		items:   make(map[string]*json.RawMessage),
	}

	return nil
}

func (esi *MockIndex) SetMapping(typeName string, mapping piazza.JsonString) error {
	return esi.addType(typeName, string(mapping))
}

func (esi *MockIndex) newId() string {
	esi.idSource++
	return strconv.Itoa(esi.idSource)
}

func (esi *MockIndex) PostData(typeName string, id string, obj interface{}) (*IndexResponse, error) {
	ok, err := esi.IndexExists()
	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, fmt.Errorf("Index does not exist")
	}
	ok, err = esi.TypeExists(typeName)
	if err != nil {
		return nil, err
	}

	var typ *MockIndexType
	if !ok {
		typ = &MockIndexType{}
		typ.items = make(map[string]*json.RawMessage)
		esi.types[typeName] = typ
	} else {
		typ = esi.types[typeName]
	}

	byts, err := json.Marshal(obj)
	if err != nil {
		return nil, err
	}

	var raw json.RawMessage
	err = raw.UnmarshalJSON(byts)
	if err != nil {
		return nil, err
	}

	if id == "" {
		id = esi.newId()
	}

	typ.items[id] = &raw

	r := &IndexResponse{Created: true, ID: id, Index: esi.name, Type: typeName}
	return r, nil
}

//TODO
func (esi *MockIndex) PutData(typeName string, id string, obj interface{}) (*IndexResponse, error) {
	return esi.PostData(typeName, id, obj)
}

func (esi *MockIndex) GetByID(typeName string, id string) (*GetResult, error) {
	ok, err := esi.TypeExists(typeName)
	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, fmt.Errorf("GetById: type does not exist: %s", typeName)
	}
	ok, err = esi.ItemExists(typeName, id)
	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, fmt.Errorf("GetById: id does not exist: %s", id)
	}

	typ := esi.types[typeName]
	item := typ.items[id]
	r := &GetResult{ID: id, Source: item, Found: true}
	return r, nil
}

func (esi *MockIndex) DeleteByID(typeName string, id string) (*DeleteResponse, error) {
	ok, err := esi.TypeExists(typeName)
	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, fmt.Errorf("GetById: type does not exist: %s", typeName)
	}
	ok, err = esi.ItemExists(typeName, id)
	if err != nil {
		return nil, err
	}
	if !ok {
		return &DeleteResponse{Found: false}, err
	}

	typ := esi.types[typeName]
	delete(typ.items, id)
	r := &DeleteResponse{Found: true}
	return r, nil

}

type srhByID []*SearchResultHit

func (a srhByID) Len() int {
	return len(a)
}
func (a srhByID) Swap(i, j int) {
	a[i], a[j] = a[j], a[i]
}
func (a srhByID) Less(i, j int) bool {
	return (*a[i]).ID < (*a[j]).ID
}
func srhSortMatches(matches []*SearchResultHit) []*SearchResultHit {
	sort.Sort(srhByID(matches))
	return matches
}

func (esi *MockIndex) FilterByMatchAll(typeName string, realFormat *piazza.JsonPagination) (*SearchResult, error) {
	format := NewQueryFormat(realFormat)

	objs := make(map[string]*json.RawMessage)

	if typeName == "" {
		for tk, tv := range esi.types {
			if tk == percolateTypeName {
				continue
			}
			for ik, iv := range tv.items {
				objs[ik] = iv
			}
		}
	} else {
		for ik, iv := range esi.types[typeName].items {
			objs[ik] = iv
		}
	}

	resp := &SearchResult{
		totalHits: int64(len(objs)),
		hits:      make([]*SearchResultHit, len(objs)),
	}

	i := 0
	for id, obj := range objs {
		tmp := &SearchResultHit{
			ID:     id,
			Source: obj,
		}
		resp.hits[i] = tmp
		i++
	}

	// TODO; sort key not supported
	// TODO: sort order not supported

	from := format.From
	size := format.Size

	resp.hits = srhSortMatches(resp.hits)

	if from >= len(resp.hits) {
		resp.hits = make([]*SearchResultHit, 0)
	}
	if from+size >= len(resp.hits) {
		size = len(resp.hits)
	}
	resp.hits = resp.hits[from : from+size]

	return resp, nil
}

func (esi *MockIndex) GetAllElements(typ string) (*SearchResult, error) {
	return nil, errors.New("GetAllElements not supported under mocking")
}

func (esi *MockIndex) FilterByMatchQuery(typ string, name string, value interface{}, realFormat *piazza.JsonPagination) (*SearchResult, error) {

	return nil, errors.New("FilterByMatchQuery not supported under mocking")
}

func (esi *MockIndex) FilterByTermQuery(typeName string, name string, value interface{}, realFormat *piazza.JsonPagination) (*SearchResult, error) {

	objs := make(map[string]*json.RawMessage)

	for ik, iv := range esi.types[typeName].items {
		objs[ik] = iv
	}

	resp := &SearchResult{
		totalHits: int64(len(objs)),
		hits:      make([]*SearchResultHit, 0),
	}

	i := 0
	for id, obj := range objs {
		var iface interface{}
		err := json.Unmarshal(*obj, &iface)
		if err != nil {
			return nil, err
		}
		actualValue := iface.(map[string]interface{})[name].(string)
		if actualValue != value.(string) {
			continue
		}
		tmp := &SearchResultHit{
			ID:     id,
			Source: obj,
		}
		resp.hits = append(resp.hits, tmp)
		i++
	}

	if len(resp.hits) > 0 {
		resp.Found = true
	}

	resp.hits = srhSortMatches(resp.hits)

	return resp, nil
}

func (esi *MockIndex) SearchByJSON(typ string, jsn string) (*SearchResult, error) {

	/*var obj interface{}
	err := json.Unmarshal([]byte(jsn), &obj)
	if err != nil {
		return nil, err
	}

	searchResult, err := esi.lib.Search().
		Index(esi.index).
		Type(typ).
		Source(obj).Do()

	return searchResult, err*/

	////resp := &SearchResult{}
	////return resp, nil

	return nil, errors.New("SearchByJSON not supported under mocking")
}

func (esi *MockIndex) GetTypes() ([]string, error) {
	var s []string

	for k := range esi.types {
		s = append(s, k)
	}

	return s, nil
}

func (esi *MockIndex) GetMapping(typ string) (interface{}, error) {
	return nil, errors.New("GetMapping not supported under mocking")
}

func (esi *MockIndex) AddPercolationQuery(id string, query piazza.JsonString) (*IndexResponse, error) {
	return esi.PostData(percolateTypeName, id, query)
}

func (esi *MockIndex) DeletePercolationQuery(id string) (*DeleteResponse, error) {
	return esi.DeleteByID(percolateTypeName, id)
}

var percid int

func (esi *MockIndex) AddPercolationDocument(typeName string, doc interface{}) (*PercolateResponse, error) {

	_, err := esi.PostData(percolateTypeName, strconv.Itoa(percid), doc)
	if err != nil {
		return nil, err
	}

	resp := &PercolateResponse{}
	return resp, nil
}

func (esi *MockIndex) DirectAccess(verb string, endpoint string, input interface{}, output interface{}) error {
	return fmt.Errorf("DirectAccess not supported")
}
<|endoftext|>


<commit_before>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package migration

import (
	"io"
	"io/ioutil"
	"net/url"
	"os"

	"github.com/juju/errors"
	"github.com/juju/loggo"
	"github.com/juju/version"
	"gopkg.in/juju/charm.v6-unstable"

	"github.com/juju/juju/core/description"
	"github.com/juju/juju/state"
	"github.com/juju/juju/tools"
)

var logger = loggo.GetLogger("juju.migration")

// StateExporter describes interface on state required to export a
// model.
type StateExporter interface {
	// Export generates an abstract representation of a model.
	Export() (description.Model, error)
}

// ExportModel creates a description.Model representation of the
// active model for StateExporter (typically a *state.State), and
// returns the serialized version. It provides the symmetric
// functionality to ImportModel.
func ExportModel(st StateExporter) ([]byte, error) {
	model, err := st.Export()
	if err != nil {
		return nil, errors.Trace(err)
	}
	bytes, err := description.Serialize(model)
	if err != nil {
		return nil, errors.Trace(err)
	}
	return bytes, nil
}

// ImportModel deserializes a model description from the bytes, transforms
// the model config based on information from the controller model, and then
// imports that as a new database model.
func ImportModel(st *state.State, bytes []byte) (*state.Model, *state.State, error) {
	model, err := description.Deserialize(bytes)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	dbModel, dbState, err := st.Import(model)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	return dbModel, dbState, nil
}

// CharmDownlaoder defines a single method that is used to download a
// charm from the source controller in a migration.
type CharmDownloader interface {
	OpenCharm(*charm.URL) (io.ReadCloser, error)
}

// CharmUploader defines a single method that is used to upload a
// charm to the target controller in a migration.
type CharmUploader interface {
	UploadCharm(*charm.URL, io.ReadSeeker) (*charm.URL, error)
}

// ToolsDownloader defines a single method that is used to download
// tools from the source controller in a migration.
type ToolsDownloader interface {
	OpenURI(string, url.Values) (io.ReadCloser, error)
}

// ToolsUploader defines a single method that is used to upload tools
// to the target controller in a migration.
type ToolsUploader interface {
	UploadTools(io.ReadSeeker, version.Binary, ...string) (tools.List, error)
}

// UploadBinariesConfig provides all the configuration that the
// UploadBinaries function needs to operate. To construct the config
// with the default helper functions, use `NewUploadBinariesConfig`.
type UploadBinariesConfig struct {
	Charms          []string
	CharmDownloader CharmDownloader
	CharmUploader   CharmUploader

	Tools           map[version.Binary]string
	ToolsDownloader ToolsDownloader
	ToolsUploader   ToolsUploader
}

// Validate makes sure that all the config values are non-nil.
func (c *UploadBinariesConfig) Validate() error {
	if c.CharmDownloader == nil {
		return errors.NotValidf("missing CharmDownloader")
	}
	if c.CharmUploader == nil {
		return errors.NotValidf("missing CharmUploader")
	}
	if c.ToolsDownloader == nil {
		return errors.NotValidf("missing ToolsDownloader")
	}
	if c.ToolsUploader == nil {
		return errors.NotValidf("missing ToolsUploader")
	}
	return nil
}

// UploadBinaries will send binaries stored in the source blobstore to
// the target controller.
func UploadBinaries(config UploadBinariesConfig) error {
	if err := config.Validate(); err != nil {
		return errors.Trace(err)
	}
	if err := uploadCharms(config); err != nil {
		return errors.Trace(err)
	}
	if err := uploadTools(config); err != nil {
		return errors.Trace(err)
	}
	return nil
}

func streamThroughTempFile(r io.Reader) (_ io.ReadSeeker, cleanup func(), err error) {
	tempFile, err := ioutil.TempFile("", "juju-migrate-binary")
	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	defer func() {
		if err != nil {
			os.Remove(tempFile.Name())
		}
	}()
	_, err = io.Copy(tempFile, r)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	tempFile.Seek(0, 0)
	rmTempFile := func() {
		filename := tempFile.Name()
		tempFile.Close()
		os.Remove(filename)
	}

	return tempFile, rmTempFile, nil
}

func uploadCharms(config UploadBinariesConfig) error {
	for _, charmURL := range config.Charms {
		logger.Debugf("sending charm %s to target", charmURL)

		curl, err := charm.ParseURL(charmURL)
		if err != nil {
			return errors.Annotate(err, "bad charm URL")
		}

		reader, err := config.CharmDownloader.OpenCharm(curl)
		if err != nil {
			return errors.Annotate(err, "cannot open charm")
		}
		defer reader.Close()

		content, cleanup, err := streamThroughTempFile(reader)
		if err != nil {
			return errors.Trace(err)
		}
		defer cleanup()

		if _, err := config.CharmUploader.UploadCharm(curl, content); err != nil {
			return errors.Annotate(err, "cannot upload charm")
		}
	}
	return nil
}

func uploadTools(config UploadBinariesConfig) error {
	for v, uri := range config.Tools {
		logger.Debugf("sending tools to target: %s", v)

		reader, err := config.ToolsDownloader.OpenURI(uri, nil)
		if err != nil {
			return errors.Annotate(err, "cannot open charm")
		}
		defer reader.Close()

		content, cleanup, err := streamThroughTempFile(reader)
		if err != nil {
			return errors.Trace(err)
		}
		defer cleanup()

		if _, err := config.ToolsUploader.UploadTools(content, v); err != nil {
			return errors.Annotate(err, "cannot upload tools")
		}
	}
	return nil
}
<commit_msg>Rough addition of resource download support to UploadBinaries<commit_after>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package migration

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/url"
	"os"

	"github.com/juju/errors"
	"github.com/juju/loggo"
	"github.com/juju/version"
	"gopkg.in/juju/charm.v6-unstable"

	"github.com/juju/juju/core/description"
	"github.com/juju/juju/state"
	"github.com/juju/juju/tools"
)

var logger = loggo.GetLogger("juju.migration")

// StateExporter describes interface on state required to export a
// model.
type StateExporter interface {
	// Export generates an abstract representation of a model.
	Export() (description.Model, error)
}

// ExportModel creates a description.Model representation of the
// active model for StateExporter (typically a *state.State), and
// returns the serialized version. It provides the symmetric
// functionality to ImportModel.
func ExportModel(st StateExporter) ([]byte, error) {
	model, err := st.Export()
	if err != nil {
		return nil, errors.Trace(err)
	}
	bytes, err := description.Serialize(model)
	if err != nil {
		return nil, errors.Trace(err)
	}
	return bytes, nil
}

// ImportModel deserializes a model description from the bytes, transforms
// the model config based on information from the controller model, and then
// imports that as a new database model.
func ImportModel(st *state.State, bytes []byte) (*state.Model, *state.State, error) {
	model, err := description.Deserialize(bytes)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	dbModel, dbState, err := st.Import(model)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	return dbModel, dbState, nil
}

// CharmDownlaoder defines a single method that is used to download a
// charm from the source controller in a migration.
type CharmDownloader interface {
	OpenCharm(*charm.URL) (io.ReadCloser, error)
}

// CharmUploader defines a single method that is used to upload a
// charm to the target controller in a migration.
type CharmUploader interface {
	UploadCharm(*charm.URL, io.ReadSeeker) (*charm.URL, error)
}

// ToolsDownloader defines a single method that is used to download
// tools from the source controller in a migration.
type ToolsDownloader interface {
	OpenURI(string, url.Values) (io.ReadCloser, error)
}

// ToolsUploader defines a single method that is used to upload tools
// to the target controller in a migration.
type ToolsUploader interface {
	UploadTools(io.ReadSeeker, version.Binary, ...string) (tools.List, error)
}

// XXX
type ResourceDownloader interface {
	OpenResource(string, string) (io.ReadCloser, error)
}

// UploadBinariesConfig provides all the configuration that the
// UploadBinaries function needs to operate. To construct the config
// with the default helper functions, use `NewUploadBinariesConfig`.
type UploadBinariesConfig struct {
	Charms          []string
	CharmDownloader CharmDownloader
	CharmUploader   CharmUploader

	Tools           map[version.Binary]string
	ToolsDownloader ToolsDownloader
	ToolsUploader   ToolsUploader

	Resources          map[string]string
	ResourceDownloader ResourceDownloader
}

// Validate makes sure that all the config values are non-nil.
func (c *UploadBinariesConfig) Validate() error {
	if c.CharmDownloader == nil {
		return errors.NotValidf("missing CharmDownloader")
	}
	if c.CharmUploader == nil {
		return errors.NotValidf("missing CharmUploader")
	}
	if c.ToolsDownloader == nil {
		return errors.NotValidf("missing ToolsDownloader")
	}
	if c.ToolsUploader == nil {
		return errors.NotValidf("missing ToolsUploader")
	}
	// XXX validate ResourceDownloader
	return nil
}

// UploadBinaries will send binaries stored in the source blobstore to
// the target controller.
func UploadBinaries(config UploadBinariesConfig) error {
	if err := config.Validate(); err != nil {
		return errors.Trace(err)
	}
	if err := uploadCharms(config); err != nil {
		return errors.Trace(err)
	}
	if err := uploadTools(config); err != nil {
		return errors.Trace(err)
	}
	if err := uploadResources(config); err != nil {
		return errors.Trace(err)
	}
	return nil
}

func streamThroughTempFile(r io.Reader) (_ io.ReadSeeker, cleanup func(), err error) {
	tempFile, err := ioutil.TempFile("", "juju-migrate-binary")
	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	defer func() {
		if err != nil {
			os.Remove(tempFile.Name())
		}
	}()
	_, err = io.Copy(tempFile, r)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	tempFile.Seek(0, 0)
	rmTempFile := func() {
		filename := tempFile.Name()
		tempFile.Close()
		os.Remove(filename)
	}

	return tempFile, rmTempFile, nil
}

func uploadCharms(config UploadBinariesConfig) error {
	for _, charmURL := range config.Charms {
		logger.Debugf("sending charm %s to target", charmURL)

		curl, err := charm.ParseURL(charmURL)
		if err != nil {
			return errors.Annotate(err, "bad charm URL")
		}

		reader, err := config.CharmDownloader.OpenCharm(curl)
		if err != nil {
			return errors.Annotate(err, "cannot open charm")
		}
		defer reader.Close()

		content, cleanup, err := streamThroughTempFile(reader)
		if err != nil {
			return errors.Trace(err)
		}
		defer cleanup()

		if _, err := config.CharmUploader.UploadCharm(curl, content); err != nil {
			return errors.Annotate(err, "cannot upload charm")
		}
	}
	return nil
}

func uploadTools(config UploadBinariesConfig) error {
	for v, uri := range config.Tools {
		logger.Debugf("sending tools to target: %s", v)

		reader, err := config.ToolsDownloader.OpenURI(uri, nil)
		if err != nil {
			return errors.Annotate(err, "cannot open charm")
		}
		defer reader.Close()

		content, cleanup, err := streamThroughTempFile(reader)
		if err != nil {
			return errors.Trace(err)
		}
		defer cleanup()

		if _, err := config.ToolsUploader.UploadTools(content, v); err != nil {
			return errors.Annotate(err, "cannot upload tools")
		}
	}
	return nil
}

func uploadResources(config UploadBinariesConfig) error {
	// XXX unfinished
	for application, name := range config.Resources {
		logger.Debugf("opening resource for %s: %s", application, name)
		reader, err := config.ResourceDownloader.OpenResource(application, name)
		if err != nil {
			return errors.Annotate(err, "cannot open resource")
		}
		defer reader.Close()

		// XXX temporary
		if err := writeResource(application, name, reader); err != nil {
			return err
		}
	}
	return nil
}

func writeResource(application, name string, r io.Reader) error {
	f, err := os.Create(fmt.Sprintf("/var/tmp/%s-%s.resource", application, name))
	if err != nil {
		return err
	}
	defer f.Close()
	_, err = io.Copy(f, r)
	return err
}
<|endoftext|>


<commit_before>package node

import (
	"fmt"
	"net/http"

	"github.com/anycable/anycable-go/utils"
	"github.com/apex/log"
	"github.com/gorilla/websocket"
)

// WSConfig contains WebSocket connection configuration.
type WSConfig struct {
	ReadBufferSize    int
	WriteBufferSize   int
	MaxMessageSize    int64
	EnableCompression bool
}

// NewWSConfig build a new WSConfig struct
func NewWSConfig() WSConfig {
	return WSConfig{}
}

// WebsocketHandler generate a new http handler for WebSocket connections
func WebsocketHandler(app *Node, fetchHeaders []string, config *WSConfig) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx := log.WithField("context", "ws")

		upgrader := websocket.Upgrader{
			CheckOrigin:       func(r *http.Request) bool { return true },
			Subprotocols:      []string{"actioncable-v1-json"},
			ReadBufferSize:    config.ReadBufferSize,
			WriteBufferSize:   config.WriteBufferSize,
			EnableCompression: config.EnableCompression,
		}

		ws, err := upgrader.Upgrade(w, r, nil)
		if err != nil {
			ctx.Debugf("Websocket connection upgrade error: %#v", err.Error())
			return
		}

		url := r.URL.String()

		if !r.URL.IsAbs() {
			// See https://github.com/golang/go/issues/28940#issuecomment-441749380
			scheme := "http://"
			if r.TLS != nil {
				scheme = "https://"
			}
			url = fmt.Sprintf("%s%s%s", scheme, r.Host, url)
		}

		headers := utils.FetchHeaders(r, fetchHeaders)

		uid, err := utils.FetchUID(r)
		if err != nil {
			utils.CloseWS(ws, websocket.CloseAbnormalClosure, "UID Retrieval Error")
			return
		}

		ws.SetReadLimit(config.MaxMessageSize)

		if config.EnableCompression {
			ws.EnableWriteCompression(true)
		}

		// Separate goroutine for better GC of caller's data.
		go func() {
			session, err := NewSession(app, ws, url, headers, uid)

			if err != nil {
				ctx.Errorf("Websocket session initialization failed: %v", err)
				return
			}

			session.Log.Debug("websocket session established")

			session.ReadMessages()

			session.Log.Debug("websocket session completed")
		}()
	})
}
<commit_msg>feat: add X-AnyCable-Version header<commit_after>package node

import (
	"fmt"
	"net/http"

	"github.com/anycable/anycable-go/utils"
	"github.com/apex/log"
	"github.com/gorilla/websocket"
)

// WSConfig contains WebSocket connection configuration.
type WSConfig struct {
	ReadBufferSize    int
	WriteBufferSize   int
	MaxMessageSize    int64
	EnableCompression bool
}

// NewWSConfig build a new WSConfig struct
func NewWSConfig() WSConfig {
	return WSConfig{}
}

// WebsocketHandler generate a new http handler for WebSocket connections
func WebsocketHandler(app *Node, fetchHeaders []string, config *WSConfig) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx := log.WithField("context", "ws")

		upgrader := websocket.Upgrader{
			CheckOrigin:       func(r *http.Request) bool { return true },
			Subprotocols:      []string{"actioncable-v1-json"},
			ReadBufferSize:    config.ReadBufferSize,
			WriteBufferSize:   config.WriteBufferSize,
			EnableCompression: config.EnableCompression,
		}

		rheader := map[string][]string{"X-AnyCable-Version": {utils.Version()}}
		ws, err := upgrader.Upgrade(w, r, rheader)
		if err != nil {
			ctx.Debugf("Websocket connection upgrade error: %#v", err.Error())
			return
		}

		url := r.URL.String()

		if !r.URL.IsAbs() {
			// See https://github.com/golang/go/issues/28940#issuecomment-441749380
			scheme := "http://"
			if r.TLS != nil {
				scheme = "https://"
			}
			url = fmt.Sprintf("%s%s%s", scheme, r.Host, url)
		}

		headers := utils.FetchHeaders(r, fetchHeaders)

		uid, err := utils.FetchUID(r)
		if err != nil {
			utils.CloseWS(ws, websocket.CloseAbnormalClosure, "UID Retrieval Error")
			return
		}

		ws.SetReadLimit(config.MaxMessageSize)

		if config.EnableCompression {
			ws.EnableWriteCompression(true)
		}

		// Separate goroutine for better GC of caller's data.
		go func() {
			session, err := NewSession(app, ws, url, headers, uid)

			if err != nil {
				ctx.Errorf("Websocket session initialization failed: %v", err)
				return
			}

			session.Log.Debug("websocket session established")

			session.ReadMessages()

			session.Log.Debug("websocket session completed")
		}()
	})
}
<|endoftext|>


<commit_before>package sudoku

type Solver struct {
	input   *Puzzle
	current *Puzzle
	results []Puzzle
	checker *Checker
}

// constructor
func NewSolver() *Solver {
	return &Solver{}
}

// methods
func (solver *Solver) Solve(p *Puzzle) []Puzzle {
	solver.input = p
	solver.checker = NewChecker()
	solver.current = NewPuzzle(p.ToString())
	solver.results = make([]Puzzle, 0) // slice with new underlying array
	solver.backtrack(0, 0)
	return solver.results
}

func (solver *Solver) backtrack(r, c int) bool {
	if r*Size+c == Cells {
		solution := CopyPuzzle(solver.current)
		solver.results = append(solver.results, *solution)
		return true
	}
	if c == Size {
		return solver.backtrack(r+1, 0)
	}
	if solver.current.Get(r, c) != 0 {
		return solver.backtrack(r, c+1)
	}

	for v := 1; v <= 9; v++ { // try each value
		solver.current.Set(r, c, v)
		if solver.checker.Check(solver.current) {
			solver.backtrack(r, c+1)
		}
		solver.current.Set(r, c, 0) // backtraking
	}
	return false
}
<commit_msg>add comments for solver<commit_after>package sudoku

import "math"

type Solver struct {
	input   *Puzzle
	current *Puzzle
	results []Puzzle
	expects int // max solutions expect to solve
	checker *Checker
}

// constructor
func NewSolver() *Solver {
	return &Solver{}
}

// methods
func (solver *Solver) SolveSome(p *Puzzle, expects int) []Puzzle {
	solver.input = p
	solver.expects = expects
	solver.checker = NewChecker()
	solver.current = CopyPuzzle(p) // new puzzle for solver
	solver.results = make([]Puzzle, 0) // slice with new underlying array
	solver.backtrack(0, 0)
	return solver.results
}

func (solver *Solver) Solve(p *Puzzle) []Puzzle {
	return solver.SolveSome(p, math.MaxInt32)
}

func (solver *Solver) backtrack(r, c int) bool {
	if r*Size + c == Cells { // the last cell.
		solution := CopyPuzzle(solver.current)
		solver.results = append(solver.results, *solution)
		return true
	}
	if c == Size { // current row complete, move to next row.
		return solver.backtrack(r+1, 0)
	}

	if solver.current.Get(r, c) != 0 { // skip the given cell.
		return solver.backtrack(r, c+1)
	}

	for v := 1; v <= 9; v++ { // try each value
		solver.current.Set(r, c, v)
		if solver.checker.Check(solver.current) {
			if solver.backtrack(r, c+1) && len(solver.results) >= solver.expects { // valid, go deep!
				return true // stop search more!
			}
		}
		solver.current.Set(r, c, 0) // backtraking
	}
	return false // no solution
}
<|endoftext|>


<commit_before>package preference

import (
	"fmt"

	"strings"

	"github.com/rancher/norman/httperror"
	"github.com/rancher/norman/store/transform"
	"github.com/rancher/norman/types"
	"github.com/rancher/norman/types/convert"
	"github.com/rancher/types/apis/core/v1"
	"github.com/rancher/types/client/management/v3"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
	NamespaceID = client.PreferenceFieldNamespaceId
)

type Store struct {
	Store    types.Store
	nsClient v1.NamespaceInterface
}

func NewStore(nsClient v1.NamespaceInterface, store types.Store) *Store {
	return &Store{
		Store: &transform.Store{
			Store:       store,
			Transformer: transformer,
		},
		nsClient: nsClient,
	}
}

func (s *Store) ByID(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) {
	user, err := getUser(apiContext)
	if err != nil {
		return nil, err
	}

	return s.Store.ByID(apiContext, schema, addNamespace(user, id))
}

func (s *Store) List(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) ([]map[string]interface{}, error) {
	user, err := getUser(apiContext)
	if err != nil {
		return nil, err
	}

	if opt == nil {
		return nil, nil
	}

	opt.Conditions = append(opt.Conditions, types.EQ(NamespaceID, getNamespace(user)))
	return s.Store.List(apiContext, schema, opt)
}

func (s *Store) Create(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) (map[string]interface{}, error) {
	user, err := getUser(apiContext)
	if err != nil || data == nil {
		return nil, err
	}

	ns := getNamespace(user)
	_, err = s.nsClient.Get(ns, metav1.GetOptions{})
	if err != nil {
		s.nsClient.Create(&corev1.Namespace{
			ObjectMeta: metav1.ObjectMeta{
				Name: ns,
			},
		})
	}

	data[NamespaceID] = getNamespace(user)
	return s.Store.Create(apiContext, schema, data)
}

func (s *Store) Update(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}, id string) (map[string]interface{}, error) {
	user, err := getUser(apiContext)
	if err != nil {
		return nil, err
	}

	return s.Store.Update(apiContext, schema, data, addNamespace(user, id))
}

func (s *Store) Delete(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) {
	user, err := getUser(apiContext)
	if err != nil {
		return nil, err
	}

	return s.Store.Delete(apiContext, schema, addNamespace(user, id))
}

func (s *Store) Watch(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) (chan map[string]interface{}, error) {
	return nil, nil
}

func getUser(apiContext *types.APIContext) (string, error) {
	user := apiContext.Request.Header.Get("Impersonate-User")
	if user == "" {
		return "", httperror.NewAPIError(httperror.NotFound, "missing user")
	}
	return user, nil
}

func addNamespace(user, id string) string {
	parts := strings.SplitN(id, ":", 2)
	if len(parts) == 1 {
		return fmt.Sprintf("%s:%s", getNamespace(user), parts[0])
	}
	return fmt.Sprintf("%s:%s", getNamespace(user), parts[1])
}

func getNamespace(user string) string {
	return fmt.Sprintf("user-%s", user)
}

func transformer(apiContext *types.APIContext, data map[string]interface{}) (map[string]interface{}, error) {
	if data == nil {
		return nil, nil
	}

	ns := convert.ToString(data[NamespaceID])
	id := convert.ToString(data[types.ResourceFieldID])

	id = strings.TrimPrefix(id, ns+":")

	data[client.PreferenceFieldName] = id
	data[types.ResourceFieldID] = id

	return data, nil
}
<commit_msg>Hide user namespaces<commit_after>package preference

import (
	"fmt"

	"strings"

	"github.com/rancher/norman/httperror"
	"github.com/rancher/norman/store/transform"
	"github.com/rancher/norman/types"
	"github.com/rancher/norman/types/convert"
	"github.com/rancher/types/apis/core/v1"
	"github.com/rancher/types/client/management/v3"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
	NamespaceID = client.PreferenceFieldNamespaceId
)

type Store struct {
	Store    types.Store
	nsClient v1.NamespaceInterface
}

func NewStore(nsClient v1.NamespaceInterface, store types.Store) *Store {
	return &Store{
		Store: &transform.Store{
			Store:       store,
			Transformer: transformer,
		},
		nsClient: nsClient,
	}
}

func (s *Store) ByID(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) {
	user, err := getUser(apiContext)
	if err != nil {
		return nil, err
	}

	return s.Store.ByID(apiContext, schema, addNamespace(user, id))
}

func (s *Store) List(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) ([]map[string]interface{}, error) {
	user, err := getUser(apiContext)
	if err != nil {
		return nil, err
	}

	if opt == nil {
		return nil, nil
	}

	opt.Conditions = append(opt.Conditions, types.EQ(NamespaceID, getNamespace(user)))
	return s.Store.List(apiContext, schema, opt)
}

func (s *Store) Create(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) (map[string]interface{}, error) {
	user, err := getUser(apiContext)
	if err != nil || data == nil {
		return nil, err
	}

	ns := getNamespace(user)
	_, err = s.nsClient.Get(ns, metav1.GetOptions{})
	if err != nil {
		s.nsClient.Create(&corev1.Namespace{
			ObjectMeta: metav1.ObjectMeta{
				Annotations: map[string]string{
					"management.cattle.io/system-namespace": "true",
				},
				Name: ns,
			},
		})
	}

	data[NamespaceID] = getNamespace(user)
	return s.Store.Create(apiContext, schema, data)
}

func (s *Store) Update(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}, id string) (map[string]interface{}, error) {
	user, err := getUser(apiContext)
	if err != nil {
		return nil, err
	}

	return s.Store.Update(apiContext, schema, data, addNamespace(user, id))
}

func (s *Store) Delete(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) {
	user, err := getUser(apiContext)
	if err != nil {
		return nil, err
	}

	return s.Store.Delete(apiContext, schema, addNamespace(user, id))
}

func (s *Store) Watch(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) (chan map[string]interface{}, error) {
	return nil, nil
}

func getUser(apiContext *types.APIContext) (string, error) {
	user := apiContext.Request.Header.Get("Impersonate-User")
	if user == "" {
		return "", httperror.NewAPIError(httperror.NotFound, "missing user")
	}
	return user, nil
}

func addNamespace(user, id string) string {
	parts := strings.SplitN(id, ":", 2)
	if len(parts) == 1 {
		return fmt.Sprintf("%s:%s", getNamespace(user), parts[0])
	}
	return fmt.Sprintf("%s:%s", getNamespace(user), parts[1])
}

func getNamespace(user string) string {
	return fmt.Sprintf("user-%s", user)
}

func transformer(apiContext *types.APIContext, data map[string]interface{}) (map[string]interface{}, error) {
	if data == nil {
		return nil, nil
	}

	ns := convert.ToString(data[NamespaceID])
	id := convert.ToString(data[types.ResourceFieldID])

	id = strings.TrimPrefix(id, ns+":")

	data[client.PreferenceFieldName] = id
	data[types.ResourceFieldID] = id

	return data, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2018 Google LLC.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
	"encoding/json"

	build "github.com/google/elafros/pkg/apis/cloudbuild/v1alpha1"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// Configuration
type Configuration struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   ConfigurationSpec   `json:"spec,omitempty"`
	Status ConfigurationStatus `json:"status,omitempty"`
}

// ConfigurationSpec defines the desired state of Configuration
type ConfigurationSpec struct {
	// TODO: Generation does not work correctly with CRD. They are scrubbed
	// by the APIserver (https://github.com/kubernetes/kubernetes/issues/58778)
	// So, we add Generation here. Once that gets fixed, remove this and use
	// ObjectMeta.Generation instead.
	Generation int64            `json:"generation,omitempty"`
	Build      *build.BuildSpec `json:"build,omitempty"`
	Template   Revision         `json:"template"`
}

// ConfigurationConditionType represents a Configuration condition value
type ConfigurationConditionType string

const (
	// RevisionConditionReady is set when the configuration is starting to materialize
	// runtime resources, and becomes true when those resources are ready.
	ConfigurationConditionReady ConfigurationConditionType = "Ready"
)

// ConfigurationCondition defines a readiness condition for a Configuration.
// See: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#typical-status-properties
type ConfigurationCondition struct {
	Type ConfigurationConditionType `json:"type" description:"type of Configuration condition"`

	Status corev1.ConditionStatus `json:"status" description:"status of the condition, one of True, False, Unknown"`

	// +optional
	Reason string `json:"reason,omitempty" description:"one-word CamelCase reason for the condition's last transition"`

	// +optional
	Message string `json:"message,omitempty" description:"human-readable message indicating details about last transition"`
}

// ConfigurationStatus defines the observed state of Configuration
type ConfigurationStatus struct {
	Conditions []ConfigurationCondition `json:"conditions,omitempty"`

	// Latest revision that is ready.
	LatestReady string `json:"latestReady,omitempty"`

	// LatestCreated is the last revision that has been created, it might not be
	// ready yet however. Hence we just keep track of it so that when it's ready
	// it will get moved to Latest.
	LatestCreated string `json:"latestCreated,omitempty"`

	// ReconciledGeneration is the 'Generation' of the Configuration that
	// was last processed by the controller. The reconciled generation is updated
	// even if the controller failed to process the spec and create the Revision.
	ReconciledGeneration int64 `json:"reconciledGeneration,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// ConfigurationList is a list of Configuration resources
type ConfigurationList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`

	Items []Configuration `json:"items"`
}

func (r *Configuration) GetGeneration() int64 {
	return r.Spec.Generation
}

func (r *Configuration) SetGeneration(generation int64) {
	r.Spec.Generation = generation
}

func (r *Configuration) GetSpecJSON() ([]byte, error) {
	return json.Marshal(r.Spec)
}

// IsReady looks at the conditions and if the Status has a condition
// ConfigurationConditionReady returns true if ConditionStatus is True
func (configStatus *ConfigurationStatus) IsReady() bool {
	if c := configStatus.GetCondition(ConfigurationConditionReady); c != nil {
		return c.Status == corev1.ConditionTrue
	}
	return false
}

func (config *ConfigurationStatus) GetCondition(t ConfigurationConditionType) *ConfigurationCondition {
	for _, cond := range config.Conditions {
		if cond.Type == t {
			return &cond
		}
	}
	return nil
}

func (configStatus *ConfigurationStatus) SetCondition(new *ConfigurationCondition) {
	if new == nil {
		return
	}

	t := new.Type
	var conditions []ConfigurationCondition
	for _, cond := range configStatus.Conditions {
		if cond.Type != t {
			conditions = append(conditions, cond)
		}
	}
	conditions = append(conditions, *new)
	configStatus.Conditions = conditions
}

func (configStatus *ConfigurationStatus) RemoveCondition(t ConfigurationConditionType) {
	var conditions []ConfigurationCondition
	for _, cond := range configStatus.Conditions {
		if cond.Type != t {
			conditions = append(conditions, cond)
		}
	}
	configStatus.Conditions = conditions
}
<commit_msg>Polish docstrings in configuration_types.go (#245)<commit_after>/*
Copyright 2018 Google LLC.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
	"encoding/json"

	build "github.com/google/elafros/pkg/apis/cloudbuild/v1alpha1"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// Configuration
type Configuration struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   ConfigurationSpec   `json:"spec,omitempty"`
	Status ConfigurationStatus `json:"status,omitempty"`
}

// ConfigurationSpec defines the desired state of Configuration
type ConfigurationSpec struct {
	// TODO: Generation does not work correctly with CRD. They are scrubbed
	// by the APIserver (https://github.com/kubernetes/kubernetes/issues/58778)
	// So, we add Generation here. Once that gets fixed, remove this and use
	// ObjectMeta.Generation instead.
	Generation int64            `json:"generation,omitempty"`
	Build      *build.BuildSpec `json:"build,omitempty"`
	Template   Revision         `json:"template"`
}

// ConfigurationConditionType represents a Configuration condition value
type ConfigurationConditionType string

const (
	// ConfigurationConditionReady is set when the configuration is starting to materialize
	// runtime resources, and becomes true when those resources are ready.
	ConfigurationConditionReady ConfigurationConditionType = "Ready"
)

// ConfigurationCondition defines a readiness condition for a Configuration.
// See: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#typical-status-properties
type ConfigurationCondition struct {
	Type ConfigurationConditionType `json:"type" description:"type of Configuration condition"`

	Status corev1.ConditionStatus `json:"status" description:"status of the condition, one of True, False, Unknown"`

	// +optional
	Reason string `json:"reason,omitempty" description:"one-word CamelCase reason for the condition's last transition"`

	// +optional
	Message string `json:"message,omitempty" description:"human-readable message indicating details about last transition"`
}

// ConfigurationStatus defines the observed state of Configuration
type ConfigurationStatus struct {
	Conditions []ConfigurationCondition `json:"conditions,omitempty"`

	// Latest revision that is ready.
	LatestReady string `json:"latestReady,omitempty"`

	// LatestCreated is the last revision that was created; it might not be
	// ready yet. When it's ready, it will get moved to LatestReady.
	LatestCreated string `json:"latestCreated,omitempty"`

	// ReconciledGeneration is the 'Generation' of the Configuration that
	// was last processed by the controller. The reconciled generation is updated
	// even if the controller failed to process the spec and create the Revision.
	ReconciledGeneration int64 `json:"reconciledGeneration,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// ConfigurationList is a list of Configuration resources
type ConfigurationList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`

	Items []Configuration `json:"items"`
}

func (r *Configuration) GetGeneration() int64 {
	return r.Spec.Generation
}

func (r *Configuration) SetGeneration(generation int64) {
	r.Spec.Generation = generation
}

func (r *Configuration) GetSpecJSON() ([]byte, error) {
	return json.Marshal(r.Spec)
}

// IsReady looks at the conditions on the ConfigurationStatus.
// ConfigurationConditionReady returns true if ConditionStatus is True
func (configStatus *ConfigurationStatus) IsReady() bool {
	if c := configStatus.GetCondition(ConfigurationConditionReady); c != nil {
		return c.Status == corev1.ConditionTrue
	}
	return false
}

func (config *ConfigurationStatus) GetCondition(t ConfigurationConditionType) *ConfigurationCondition {
	for _, cond := range config.Conditions {
		if cond.Type == t {
			return &cond
		}
	}
	return nil
}

func (configStatus *ConfigurationStatus) SetCondition(new *ConfigurationCondition) {
	if new == nil {
		return
	}

	t := new.Type
	var conditions []ConfigurationCondition
	for _, cond := range configStatus.Conditions {
		if cond.Type != t {
			conditions = append(conditions, cond)
		}
	}
	conditions = append(conditions, *new)
	configStatus.Conditions = conditions
}

func (configStatus *ConfigurationStatus) RemoveCondition(t ConfigurationConditionType) {
	var conditions []ConfigurationCondition
	for _, cond := range configStatus.Conditions {
		if cond.Type != t {
			conditions = append(conditions, cond)
		}
	}
	configStatus.Conditions = conditions
}
<|endoftext|>