<commit_before>package e2e

import (
	"context"
	"fmt"

	"github.com/blang/semver"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/stretchr/testify/require"
	corev1 "k8s.io/api/core/v1"
	rbacv1 "k8s.io/api/rbac/v1"
	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
	k8serrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/rand"
	apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"

	"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned"
	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
	"github.com/operator-framework/operator-lifecycle-manager/test/e2e/ctx"
	. "github.com/operator-framework/operator-lifecycle-manager/test/e2e/dsl"
)

var _ = Describe("Garbage collector", func() {
	var (
		kubeClient     operatorclient.ClientInterface
		operatorClient versioned.Interface
	)

	BeforeEach(func() {
		kubeClient = ctx.Ctx().KubeClient()
		operatorClient = ctx.Ctx().OperatorClient()
	})

	It("should delete a ClusterRole owned by a CustomResourceDefinition when the owner is deleted", func() {
		group := fmt.Sprintf("%s.com", rand.String(16))
		crd, err := kubeClient.ApiextensionsInterface().ApiextensionsV1().CustomResourceDefinitions().Create(context.TODO(), &apiextensionsv1.CustomResourceDefinition{
			ObjectMeta: metav1.ObjectMeta{
				Name: fmt.Sprintf("plural.%s", group),
			},
			Spec: apiextensionsv1.CustomResourceDefinitionSpec{
				Group: group,
				Scope: apiextensionsv1.ClusterScoped,
				Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
					{
						Name:    "v1",
						Served:  true,
						Storage: true,
						Schema: &apiextensionsv1.CustomResourceValidation{
							OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{Type: "object"},
						},
					},
				},
				Names: apiextensionsv1.CustomResourceDefinitionNames{
					Plural:   "plural",
					Singular: "singular",
					Kind:     "Kind",
					ListKind: "KindList",
				},
			},
		}, metav1.CreateOptions{})
		Expect(err).NotTo(HaveOccurred())
		defer func() {
			IgnoreError(kubeClient.ApiextensionsInterface().ApiextensionsV1().CustomResourceDefinitions().Delete(context.TODO(), crd.GetName(), metav1.DeleteOptions{}))
		}()

		cr, err := kubeClient.CreateClusterRole(&rbacv1.ClusterRole{
			ObjectMeta: metav1.ObjectMeta{
				GenerateName:    "clusterrole-",
				OwnerReferences: []metav1.OwnerReference{ownerutil.NonBlockingOwner(crd)},
			},
		})
		Expect(err).NotTo(HaveOccurred())
		defer func() {
			IgnoreError(kubeClient.DeleteClusterRole(cr.GetName(), &metav1.DeleteOptions{}))
		}()

		Expect(kubeClient.ApiextensionsInterface().ApiextensionsV1().CustomResourceDefinitions().Delete(context.TODO(), crd.GetName(), metav1.DeleteOptions{})).To(Succeed())
		Eventually(func() bool {
			_, err := kubeClient.GetClusterRole(cr.GetName())
			return k8serrors.IsNotFound(err)
		}).Should(BeTrue(), "get cluster role should eventually return \"not found\"")
	})

	It("should delete a ClusterRole owned by an APIService when the owner is deleted", func() {
		group := rand.String(16)
		as, err := kubeClient.CreateAPIService(&apiregistrationv1.APIService{
			ObjectMeta: metav1.ObjectMeta{
				Name: fmt.Sprintf("v1.%s", group),
			},
			Spec: apiregistrationv1.APIServiceSpec{
				Group:                group,
				Version:              "v1",
				GroupPriorityMinimum: 1,
				VersionPriority:      1,
			},
		})
		Expect(err).NotTo(HaveOccurred())
		defer func() {
			IgnoreError(kubeClient.DeleteAPIService(as.GetName(), &metav1.DeleteOptions{}))
		}()

		cr, err := kubeClient.CreateClusterRole(&rbacv1.ClusterRole{
			ObjectMeta: metav1.ObjectMeta{
				GenerateName:    "clusterrole-",
				OwnerReferences: []metav1.OwnerReference{ownerutil.NonBlockingOwner(as)},
			},
		})
		Expect(err).NotTo(HaveOccurred())
		defer func() {
			IgnoreError(kubeClient.DeleteClusterRole(cr.GetName(), &metav1.DeleteOptions{}))
		}()

		Expect(kubeClient.DeleteAPIService(as.GetName(), &metav1.DeleteOptions{})).To(Succeed())
		Eventually(func() bool {
			_, err := kubeClient.GetClusterRole(cr.GetName())
			return k8serrors.IsNotFound(err)
		}).Should(BeTrue(), "get cluster role should eventually return \"not found\"")
	})

	It("owner reference GC behavior", func() {

		// TestOwnerReferenceGCBehavior runs a simple check on OwnerReference behavior to ensure
		// a resource with multiple OwnerReferences will not be garbage collected when one of its
		// owners has been deleted.
		// Test Case:
		//				CSV-A     CSV-B                        CSV-B
		//				   \      /      --Delete CSV-A-->       |
		//				   ConfigMap						 ConfigMap

		defer cleaner.NotifyTestComplete(GinkgoT(), true)

		ownerA := newCSV("ownera", testNamespace, "", semver.MustParse("0.0.0"), nil, nil, newNginxInstallStrategy("dep-", nil, nil))
		ownerB := newCSV("ownerb", testNamespace, "", semver.MustParse("0.0.0"), nil, nil, newNginxInstallStrategy("dep-", nil, nil))

		// create all owners
		fetchedA, err := operatorClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Create(context.TODO(), &ownerA, metav1.CreateOptions{})
		require.NoError(GinkgoT(), err)
		fetchedB, err := operatorClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Create(context.TODO(), &ownerB, metav1.CreateOptions{})
		require.NoError(GinkgoT(), err)

		dependent := &corev1.ConfigMap{
			ObjectMeta: metav1.ObjectMeta{
				Name: "dependent",
			},
			Data: map[string]string{},
		}

		// add owners
		ownerutil.AddOwner(dependent, fetchedA, true, false)
		ownerutil.AddOwner(dependent, fetchedB, true, false)

		// create dependent
		_, err = kubeClient.KubernetesInterface().CoreV1().ConfigMaps(testNamespace).Create(context.TODO(), dependent, metav1.CreateOptions{})
		require.NoError(GinkgoT(), err, "dependent could not be created")

		// delete ownerA in the foreground (to ensure any "blocking" dependents are deleted before ownerA)
		propagation := metav1.DeletionPropagation("Foreground")
		options := metav1.DeleteOptions{PropagationPolicy: &propagation}
		err = operatorClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Delete(context.TODO(), fetchedA.GetName(), options)
		require.NoError(GinkgoT(), err)

		// wait for deletion of ownerA
		require.NoError(GinkgoT(), waitForDelete(func() error {
			_, err := operatorClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Get(context.TODO(), ownerA.GetName(), metav1.GetOptions{})
			return err
		}))

		// check for dependent (should still exist since it still has one owner present)
		_, err = kubeClient.KubernetesInterface().CoreV1().ConfigMaps(testNamespace).Get(context.TODO(), dependent.GetName(), metav1.GetOptions{})
		require.NoError(GinkgoT(), err, "dependent deleted after one owner was deleted")
		GinkgoT().Log("dependent still exists after one owner was deleted")

		// delete ownerB in the foreground (to ensure any "blocking" dependents are deleted before ownerB)
		err = operatorClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Delete(context.TODO(), fetchedB.GetName(), options)
		require.NoError(GinkgoT(), err)

		// wait for deletion of ownerB
		require.NoError(GinkgoT(), waitForDelete(func() error {
			_, err := operatorClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Get(context.TODO(), ownerB.GetName(), metav1.GetOptions{})
			return err
		}))

		// check for dependent (should be deleted since last blocking owner was deleted)
		_, err = kubeClient.KubernetesInterface().CoreV1().ConfigMaps(testNamespace).Get(context.TODO(), dependent.GetName(), metav1.GetOptions{})
		require.Error(GinkgoT(), err)
		require.True(GinkgoT(), k8serrors.IsNotFound(err))
		GinkgoT().Log("dependent successfully garbage collected after both owners were deleted")
	})
})
<commit_msg>Convert gc_e2e to use ginkgo<commit_after>package e2e

import (
	"context"
	"fmt"
	"github.com/operator-framework/api/pkg/operators/v1alpha1"

	"github.com/blang/semver"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	corev1 "k8s.io/api/core/v1"
	rbacv1 "k8s.io/api/rbac/v1"
	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
	k8serrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/rand"
	apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"

	"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned"
	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
	"github.com/operator-framework/operator-lifecycle-manager/test/e2e/ctx"
	. "github.com/operator-framework/operator-lifecycle-manager/test/e2e/dsl"
)

var _ = Describe("Garbage collection for dependent resources", func() {
	var (
		kubeClient     operatorclient.ClientInterface
		operatorClient versioned.Interface
	)

	BeforeEach(func() {
		kubeClient = ctx.Ctx().KubeClient()
		operatorClient = ctx.Ctx().OperatorClient()
	})

	AfterEach(func() {
		cleaner.NotifyTestComplete(GinkgoT(), true)
	})

	Context("Given a ClusterRole owned by a CustomResourceDefinition", func() {
		var (
			crd *apiextensionsv1.CustomResourceDefinition
			cr  *rbacv1.ClusterRole
		)

		BeforeEach(func() {
			group := fmt.Sprintf("%s.com", rand.String(16))

			// Create a CustomResourceDefinition
			var err error
			crd, err = kubeClient.ApiextensionsInterface().ApiextensionsV1().CustomResourceDefinitions().Create(context.TODO(), &apiextensionsv1.CustomResourceDefinition{
				ObjectMeta: metav1.ObjectMeta{
					Name: fmt.Sprintf("plural.%s", group),
				},
				Spec: apiextensionsv1.CustomResourceDefinitionSpec{
					Group: group,
					Scope: apiextensionsv1.ClusterScoped,
					Versions: []apiextensionsv1.CustomResourceDefinitionVersion{
						{
							Name:    "v1",
							Served:  true,
							Storage: true,
							Schema: &apiextensionsv1.CustomResourceValidation{
								OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{Type: "object"},
							},
						},
					},
					Names: apiextensionsv1.CustomResourceDefinitionNames{
						Plural:   "plural",
						Singular: "singular",
						Kind:     "Kind",
						ListKind: "KindList",
					},
				},
			}, metav1.CreateOptions{})
			Expect(err).NotTo(HaveOccurred())

			// Create a ClusterRole for the crd
			cr, err = kubeClient.CreateClusterRole(&rbacv1.ClusterRole{
				ObjectMeta: metav1.ObjectMeta{
					GenerateName:    "clusterrole-",
					OwnerReferences: []metav1.OwnerReference{ownerutil.NonBlockingOwner(crd)},
				},
			})
			Expect(err).NotTo(HaveOccurred())

		})

		AfterEach(func() {

			// Clean up cluster role
			IgnoreError(kubeClient.DeleteClusterRole(cr.GetName(), &metav1.DeleteOptions{}))

			// Clean up CRD
			IgnoreError(kubeClient.ApiextensionsInterface().ApiextensionsV1().CustomResourceDefinitions().Delete(context.TODO(), crd.GetName(), metav1.DeleteOptions{}))
		})

		When("CustomResourceDefinition is deleted", func() {

			BeforeEach(func() {
				// Delete CRD
				Expect(kubeClient.ApiextensionsInterface().ApiextensionsV1().CustomResourceDefinitions().Delete(context.TODO(), crd.GetName(), metav1.DeleteOptions{})).To(Succeed())
			})

			It("should delete the associated ClusterRole", func() {

				Eventually(func() bool {
					_, err := kubeClient.GetClusterRole(cr.GetName())
					return k8serrors.IsNotFound(err)
				}).Should(BeTrue(), "get cluster role should eventually return \"not found\"")
			})

		})
	})

	Context("Given a ClusterRole owned by a APIService", func() {

		var (
			as *apiregistrationv1.APIService
			cr *rbacv1.ClusterRole
		)

		BeforeEach(func() {
			group := rand.String(16)

			// Create an API Service
			var err error
			as, err = kubeClient.CreateAPIService(&apiregistrationv1.APIService{
				ObjectMeta: metav1.ObjectMeta{
					Name: fmt.Sprintf("v1.%s", group),
				},
				Spec: apiregistrationv1.APIServiceSpec{
					Group:                group,
					Version:              "v1",
					GroupPriorityMinimum: 1,
					VersionPriority:      1,
				},
			})
			Expect(err).NotTo(HaveOccurred())

			// Create a ClusterRole
			cr, err = kubeClient.CreateClusterRole(&rbacv1.ClusterRole{
				ObjectMeta: metav1.ObjectMeta{
					GenerateName:    "clusterrole-",
					OwnerReferences: []metav1.OwnerReference{ownerutil.NonBlockingOwner(as)},
				},
			})
			Expect(err).NotTo(HaveOccurred())
		})

		AfterEach(func() {

			IgnoreError(kubeClient.DeleteClusterRole(cr.GetName(), &metav1.DeleteOptions{}))

			IgnoreError(kubeClient.DeleteAPIService(as.GetName(), &metav1.DeleteOptions{}))

		})

		When("APIService is deleted", func() {

			BeforeEach(func() {
				// Delete API service
				Expect(kubeClient.DeleteAPIService(as.GetName(), &metav1.DeleteOptions{})).To(Succeed())
			})

			It("should delete the associated ClusterRole", func() {
				Eventually(func() bool {
					_, err := kubeClient.GetClusterRole(cr.GetName())
					return k8serrors.IsNotFound(err)
				}).Should(BeTrue(), "get cluster role should eventually return \"not found\"")
			})

		})
	})

	// TestOwnerReferenceGCBehavior runs a simple check on OwnerReference behavior to ensure
	// a resource with multiple OwnerReferences will not be garbage collected when one of its
	// owners has been deleted.
	// Test Case:
	//				CSV-A     CSV-B                        CSV-B
	//				   \      /      --Delete CSV-A-->       |
	//				   ConfigMap						 ConfigMap
	Context("Given a dependent resource associated with multiple owners", func() {
		var (
			ownerA   v1alpha1.ClusterServiceVersion
			ownerB   v1alpha1.ClusterServiceVersion
			fetchedA *v1alpha1.ClusterServiceVersion
			fetchedB *v1alpha1.ClusterServiceVersion

			dependent *corev1.ConfigMap

			propagation metav1.DeletionPropagation
			options     metav1.DeleteOptions
		)

		BeforeEach(func() {

			ownerA = newCSV("ownera", testNamespace, "", semver.MustParse("0.0.0"), nil, nil, newNginxInstallStrategy("dep-", nil, nil))
			ownerB = newCSV("ownerb", testNamespace, "", semver.MustParse("0.0.0"), nil, nil, newNginxInstallStrategy("dep-", nil, nil))

			// create all owners
			var err error
			fetchedA, err = operatorClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Create(context.TODO(), &ownerA, metav1.CreateOptions{})
			Expect(err).NotTo(HaveOccurred())
			fetchedB, err = operatorClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Create(context.TODO(), &ownerB, metav1.CreateOptions{})
			Expect(err).NotTo(HaveOccurred())

			dependent = &corev1.ConfigMap{
				ObjectMeta: metav1.ObjectMeta{
					Name: "dependent",
				},
				Data: map[string]string{},
			}

			// add owners
			ownerutil.AddOwner(dependent, fetchedA, true, false)
			ownerutil.AddOwner(dependent, fetchedB, true, false)

			// create ConfigMap dependent
			_, err = kubeClient.KubernetesInterface().CoreV1().ConfigMaps(testNamespace).Create(context.TODO(), dependent, metav1.CreateOptions{})
			Expect(err).NotTo(HaveOccurred(), "dependent could not be created")

			propagation = metav1.DeletePropagationForeground
			options = metav1.DeleteOptions{PropagationPolicy: &propagation}
		})

		When("removing one of the owner using 'Foreground' deletion policy", func() {

			BeforeEach(func() {
				// delete ownerA in the foreground (to ensure any "blocking" dependents are deleted before ownerA)
				err := operatorClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Delete(context.TODO(), fetchedA.GetName(), options)
				Expect(err).NotTo(HaveOccurred())

				// wait for deletion of ownerA
				Eventually(func() bool {
					_, err := operatorClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Get(context.TODO(), ownerA.GetName(), metav1.GetOptions{})
					return k8serrors.IsNotFound(err)
				}).Should(BeTrue())

			})

			It("should not have deleted the dependent since ownerB CSV is still present", func() {
				_, err := kubeClient.KubernetesInterface().CoreV1().ConfigMaps(testNamespace).Get(context.TODO(), dependent.GetName(), metav1.GetOptions{})
				Expect(err).NotTo(HaveOccurred(), "dependent deleted after one of the owner was deleted")
				ctx.Ctx().Logf("dependent still exists after one owner was deleted")

			})

		})

		When("removing both the owners using 'Foreground' deletion policy", func() {

			BeforeEach(func() {
				// delete ownerA in the foreground (to ensure any "blocking" dependents are deleted before ownerA)
				err := operatorClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Delete(context.TODO(), fetchedA.GetName(), options)
				Expect(err).NotTo(HaveOccurred())

				// wait for deletion of ownerA
				Eventually(func() bool {
					_, err := operatorClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Get(context.TODO(), ownerA.GetName(), metav1.GetOptions{})
					return k8serrors.IsNotFound(err)
				}).Should(BeTrue())

				// delete ownerB in the foreground (to ensure any "blocking" dependents are deleted before ownerB)
				err = operatorClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Delete(context.TODO(), fetchedB.GetName(), options)
				Expect(err).NotTo(HaveOccurred())

				// wait for deletion of ownerB
				Eventually(func() bool {
					_, err := operatorClient.OperatorsV1alpha1().ClusterServiceVersions(testNamespace).Get(context.TODO(), ownerB.GetName(), metav1.GetOptions{})
					return k8serrors.IsNotFound(err)
				}).Should(BeTrue())
			})

			It("should have deleted the dependent since both the owners were deleted", func() {
				_, err := kubeClient.KubernetesInterface().CoreV1().ConfigMaps(testNamespace).Get(context.TODO(), dependent.GetName(), metav1.GetOptions{})
				Expect(err).To(HaveOccurred())
				Expect(k8serrors.IsNotFound(err)).To(BeTrue())
				ctx.Ctx().Logf("dependent successfully garbage collected after both owners were deleted")
			})

		})

	})

})
<|endoftext|>


<commit_before>package sqlx

import (
	"database/sql"
	"fmt"
	"github.com/jmoiron/sqlx"
	"github.com/Cepave/open-falcon-backend/common/db"
)

// The interface of transaction callback for sqlx package
type TxCallback interface {
	InTx(tx *sqlx.Tx) db.TxFinale
}

// The function object delegates the TxCallback interface
type TxCallbackFunc func(*sqlx.Tx) db.TxFinale
func (callbackFunc TxCallbackFunc) InTx(tx *sqlx.Tx) db.TxFinale {
	return callbackFunc(tx)
}

type DbController struct {
	sqlxDb *sqlx.DB
}

// Extentsion for *sqlx.Tx
type TxExt sqlx.Tx

func ToTxExt(tx *sqlx.Tx) *TxExt {
	return (*TxExt)(tx)
}

// Query row and scan the result with panic
func (txExt *TxExt) QueryRowAndScan(query string, args []interface{}, dest []interface{}) {
	tx := (*sqlx.Tx)(txExt)

	err := tx.QueryRow(query, args...).Scan(dest...)
	db.PanicIfError(err)
}

func (txExt *TxExt) QueryRowxAndMapScan(dest map[string]interface{}, query string, args ...interface{}) {
	tx := (*sqlx.Tx)(txExt)

	row := tx.QueryRowx(query, args...)
	db.PanicIfError(row.MapScan(dest))
}
func (txExt *TxExt) QueryRowxAndScan(query string, args []interface{}, dest ...interface{}) {
	tx := (*sqlx.Tx)(txExt)

	row := tx.QueryRowx(query, args...)
	db.PanicIfError(row.Scan(dest...))
}
func (txExt *TxExt) QueryRowxAndSliceScan(query string, args ...interface{}) []interface{} {
	tx := (*sqlx.Tx)(txExt)

	row := tx.QueryRowx(query, args...)
	result, err := row.SliceScan()
	db.PanicIfError(err)

	return result
}
func (txExt *TxExt) QueryRowxAndStructScan(dest interface{}, query string, args ...interface{}) {
	tx := (*sqlx.Tx)(txExt)

	row := tx.QueryRowx(query, args...)
	db.PanicIfError(row.StructScan(dest))
}

func (txExt *TxExt) NamedExec(query string, arg interface{}) sql.Result {
	tx := (*sqlx.Tx)(txExt)

	result, err := tx.NamedExec(query, arg)
	db.PanicIfError(err)

	return result
}
func (txExt *TxExt) NamedQuery(query string, arg interface{}) *sqlx.Rows {
	tx := (*sqlx.Tx)(txExt)

	rows, err := tx.NamedQuery(query, arg)
	db.PanicIfError(err)

	return rows
}

func (txExt *TxExt) Queryx(query string, args ...interface{}) *sqlx.Rows {
	tx := (*sqlx.Tx)(txExt)

	rows, err := tx.Queryx(query, args...)
	db.PanicIfError(err)

	return rows
}

func (txExt *TxExt) Get(dest interface{}, query string, args ...interface{}) {
	tx := (*sqlx.Tx)(txExt)

	err := tx.Get(dest, query, args...)
	db.PanicIfError(err)
}

func (txExt *TxExt) Select(dest interface{}, query string, args ...interface{}) {
	tx := (*sqlx.Tx)(txExt)

	err := tx.Select(dest, query, args...)
	db.PanicIfError(err)
}

func (txExt *TxExt) BindNamed(query string, arg interface{}) (string, []interface{}) {
	tx := (*sqlx.Tx)(txExt)

	newQuery, newArgs, err := tx.BindNamed(query, arg)
	db.PanicIfError(err)

	return newQuery, newArgs
}

func NewDbController(newSqlxDb *sqlx.DB) *DbController {
	return &DbController{
		sqlxDb: newSqlxDb,
	}
}

// Prepares transaction and feed it to callback function
func (ctrl *DbController) InTx(txCallback TxCallback) {
	tx := ctrl.sqlxDb.MustBegin()

	defer func() {
		p := recover()
		if p == nil {
			return
		}

		rollbackError := tx.Rollback()
		if rollbackError != nil {
			p = fmt.Errorf("Transaction has error: %v. Rollback has error too: %v", p, rollbackError)
		}

		panic(p)
	}()

	switch txCallback.InTx(tx) {
	case db.TxCommit:
		db.PanicIfError(tx.Commit())
	case db.TxRollback:
		db.PanicIfError(tx.Rollback())
	}
}

func (ctrl *DbController) BindNamed(query string, arg interface{}) (string, []interface{}) {
	r1, r2, err := ctrl.sqlxDb.BindNamed(query, arg)
	db.PanicIfError(err)

	return r1, r2
}
func (ctrl *DbController) Get(dest interface{}, query string, args ...interface{}) {
	err := ctrl.sqlxDb.Get(dest, query, args...)
	db.PanicIfError(err)
}
func (ctrl *DbController) NamedExec(query string, arg interface{}) sql.Result {
	result, err := ctrl.sqlxDb.NamedExec(query, arg)
	db.PanicIfError(err)

	return result
}
func (ctrl *DbController) NamedQuery(query string, arg interface{}) *sqlx.Rows {
	rows, err := ctrl.sqlxDb.NamedQuery(query, arg)
	db.PanicIfError(err)

	return rows
}
func (ctrl *DbController) PrepareNamed(query string) *sqlx.NamedStmt {
	stmt, err := ctrl.sqlxDb.PrepareNamed(query)
	db.PanicIfError(err)

	return stmt
}
func (ctrl *DbController) Preparex(query string) *sqlx.Stmt {
	stmt, err := ctrl.sqlxDb.Preparex(query)
	db.PanicIfError(err)

	return stmt
}
func (ctrl *DbController) Queryx(query string, args ...interface{}) *sqlx.Rows {
	rows, err := ctrl.sqlxDb.Queryx(query, args...)
	db.PanicIfError(err)

	return rows
}
func (ctrl *DbController) Select(dest interface{}, query string, args ...interface{}) {
	err := ctrl.sqlxDb.Select(dest, query, args...)
	db.PanicIfError(err)
}

func (ctrl *DbController) QueryRowxAndMapScan(dest map[string]interface{}, query string, args ...interface{}) {
	row := ctrl.sqlxDb.QueryRowx(query, args...)
	db.PanicIfError(row.MapScan(dest))
}
func (ctrl *DbController) QueryRowxAndScan(query string, args []interface{}, dest ...interface{}) {
	row := ctrl.sqlxDb.QueryRowx(query, args...)
	db.PanicIfError(row.Scan(dest...))
}
func (ctrl *DbController) QueryRowxAndSliceScan(query string, args ...interface{}) []interface{} {
	row := ctrl.sqlxDb.QueryRowx(query, args...)
	result, err := row.SliceScan()
	db.PanicIfError(err)

	return result
}
func (ctrl *DbController) QueryRowxAndStructScan(dest interface{}, query string, args ...interface{}) {
	row := ctrl.sqlxDb.QueryRowx(query, args...)
	db.PanicIfError(row.StructScan(dest))
}
<commit_msg>[OWL-1167] Add rows ext of sqlx<commit_after>package sqlx

import (
	"database/sql"
	"fmt"
	"github.com/jmoiron/sqlx"
	"github.com/Cepave/open-falcon-backend/common/db"
)

// The interface of transaction callback for sqlx package
type TxCallback interface {
	InTx(tx *sqlx.Tx) db.TxFinale
}

// The function object delegates the TxCallback interface
type TxCallbackFunc func(*sqlx.Tx) db.TxFinale
func (callbackFunc TxCallbackFunc) InTx(tx *sqlx.Tx) db.TxFinale {
	return callbackFunc(tx)
}

type DbController struct {
	sqlxDb *sqlx.DB
}

// Extentsion for *sqlx.Tx
type TxExt sqlx.Tx

func ToTxExt(tx *sqlx.Tx) *TxExt {
	return (*TxExt)(tx)
}

// Query row and scan the result with panic
func (txExt *TxExt) QueryRowAndScan(query string, args []interface{}, dest []interface{}) {
	tx := (*sqlx.Tx)(txExt)

	err := tx.QueryRow(query, args...).Scan(dest...)
	db.PanicIfError(err)
}

func (txExt *TxExt) QueryRowxAndMapScan(dest map[string]interface{}, query string, args ...interface{}) {
	tx := (*sqlx.Tx)(txExt)

	row := tx.QueryRowx(query, args...)
	db.PanicIfError(row.MapScan(dest))
}
func (txExt *TxExt) QueryRowxAndScan(query string, args []interface{}, dest ...interface{}) {
	tx := (*sqlx.Tx)(txExt)

	row := tx.QueryRowx(query, args...)
	db.PanicIfError(row.Scan(dest...))
}
func (txExt *TxExt) QueryRowxAndSliceScan(query string, args ...interface{}) []interface{} {
	tx := (*sqlx.Tx)(txExt)

	row := tx.QueryRowx(query, args...)
	result, err := row.SliceScan()
	db.PanicIfError(err)

	return result
}
func (txExt *TxExt) QueryRowxAndStructScan(dest interface{}, query string, args ...interface{}) {
	tx := (*sqlx.Tx)(txExt)

	row := tx.QueryRowx(query, args...)
	db.PanicIfError(row.StructScan(dest))
}

func (txExt *TxExt) NamedExec(query string, arg interface{}) sql.Result {
	tx := (*sqlx.Tx)(txExt)

	result, err := tx.NamedExec(query, arg)
	db.PanicIfError(err)

	return result
}
func (txExt *TxExt) NamedQuery(query string, arg interface{}) *sqlx.Rows {
	tx := (*sqlx.Tx)(txExt)

	rows, err := tx.NamedQuery(query, arg)
	db.PanicIfError(err)

	return rows
}

func (txExt *TxExt) Queryx(query string, args ...interface{}) *sqlx.Rows {
	tx := (*sqlx.Tx)(txExt)

	rows, err := tx.Queryx(query, args...)
	db.PanicIfError(err)

	return rows
}

func (txExt *TxExt) Get(dest interface{}, query string, args ...interface{}) {
	tx := (*sqlx.Tx)(txExt)

	err := tx.Get(dest, query, args...)
	db.PanicIfError(err)
}

func (txExt *TxExt) Select(dest interface{}, query string, args ...interface{}) {
	tx := (*sqlx.Tx)(txExt)

	err := tx.Select(dest, query, args...)
	db.PanicIfError(err)
}

func (txExt *TxExt) BindNamed(query string, arg interface{}) (string, []interface{}) {
	tx := (*sqlx.Tx)(txExt)

	newQuery, newArgs, err := tx.BindNamed(query, arg)
	db.PanicIfError(err)

	return newQuery, newArgs
}

func NewDbController(newSqlxDb *sqlx.DB) *DbController {
	return &DbController{
		sqlxDb: newSqlxDb,
	}
}

// Prepares transaction and feed it to callback function
func (ctrl *DbController) InTx(txCallback TxCallback) {
	tx := ctrl.sqlxDb.MustBegin()

	defer func() {
		p := recover()
		if p == nil {
			return
		}

		rollbackError := tx.Rollback()
		if rollbackError != nil {
			p = fmt.Errorf("Transaction has error: %v. Rollback has error too: %v", p, rollbackError)
		}

		panic(p)
	}()

	switch txCallback.InTx(tx) {
	case db.TxCommit:
		db.PanicIfError(tx.Commit())
	case db.TxRollback:
		db.PanicIfError(tx.Rollback())
	}
}

func (ctrl *DbController) BindNamed(query string, arg interface{}) (string, []interface{}) {
	r1, r2, err := ctrl.sqlxDb.BindNamed(query, arg)
	db.PanicIfError(err)

	return r1, r2
}
func (ctrl *DbController) Get(dest interface{}, query string, args ...interface{}) {
	err := ctrl.sqlxDb.Get(dest, query, args...)
	db.PanicIfError(err)
}
func (ctrl *DbController) NamedExec(query string, arg interface{}) sql.Result {
	result, err := ctrl.sqlxDb.NamedExec(query, arg)
	db.PanicIfError(err)

	return result
}
func (ctrl *DbController) NamedQuery(query string, arg interface{}) *sqlx.Rows {
	rows, err := ctrl.sqlxDb.NamedQuery(query, arg)
	db.PanicIfError(err)

	return rows
}
func (ctrl *DbController) PrepareNamed(query string) *sqlx.NamedStmt {
	stmt, err := ctrl.sqlxDb.PrepareNamed(query)
	db.PanicIfError(err)

	return stmt
}
func (ctrl *DbController) Preparex(query string) *sqlx.Stmt {
	stmt, err := ctrl.sqlxDb.Preparex(query)
	db.PanicIfError(err)

	return stmt
}
func (ctrl *DbController) Queryx(query string, args ...interface{}) *sqlx.Rows {
	rows, err := ctrl.sqlxDb.Queryx(query, args...)
	db.PanicIfError(err)

	return rows
}
func (ctrl *DbController) Select(dest interface{}, query string, args ...interface{}) {
	err := ctrl.sqlxDb.Select(dest, query, args...)
	db.PanicIfError(err)
}

func (ctrl *DbController) QueryRowxAndMapScan(dest map[string]interface{}, query string, args ...interface{}) {
	row := ctrl.sqlxDb.QueryRowx(query, args...)
	db.PanicIfError(row.MapScan(dest))
}
func (ctrl *DbController) QueryRowxAndScan(query string, args []interface{}, dest ...interface{}) {
	row := ctrl.sqlxDb.QueryRowx(query, args...)
	db.PanicIfError(row.Scan(dest...))
}
func (ctrl *DbController) QueryRowxAndSliceScan(query string, args ...interface{}) []interface{} {
	row := ctrl.sqlxDb.QueryRowx(query, args...)
	result, err := row.SliceScan()
	db.PanicIfError(err)

	return result
}
func (ctrl *DbController) QueryRowxAndStructScan(dest interface{}, query string, args ...interface{}) {
	row := ctrl.sqlxDb.QueryRowx(query, args...)
	db.PanicIfError(row.StructScan(dest))
}

type RowsExt sqlx.Rows

func ToRowsExt(row *sqlx.Rows) *RowsExt {
	return (*RowsExt)(row)
}

func (r *RowsExt) MapScan(dest map[string]interface{}) {
	rows := (*sqlx.Rows)(r)
	db.PanicIfError(rows.MapScan(dest))
}
func (r *RowsExt) SliceScan() []interface{} {
	rows := (*sqlx.Rows)(r)

	result, err := rows.SliceScan()
	db.PanicIfError(err)

	return result
}
func (r *RowsExt) StructScan(dest interface{}) {
	rows := (*sqlx.Rows)(r)
	db.PanicIfError(rows.StructScan(dest))
}
<|endoftext|>


<commit_before>package gweb

import (
	"encoding/json"
	"log"
	"net/http"
	"os"
	"strings"

	. "github.com/eynstudio/gobreak"
	"github.com/eynstudio/gobreak/dddd/cmdbus"
	"github.com/eynstudio/gobreak/dddd/ddd"
	"github.com/eynstudio/gobreak/di"
)

type Ctx struct {
	*App
	di.Container
	*Req
	*Resp
	Scope   M
	isErr   bool
	afters  []Handler
	Handled bool
	session ISession
}

func (p *Ctx) Error(code int) *Ctx {
	p.WriteHeader(code)
	p.isErr = true
	return p
}

func (p *Ctx) Set(k string, v T)   { p.Scope[k] = v }
func (p *Ctx) IsErr() bool         { return p.isErr }
func (p *Ctx) Get(k string) string { return p.Scope.GetStr(k) }

func (p *Ctx) SetHandled()         { p.Handled = true }
func (p *Ctx) OK()                 { p.WriteHeader(http.StatusOK) }
func (p *Ctx) NotFound()           { p.Error(http.StatusNotFound) }
func (p *Ctx) Forbidden()          { p.Error(http.StatusForbidden) }
func (p *Ctx) Redirect(url string) { http.Redirect(p.Resp, p.Request, url, http.StatusFound) }
func (p *Ctx) HandleStatusJson(s Status) {
	p.Json(s)
	p.Handled = true
}
func (p *Ctx) Json(m T) {
	if p.IsErr() {
		return
	}
	if b, err := json.Marshal(m); err != nil {
		p.Error(http.StatusInternalServerError)
	} else {
		p.Resp.Header().Set("Content-Type", "application/json; charset=utf-8")
		p.Resp.Write(b)
	}
}

func (p *Ctx) Tmpl(tpl string, o T) {
	p.Resp.Header().Set("Content-Type", "text/html; charset=utf-8")
	if err := p.App.Tmpl.Execute(p.Resp, tpl, o); err != nil {
		log.Println(err)
		p.Error(http.StatusInternalServerError)
	}
}

func (p *Ctx) ServeFile() bool {
	url := p.Url()
	for _, path := range p.Cfg.ServeFiles {
		if strings.HasPrefix(url, path) {
			if fi, err := os.Stat(url[1:]); err != nil || fi.IsDir() {
				p.NotFound()
			} else {
				http.ServeFile(p.Resp, p.Request, url[1:])
			}
			return true
		}
	}
	return false
}

func (p *Ctx) Session() ISession {
	if p.session == nil {
		p.session, _ = p.Sessions.GetSession(p.Token)
	}
	return p.session
}
func (p Ctx) HasSession() bool        { return p.Session() != nil }
func (p *Ctx) UserId() GUID           { return p.Session().UserId() }
func (p *Ctx) Exec(cmd ddd.Cmd) error { return cmdbus.Exec(cmd) }
<commit_msg>update<commit_after>package gweb

import (
	"encoding/json"
	"log"
	"net/http"
	"os"
	"strings"

	. "github.com/eynstudio/gobreak"
	"github.com/eynstudio/gobreak/dddd/cmdbus"
	"github.com/eynstudio/gobreak/dddd/ddd"
	"github.com/eynstudio/gobreak/di"
)

type Ctx struct {
	*App
	di.Container
	*Req
	*Resp
	Scope   M
	isErr   bool
	afters  []Handler
	Handled bool
	session ISession
}

func (p *Ctx) Error(code int) *Ctx {
	p.WriteHeader(code)
	p.isErr = true
	return p
}

func (p *Ctx) Set(k string, v T)   { p.Scope[k] = v }
func (p *Ctx) IsErr() bool         { return p.isErr }
func (p *Ctx) Get(k string) string { return p.Scope.GetStr(k) }

func (p *Ctx) SetHandled()         { p.Handled = true }
func (p *Ctx) OK()                 { p.WriteHeader(http.StatusOK) }
func (p *Ctx) NotFound()           { p.Error(http.StatusNotFound) }
func (p *Ctx) Forbidden()          { p.Error(http.StatusForbidden) }
func (p *Ctx) Redirect(url string) { http.Redirect(p.Resp, p.Request, url, http.StatusFound) }
func (p *Ctx) HandleStatusJson(s Status) {
	p.Json(s)
	p.Handled = true
}

func (p *Ctx) Json(m T) {
	if p.IsErr() {
		return
	}
	if b, err := json.Marshal(m); err != nil {
		p.Error(http.StatusInternalServerError)
	} else {
		p.Resp.Header().Set("Content-Type", "application/json; charset=utf-8")
		p.Resp.Write(b)
	}
}

func (p *Ctx) SetCookie(c http.Cookie) { http.SetCookie(p.Resp, &c) }

func (p *Ctx) Tmpl(tpl string, o T) {
	p.Resp.Header().Set("Content-Type", "text/html; charset=utf-8")
	if err := p.App.Tmpl.Execute(p.Resp, tpl, o); err != nil {
		log.Println(err)
		p.Error(http.StatusInternalServerError)
	}
}

func (p *Ctx) ServeFile() bool {
	url := p.Url()
	for _, path := range p.Cfg.ServeFiles {
		if strings.HasPrefix(url, path) {
			if fi, err := os.Stat(url[1:]); err != nil || fi.IsDir() {
				p.NotFound()
			} else {
				http.ServeFile(p.Resp, p.Request, url[1:])
			}
			return true
		}
	}
	return false
}

func (p *Ctx) Session() ISession {
	if p.session == nil {
		p.session, _ = p.Sessions.GetSession(p.Token)
	}
	return p.session
}
func (p Ctx) HasSession() bool        { return p.Session() != nil }
func (p *Ctx) UserId() GUID           { return p.Session().UserId() }
func (p *Ctx) Exec(cmd ddd.Cmd) error { return cmdbus.Exec(cmd) }
<|endoftext|>


<commit_before>// Copyright (c) 2018 Timo Savola. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package compile

import (
	"bytes"
	"io/ioutil"
	"os"
	"path"
	"testing"

	"github.com/tsavola/wag/buffer"
	"github.com/tsavola/wag/compile/event"
	"github.com/tsavola/wag/section"
)

var benchDir = "../wag-bench" // Relative to project root directory.

func init() {
	if s := os.Getenv("WAG_BENCH_DIR"); s != "" {
		benchDir = path.Join("..", s)
	}
}

var (
	benchTextBuf = make([]byte, 16*1024*1024)
	benchDataBuf = make([]byte, 16*1024*1024)
)

func BenchmarkLoad000(b *testing.B)  { bench(b, "000", "run") }
func BenchmarkLoad000E(b *testing.B) { benchE(b, "000", "run", func(event.Event) {}) }
func BenchmarkLoad001(b *testing.B)  { bench(b, "001", "main") } // Gain hello example, debug build
func BenchmarkLoad002(b *testing.B)  { bench(b, "002", "main") } // Gain hello example, release build

func bench(b *testing.B, filename, entrySymbol string) {
	benchE(b, filename, entrySymbol, nil)
}

func benchE(b *testing.B, filename, entrySymbol string, eventHandler func(event.Event)) {
	b.Helper()

	wasm, err := ioutil.ReadFile(path.Join("..", benchDir, filename) + ".wasm")
	if err != nil {
		if os.IsNotExist(err) {
			b.Skip(err)
		} else {
			b.Fatal(err)
		}
	}

	r := bytes.NewReader(wasm)
	loadInitialSections(nil, r)

	initLen := len(wasm) - r.Len()

	if err := section.SkipCustomSections(r, nil); err != nil {
		b.Fatal(err)
	}

	codePos := len(wasm) - r.Len()

	codePayloadLen, err := section.CopyStandardSection(ioutil.Discard, r, section.Code, nil)
	if err != nil {
		b.Fatal(err)
	}

	if err := section.SkipCustomSections(r, nil); err != nil {
		b.Fatal(err)
	}

	dataPos := len(wasm) - r.Len()

	var mod Module

	b.Run("Init", func(b *testing.B) {
		b.SetBytes(int64(initLen))

		for i := 0; i < b.N; i++ {
			mod = loadInitialSections(nil, bytes.NewReader(wasm))

			for i := 0; i < mod.NumImportFuncs(); i++ {
				// Arbitrary (but existing) implementation.
				mod.SetImportFunc(i, uint32(lib.NumImportFuncs()))
			}
		}
	})

	b.Run("Code", func(b *testing.B) {
		b.SetBytes(int64(codePayloadLen))

		for i := 0; i < b.N; i++ {
			code := CodeConfig{
				Text:         buffer.NewStatic(benchTextBuf[:0:len(benchTextBuf)]),
				EventHandler: eventHandler,
			}

			code.LastInitFunc, _, _ = mod.ExportFunc(entrySymbol)
			loadCodeSection(&code, bytes.NewReader(wasm[codePos:]), mod, &lib.l)
		}
	})

	b.Run("Data", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			data := DataConfig{
				GlobalsMemory: buffer.NewStatic(benchDataBuf[:0:len(benchDataBuf)]),
			}

			loadDataSection(&data, bytes.NewReader(wasm[dataPos:]), mod)
		}
	})
}
<commit_msg>compile: add benchmark<commit_after>// Copyright (c) 2018 Timo Savola. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package compile

import (
	"bytes"
	"io/ioutil"
	"os"
	"path"
	"testing"

	"github.com/tsavola/wag/buffer"
	"github.com/tsavola/wag/compile/event"
	"github.com/tsavola/wag/section"
)

var benchDir = "../wag-bench" // Relative to project root directory.

func init() {
	if s := os.Getenv("WAG_BENCH_DIR"); s != "" {
		benchDir = path.Join("..", s)
	}
}

var (
	benchTextBuf = make([]byte, 16*1024*1024)
	benchDataBuf = make([]byte, 32*1024*1024)
)

func BenchmarkLoad000(b *testing.B)  { bench(b, "000", "run") }
func BenchmarkLoad000E(b *testing.B) { benchE(b, "000", "run", func(event.Event) {}) }
func BenchmarkLoad001(b *testing.B)  { bench(b, "001", "main") }   // Gain hello example, debug build
func BenchmarkLoad002(b *testing.B)  { bench(b, "002", "main") }   // Gain hello example, release build
func BenchmarkLoad003(b *testing.B)  { bench(b, "003", "_start") } // DOOM

func bench(b *testing.B, filename, entrySymbol string) {
	benchE(b, filename, entrySymbol, nil)
}

func benchE(b *testing.B, filename, entrySymbol string, eventHandler func(event.Event)) {
	b.Helper()

	wasm, err := ioutil.ReadFile(path.Join("..", benchDir, filename) + ".wasm")
	if err != nil {
		if os.IsNotExist(err) {
			b.Skip(err)
		} else {
			b.Fatal(err)
		}
	}

	r := bytes.NewReader(wasm)
	loadInitialSections(nil, r)

	initLen := len(wasm) - r.Len()

	if err := section.SkipCustomSections(r, nil); err != nil {
		b.Fatal(err)
	}

	codePos := len(wasm) - r.Len()

	codePayloadLen, err := section.CopyStandardSection(ioutil.Discard, r, section.Code, nil)
	if err != nil {
		b.Fatal(err)
	}

	if err := section.SkipCustomSections(r, nil); err != nil {
		b.Fatal(err)
	}

	dataPos := len(wasm) - r.Len()

	var mod Module

	b.Run("Init", func(b *testing.B) {
		b.SetBytes(int64(initLen))

		for i := 0; i < b.N; i++ {
			mod = loadInitialSections(nil, bytes.NewReader(wasm))

			for i := 0; i < mod.NumImportFuncs(); i++ {
				// Arbitrary (but existing) implementation.
				mod.SetImportFunc(i, uint32(lib.NumImportFuncs()))
			}
		}
	})

	b.Run("Code", func(b *testing.B) {
		b.SetBytes(int64(codePayloadLen))

		for i := 0; i < b.N; i++ {
			code := CodeConfig{
				Text:         buffer.NewStatic(benchTextBuf[:0:len(benchTextBuf)]),
				EventHandler: eventHandler,
			}

			code.LastInitFunc, _, _ = mod.ExportFunc(entrySymbol)
			loadCodeSection(&code, bytes.NewReader(wasm[codePos:]), mod, &lib.l)
		}
	})

	b.Run("Data", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			data := DataConfig{
				GlobalsMemory: buffer.NewStatic(benchDataBuf[:0:len(benchDataBuf)]),
			}

			loadDataSection(&data, bytes.NewReader(wasm[dataPos:]), mod)
		}
	})
}
<|endoftext|>


<commit_before>package elog

import (
	"io"
	"time"
)

type writer struct {
	io.Writer
	timeFormat string
}

func (w writer) Write(b []byte) (n int, err error) {
	return w.Writer.Write(append([]byte(time.Now().Format(w.timeFormat)), b...))
}

// NewWriter returns an io.Writer that writes timestamps as prefix
func NewWriter(writer io.Writer, timeFormat string) *writer {
	if timeFormat == "" {
		timeFormat = "2006-01-02 15:04:05 "
	}
	return &writer{writer, timeFormat}
}
<commit_msg>created getter for unexported writer (2)<commit_after>package elog

import (
	"io"
	"time"
)

type writer struct {
	io.Writer
	timeFormat string
}

func (w writer) Write(b []byte) (n int, err error) {
	return w.Writer.Write(append([]byte(time.Now().Format(w.timeFormat)), b...))
}

/*
NewWriter returns a new io.Writer that writes timestamps as prefix

E.g. usage:

	logger := log.New(elog.NewWriter(os.Stdout), "[info] ", 0)
	logger.Println("Hello.")

	Prints: 2016/07/19 17:34:10 [info] Hello.
*/
func NewWriter(w io.Writer, timeFormat ...string) *writer {
	tf := "2006-01-02 15:04:05 "
	if len(timeFormat) == 1 {
		tf = timeFormat[0]
	}
	return &writer{w, tf}
}
<|endoftext|>


<commit_before>package images

import (
	"time"

	"github.com/Symantec/Dominator/imageserver/client"
	"github.com/Symantec/Dominator/lib/image"
	"github.com/Symantec/Dominator/lib/log"
	"github.com/Symantec/Dominator/lib/srpc"
	"github.com/Symantec/Dominator/lib/stringutil"
)

func newManager(imageServerAddress string, logger log.Logger) *Manager {
	imageInterestChannel := make(chan map[string]struct{})
	imageRequestChannel := make(chan string)
	imageExpireChannel := make(chan string, 16)
	m := &Manager{
		imageServerAddress:   imageServerAddress,
		logger:               logger,
		deduper:              stringutil.NewStringDeduplicator(false),
		imageInterestChannel: imageInterestChannel,
		imageRequestChannel:  imageRequestChannel,
		imageExpireChannel:   imageExpireChannel,
		imagesByName:         make(map[string]*image.Image),
		missingImages:        make(map[string]error),
	}
	go m.manager(imageInterestChannel, imageRequestChannel, imageExpireChannel)
	return m
}

func (m *Manager) getNoWait(name string) (*image.Image, error) {
	m.RLock()
	defer m.RUnlock()
	if image := m.imagesByName[name]; image != nil {
		return image, nil
	}
	if err, ok := m.missingImages[name]; ok {
		return nil, err
	}
	return nil, nil
}

func (m *Manager) getWait(name string) (*image.Image, error) {
	if image, err := m.getNoWait(name); err != nil {
		return nil, err
	} else if image != nil {
		return image, nil
	}
	m.imageRequestChannel <- name
	m.imageRequestChannel <- ""
	return m.getNoWait(name)
}

func (m *Manager) setImageInterestList(images map[string]struct{}, wait bool) {
	delete(images, "")
	m.imageInterestChannel <- images
	if wait {
		m.imageRequestChannel <- ""
	}
}

func (m *Manager) manager(imageInterestChannel <-chan map[string]struct{},
	imageRequestChannel <-chan string,
	imageExpireChannel <-chan string) {
	var imageClient *srpc.Client
	timer := time.NewTimer(time.Second)
	for {
		select {
		case imageList := <-imageInterestChannel:
			imageClient = m.setInterest(imageClient, imageList)
		case name := <-imageRequestChannel:
			if name == "" {
				continue
			}
			imageClient = m.requestImage(imageClient, name)
		case name := <-imageExpireChannel:
			m.Lock()
			delete(m.imagesByName, name)
			m.Unlock()
			m.rebuildDeDuper()
		case <-timer.C:
			// Loop over missing (pending) images. First obtain a copy.
			missingImages := make(map[string]struct{})
			for name := range m.missingImages {
				missingImages[name] = struct{}{}
			}
			for name := range missingImages {
				imageClient = m.requestImage(imageClient, name)
			}
		}
		if len(m.missingImages) > 0 {
			timer.Reset(time.Second)
		}
	}
}

func (m *Manager) setInterest(imageClient *srpc.Client,
	imageList map[string]struct{}) *srpc.Client {
	for name := range imageList {
		imageClient = m.requestImage(imageClient, name)
	}
	deletedSome := false
	// Clean up unreferenced images.
	for name := range m.imagesByName {
		if _, ok := imageList[name]; !ok {
			m.Lock()
			delete(m.imagesByName, name)
			m.Unlock()
			deletedSome = true
		}
	}
	for name := range m.missingImages {
		if _, ok := imageList[name]; !ok {
			m.Lock()
			delete(m.missingImages, name)
			m.Unlock()
		}
	}
	if deletedSome {
		m.rebuildDeDuper()
	}
	return imageClient
}

func (m *Manager) requestImage(imageClient *srpc.Client,
	name string) *srpc.Client {
	if _, ok := m.imagesByName[name]; ok {
		return imageClient
	}
	var img *image.Image
	var err error
	imageClient, img, err = m.loadImage(imageClient, name)
	m.Lock()
	defer m.Unlock()
	if img != nil && err == nil {
		delete(m.missingImages, name)
		m.imagesByName[name] = img
		return imageClient
	}
	delete(m.imagesByName, name)
	m.missingImages[name] = err
	return imageClient
}

func (m *Manager) loadImage(imageClient *srpc.Client, name string) (
	*srpc.Client, *image.Image, error) {
	if imageClient == nil {
		var err error
		imageClient, err = srpc.DialHTTP("tcp", m.imageServerAddress, 0)
		if err != nil {
			if !m.loggedDialFailure {
				m.logger.Printf("Error dialing: %s: %s\n",
					m.imageServerAddress, err)
				m.loggedDialFailure = true
			}
			return nil, nil, err
		}
	}
	img, err := client.GetImage(imageClient, name)
	if err != nil {
		m.logger.Printf("Error calling: %s\n", err)
		imageClient.Close()
		return nil, nil, err
	}
	if img == nil || m.scheduleExpiration(img, name) {
		return imageClient, nil, nil
	}
	if err := img.FileSystem.RebuildInodePointers(); err != nil {
		m.logger.Printf("Error building inode pointers for image: %s %s",
			name, err)
		return imageClient, nil, err
	}
	img.ReplaceStrings(m.deduper.DeDuplicate)
	img.FileSystem = img.FileSystem.Filter(img.Filter) // Apply filter.
	// Build cache data now to avoid potential concurrent builds later.
	img.FileSystem.InodeToFilenamesTable()
	img.FileSystem.FilenameToInodeTable()
	img.FileSystem.HashToInodesTable()
	img.FileSystem.ComputeTotalDataBytes()
	img.FileSystem.BuildEntryMap()
	m.logger.Printf("Got image: %s\n", name)
	return imageClient, img, nil
}

func (m *Manager) rebuildDeDuper() {
	m.deduper.Clear()
	for _, image := range m.imagesByName {
		image.ReplaceStrings(m.deduper.DeDuplicate)
	}
}

func (m *Manager) scheduleExpiration(image *image.Image, name string) bool {
	if image.ExpiresAt.IsZero() {
		return false
	}
	duration := image.ExpiresAt.Sub(time.Now())
	if duration <= 0 {
		return true
	}
	time.AfterFunc(duration, func() {
		m.logger.Printf("Auto expiring (deleting) image: %s\n", name)
		m.imageExpireChannel <- name
	})
	return false
}
<commit_msg>dominator: schedule re-check of expired image.<commit_after>package images

import (
	"time"

	"github.com/Symantec/Dominator/imageserver/client"
	"github.com/Symantec/Dominator/lib/image"
	"github.com/Symantec/Dominator/lib/log"
	"github.com/Symantec/Dominator/lib/srpc"
	"github.com/Symantec/Dominator/lib/stringutil"
)

func newManager(imageServerAddress string, logger log.Logger) *Manager {
	imageInterestChannel := make(chan map[string]struct{})
	imageRequestChannel := make(chan string)
	imageExpireChannel := make(chan string, 16)
	m := &Manager{
		imageServerAddress:   imageServerAddress,
		logger:               logger,
		deduper:              stringutil.NewStringDeduplicator(false),
		imageInterestChannel: imageInterestChannel,
		imageRequestChannel:  imageRequestChannel,
		imageExpireChannel:   imageExpireChannel,
		imagesByName:         make(map[string]*image.Image),
		missingImages:        make(map[string]error),
	}
	go m.manager(imageInterestChannel, imageRequestChannel, imageExpireChannel)
	return m
}

func (m *Manager) getNoWait(name string) (*image.Image, error) {
	m.RLock()
	defer m.RUnlock()
	if image := m.imagesByName[name]; image != nil {
		return image, nil
	}
	if err, ok := m.missingImages[name]; ok {
		return nil, err
	}
	return nil, nil
}

func (m *Manager) getWait(name string) (*image.Image, error) {
	if image, err := m.getNoWait(name); err != nil {
		return nil, err
	} else if image != nil {
		return image, nil
	}
	m.imageRequestChannel <- name
	m.imageRequestChannel <- ""
	return m.getNoWait(name)
}

func (m *Manager) setImageInterestList(images map[string]struct{}, wait bool) {
	delete(images, "")
	m.imageInterestChannel <- images
	if wait {
		m.imageRequestChannel <- ""
	}
}

func (m *Manager) manager(imageInterestChannel <-chan map[string]struct{},
	imageRequestChannel <-chan string,
	imageExpireChannel <-chan string) {
	var imageClient *srpc.Client
	timer := time.NewTimer(time.Second)
	for {
		select {
		case imageList := <-imageInterestChannel:
			imageClient = m.setInterest(imageClient, imageList)
		case name := <-imageRequestChannel:
			if name == "" {
				continue
			}
			imageClient = m.requestImage(imageClient, name)
		case name := <-imageExpireChannel:
			m.Lock()
			delete(m.imagesByName, name)
			m.missingImages[name] = nil // Try to get it again (expire extended)
			m.Unlock()
			m.rebuildDeDuper()
		case <-timer.C:
			// Loop over missing (pending) images. First obtain a copy.
			missingImages := make(map[string]struct{})
			for name := range m.missingImages {
				missingImages[name] = struct{}{}
			}
			for name := range missingImages {
				imageClient = m.requestImage(imageClient, name)
			}
		}
		if len(m.missingImages) > 0 {
			timer.Reset(time.Second)
		}
	}
}

func (m *Manager) setInterest(imageClient *srpc.Client,
	imageList map[string]struct{}) *srpc.Client {
	for name := range imageList {
		imageClient = m.requestImage(imageClient, name)
	}
	deletedSome := false
	// Clean up unreferenced images.
	for name := range m.imagesByName {
		if _, ok := imageList[name]; !ok {
			m.Lock()
			delete(m.imagesByName, name)
			m.Unlock()
			deletedSome = true
		}
	}
	for name := range m.missingImages {
		if _, ok := imageList[name]; !ok {
			m.Lock()
			delete(m.missingImages, name)
			m.Unlock()
		}
	}
	if deletedSome {
		m.rebuildDeDuper()
	}
	return imageClient
}

func (m *Manager) requestImage(imageClient *srpc.Client,
	name string) *srpc.Client {
	if _, ok := m.imagesByName[name]; ok {
		return imageClient
	}
	var img *image.Image
	var err error
	imageClient, img, err = m.loadImage(imageClient, name)
	m.Lock()
	defer m.Unlock()
	if img != nil && err == nil {
		delete(m.missingImages, name)
		m.imagesByName[name] = img
		return imageClient
	}
	delete(m.imagesByName, name)
	m.missingImages[name] = err
	return imageClient
}

func (m *Manager) loadImage(imageClient *srpc.Client, name string) (
	*srpc.Client, *image.Image, error) {
	if imageClient == nil {
		var err error
		imageClient, err = srpc.DialHTTP("tcp", m.imageServerAddress, 0)
		if err != nil {
			if !m.loggedDialFailure {
				m.logger.Printf("Error dialing: %s: %s\n",
					m.imageServerAddress, err)
				m.loggedDialFailure = true
			}
			return nil, nil, err
		}
	}
	img, err := client.GetImage(imageClient, name)
	if err != nil {
		m.logger.Printf("Error calling: %s\n", err)
		imageClient.Close()
		return nil, nil, err
	}
	if img == nil || m.scheduleExpiration(img, name) {
		return imageClient, nil, nil
	}
	if err := img.FileSystem.RebuildInodePointers(); err != nil {
		m.logger.Printf("Error building inode pointers for image: %s %s",
			name, err)
		return imageClient, nil, err
	}
	img.ReplaceStrings(m.deduper.DeDuplicate)
	img.FileSystem = img.FileSystem.Filter(img.Filter) // Apply filter.
	// Build cache data now to avoid potential concurrent builds later.
	img.FileSystem.InodeToFilenamesTable()
	img.FileSystem.FilenameToInodeTable()
	img.FileSystem.HashToInodesTable()
	img.FileSystem.ComputeTotalDataBytes()
	img.FileSystem.BuildEntryMap()
	m.logger.Printf("Got image: %s\n", name)
	return imageClient, img, nil
}

func (m *Manager) rebuildDeDuper() {
	m.deduper.Clear()
	for _, image := range m.imagesByName {
		image.ReplaceStrings(m.deduper.DeDuplicate)
	}
}

func (m *Manager) scheduleExpiration(image *image.Image, name string) bool {
	if image.ExpiresAt.IsZero() {
		return false
	}
	duration := image.ExpiresAt.Sub(time.Now())
	if duration <= 0 {
		return true
	}
	time.AfterFunc(duration, func() {
		m.logger.Printf("Auto expiring (deleting) image: %s\n", name)
		m.imageExpireChannel <- name
	})
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/fluffle/goirc/client"
	"github.com/ianremmler/igopher/flip"
	"github.com/ianremmler/igopher/weather"

	"flag"
	"fmt"
	"log"
	"os"
	"strings"
)

const (
	nick       = "iGopher"
	flipCmd    = "!flip"
	weatherCmd = "!weather"
	table      = "┻━┻"
)

var channel string

func main() {
	if len(os.Args) < 2 {
		log.Fatalln("usage: igopher #channel")
	}
	if !strings.HasPrefix(os.Args[1], "#") {
		log.Fatalf("usage: %s is not a valid channel", os.Args[1])
	}
	flag.Parse() // parses the goirc logging flags

	channel = os.Args[1]
	quit := make(chan bool)
	c := client.SimpleClient(nick)
	c.HandleFunc(client.CONNECTED, func(conn *client.Conn, line *client.Line) {
		conn.Join(channel)
	})
	c.HandleFunc(client.DISCONNECTED, func(conn *client.Conn, line *client.Line) {
		fmt.Println("disconnected :(")
		quit <- true
	})
	c.HandleFunc(client.PRIVMSG, handlePrivMsg)
	if err := c.ConnectTo("irc.freenode.net"); err != nil {
		fmt.Printf("Connection error: %s\n", err)
	}
	<-quit
}

func handlePrivMsg(conn *client.Conn, line *client.Line) {
	text := strings.TrimSpace(line.Text())
	switch {
	case strings.HasPrefix(text, flipCmd):
		text = strings.TrimSpace(text[len(flipCmd):])
		flipped := ""
		if len(text) > 0 {
			flipped = flip.Flip(text)
		} else {
			flipped = table
		}
		conn.Action(channel, "(ノಠ益ಠ)ノ彡 "+flipped)
	case strings.HasPrefix(text, weatherCmd):
		for _, text := range strings.Split(weather.Info(), "\n") {
			conn.Privmsg(channel, text)
		}
	}
}
<commit_msg>Changed throw from action to normal message.<commit_after>package main

import (
	"github.com/fluffle/goirc/client"
	"github.com/ianremmler/igopher/flip"
	"github.com/ianremmler/igopher/weather"

	"flag"
	"fmt"
	"log"
	"os"
	"strings"
)

const (
	nick       = "iGopher"
	flipCmd    = "!flip"
	weatherCmd = "!weather"
	table      = "┻━┻"
)

var channel string

func main() {
	if len(os.Args) < 2 {
		log.Fatalln("usage: igopher #channel")
	}
	if !strings.HasPrefix(os.Args[1], "#") {
		log.Fatalf("usage: %s is not a valid channel", os.Args[1])
	}
	flag.Parse() // parses the goirc logging flags

	channel = os.Args[1]
	quit := make(chan bool)
	c := client.SimpleClient(nick)
	c.HandleFunc(client.CONNECTED, func(conn *client.Conn, line *client.Line) {
		conn.Join(channel)
	})
	c.HandleFunc(client.DISCONNECTED, func(conn *client.Conn, line *client.Line) {
		fmt.Println("disconnected :(")
		quit <- true
	})
	c.HandleFunc(client.PRIVMSG, handlePrivMsg)
	if err := c.ConnectTo("irc.freenode.net"); err != nil {
		fmt.Printf("Connection error: %s\n", err)
	}
	<-quit
}

func handlePrivMsg(conn *client.Conn, line *client.Line) {
	text := strings.TrimSpace(line.Text())
	switch {
	case strings.HasPrefix(text, flipCmd):
		text = strings.TrimSpace(text[len(flipCmd):])
		flipped := ""
		if len(text) > 0 {
			flipped = flip.Flip(text)
		} else {
			flipped = table
		}
		conn.Privmsg(channel, "(ノಠ益ಠ)ノ彡 "+flipped)
	case strings.HasPrefix(text, weatherCmd):
		for _, text := range strings.Split(weather.Info(), "\n") {
			conn.Privmsg(channel, text)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"encoding/base64"
	"fmt"
	"strconv"
	"time"

	"gitlab.com/hartsfield/gmailAPI"
	gmail "google.golang.org/api/gmail/v1"
)

func main() {
	check()
}

func check() {
	// Connect to the gmail API service.
	ctx := context.Background()
	srv := gmailAPI.ConnectToService(ctx, gmail.MailGoogleComScope)

	// Get the messages
	msgs, err := srv.Users.Messages.List("me").Do()
	if err != nil {
		fmt.Println(err)
	}

	// Range over the messages
	for _, v := range msgs.Messages[:5] {
		msg, _ := srv.Users.Messages.Get("me", v.Id).Do()

		fmt.Println(msg.Snippet)
		fmt.Println(msg.LabelIds)

		// Time
		fmt.Println(getTime(msg.InternalDate))

		// dec, err := decodeEmailBody(msg.Payload.Parts[0].Body.Data)
		// if err != nil {
		// 	fmt.Println(err)
		// }
		// fmt.Println(dec)

	}

}

func decodeEmailBody(data string) (string, error) {
	decoded, err := base64.URLEncoding.DecodeString(data)
	if err != nil {
		fmt.Println("decode error:", err)
		return "", err
	}
	return string(decoded), nil
}

func getTime(datetime int64) time.Time {
	conv := strconv.FormatInt(datetime, 10)
	cut := s[:len(s)-3]
	tc, err := strconv.ParseInt(t, 10, 64)
	if err != nil {
		fmt.Println(err)
	}
	return time.Unix(tc, 0)
}
<commit_msg>updates<commit_after>package main

import (
	"context"
	"encoding/base64"
	"fmt"
	"strconv"
	"strings"
	"time"

	"gitlab.com/hartsfield/gmailAPI"
	gmail "google.golang.org/api/gmail/v1"
)

func main() {
	// Connect to the gmail API service.
	ctx := context.Background()
	srv := gmailAPI.ConnectToService(ctx, gmail.MailGoogleComScope)

	// Get the messages
	msgs, err := srv.Users.Messages.List("me").Do()
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("--------------------------------------------------------")
	// Range over the messages
	for _, v := range msgs.Messages[:10] {
		msg, _ := srv.Users.Messages.Get("me", v.Id).Do()
		info := getSender2(msg)
		fmt.Println(info.From, info.Sender, info.Subject)
		// fmt.Println(getSender(msg), getTime(msg.InternalDate))
		if getByLabel(strings.ToUpper("UNREAD"), msg) {
			// fmt.Println(msg.Snippet)
			// fmt.Println("--------------------------------------------------------")
		}
	}
}

func getBody(msg *gmail.Message) (string, error) {
	dec, err := decodeEmailBody(msg.Payload.Parts[0].Body.Data)
	if err != nil {
		return "", err
	}
	return dec, nil
}

func getByLabel(label string, msg *gmail.Message) bool {
	for _, v := range msg.LabelIds {
		if v == label {
			return true
		}
	}
	return false
}

type senderInfo struct {
	Sender, From, To, CC, Subject, MailingList, DeliveredTo, ThreadTopic []string
}

func getSender2(msg *gmail.Message) *senderInfo {
	info := &senderInfo{}
	fmt.Println("--------------------------------------------------------")
	for _, v := range msg.Payload.Headers {
		switch v.Name {
		case "Sender":
			info.Sender = append(info.Sender, v.Value)
		case "From":
			info.From = append(info.From, v.Value)
		case "To":
			info.To = append(info.To, v.Value)
		case "CC":
			info.CC = append(info.CC, v.Value)
		case "Subject":
			info.Subject = append(info.Subject, v.Value)
		case "Mailing-list":
			info.MailingList = append(info.MailingList, v.Value)
		case "Delivered-To":
			info.DeliveredTo = append(info.DeliveredTo, v.Value)
		case "Thread-Topic":
			info.ThreadTopic = append(info.ThreadTopic, v.Value)
		}
	}
	return info
}

func decodeEmailBody(data string) (string, error) {
	decoded, err := base64.URLEncoding.DecodeString(data)
	if err != nil {
		fmt.Println("decode error:", err)
		return "", err
	}
	return string(decoded), nil
}

func getTime(datetime int64) time.Time {
	conv := strconv.FormatInt(datetime, 10)
	cut := conv[:len(conv)-3]
	tc, err := strconv.ParseInt(cut, 10, 64)
	if err != nil {
		fmt.Println(err)
	}
	return time.Unix(tc, 0)
}

// func watchInbox() {
// 	req := &gmail.WatchRequest{
// 		LabelFilterAction: "include",
// 		LabelIds:          []string{"UNREAD"},
// 		TopicName:         "gmailmsg",
// 	}

// 	wr, _ := srv.Users.Watch("me", req).Do()
// 	fmt.Println(wr.ForceSendFields)
// }

// func getMessages() (*gmail.ListMessagesResponse, error) {
// 	// Connect to the gmail API service.
// 	ctx := context.Background()
// 	srv := gmailAPI.ConnectToService(ctx, gmail.MailGoogleComScope)

// 	// Get the messages
// 	msgs, err := srv.Users.Messages.List("me").Do()
// 	if err != nil {
// 		return &gmail.ListMessagesResponse{}, err
// 	}

// 	return msgs, nil
// }
<|endoftext|>


<commit_before>package main

import (
	"time"
)

type email struct {
	Email                      string `json:"email"`
	UnsubscribeSecretHex       string `json:"unsubscribeSecretHex"`
	LastEmailNotificationDate  time.Time `json:"lastEmailNotificationDate"`
	PendingEmails              int `json:"-"`
	SendReplyNotifications     bool `json:"sendReplyNotifications"`
	SendModeratorNotifications bool `json:"sendModeratorNotifications"`
}
<commit_msg>email.go: run go fmt<commit_after>package main

import (
	"time"
)

type email struct {
	Email                      string    `json:"email"`
	UnsubscribeSecretHex       string    `json:"unsubscribeSecretHex"`
	LastEmailNotificationDate  time.Time `json:"lastEmailNotificationDate"`
	PendingEmails              int       `json:"-"`
	SendReplyNotifications     bool      `json:"sendReplyNotifications"`
	SendModeratorNotifications bool      `json:"sendModeratorNotifications"`
}
<|endoftext|>


<commit_before>package driver

import (
    "fmt"
    "sync"
    "strings"
)

type MemStoreDriver struct {
    data map[int64]*Job
    nameIndex map[string]int64
    lastId int64
    locker *sync.Mutex
}

func NewMemStroeDriver() *MemStoreDriver {
    mem := new(MemStoreDriver)
    mem.locker = new(sync.Mutex)
    mem.nameIndex = make(map[string]int64)
    mem.data = make(map[int64]*Job)
    mem.lastId = 0
    return mem
}

func (m *MemStoreDriver) Save(job *Job) (err error) {
    defer m.locker.Unlock()
    m.locker.Lock()
    if job.Id > 0 {
        old, ok := m.data[job.Id]
        if !ok {
            return fmt.Errorf("Update Job %d fail, the job is not exists.", job.Id)
        }
        if old.Name != job.Name {
            delete(m.nameIndex, old.Func + ":" + old.Name)
            m.nameIndex[job.Func + ":" + job.Name] = job.Id
        }
    } else {
        m.lastId += 1
        job.Id = m.lastId
        m.nameIndex[job.Func + ":" + job.Name] = job.Id
    }
    m.data[job.Id] = job
    return
}

func (m *MemStoreDriver) Delete(jobId int64) (err error) {
    defer m.locker.Unlock()
    m.locker.Lock()
    var job Job
    job, err = m.Get(jobId)
    if err != nil {
        return
    }
    delete(m.data, job.Id)
    delete(m.nameIndex, job.Func + ":" + job.Name)
    return
}

func (m *MemStoreDriver) Get(jobId int64) (job Job, err error) {
    j, ok := m.data[jobId]
    if !ok {
        err = fmt.Errorf("Job %d not exists.", jobId)
        return
    }
    job = *j
    return
}

func (m *MemStoreDriver) GetOne(Func, name string) (job Job, err error) {
    jobId, ok := m.nameIndex[Func + ":" + name]
    if !ok {
        err = fmt.Errorf("Job %s:%s not exists.", Func, name)
        return
    }
    job, err = m.Get(jobId)
    return
}

func (m *MemStoreDriver) NewIterator(Func []byte) JobIterator {
    m.locker.Lock()
    var data = make([]int64, 0)
    if Func == nil {
        for jobId, _ := range m.data {
            data = append(data, jobId)
        }
    } else {
        prefix := string(Func)
        for key, jobId := range m.nameIndex {
            if strings.HasPrefix(key, prefix) {
                data = append(data, jobId)
            }
        }
    }
    return &MemIterator{
        data: data,
        m: m,
        cursor: 0,
    }
}

func (m *MemStoreDriver) Close() error {
    return nil
}

type MemIterator struct {
    data []int64
    m *MemStoreDriver
    cursor int
    job Job
    err error
}

func (iter *MemIterator) Next() bool {
    if len(iter.data) <= iter.cursor {
        return false
    }
    iter.job, iter.err = iter.m.Get(iter.data[iter.cursor])
    if iter.err != nil {
        return false
    }
    iter.cursor += 1
    return true
}

func (iter *MemIterator) Value() Job {
    return iter.job
}

func (iter *MemIterator) Error() error {
    return iter.err
}

func (iter *MemIterator) Close() {
    iter.m.locker.Unlock()
}
<commit_msg>replace += 1 -> ++<commit_after>package driver

import (
    "fmt"
    "sync"
    "strings"
)

type MemStoreDriver struct {
    data map[int64]*Job
    nameIndex map[string]int64
    lastId int64
    locker *sync.Mutex
}

func NewMemStroeDriver() *MemStoreDriver {
    mem := new(MemStoreDriver)
    mem.locker = new(sync.Mutex)
    mem.nameIndex = make(map[string]int64)
    mem.data = make(map[int64]*Job)
    mem.lastId = 0
    return mem
}

func (m *MemStoreDriver) Save(job *Job) (err error) {
    defer m.locker.Unlock()
    m.locker.Lock()
    if job.Id > 0 {
        old, ok := m.data[job.Id]
        if !ok {
            return fmt.Errorf("Update Job %d fail, the job is not exists.", job.Id)
        }
        if old.Name != job.Name {
            delete(m.nameIndex, old.Func + ":" + old.Name)
            m.nameIndex[job.Func + ":" + job.Name] = job.Id
        }
    } else {
        m.lastId ++
        job.Id = m.lastId
        m.nameIndex[job.Func + ":" + job.Name] = job.Id
    }
    m.data[job.Id] = job
    return
}

func (m *MemStoreDriver) Delete(jobId int64) (err error) {
    defer m.locker.Unlock()
    m.locker.Lock()
    var job Job
    job, err = m.Get(jobId)
    if err != nil {
        return
    }
    delete(m.data, job.Id)
    delete(m.nameIndex, job.Func + ":" + job.Name)
    return
}

func (m *MemStoreDriver) Get(jobId int64) (job Job, err error) {
    j, ok := m.data[jobId]
    if !ok {
        err = fmt.Errorf("Job %d not exists.", jobId)
        return
    }
    job = *j
    return
}

func (m *MemStoreDriver) GetOne(Func, name string) (job Job, err error) {
    jobId, ok := m.nameIndex[Func + ":" + name]
    if !ok {
        err = fmt.Errorf("Job %s:%s not exists.", Func, name)
        return
    }
    job, err = m.Get(jobId)
    return
}

func (m *MemStoreDriver) NewIterator(Func []byte) JobIterator {
    m.locker.Lock()
    var data = make([]int64, 0)
    if Func == nil {
        for jobId, _ := range m.data {
            data = append(data, jobId)
        }
    } else {
        prefix := string(Func)
        for key, jobId := range m.nameIndex {
            if strings.HasPrefix(key, prefix) {
                data = append(data, jobId)
            }
        }
    }
    return &MemIterator{
        data: data,
        m: m,
        cursor: 0,
    }
}

func (m *MemStoreDriver) Close() error {
    return nil
}

type MemIterator struct {
    data []int64
    m *MemStoreDriver
    cursor int
    job Job
    err error
}

func (iter *MemIterator) Next() bool {
    if len(iter.data) <= iter.cursor {
        return false
    }
    iter.job, iter.err = iter.m.Get(iter.data[iter.cursor])
    if iter.err != nil {
        return false
    }
    iter.cursor ++
    return true
}

func (iter *MemIterator) Value() Job {
    return iter.job
}

func (iter *MemIterator) Error() error {
    return iter.err
}

func (iter *MemIterator) Close() {
    iter.m.locker.Unlock()
}
<|endoftext|>


<commit_before>package zeromq

import (
	"fmt"
	"syscall"
	zmq "github.com/pebbe/zmq4"

	"github.com/zinic/gbus/bus"
	"github.com/zinic/gbus/log"
	"github.com/zinic/gbus/context"
	"github.com/zinic/gbus/concurrent"
)

type Message struct {
	Contents string
	Source string
	Destination string
}

type MessageMarshaller func(value interface{}) (data []byte, err error)
type MessageUnmarshaller func(data []byte, value interface{}) (unmarshalled bool, err error)

type SocketManager struct {
	sockets map[string]*zmq.Socket
	socketsContext context.Context
	socketWorkerGroup *concurrent.TaskGroup
}

func (sm *SocketManager) pushSocket(addr string) (socket *zmq.Socket, err error) {
	if addr != "" {
		sm.socketsContext(func() {
			if socket = sm.sockets[addr]; socket == nil {
				if socket, err = zmq.NewSocket(zmq.PUSH); err == nil {
					err = socket.Connect(addr)
				}
			}
		})
	} else {
		err = fmt.Errorf("Destination specified for message is empty.")
	}

	return
}

func DefaultZMQSink() (sink bus.Sink) {
	return NewZMQSink(JSONMessageMarshaller)
}

func NewZMQSink(marshaller MessageMarshaller) (sink bus.Sink) {
	return &ZMQSink {
		SocketManager {
			sockets: make(map[string]*zmq.Socket),
			socketsContext: context.NewLockerContext(),
			socketWorkerGroup: concurrent.NewTaskGroup(&concurrent.TaskGroupConfig {
				Name: "zmq-workers",
				MaxQueuedTasks: 4096,
				MaxActiveWorkers: 4,
			}),
		},
		marshaller,
	}
}

type ZMQSink struct {
	SocketManager
	marshaller MessageMarshaller
}

func (zmqs *ZMQSink) Init(actx bus.ActorContext) (err error) {
	return
}

func (zmqs *ZMQSink) Shutdown() (err error) {
	zmqs.socketsContext(func() {
		for _, sock := range zmqs.sockets {
			sock.Close()
		}

		zmqs.sockets = make(map[string]*zmq.Socket)
	})

	return
}

func (zmqs *ZMQSink) Push(event bus.Event) {
	payload := event.Payload()

	if payload != nil {
		if message, typeOk := payload.(*Message); typeOk {
			output := struct {
				Action interface{}
				Payload interface{}
			}{
				Action: event.Action(),
				Payload: message,
			}

			if data, err := zmqs.marshaller(output); err == nil {
				if socket, err := zmqs.pushSocket(message.Destination); err == nil {
					go func() {
						for sent := 0; sent < len(data); {
							if written, err := socket.SendBytes(data[sent:], 0); err == nil {
								sent += written
							} else {
								log.Errorf("ZMQ send failed: %v", err)
								break
							}
						}
					}()
				} else {
					log.Errorf("Failed to get socket for %s: %v", message.Destination, err)
				}
			} else {
				log.Errorf("Failed to JSON encode %v: %v", output, err)
			}
		}
	}
}

func DefaultZMQGetSource() (source bus.Source) {
	unmarshaller := &JSONMessageUnmarshaller{}
	return NewZMQSource(unmarshaller.Unmarshall)
}

func NewZMQSource(unmarshaller MessageUnmarshaller) (source bus.Source) {
	return &ZMQSource {
		unmarshaller: unmarshaller,
	}
}

type ZMQSource struct {
	socket *zmq.Socket
	unmarshaller MessageUnmarshaller
}

func (zmqs *ZMQSource) Init(actx bus.ActorContext) (err error) {
	if zmqs.socket, err = zmq.NewSocket(zmq.PULL); err == nil {
		err = zmqs.socket.Bind("tcp://127.0.0.1:5555")
	} else {
		log.Errorf("Failed to init ZMQ PULL socket: %v", err)
	}

	return
}

func (zmqs *ZMQSource) Shutdown() (err error) {
	zmqs.socket.Close()
	return
}

func (zmqs *ZMQSource) Pull() (reply bus.Event) {
	if recvStr, err := zmqs.socket.Recv(zmq.DONTWAIT); err != nil {
		if err != syscall.EAGAIN {
			log.Errorf("Failed to recieve from ZMQ PULL socket: %v", err)
		}
	} else {
		var event struct {
			Action interface{}
			Payload *Message
		}

		if unmarshalled, err := zmqs.unmarshaller([]byte(recvStr), &event); err == nil && unmarshalled {
			reply = bus.NewEvent(event.Action, event.Payload)
		} else if err != nil {
			log.Debugf("Failed to unmarshal ZMQ message: %v", err)
		}
	}

	return
}<commit_msg>channel per socket<commit_after>package zeromq

import (
	"fmt"
	"syscall"
	zmq "github.com/pebbe/zmq4"

	"github.com/zinic/gbus/bus"
	"github.com/zinic/gbus/log"
	"github.com/zinic/gbus/context"
	"github.com/zinic/gbus/concurrent"
)

type Message struct {
	Contents string
	Source string
	Destination string
}

type MessageMarshaller func(value interface{}) (data []byte, err error)
type MessageUnmarshaller func(data []byte, value interface{}) (unmarshalled bool, err error)

type SocketContext struct {
	socket *zmq.Socket
	workChannel chan []byte
}

type SocketManager struct {
	sockets map[string]*SocketContext
	activeSockets []string
	socketsContext context.Context
	socketWorkerGroup *concurrent.TaskGroup
}

func (sm *SocketManager) SetInactive(addr string) {
	var idx int
	for idx = 0; idx < len(sm.activeSockets); idx++ {
		if sm.activeSockets[idx] == addr {
			sm.activeSockets = append(sm.activeSockets[:idx], sm.activeSockets[idx+1:]...)
			break
		}
	}
}

func (sm *SocketManager) SetActive(addr string) {
	sm.activeSockets = append(sm.activeSockets, addr)
}

func (sm *SocketManager) Active(addr string) (active bool) {
	active = false
	for _, activeAddr := range sm.activeSockets {
		if activeAddr == addr {
			active = true
			break
		}
	}

	return
}

func (sm *SocketManager) send(socket *zmq.Socket, data []byte) (err error) {
	for sent := 0; sent < len(data); {
		if written, err := socket.SendBytes(data[sent:], 0); err == nil {
			sent += written
		} else {
			log.Errorf("ZMQ send failed: %v", err)
			break
		}
	}

	return
}

func (sm *SocketManager) Send(dst string, data []byte) (err error) {
	sm.socketsContext(func() {
		socketCtx := sm.sockets[dst]

		if socketCtx == nil {
			var socket *zmq.Socket

			if socket, err = zmq.NewSocket(zmq.PUSH); err == nil {
				if err = socket.Connect(dst); err == nil {
					socketCtx = &SocketContext {
						socket: socket,
						workChannel: make(chan []byte, 4096),
					}
				}
			}
		}

		if socketCtx != nil {
			socketCtx.workChannel <- data

			if !sm.Active(dst) {
				sm.SetActive(dst)

				var socketSend func() (err error)
				socketSend = func() (err error) {
					select {
						case event := <- socketCtx.workChannel:
							sm.send(socketCtx.socket, event)
							sm.socketWorkerGroup.Schedule(socketSend)

						default:
							sm.SetInactive(dst)
					}

					return
				}

				sm.socketWorkerGroup.Schedule(socketSend)
			}
		} else {	log.Infof("Sending %v %v", dst, data)

			err = fmt.Errorf("No destination %s found.", dst)
		}
	})

	return
}

func DefaultZMQSink() (sink bus.Sink) {
	return NewZMQSink(JSONMessageMarshaller)
}

func NewZMQSink(marshaller MessageMarshaller) (sink bus.Sink) {
	return &ZMQSink {
		SocketManager {
			sockets: make(map[string]*SocketContext),
			socketsContext: context.NewLockerContext(),
			socketWorkerGroup: concurrent.NewTaskGroup(&concurrent.TaskGroupConfig {
				Name: "zmq-workers",
				MaxQueuedTasks: 4096,
				MaxActiveWorkers: 4,
			}),
		},
		marshaller,
	}
}

type ZMQSink struct {
	SocketManager
	marshaller MessageMarshaller
}

func (zmqs *ZMQSink) Init(actx bus.ActorContext) (err error) {
	zmqs.socketWorkerGroup.Start()

	return
}

func (zmqs *ZMQSink) Shutdown() (err error) {
	zmqs.socketWorkerGroup.Stop()
	zmqs.socketWorkerGroup.Join()

	zmqs.socketsContext(func() {
		for _, sockCtx := range zmqs.sockets {
			sockCtx.socket.Close()
		}

		zmqs.sockets = make(map[string]*SocketContext)
	})
	return
}

func (zmqs *ZMQSink) Push(event bus.Event) {
	payload := event.Payload()

	if payload != nil {
		if message, typeOk := payload.(*Message); typeOk {
			output := struct {
				Action interface{}
				Payload interface{}
			}{
				Action: event.Action(),
				Payload: message,
			}

			if data, err := zmqs.marshaller(output); err == nil {
				zmqs.Send(message.Destination, data)
			} else {
				log.Errorf("Failed to encode %v: %v", output, err)
			}
		}
	}
}

func DefaultZMQGetSource() (source bus.Source) {
	unmarshaller := &JSONMessageUnmarshaller{}
	return NewZMQSource(unmarshaller.Unmarshall)
}

func NewZMQSource(unmarshaller MessageUnmarshaller) (source bus.Source) {
	return &ZMQSource {
		unmarshaller: unmarshaller,
	}
}

type ZMQSource struct {
	socket *zmq.Socket
	unmarshaller MessageUnmarshaller
}

func (zmqs *ZMQSource) Init(actx bus.ActorContext) (err error) {
	if zmqs.socket, err = zmq.NewSocket(zmq.PULL); err == nil {
		err = zmqs.socket.Bind("tcp://127.0.0.1:5555")
	} else {
		log.Errorf("Failed to init ZMQ PULL socket: %v", err)
	}

	return
}

func (zmqs *ZMQSource) Shutdown() (err error) {
	zmqs.socket.Close()
	return
}

func (zmqs *ZMQSource) Pull() (reply bus.Event) {
	if recvStr, err := zmqs.socket.Recv(zmq.DONTWAIT); err != nil {
		if err != syscall.EAGAIN {
			log.Errorf("Failed to recieve from ZMQ PULL socket: %v", err)
		}
	} else {
		var event struct {
			Action interface{}
			Payload *Message
		}

		if unmarshalled, err := zmqs.unmarshaller([]byte(recvStr), &event); err == nil && unmarshalled {
			reply = bus.NewEvent(event.Action, event.Payload)
		} else if err != nil {
			log.Debugf("Failed to unmarshal ZMQ message: %v", err)
		}
	}

	return
}<|endoftext|>


<commit_before>package fuse

// Written with a look to http://ptspts.blogspot.com/2009/11/fuse-protocol-tutorial-for-linux-26.html
import (
	"errors"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"syscall"
	"unsafe"
)

var fusermountBinary string
var umountBinary string

func Socketpair(network string) (l, r *os.File, err error) {
	var domain int
	var typ int
	switch network {
	case "unix":
		domain = syscall.AF_UNIX
		typ = syscall.SOCK_STREAM
	case "unixgram":
		domain = syscall.AF_UNIX
		typ = syscall.SOCK_SEQPACKET
	default:
		log.Panicf("unknown network %q", network)
	}
	fd, errno := syscall.Socketpair(domain, typ, 0)
	if errno != 0 {
		return nil, nil, os.NewSyscallError("socketpair", errno)
	}
	l = os.NewFile(fd[0], "socketpair-half1")
	r = os.NewFile(fd[1], "socketpair-half2")
	return
}

// Create a FUSE FS on the specified mount point.  The returned
// mount point is always absolute.
func mount(mountPoint string, options string) (f *os.File, finalMountPoint string, err error) {
	local, remote, err := Socketpair("unixgram")
	if err != nil {
		return
	}

	defer local.Close()
	defer remote.Close()

	mountPoint = filepath.Clean(mountPoint)
	if !filepath.IsAbs(mountPoint) {
		cwd := ""
		cwd, err = os.Getwd()
		if err != nil {
			return
		}
		mountPoint = filepath.Clean(filepath.Join(cwd, mountPoint))
	}

	cmd := []string{fusermountBinary, mountPoint}
	if options != "" {
		cmd = append(cmd, "-o")
		cmd = append(cmd, options)
	}

	proc, err := os.StartProcess(fusermountBinary,
		cmd,
		&os.ProcAttr{
			Env:   []string{"_FUSE_COMMFD=3"},
			Files: []*os.File{os.Stdin, os.Stdout, os.Stderr, remote}})

	if err != nil {
		return
	}
	w, err := os.Wait(proc.Pid, 0)
	if err != nil {
		return
	}
	if w.ExitStatus() != 0 {
		err = errors.New(fmt.Sprintf("fusermount exited with code %d\n", w.ExitStatus()))
		return
	}

	f, err = getConnection(local)
	finalMountPoint = mountPoint
	return
}

func privilegedUnmount(mountPoint string) error {
	dir, _ := filepath.Split(mountPoint)
	proc, err := os.StartProcess(umountBinary,
		[]string{umountBinary, mountPoint},
		&os.ProcAttr{Dir: dir, Files: []*os.File{nil, nil, os.Stderr}})
	if err != nil {
		return err
	}
	w, err := os.Wait(proc.Pid, 0)
	if w.ExitStatus() != 0 {
		return errors.New(fmt.Sprintf("umount exited with code %d\n", w.ExitStatus()))
	}
	return err
}

func unmount(mountPoint string) (err error) {
	if os.Geteuid() == 0 {
		return privilegedUnmount(mountPoint)
	}
	dir, _ := filepath.Split(mountPoint)
	proc, err := os.StartProcess(fusermountBinary,
		[]string{fusermountBinary, "-u", mountPoint},
		&os.ProcAttr{Dir: dir, Files: []*os.File{nil, nil, os.Stderr}})
	if err != nil {
		return
	}
	w, err := os.Wait(proc.Pid, 0)
	if err != nil {
		return
	}
	if w.ExitStatus() != 0 {
		return errors.New(fmt.Sprintf("fusermount -u exited with code %d\n", w.ExitStatus()))
	}
	return
}

func getConnection(local *os.File) (f *os.File, err error) {
	var data [4]byte
	control := make([]byte, 4*256)

	// n, oobn, recvflags, from, errno  - todo: error checking.
	_, oobn, _, _,
		errno := syscall.Recvmsg(
		local.Fd(), data[:], control[:], 0)
	if errno != 0 {
		return
	}

	message := *(*syscall.Cmsghdr)(unsafe.Pointer(&control[0]))
	fd := *(*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&control[0])) + syscall.SizeofCmsghdr))

	if message.Type != 1 {
		err = errors.New(fmt.Sprintf("getConnection: recvmsg returned wrong control type: %d", message.Type))
		return
	}
	if oobn <= syscall.SizeofCmsghdr {
		err = errors.New(fmt.Sprintf("getConnection: too short control message. Length: %d", oobn))
		return
	}
	if fd < 0 {
		err = errors.New(fmt.Sprintf("getConnection: fd < 0: %d", fd))
		return
	}
	f = os.NewFile(int(fd), "<fuseConnection>")
	return
}

func init() {
	var err error
	fusermountBinary, err = exec.LookPath("fusermount")
	if err != nil {
		log.Fatal("Could not find fusermount binary: %v", err)
	}
	umountBinary, _ = exec.LookPath("umount")
	if err != nil {
		log.Fatalf("Could not find umount binary: %v", err)
	}
}
<commit_msg>Use fmt.Errorf()<commit_after>package fuse

// Written with a look to http://ptspts.blogspot.com/2009/11/fuse-protocol-tutorial-for-linux-26.html
import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"syscall"
	"unsafe"
)

var fusermountBinary string
var umountBinary string

func Socketpair(network string) (l, r *os.File, err error) {
	var domain int
	var typ int
	switch network {
	case "unix":
		domain = syscall.AF_UNIX
		typ = syscall.SOCK_STREAM
	case "unixgram":
		domain = syscall.AF_UNIX
		typ = syscall.SOCK_SEQPACKET
	default:
		log.Panicf("unknown network %q", network)
	}
	fd, errno := syscall.Socketpair(domain, typ, 0)
	if errno != 0 {
		return nil, nil, os.NewSyscallError("socketpair", errno)
	}
	l = os.NewFile(fd[0], "socketpair-half1")
	r = os.NewFile(fd[1], "socketpair-half2")
	return
}

// Create a FUSE FS on the specified mount point.  The returned
// mount point is always absolute.
func mount(mountPoint string, options string) (f *os.File, finalMountPoint string, err error) {
	local, remote, err := Socketpair("unixgram")
	if err != nil {
		return
	}

	defer local.Close()
	defer remote.Close()

	mountPoint = filepath.Clean(mountPoint)
	if !filepath.IsAbs(mountPoint) {
		cwd := ""
		cwd, err = os.Getwd()
		if err != nil {
			return
		}
		mountPoint = filepath.Clean(filepath.Join(cwd, mountPoint))
	}

	cmd := []string{fusermountBinary, mountPoint}
	if options != "" {
		cmd = append(cmd, "-o")
		cmd = append(cmd, options)
	}

	proc, err := os.StartProcess(fusermountBinary,
		cmd,
		&os.ProcAttr{
			Env:   []string{"_FUSE_COMMFD=3"},
			Files: []*os.File{os.Stdin, os.Stdout, os.Stderr, remote}})

	if err != nil {
		return
	}
	w, err := os.Wait(proc.Pid, 0)
	if err != nil {
		return
	}
	if w.ExitStatus() != 0 {
		err = fmt.Errorf("fusermount exited with code %d\n", w.ExitStatus())
		return
	}

	f, err = getConnection(local)
	finalMountPoint = mountPoint
	return
}

func privilegedUnmount(mountPoint string) error {
	dir, _ := filepath.Split(mountPoint)
	proc, err := os.StartProcess(umountBinary,
		[]string{umountBinary, mountPoint},
		&os.ProcAttr{Dir: dir, Files: []*os.File{nil, nil, os.Stderr}})
	if err != nil {
		return err
	}
	w, err := os.Wait(proc.Pid, 0)
	if w.ExitStatus() != 0 {
		return fmt.Errorf("umount exited with code %d\n", w.ExitStatus())
	}
	return err
}

func unmount(mountPoint string) (err error) {
	if os.Geteuid() == 0 {
		return privilegedUnmount(mountPoint)
	}
	dir, _ := filepath.Split(mountPoint)
	proc, err := os.StartProcess(fusermountBinary,
		[]string{fusermountBinary, "-u", mountPoint},
		&os.ProcAttr{Dir: dir, Files: []*os.File{nil, nil, os.Stderr}})
	if err != nil {
		return
	}
	w, err := os.Wait(proc.Pid, 0)
	if err != nil {
		return
	}
	if w.ExitStatus() != 0 {
		return fmt.Errorf("fusermount -u exited with code %d\n", w.ExitStatus())
	}
	return
}

func getConnection(local *os.File) (f *os.File, err error) {
	var data [4]byte
	control := make([]byte, 4*256)

	// n, oobn, recvflags, from, errno  - todo: error checking.
	_, oobn, _, _,
		errno := syscall.Recvmsg(
		local.Fd(), data[:], control[:], 0)
	if errno != 0 {
		return
	}

	message := *(*syscall.Cmsghdr)(unsafe.Pointer(&control[0]))
	fd := *(*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&control[0])) + syscall.SizeofCmsghdr))

	if message.Type != 1 {
		err = fmt.Errorf("getConnection: recvmsg returned wrong control type: %d", message.Type)
		return
	}
	if oobn <= syscall.SizeofCmsghdr {
		err = fmt.Errorf("getConnection: too short control message. Length: %d", oobn)
		return
	}
	if fd < 0 {
		err = fmt.Errorf("getConnection: fd < 0: %d", fd)
		return
	}
	f = os.NewFile(int(fd), "<fuseConnection>")
	return
}

func init() {
	var err error
	fusermountBinary, err = exec.LookPath("fusermount")
	if err != nil {
		log.Fatal("Could not find fusermount binary: %v", err)
	}
	umountBinary, _ = exec.LookPath("umount")
	if err != nil {
		log.Fatalf("Could not find umount binary: %v", err)
	}
}
<|endoftext|>


<commit_before>package vsolver

import (
	"fmt"
	"strings"
)

// dsp - "depspec with packages"
//
// Wraps a set of tpkgs onto a depspec, and returns it.
func dsp(ds depspec, pkgs ...tpkg) depspec {
	ds.pkgs = pkgs
	return ds
}

// pk makes a tpkg appropriate for use in bimodal testing
func pk(path string, imports ...string) tpkg {
	return tpkg{
		path:    path,
		imports: imports,
	}
}

func init() {
	for k, fix := range bimodalFixtures {
		// Assign the name into the fixture itself
		fix.n = k
		bimodalFixtures[k] = fix
	}
}

// Fixtures that rely on simulated bimodal (project and package-level)
// analysis for correct operation. These all have some extra work done on
// them down in init().
var bimodalFixtures = map[string]bimodalFixture{
	// Simple case, ensures that we do the very basics of picking up and
	// including a single, simple import that is expressed an import
	"simple bimodal add": {
		ds: []depspec{
			dsp(dsv("root 0.0.0"),
				pk("root", "a")),
			dsp(dsv("a 1.0.0"),
				pk("a")),
		},
		r: mkresults(
			"a 1.0.0",
		),
	},
	// Ensure it works when the import jump is not from the package with the
	// same path as root, but from a subpkg
	"subpkg bimodal add": {
		ds: mkbmu(
			dsp(dsv("root 0.0.0"),
				pk("root", "root/foo"),
				pk("root/foo", "a"),
			),
			dsp(dsv("a 1.0.0"),
				pk("a"),
			),
		),
		r: mkresults(
			"a 1.0.0",
		),
	},
	// Ensure that if a constraint is expressed, but no actual import exists,
	// then the constraint is disregarded - the project named in the constraint
	// is not part of the solution.
	"ignore constraint without import": {
		ds: mkbmu(
			dsp(dsv("root 0.0.0", "a 1.0.0"),
				pk("root", "root/foo"),
			),
			dsp(dsv("a 1.0.0"),
				pk("a"),
			),
		),
		r: mkresults(),
	},
}

type tpkg struct {
	// Full import path of this package
	path string
	// Slice of full paths to its virtual imports
	imports []string
}

type bmelem interface {
	_bmelem()
}

func (p tpkg) _bmelem() {}

type bimodalFixture struct {
	// name of this fixture datum
	n string
	// bimodal project. first is always treated as root project
	ds []depspec
	// results; map of name/version pairs
	r map[string]Version
	// max attempts the solver should need to find solution. 0 means no limit
	maxAttempts int
	// Use downgrade instead of default upgrade sorter
	downgrade bool
	// lock file simulator, if one's to be used at all
	l fixLock
	// projects expected to have errors, if any
	errp []string
	// request up/downgrade to all projects
	changeall bool
}

func (f bimodalFixture) name() string {
	return f.n
}

func (f bimodalFixture) specs() []depspec {
	return f.ds
}

func (f bimodalFixture) maxTries() int {
	return f.maxAttempts
}

func (f bimodalFixture) expectErrs() []string {
	return f.errp
}

func (f bimodalFixture) result() map[string]Version {
	return f.r
}

type bmSourceManager struct {
	depspecSourceManager
}

var _ SourceManager = &bmSourceManager{}

func newbmSM(ds []depspec) *bmSourceManager {
	sm := &bmSourceManager{}
	sm.specs = ds
	sm.rm = computeBimodalExternalMap(ds)

	return sm
}

func (sm *bmSourceManager) ExternalReach(n ProjectName, v Version) (map[string][]string, error) {
	for _, ds := range sm.specs {
		if ds.n == n && v.Matches(ds.v) {
			rm := make(map[string][]string)
			for _, pkg := range ds.pkgs {
				rm[pkg.path] = pkg.imports
			}

			return rm, nil
		}
	}

	// TODO proper solver errs
	return nil, fmt.Errorf("No reach data for %s at version %s", n, v)
}

func computeBimodalExternalMap(ds []depspec) map[pident][]string {
	rm := make(map[pident][]string)

	for _, d := range ds {
		exmap := make(map[string]struct{})

		for _, pkg := range d.pkgs {
			for _, ex := range pkg.imports {
				if !strings.HasPrefix(ex, string(d.n)) {
					exmap[ex] = struct{}{}
				}
			}
		}

		var list []string
		for ex := range exmap {
			list = append(list, ex)
		}
		id := pident{
			n: d.n,
			v: d.v,
		}
		rm[id] = list
	}

	return rm
}
<commit_msg>Several more tests; transitive subpkg fails<commit_after>package vsolver

import (
	"fmt"
	"strings"
)

// dsp - "depspec with packages"
//
// Wraps a set of tpkgs onto a depspec, and returns it.
func dsp(ds depspec, pkgs ...tpkg) depspec {
	ds.pkgs = pkgs
	return ds
}

// pkg makes a tpkg appropriate for use in bimodal testing
func pkg(path string, imports ...string) tpkg {
	return tpkg{
		path:    path,
		imports: imports,
	}
}

func init() {
	for k, fix := range bimodalFixtures {
		// Assign the name into the fixture itself
		fix.n = k
		bimodalFixtures[k] = fix
	}
}

// Fixtures that rely on simulated bimodal (project and package-level)
// analysis for correct operation. These all have some extra work done on
// them down in init().
var bimodalFixtures = map[string]bimodalFixture{
	// Simple case, ensures that we do the very basics of picking up and
	// including a single, simple import that is expressed an import
	"simple bm-add": {
		ds: []depspec{
			dsp(dsv("root 0.0.0"),
				pkg("root", "a")),
			dsp(dsv("a 1.0.0"),
				pkg("a")),
		},
		r: mkresults(
			"a 1.0.0",
		),
	},
	// Ensure it works when the import jump is not from the package with the
	// same path as root, but from a subpkg
	"subpkg bm-add": {
		ds: []depspec{
			dsp(dsv("root 0.0.0"),
				pkg("root", "root/foo"),
				pkg("root/foo", "a"),
			),
			dsp(dsv("a 1.0.0"),
				pkg("a"),
			),
		},
		r: mkresults(
			"a 1.0.0",
		),
	},
	// Importing package from project with no root package
	"bm-add on project with no pkg in root dir": {
		ds: []depspec{
			dsp(dsv("root 0.0.0"),
				pkg("root", "a/foo")),
			dsp(dsv("a 1.0.0"),
				pkg("a/foo")),
		},
		r: mkresults(
			"a 1.0.0",
		),
	},
	// Import jump is in a dep, and points to a transitive dep
	"transitive bm-add": {
		ds: []depspec{
			dsp(dsv("root 0.0.0"),
				pkg("root", "root/foo"),
				pkg("root/foo", "a"),
			),
			dsp(dsv("a 1.0.0"),
				pkg("a", "b"),
			),
			dsp(dsv("b 1.0.0"),
				pkg("b"),
			),
		},
		r: mkresults(
			"a 1.0.0",
			"b 1.0.0",
		),
	},
	// Import jump is in a dep subpkg, and points to a transitive dep
	"transitive subpkg bm-add": {
		ds: []depspec{
			dsp(dsv("root 0.0.0"),
				pkg("root", "root/foo"),
				pkg("root/foo", "a"),
			),
			dsp(dsv("a 1.0.0"),
				pkg("a", "a/bar"),
				pkg("a/bar", "b"),
			),
			dsp(dsv("b 1.0.0"),
				pkg("b"),
			),
		},
		r: mkresults(
			"a 1.0.0",
			"b 1.0.0",
		),
	},
	// Ensure that if a constraint is expressed, but no actual import exists,
	// then the constraint is disregarded - the project named in the constraint
	// is not part of the solution.
	"ignore constraint without import": {
		ds: []depspec{
			dsp(dsv("root 0.0.0", "a 1.0.0"),
				pkg("root", "root/foo"),
			),
			dsp(dsv("a 1.0.0"),
				pkg("a"),
			),
		},
		r: mkresults(),
	},
}

type tpkg struct {
	// Full import path of this package
	path string
	// Slice of full paths to its virtual imports
	imports []string
}

type bmelem interface {
	_bmelem()
}

func (p tpkg) _bmelem() {}

type bimodalFixture struct {
	// name of this fixture datum
	n string
	// bimodal project. first is always treated as root project
	ds []depspec
	// results; map of name/version pairs
	r map[string]Version
	// max attempts the solver should need to find solution. 0 means no limit
	maxAttempts int
	// Use downgrade instead of default upgrade sorter
	downgrade bool
	// lock file simulator, if one's to be used at all
	l fixLock
	// projects expected to have errors, if any
	errp []string
	// request up/downgrade to all projects
	changeall bool
}

func (f bimodalFixture) name() string {
	return f.n
}

func (f bimodalFixture) specs() []depspec {
	return f.ds
}

func (f bimodalFixture) maxTries() int {
	return f.maxAttempts
}

func (f bimodalFixture) expectErrs() []string {
	return f.errp
}

func (f bimodalFixture) result() map[string]Version {
	return f.r
}

type bmSourceManager struct {
	depspecSourceManager
}

var _ SourceManager = &bmSourceManager{}

func newbmSM(ds []depspec) *bmSourceManager {
	sm := &bmSourceManager{}
	sm.specs = ds
	sm.rm = computeBimodalExternalMap(ds)

	return sm
}

func (sm *bmSourceManager) ExternalReach(n ProjectName, v Version) (map[string][]string, error) {
	for _, ds := range sm.specs {
		if ds.n == n && v.Matches(ds.v) {
			rm := make(map[string][]string)
			for _, pkg := range ds.pkgs {
				rm[pkg.path] = pkg.imports
			}

			return rm, nil
		}
	}

	// TODO proper solver errs
	return nil, fmt.Errorf("No reach data for %s at version %s", n, v)
}

func computeBimodalExternalMap(ds []depspec) map[pident][]string {
	rm := make(map[pident][]string)

	for _, d := range ds {
		exmap := make(map[string]struct{})

		for _, pkg := range d.pkgs {
			for _, ex := range pkg.imports {
				if !strings.HasPrefix(ex, string(d.n)) {
					exmap[ex] = struct{}{}
				}
			}
		}

		var list []string
		for ex := range exmap {
			list = append(list, ex)
		}
		id := pident{
			n: d.n,
			v: d.v,
		}
		rm[id] = list
	}

	return rm
}
<|endoftext|>


<commit_before>package main

import (
    "os"
    "os/exec"
    "os/signal"
    "syscall"
   // "net/http"
    "log"
    "flag"
    "fmt"
)

var localPort *string = flag.String("p", "3000", "local port")
var logpath *string = flag.String("l", "path", "log file path")
var lines *string = flag.String("n", "100", "log file path")

func signalCatcher() {
        ch := make(chan os.Signal)
        signal.Notify(ch, syscall.SIGINT)
        <-ch
        log.Println("CTRL-C; exiting")
        os.Exit(0)
}

func main() {
	go signalCatcher()
  flag.Parse()
  fmt.Printf("Listening: %v Serving: %v\n", *localPort, *logpath)
fmt.Printf("Tail: \n")
tail()
fmt.Printf("Head: \n")
head()
search := "controller"
fmt.Printf("grep: %s\n",search)
grep(search)
}

func tail(){
    app := "tail"
    arg0 := *logpath //*lines
    cmd := exec.Command(app, arg0)
    out, err := cmd.Output()

    if err != nil {
        println(err.Error())
        return
    }
print(string(out))

}

func head(){
    app := "head"
    arg0 := *logpath //*lines
    cmd := exec.Command(app, arg0)
    out, err := cmd.Output()

    if err != nil {
        println(err.Error())
        return
    }
print(string(out))
}

func grep(search string){
    app := "grep"
    arg1 := *logpath //*lines
    arg0:= search
    cmd := exec.Command(app, arg0, arg1)
    out, err := cmd.Output()

    if err != nil {
        println(err.Error())
        return
    }
print(string(out))
}<commit_msg>:) started working, need to tweak and clean it up<commit_after>package main

import (
    "os"
    "os/exec"
    "os/signal"
    "syscall"
    "net/http"
    "log"
    "flag"
    "fmt"
)

var localPort *string = flag.String("p", "3000", "local port")
var logpath *string = flag.String("l", "path", "log file path")
var lines *string = flag.String("n", "100", "log file path")

func signalCatcher() {
        ch := make(chan os.Signal)
        signal.Notify(ch, syscall.SIGINT)
        <-ch
        log.Println("CTRL-C; exiting")
        os.Exit(0)
}

func main() {
	go signalCatcher()
  flag.Parse()
  fmt.Printf("Listening: %v Serving: %v\n", *localPort, *logpath)
fmt.Printf("Tail: \n")
 tail()
fmt.Printf("Head: \n")
 head()
search := "controller"
fmt.Printf("grep: %s\n",search)
 grep(search)

 http.HandleFunc("/", handler)
 http.HandleFunc("/tail", tailhandler)
 http.HandleFunc("/head", headhandler)
 http.HandleFunc("/grep", grephandler)
 err := http.ListenAndServe(":8000", nil)
        if err != nil {
                panic(err)
        }
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "log server")
}

func tailhandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, tail())
}

func headhandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, head())
}

func grephandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, grep("controller"))
}

func tail() string{
    app := "tail"
    arg0 := *logpath //*lines
    cmd := exec.Command(app, arg0)
    out, err := cmd.Output()

    if err != nil {
        println(err.Error())
        return "error"
    }
return string(out)

}

func head() string{
    app := "head"
    arg0 := *logpath //*lines
    cmd := exec.Command(app, arg0)
    out, err := cmd.Output()

    if err != nil {
        println(err.Error())
        return "error"
    }
return string(out)
}

func grep(search string) string{
    app := "grep"
    arg1 := *logpath //*lines
    arg0:= search
    cmd := exec.Command(app, arg0, arg1)
    out, err := cmd.Output()

    if err != nil {
        println(err.Error())
        return "error"
    }
return string(out)
}<|endoftext|>


<commit_before>package gen

type Config struct {
	Source      string   `json:"source"`
	Destination string   `json:'destination"`
	Safe        bool     `json:"safe"`
	Excluede    []string `json:"exclude"`
	Include     string   `json""include"`
	KeepFiles   string   `json:"keep_files"`
	TimeZone    string   `json:"timezone"`
	Encoding    string   `json:"encoding"`
	Port        int      `json:"port"`
	Host        string   `json:"host"`
	BaseURL     string   `json:"base_url"`
}

type System struct {
	Boot    *Boot   `json:"boot"`
	Config  *Config `json:"config"`
	Plan    *Plan   `json:"plan"`
	WorkDir string  `json:"work_dir"`
}

type Boot struct {
	ConfiFile string            `json:"config_file"`
	PlanFile  string            `json:"plan_file"`
	ENV       map[string]string `json:"env"`
}

type Theme struct {
	Name   string   `json:"name"`
	Author []Author `json:"author"`
}

type Author struct {
	Name     string `json:"name"`
	Github   string `json:"github"`
	Twitter  string `json:"twitter"`
	Linkedin string `json:"linkedin"`
	Email    string `json:"email"`
	Website  string `json:"website"`
}
<commit_msg>Include a list of files<commit_after>package gen

type Config struct {
	Source      string   `json:"source"`
	Destination string   `json:'destination"`
	Safe        bool     `json:"safe"`
	Excluede    []string `json:"exclude"`
	Include     []string `json""include"`
	KeepFiles   string   `json:"keep_files"`
	TimeZone    string   `json:"timezone"`
	Encoding    string   `json:"encoding"`
	Port        int      `json:"port"`
	Host        string   `json:"host"`
	BaseURL     string   `json:"base_url"`
}

type System struct {
	Boot    *Boot   `json:"boot"`
	Config  *Config `json:"config"`
	Plan    *Plan   `json:"plan"`
	WorkDir string  `json:"work_dir"`
}

type Boot struct {
	ConfiFile string            `json:"config_file"`
	PlanFile  string            `json:"plan_file"`
	ENV       map[string]string `json:"env"`
}

type Theme struct {
	Name   string   `json:"name"`
	Author []Author `json:"author"`
}

type Author struct {
	Name     string `json:"name"`
	Github   string `json:"github"`
	Twitter  string `json:"twitter"`
	Linkedin string `json:"linkedin"`
	Email    string `json:"email"`
	Website  string `json:"website"`
}
<|endoftext|>


<commit_before>package main

import "fmt"
import "os"

func main() {
	er := os.MkdirAll(os.Args[1],0777)
	if er != nil {
		fmt.Println(er);
	}
}<commit_msg>format package<commit_after>package main

import "fmt"
import "os"

func main() {
	er := os.MkdirAll(os.Args[1], 0777)
	if er != nil {
		fmt.Println(er)
	}
}<|endoftext|>