<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/codegangsta/cli"
	"github.com/koding/klientctl/klientctlerrors"
)

const kiteHTTPResponse = "Welcome to SockJS!\n"

var defaultHealthChecker *HealthChecker

func init() {
	defaultHealthChecker = &HealthChecker{
		HTTPClient: &http.Client{
			Timeout: 4 * time.Second,
		},
		LocalKiteAddress:  KlientAddress,
		RemoteKiteAddress: KontrolURL,
		RemoteHTTPAddress: S3UpdateLocation,
	}
}

// HealthChecker implements state for the various HealthCheck functions,
// ideal for mocking the health check interfaces (local kite, remote http,
// remote kite, etc)
type HealthChecker struct {
	HTTPClient *http.Client

	// Used for verifying a locally / remotely running kite
	LocalKiteAddress  string
	RemoteKiteAddress string

	// Used for verifying a working internet connection
	RemoteHTTPAddress string
}

// ErrHealthDialFailed is used when dialing klient itself is failing. Local or remote,
// it depends on the error message.
type ErrHealthDialFailed struct{ Message string }

// ErrHealthNoHTTPReponse is used when a klient is not returning an http
// response. Local or remote, it depends on the error message.
type ErrHealthNoHTTPReponse struct{ Message string }

// ErrHealthUnreadableKiteKey is used when we are unable to read the kite.key,
// so it either doesn't exist at the specified location or the permissions are
// broken relative to the current user.
type ErrHealthUnreadableKiteKey struct{ Message string }

// ErrHealthUnexpectedResponse is used when a klient's http response on
// kiteAddress:/kite does not match the "Welcome to SockJS!" response. Local or
// remote, it depends on the error message.
type ErrHealthUnexpectedResponse struct{ Message string }

// ErrHealthNoInternet is used when the http response to a reliable endpoint
// (Google.com, for example) was unable to connect. If this is the case, the
// user is having internet troubles.
type ErrHealthNoInternet struct{ Message string }

// ErrHealthNoKontrolHTTPResponse is used when the http response from
// https://koding.com/kontrol/kite failed. Koding itself might be down, or the
// users internet might be spotty.
type ErrHealthNoKontrolHTTPResponse struct{ Message string }

func (e ErrHealthDialFailed) Error() string            { return e.Message }
func (e ErrHealthNoHTTPReponse) Error() string         { return e.Message }
func (e ErrHealthUnreadableKiteKey) Error() string     { return e.Message }
func (e ErrHealthUnexpectedResponse) Error() string    { return e.Message }
func (e ErrHealthNoInternet) Error() string            { return e.Message }
func (e ErrHealthNoKontrolHTTPResponse) Error() string { return e.Message }

// StatusCommand informs the user about the status of the Klient service. It
// does this in multiple stages, to help identify specific problems.
//
// 1. First it checks if the expected localhost http response is
// available. If it isn't, klient is not running properly or something
// else had taken the port.
//
// 2. Next, it checks if the auth is working properly, by dialing
// klient. Because we already checked if the http response was working,
// something else may be wrong. Such as the key not existing, or
// somehow kd using the wrong key, etc.
//
// 3. Lastly it checks if the user's IP has the exposed klient port. This
// is not an error because outgoing klient communication will still work,
// but incoming klient functionality will obviously be limited. So by
// checking, we can inform the user.
func StatusCommand(c *cli.Context) int {
	if len(c.Args()) != 0 {
		cli.ShowCommandHelp(c, "status")
		return 1
	}

	res, ok := defaultHealthChecker.CheckAllWithResponse()
	fmt.Println(res)
	if !ok {
		return 1
	}

	return 0
}

// CheckLocal runs several diagnostics on the local Klient. Errors
// indicate an unhealthy or not running Klient, and can be compare to
// the ErrHealth* types.
//
// TODO: Possibly return a set of warnings too? If we have any..
func (c *HealthChecker) CheckLocal() error {
	res, err := c.HTTPClient.Get(c.LocalKiteAddress)
	// If there was an error even talking to Klient, something is wrong.
	if err != nil {
		return ErrHealthNoHTTPReponse{Message: fmt.Sprintf(
			"The local klient /kite route is returning an error: '%s'", err,
		)}
	}
	defer res.Body.Close()

	// It should be safe to ignore any errors dumping the response data,
	// since we just want to check the data itself. Handling the error
	// might aid with debugging any problems though.
	resData, _ := ioutil.ReadAll(res.Body)
	if string(resData) != kiteHTTPResponse {
		return ErrHealthUnexpectedResponse{Message: fmt.Sprintf(
			"The local klient /kite route is returning an unexpected response: '%s'",
			string(resData),
		)}
	}

	// The only error CreateKlientClient returns (currently) is kite read
	// error, so we can handle that.
	k, err := CreateKlientClient(NewKlientOptions())
	if err != nil {
		return ErrHealthUnreadableKiteKey{Message: fmt.Sprintf(
			"The klient kite key is unable to be read. Reason: '%s'", err.Error(),
		)}
	}

	// TODO: Identify varing Dial errors to produce meaningful health
	// responses.
	if err = k.Dial(); err != nil {
		return ErrHealthDialFailed{Message: fmt.Sprintf(
			"Dailing local klient failed. Reason: %s", err,
		)}
	}

	return nil
}

// CheckRemote checks the integrity of the ability to connect
// to remote addresses, and thus verifying internet.
func (c *HealthChecker) CheckRemote() error {
	// Attempt to connect to google (or some reliable service) to
	// confirm the user's outbound internet connection.
	res, err := c.HTTPClient.Get(c.RemoteHTTPAddress)
	if err != nil {
		return ErrHealthNoInternet{Message: fmt.Sprintf(
			"The internet connection fails to '%s'. Reason: %s",
			c.RemoteHTTPAddress, err.Error(),
		)}
	}
	defer res.Body.Close()

	// Attempt to connect to kontrol's http page, simply to get an idea
	// if Koding is running or not.
	res, err = c.HTTPClient.Get(c.RemoteKiteAddress)
	if err != nil {
		return ErrHealthNoKontrolHTTPResponse{Message: fmt.Sprintf(
			"A http request to Kontrol failed. Reason: %s", err.Error(),
		)}
	}
	defer res.Body.Close()

	// Kontrol should return a 200 response.
	if res.StatusCode < 200 || res.StatusCode > 299 {
		return ErrHealthNoKontrolHTTPResponse{Message: fmt.Sprintf(
			"A http request to Kontrol returned bad status code. Code: %d",
			res.StatusCode,
		)}
	}

	// It should be safe to ignore any errors dumping the response data,
	// since we just want to check the data itself. Handling the error
	// might aid with debugging any problems though.
	//
	// TODO: Log the response if it's not as expected, to help
	// debug Cloudflare/nginx issues.
	resData, _ := ioutil.ReadAll(res.Body)
	if string(resData) != kiteHTTPResponse {
		return ErrHealthUnexpectedResponse{Message: fmt.Sprintf(
			"The '%s' route is returning an unexpected response: '%s'",
			c.RemoteKiteAddress, string(resData),
		)}
	}

	// TODO: Check the local ip address for an open port. We
	// need to implement a service on Koding to properly ip check though,
	// since we've been having problems with echoip.net failing.

	return nil
}

// CheckAllWithResponse checks local and remote, and parses the response to a
// user-friendly response. Because a response may be good or bad, a bool is also
// returned. If true, the response is good _(ie, positive, not an problem)_, and
// if it is false the response represents a problem.
//
// TODO: Enable debug logs
// log.Print(err.Error())
func (c *HealthChecker) CheckAllWithResponse() (res string, ok bool) {
	if err := defaultHealthChecker.CheckLocal(); err != nil {
		switch err.(type) {
		case ErrHealthNoHTTPReponse:
			res = fmt.Sprintf(
				`Error: The %s does not appear to be running. Please run
the following command to start it:

    sudo kd start
`,
				KlientName)

		case ErrHealthUnexpectedResponse:
			res = fmt.Sprintf(`Error: The %s is not running properly. Please run the
following command to restart it:

    sudo kd restart
`,
				KlientName)

		case ErrHealthUnreadableKiteKey:
			res = fmt.Sprintf(`Error: The authorization file for the %s is malformed
or missing. Please run the following command:

    sudo kd install
`,
				KlientName)

		// TODO: What are some good steps for the user to take if dial fails?
		case ErrHealthDialFailed:
			res = fmt.Sprintf(`Error: The %s does not appear to be running properly.
Please run the following command:

    sudo kd restart
`,
				KlientName)

		default:
			res = fmt.Sprintf("Unknown local healthcheck error: %s", err.Error())
		}

		return res, false
	}

	if err := defaultHealthChecker.CheckRemote(); err != nil {
		switch err.(type) {
		case ErrHealthNoInternet:
			res = fmt.Sprintf(`Error: You do not appear to have a properly working internet connection.`)

		case ErrHealthNoKontrolHTTPResponse:
			res = fmt.Sprintf(`Error: koding.com does not appear to be responding.
If this problem persists, please contact us at: support@koding.com
`)

		default:
			res = fmt.Sprintf("Unknown remote healthcheck error: %s", err.Error())
		}

		return res, false
	}

	res = fmt.Sprintf(
		"The %s appears to be running and is healthy.", KlientName,
	)

	return res, true
}

// CheckAllFailureOrMessagef runs CheckAllWithResponse and if there is a failure,
// returns that status message. If CheckAllWithResponse returns ok, the formatted
// message is returned. This *does not* print success messages.
//
// This is a shorthand for informing the user about an error. There already was an
// error, we're just trying to inform the user what it was about. For comparison,
// here is the syntax that this method provides:
//
//     fmt.Println(defaultHealthChecker.FailureResponseOrMessagef(
//       "Error connecting to %s: '%s'\n", KlientName, err,
//     ))
//
// And here is the syntax we're avoiding:
//
//     s, ok := defaultHealthChecker.CheckAllWithResponse()
//     if ok {
//       fmt.Printf("Error connecting to %s: '%s'\n", KlientName, err)
//     } else {
//       fmt.Println(s)
//     }
func (c *HealthChecker) CheckAllFailureOrMessagef(f string, i ...interface{}) string {
	if s, ok := c.CheckAllWithResponse(); !ok {
		return s
	}

	return fmt.Sprintf(f, i...)
}

// IsKlientRunning does a quick check against klient's http server
// to verify that it is running. It does *not* check the auth or tcp
// connection, it *just* attempts to verify that klient is running.
func IsKlientRunning(a string) bool {
	res, err := http.Get(a)

	if res != nil {
		defer res.Body.Close()
	}

	// If there was an error even talking to Klient, something is wrong.
	if err != nil {
		return false
	}

	// It should be safe to ignore any errors dumping the response data,
	// since we just want to check the data itself. Handling the error
	// might aid with debugging any problems though.
	resData, _ := ioutil.ReadAll(res.Body)
	if string(resData) != kiteHTTPResponse {
		return false
	}

	return true
}

func getListErrRes(err error, healthChecker *HealthChecker) string {
	res, ok := defaultHealthChecker.CheckAllWithResponse()

	// If the health check response is not okay, return that because it's likely
	// more informed (such as no internet, etc)
	if !ok {
		return res
	}

	// Because healthChecker couldn't find anything wrong, but we know there is an
	// err, check to see if it's a getKites err
	if klientctlerrors.IsListReconnectingErr(err) {
		return ReconnectingToKontrol
	} else {
		return FailedListMachines
	}
}
<commit_msg>styleguide: Removed unneeded else<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/codegangsta/cli"
	"github.com/koding/klientctl/klientctlerrors"
)

const kiteHTTPResponse = "Welcome to SockJS!\n"

var defaultHealthChecker *HealthChecker

func init() {
	defaultHealthChecker = &HealthChecker{
		HTTPClient: &http.Client{
			Timeout: 4 * time.Second,
		},
		LocalKiteAddress:  KlientAddress,
		RemoteKiteAddress: KontrolURL,
		RemoteHTTPAddress: S3UpdateLocation,
	}
}

// HealthChecker implements state for the various HealthCheck functions,
// ideal for mocking the health check interfaces (local kite, remote http,
// remote kite, etc)
type HealthChecker struct {
	HTTPClient *http.Client

	// Used for verifying a locally / remotely running kite
	LocalKiteAddress  string
	RemoteKiteAddress string

	// Used for verifying a working internet connection
	RemoteHTTPAddress string
}

// ErrHealthDialFailed is used when dialing klient itself is failing. Local or remote,
// it depends on the error message.
type ErrHealthDialFailed struct{ Message string }

// ErrHealthNoHTTPReponse is used when a klient is not returning an http
// response. Local or remote, it depends on the error message.
type ErrHealthNoHTTPReponse struct{ Message string }

// ErrHealthUnreadableKiteKey is used when we are unable to read the kite.key,
// so it either doesn't exist at the specified location or the permissions are
// broken relative to the current user.
type ErrHealthUnreadableKiteKey struct{ Message string }

// ErrHealthUnexpectedResponse is used when a klient's http response on
// kiteAddress:/kite does not match the "Welcome to SockJS!" response. Local or
// remote, it depends on the error message.
type ErrHealthUnexpectedResponse struct{ Message string }

// ErrHealthNoInternet is used when the http response to a reliable endpoint
// (Google.com, for example) was unable to connect. If this is the case, the
// user is having internet troubles.
type ErrHealthNoInternet struct{ Message string }

// ErrHealthNoKontrolHTTPResponse is used when the http response from
// https://koding.com/kontrol/kite failed. Koding itself might be down, or the
// users internet might be spotty.
type ErrHealthNoKontrolHTTPResponse struct{ Message string }

func (e ErrHealthDialFailed) Error() string            { return e.Message }
func (e ErrHealthNoHTTPReponse) Error() string         { return e.Message }
func (e ErrHealthUnreadableKiteKey) Error() string     { return e.Message }
func (e ErrHealthUnexpectedResponse) Error() string    { return e.Message }
func (e ErrHealthNoInternet) Error() string            { return e.Message }
func (e ErrHealthNoKontrolHTTPResponse) Error() string { return e.Message }

// StatusCommand informs the user about the status of the Klient service. It
// does this in multiple stages, to help identify specific problems.
//
// 1. First it checks if the expected localhost http response is
// available. If it isn't, klient is not running properly or something
// else had taken the port.
//
// 2. Next, it checks if the auth is working properly, by dialing
// klient. Because we already checked if the http response was working,
// something else may be wrong. Such as the key not existing, or
// somehow kd using the wrong key, etc.
//
// 3. Lastly it checks if the user's IP has the exposed klient port. This
// is not an error because outgoing klient communication will still work,
// but incoming klient functionality will obviously be limited. So by
// checking, we can inform the user.
func StatusCommand(c *cli.Context) int {
	if len(c.Args()) != 0 {
		cli.ShowCommandHelp(c, "status")
		return 1
	}

	res, ok := defaultHealthChecker.CheckAllWithResponse()
	fmt.Println(res)
	if !ok {
		return 1
	}

	return 0
}

// CheckLocal runs several diagnostics on the local Klient. Errors
// indicate an unhealthy or not running Klient, and can be compare to
// the ErrHealth* types.
//
// TODO: Possibly return a set of warnings too? If we have any..
func (c *HealthChecker) CheckLocal() error {
	res, err := c.HTTPClient.Get(c.LocalKiteAddress)
	// If there was an error even talking to Klient, something is wrong.
	if err != nil {
		return ErrHealthNoHTTPReponse{Message: fmt.Sprintf(
			"The local klient /kite route is returning an error: '%s'", err,
		)}
	}
	defer res.Body.Close()

	// It should be safe to ignore any errors dumping the response data,
	// since we just want to check the data itself. Handling the error
	// might aid with debugging any problems though.
	resData, _ := ioutil.ReadAll(res.Body)
	if string(resData) != kiteHTTPResponse {
		return ErrHealthUnexpectedResponse{Message: fmt.Sprintf(
			"The local klient /kite route is returning an unexpected response: '%s'",
			string(resData),
		)}
	}

	// The only error CreateKlientClient returns (currently) is kite read
	// error, so we can handle that.
	k, err := CreateKlientClient(NewKlientOptions())
	if err != nil {
		return ErrHealthUnreadableKiteKey{Message: fmt.Sprintf(
			"The klient kite key is unable to be read. Reason: '%s'", err.Error(),
		)}
	}

	// TODO: Identify varing Dial errors to produce meaningful health
	// responses.
	if err = k.Dial(); err != nil {
		return ErrHealthDialFailed{Message: fmt.Sprintf(
			"Dailing local klient failed. Reason: %s", err,
		)}
	}

	return nil
}

// CheckRemote checks the integrity of the ability to connect
// to remote addresses, and thus verifying internet.
func (c *HealthChecker) CheckRemote() error {
	// Attempt to connect to google (or some reliable service) to
	// confirm the user's outbound internet connection.
	res, err := c.HTTPClient.Get(c.RemoteHTTPAddress)
	if err != nil {
		return ErrHealthNoInternet{Message: fmt.Sprintf(
			"The internet connection fails to '%s'. Reason: %s",
			c.RemoteHTTPAddress, err.Error(),
		)}
	}
	defer res.Body.Close()

	// Attempt to connect to kontrol's http page, simply to get an idea
	// if Koding is running or not.
	res, err = c.HTTPClient.Get(c.RemoteKiteAddress)
	if err != nil {
		return ErrHealthNoKontrolHTTPResponse{Message: fmt.Sprintf(
			"A http request to Kontrol failed. Reason: %s", err.Error(),
		)}
	}
	defer res.Body.Close()

	// Kontrol should return a 200 response.
	if res.StatusCode < 200 || res.StatusCode > 299 {
		return ErrHealthNoKontrolHTTPResponse{Message: fmt.Sprintf(
			"A http request to Kontrol returned bad status code. Code: %d",
			res.StatusCode,
		)}
	}

	// It should be safe to ignore any errors dumping the response data,
	// since we just want to check the data itself. Handling the error
	// might aid with debugging any problems though.
	//
	// TODO: Log the response if it's not as expected, to help
	// debug Cloudflare/nginx issues.
	resData, _ := ioutil.ReadAll(res.Body)
	if string(resData) != kiteHTTPResponse {
		return ErrHealthUnexpectedResponse{Message: fmt.Sprintf(
			"The '%s' route is returning an unexpected response: '%s'",
			c.RemoteKiteAddress, string(resData),
		)}
	}

	// TODO: Check the local ip address for an open port. We
	// need to implement a service on Koding to properly ip check though,
	// since we've been having problems with echoip.net failing.

	return nil
}

// CheckAllWithResponse checks local and remote, and parses the response to a
// user-friendly response. Because a response may be good or bad, a bool is also
// returned. If true, the response is good _(ie, positive, not an problem)_, and
// if it is false the response represents a problem.
//
// TODO: Enable debug logs
// log.Print(err.Error())
func (c *HealthChecker) CheckAllWithResponse() (res string, ok bool) {
	if err := defaultHealthChecker.CheckLocal(); err != nil {
		switch err.(type) {
		case ErrHealthNoHTTPReponse:
			res = fmt.Sprintf(
				`Error: The %s does not appear to be running. Please run
the following command to start it:

    sudo kd start
`,
				KlientName)

		case ErrHealthUnexpectedResponse:
			res = fmt.Sprintf(`Error: The %s is not running properly. Please run the
following command to restart it:

    sudo kd restart
`,
				KlientName)

		case ErrHealthUnreadableKiteKey:
			res = fmt.Sprintf(`Error: The authorization file for the %s is malformed
or missing. Please run the following command:

    sudo kd install
`,
				KlientName)

		// TODO: What are some good steps for the user to take if dial fails?
		case ErrHealthDialFailed:
			res = fmt.Sprintf(`Error: The %s does not appear to be running properly.
Please run the following command:

    sudo kd restart
`,
				KlientName)

		default:
			res = fmt.Sprintf("Unknown local healthcheck error: %s", err.Error())
		}

		return res, false
	}

	if err := defaultHealthChecker.CheckRemote(); err != nil {
		switch err.(type) {
		case ErrHealthNoInternet:
			res = fmt.Sprintf(`Error: You do not appear to have a properly working internet connection.`)

		case ErrHealthNoKontrolHTTPResponse:
			res = fmt.Sprintf(`Error: koding.com does not appear to be responding.
If this problem persists, please contact us at: support@koding.com
`)

		default:
			res = fmt.Sprintf("Unknown remote healthcheck error: %s", err.Error())
		}

		return res, false
	}

	res = fmt.Sprintf(
		"The %s appears to be running and is healthy.", KlientName,
	)

	return res, true
}

// CheckAllFailureOrMessagef runs CheckAllWithResponse and if there is a failure,
// returns that status message. If CheckAllWithResponse returns ok, the formatted
// message is returned. This *does not* print success messages.
//
// This is a shorthand for informing the user about an error. There already was an
// error, we're just trying to inform the user what it was about. For comparison,
// here is the syntax that this method provides:
//
//     fmt.Println(defaultHealthChecker.FailureResponseOrMessagef(
//       "Error connecting to %s: '%s'\n", KlientName, err,
//     ))
//
// And here is the syntax we're avoiding:
//
//     s, ok := defaultHealthChecker.CheckAllWithResponse()
//     if ok {
//       fmt.Printf("Error connecting to %s: '%s'\n", KlientName, err)
//     } else {
//       fmt.Println(s)
//     }
func (c *HealthChecker) CheckAllFailureOrMessagef(f string, i ...interface{}) string {
	if s, ok := c.CheckAllWithResponse(); !ok {
		return s
	}

	return fmt.Sprintf(f, i...)
}

// IsKlientRunning does a quick check against klient's http server
// to verify that it is running. It does *not* check the auth or tcp
// connection, it *just* attempts to verify that klient is running.
func IsKlientRunning(a string) bool {
	res, err := http.Get(a)

	if res != nil {
		defer res.Body.Close()
	}

	// If there was an error even talking to Klient, something is wrong.
	if err != nil {
		return false
	}

	// It should be safe to ignore any errors dumping the response data,
	// since we just want to check the data itself. Handling the error
	// might aid with debugging any problems though.
	resData, _ := ioutil.ReadAll(res.Body)
	if string(resData) != kiteHTTPResponse {
		return false
	}

	return true
}

func getListErrRes(err error, healthChecker *HealthChecker) string {
	res, ok := defaultHealthChecker.CheckAllWithResponse()

	// If the health check response is not okay, return that because it's likely
	// more informed (such as no internet, etc)
	if !ok {
		return res
	}

	// Because healthChecker couldn't find anything wrong, but we know there is an
	// err, check to see if it's a getKites err
	if klientctlerrors.IsListReconnectingErr(err) {
		return ReconnectingToKontrol
	}

	return FailedListMachines
}
<|endoftext|>


<commit_before>package job

import (
	"fmt"
	"os/exec"
	"strconv"
	"strings"
	"time"

	"../utils/iso8601"

	"github.com/222Labs/common/go/logging"
	"github.com/nu7hatch/gouuid"
)

var (
	AllJobs = make(map[string]*Job)
	log     = logging.GetLogger("kala")
)

type Job struct {
	Name string `json:"name"`
	Id   string `json:"id"`

	// Command to run
	// e.g. "bash /path/to/my/script.sh"
	Command string `json:"command"`

	// Email of the owner of this job
	// e.g. "admin@example.com"
	Owner string `json:"owner"`

	// Is this job disabled?
	Disabled bool `json:"disabled"`

	// Jobs that are dependent upon this one.
	// Will be run after this job runs.
	DependentJobs []string `json:"dependent_jobs"`
	ParentJobs    []string `json:"parent_jobs"`

	// ISO 8601 String
	// e.g. "R/2014-03-08T20:00:00.000Z/PT2H"
	Schedule     string `json:"schedule"`
	scheduleTime time.Time
	// ISO 8601 Duration struct, used for scheduling
	// job after each run.
	delayDuration *iso8601.Duration

	// Number of times to schedule this job after the
	// first run.
	timesToRepeat int64

	// Number of times to retry on failed attempt for each run.
	Retries         uint `json:"retries"`
	currentRetries  uint
	Epsilon         string `json:"epsilon"`
	epsilonDuration *iso8601.Duration

	// Meta data about successful and failed runs.
	SuccessCount     uint      `json:"success_count"`
	LastSuccess      time.Time `json:"last_success"`
	ErrorCount       uint      `json:"error_count"`
	LastError        time.Time `json:"last_error"`
	LastAttemptedRun time.Time `json:"last_attempted_run"`

	jobTimer  *time.Timer
	nextRunAt time.Time

	// TODO
	// RunAsUser string `json:""`
	// EnvironmentVariables map[string]string `json:""`
}

// Init() fills in the protected fields and parses the iso8601 notation.
func (j *Job) Init() error {
	u4, err := uuid.NewV4()
	if err != nil {
		log.Error("Error occured when generating uuid: %s", err)
		return err
	}
	j.Id = u4.String()

	if len(j.ParentJobs) != 0 {
		// Add new job to parent jobs
		for _, p := range j.ParentJobs {
			AllJobs[p].DependentJobs = append(AllJobs[p].DependentJobs, j.Id)
		}
		return nil
	}

	if j.Schedule == "" {
		// If schedule is empty, its a one-off job.
		go j.Run()
		return nil
	}

	splitTime := strings.Split(j.Schedule, "/")
	if len(splitTime) != 3 {
		return fmt.Errorf("Schedule not formatted correctly. Should look like: R/2014-03-08T20:00:00Z/PT2H")
	}

	// Handle Repeat Amount
	if splitTime[0] == "R" {
		// Repeat forever
		j.timesToRepeat = -1
	} else {
		j.timesToRepeat, err = strconv.ParseInt(strings.Split(splitTime[0], "R")[1], 10, 0)
		if err != nil {
			log.Error("Error converting timesToRepeat to an int: %s", err)
			return err
		}
	}
	log.Debug("timesToRepeat: %d", j.timesToRepeat)

	j.scheduleTime, err = time.Parse(time.RFC3339, splitTime[1])
	if err != nil {
		log.Error("Error converting scheduleTime to a time.Time: %s", err)
		return err
	}
	if (time.Duration(j.scheduleTime.UnixNano() - time.Now().UnixNano())) < 0 {
		return fmt.Errorf("Schedule time has passed.")
	}
	log.Debug("Schedule Time: %s", j.scheduleTime)

	j.delayDuration, err = iso8601.FromString(splitTime[2])
	if err != nil {
		log.Error("Error converting delayDuration to a time.Duration: %s", err)
		return err
	}
	log.Debug("Delay Duration: %s", j.delayDuration.ToDuration())

	if j.Epsilon != "" {
		j.epsilonDuration, err = iso8601.FromString(j.Epsilon)
		if err != nil {
			log.Error("Error converting j.Epsilon to iso8601.Duration: %s", err)
			return err
		}
	}

	j.StartWaiting()

	return nil
}

// StartWaiting begins a timer for when it should execute the Jobs .Run() method.
func (j *Job) StartWaiting() {
	waitDuration := time.Duration(j.scheduleTime.UnixNano() - time.Now().UnixNano())
	log.Debug("Wait Duration initial: %s", waitDuration)
	if waitDuration < 0 {
		// Needs to be recalculated each time because of Months.
		waitDuration = j.delayDuration.ToDuration()
	}
	log.Info("Job Scheduled to run in: %s", waitDuration)
	j.nextRunAt = time.Now().Add(waitDuration)
	j.jobTimer = time.AfterFunc(waitDuration, j.Run)
}

func (j *Job) Disable() {
	// TODO - revisit error handling
	//hasBeenStopped := j.jobTimer.Stop()
	_ = j.jobTimer.Stop()
	j.Disabled = true
}

// Run() executes the Job's command, collects metadata around the success
// or failure of the Job's execution, and schedules the next run.
func (j *Job) Run() {
	log.Info("Job %s running", j.Name)

	// Schedule next run
	if j.timesToRepeat != 0 {
		j.timesToRepeat -= 1
		go j.StartWaiting()
	}

	j.LastAttemptedRun = time.Now()

	// TODO - Make thread safe
	// Init retries
	if j.currentRetries == 0 && j.Retries != 0 {
		j.currentRetries = j.Retries
	}

	// Execute command
	args := strings.Split(j.Command, " ")
	cmd := exec.Command(args[0], args[1:]...)
	err := cmd.Run()
	if err != nil {
		log.Error("Run Command got an Error: %s", err)
		j.ErrorCount += 1
		j.LastError = time.Now()
		// Handle retrying
		if j.currentRetries != 0 {
			if j.epsilonDuration.ToDuration() == 0 {
				timeLeftToRetry := time.Duration(j.epsilonDuration.ToDuration()) - time.Duration(time.Now().UnixNano()-j.nextRunAt.UnixNano())
				if timeLeftToRetry < 0 {
					// TODO - Make thread safe
					// Reset retries and exit.
					j.currentRetries = 0
					return
				}
			}
			j.currentRetries -= 0
			j.Run()
		}
		return
	}

	log.Info("%s was successful!", j.Name)
	j.SuccessCount += 1
	j.LastSuccess = time.Now()

	// Run Dependent Jobs
	if len(j.DependentJobs) != 0 {
		for _, id := range j.DependentJobs {
			go AllJobs[id].Run()
		}
	}
}
<commit_msg>Corrected Error logging in job/job.go<commit_after>package job

import (
	"fmt"
	"os/exec"
	"strconv"
	"strings"
	"time"

	"../utils/iso8601"

	"github.com/222Labs/common/go/logging"
	"github.com/nu7hatch/gouuid"
)

var (
	AllJobs = make(map[string]*Job)
	log     = logging.GetLogger("kala")
)

type Job struct {
	Name string `json:"name"`
	Id   string `json:"id"`

	// Command to run
	// e.g. "bash /path/to/my/script.sh"
	Command string `json:"command"`

	// Email of the owner of this job
	// e.g. "admin@example.com"
	Owner string `json:"owner"`

	// Is this job disabled?
	Disabled bool `json:"disabled"`

	// Jobs that are dependent upon this one.
	// Will be run after this job runs.
	DependentJobs []string `json:"dependent_jobs"`
	ParentJobs    []string `json:"parent_jobs"`

	// ISO 8601 String
	// e.g. "R/2014-03-08T20:00:00.000Z/PT2H"
	Schedule     string `json:"schedule"`
	scheduleTime time.Time
	// ISO 8601 Duration struct, used for scheduling
	// job after each run.
	delayDuration *iso8601.Duration

	// Number of times to schedule this job after the
	// first run.
	timesToRepeat int64

	// Number of times to retry on failed attempt for each run.
	Retries         uint `json:"retries"`
	currentRetries  uint
	Epsilon         string `json:"epsilon"`
	epsilonDuration *iso8601.Duration

	// Meta data about successful and failed runs.
	SuccessCount     uint      `json:"success_count"`
	LastSuccess      time.Time `json:"last_success"`
	ErrorCount       uint      `json:"error_count"`
	LastError        time.Time `json:"last_error"`
	LastAttemptedRun time.Time `json:"last_attempted_run"`

	jobTimer  *time.Timer
	nextRunAt time.Time

	// TODO
	// RunAsUser string `json:""`
	// EnvironmentVariables map[string]string `json:""`
}

// Init() fills in the protected fields and parses the iso8601 notation.
func (j *Job) Init() error {
	u4, err := uuid.NewV4()
	if err != nil {
		log.Error("Error occured when generating uuid: %s", err)
		return err
	}
	j.Id = u4.String()

	if len(j.ParentJobs) != 0 {
		// Add new job to parent jobs
		for _, p := range j.ParentJobs {
			AllJobs[p].DependentJobs = append(AllJobs[p].DependentJobs, j.Id)
		}
		return nil
	}

	if j.Schedule == "" {
		// If schedule is empty, its a one-off job.
		go j.Run()
		return nil
	}

	splitTime := strings.Split(j.Schedule, "/")
	if len(splitTime) != 3 {
		return fmt.Errorf("Schedule not formatted correctly. Should look like: R/2014-03-08T20:00:00Z/PT2H")
	}

	// Handle Repeat Amount
	if splitTime[0] == "R" {
		// Repeat forever
		j.timesToRepeat = -1
	} else {
		j.timesToRepeat, err = strconv.ParseInt(strings.Split(splitTime[0], "R")[1], 10, 0)
		if err != nil {
			log.Error("Error converting timesToRepeat to an int: %s", err)
			return err
		}
	}
	log.Debug("timesToRepeat: %d", j.timesToRepeat)

	j.scheduleTime, err = time.Parse(time.RFC3339, splitTime[1])
	if err != nil {
		log.Error("Error converting scheduleTime to a time.Time: %s", err)
		return err
	}
	if (time.Duration(j.scheduleTime.UnixNano() - time.Now().UnixNano())) < 0 {
		return fmt.Errorf("Schedule time has passed.")
	}
	log.Debug("Schedule Time: %s", j.scheduleTime)

	j.delayDuration, err = iso8601.FromString(splitTime[2])
	if err != nil {
		log.Error("Error converting delayDuration to a iso8601.Duration: %s", err)
		return err
	}
	log.Debug("Delay Duration: %s", j.delayDuration.ToDuration())

	if j.Epsilon != "" {
		j.epsilonDuration, err = iso8601.FromString(j.Epsilon)
		if err != nil {
			log.Error("Error converting j.Epsilon to iso8601.Duration: %s", err)
			return err
		}
	}

	j.StartWaiting()

	return nil
}

// StartWaiting begins a timer for when it should execute the Jobs .Run() method.
func (j *Job) StartWaiting() {
	waitDuration := time.Duration(j.scheduleTime.UnixNano() - time.Now().UnixNano())
	log.Debug("Wait Duration initial: %s", waitDuration)
	if waitDuration < 0 {
		// Needs to be recalculated each time because of Months.
		waitDuration = j.delayDuration.ToDuration()
	}
	log.Info("Job Scheduled to run in: %s", waitDuration)
	j.nextRunAt = time.Now().Add(waitDuration)
	j.jobTimer = time.AfterFunc(waitDuration, j.Run)
}

func (j *Job) Disable() {
	// TODO - revisit error handling
	//hasBeenStopped := j.jobTimer.Stop()
	_ = j.jobTimer.Stop()
	j.Disabled = true
}

// Run() executes the Job's command, collects metadata around the success
// or failure of the Job's execution, and schedules the next run.
func (j *Job) Run() {
	log.Info("Job %s running", j.Name)

	// Schedule next run
	if j.timesToRepeat != 0 {
		j.timesToRepeat -= 1
		go j.StartWaiting()
	}

	j.LastAttemptedRun = time.Now()

	// TODO - Make thread safe
	// Init retries
	if j.currentRetries == 0 && j.Retries != 0 {
		j.currentRetries = j.Retries
	}

	// Execute command
	args := strings.Split(j.Command, " ")
	cmd := exec.Command(args[0], args[1:]...)
	err := cmd.Run()
	if err != nil {
		log.Error("Run Command got an Error: %s", err)
		j.ErrorCount += 1
		j.LastError = time.Now()
		// Handle retrying
		if j.currentRetries != 0 {
			if j.epsilonDuration.ToDuration() == 0 {
				timeLeftToRetry := time.Duration(j.epsilonDuration.ToDuration()) - time.Duration(time.Now().UnixNano()-j.nextRunAt.UnixNano())
				if timeLeftToRetry < 0 {
					// TODO - Make thread safe
					// Reset retries and exit.
					j.currentRetries = 0
					return
				}
			}
			j.currentRetries -= 0
			j.Run()
		}
		return
	}

	log.Info("%s was successful!", j.Name)
	j.SuccessCount += 1
	j.LastSuccess = time.Now()

	// Run Dependent Jobs
	if len(j.DependentJobs) != 0 {
		for _, id := range j.DependentJobs {
			go AllJobs[id].Run()
		}
	}
}
<|endoftext|>


<commit_before>package quic

import (
	"io"
	"sync"
	"sync/atomic"

	"github.com/lucas-clemente/quic-go/flowcontrol"
	"github.com/lucas-clemente/quic-go/frames"
	"github.com/lucas-clemente/quic-go/protocol"
	"github.com/lucas-clemente/quic-go/qerr"
	"github.com/lucas-clemente/quic-go/utils"
)

// A Stream assembles the data from StreamFrames and provides a super-convenient Read-Interface
//
// Read() and Write() may be called concurrently, but multiple calls to Read() or Write() individually must be synchronized manually.
type stream struct {
	streamID protocol.StreamID
	onData   func()

	readPosInFrame int
	writeOffset    protocol.ByteCount
	readOffset     protocol.ByteCount

	// Once set, err must not be changed!
	err   error
	mutex sync.Mutex

	// eof is set if we are finished reading
	eof int32 // really a bool
	// closed is set when we are finished writing
	closed int32 // really a bool

	frameQueue        *streamFrameSorter
	newFrameOrErrCond sync.Cond

	dataForWriting       []byte
	finSent              bool
	doneWritingOrErrCond sync.Cond

	flowControlManager flowcontrol.FlowControlManager
}

// newStream creates a new Stream
func newStream(StreamID protocol.StreamID, onData func(), flowControlManager flowcontrol.FlowControlManager) (*stream, error) {
	s := &stream{
		onData:             onData,
		streamID:           StreamID,
		flowControlManager: flowControlManager,
		frameQueue:         newStreamFrameSorter(),
	}

	s.newFrameOrErrCond.L = &s.mutex
	s.doneWritingOrErrCond.L = &s.mutex

	return s, nil
}

// Read implements io.Reader. It is not thread safe!
func (s *stream) Read(p []byte) (int, error) {
	if atomic.LoadInt32(&s.eof) != 0 {
		return 0, io.EOF
	}

	bytesRead := 0
	for bytesRead < len(p) {
		s.mutex.Lock()
		frame := s.frameQueue.Head()

		if frame == nil && bytesRead > 0 {
			s.mutex.Unlock()
			return bytesRead, s.err
		}

		var err error
		for {
			// Stop waiting on errors
			if s.err != nil {
				err = s.err
				break
			}
			if frame != nil {
				s.readPosInFrame = int(s.readOffset - frame.Offset)
				break
			}
			s.newFrameOrErrCond.Wait()
			frame = s.frameQueue.Head()
		}
		s.mutex.Unlock()
		// Here, either frame != nil xor err != nil

		if frame == nil {
			atomic.StoreInt32(&s.eof, 1)
			// We have an err and no data, return the error
			return bytesRead, err
		}

		m := utils.Min(len(p)-bytesRead, int(frame.DataLen())-s.readPosInFrame)
		copy(p[bytesRead:], frame.Data[s.readPosInFrame:])

		s.readPosInFrame += m
		bytesRead += m
		s.readOffset += protocol.ByteCount(m)

		s.flowControlManager.AddBytesRead(s.streamID, protocol.ByteCount(m))
		s.onData() // so that a possible WINDOW_UPDATE is sent

		if s.readPosInFrame >= int(frame.DataLen()) {
			fin := frame.FinBit
			s.mutex.Lock()
			s.frameQueue.Pop()
			s.mutex.Unlock()
			if fin {
				atomic.StoreInt32(&s.eof, 1)
				return bytesRead, io.EOF
			}
		}
	}

	return bytesRead, nil
}

// ReadByte implements io.ByteReader
func (s *stream) ReadByte() (byte, error) {
	p := make([]byte, 1)
	_, err := io.ReadFull(s, p)
	return p[0], err
}

func (s *stream) Write(p []byte) (int, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	if s.err != nil {
		return 0, s.err
	}

	if len(p) == 0 {
		return 0, nil
	}

	s.dataForWriting = make([]byte, len(p))
	copy(s.dataForWriting, p)

	s.onData()

	for s.dataForWriting != nil && s.err == nil {
		s.doneWritingOrErrCond.Wait()
	}

	if s.err != nil {
		return 0, s.err
	}

	return len(p), nil
}

func (s *stream) lenOfDataForWriting() protocol.ByteCount {
	s.mutex.Lock()
	l := protocol.ByteCount(len(s.dataForWriting))
	s.mutex.Unlock()
	return l
}

func (s *stream) getDataForWriting(maxBytes protocol.ByteCount) []byte {
	s.mutex.Lock()
	if s.dataForWriting == nil {
		s.mutex.Unlock()
		return nil
	}
	var ret []byte
	if protocol.ByteCount(len(s.dataForWriting)) > maxBytes {
		ret = s.dataForWriting[:maxBytes]
		s.dataForWriting = s.dataForWriting[maxBytes:]
	} else {
		ret = s.dataForWriting
		s.dataForWriting = nil
		s.doneWritingOrErrCond.Signal()
	}
	s.writeOffset += protocol.ByteCount(len(ret))
	s.mutex.Unlock()
	return ret
}

// Close implements io.Closer
func (s *stream) Close() error {
	atomic.StoreInt32(&s.closed, 1)
	s.onData()
	return nil
}

func (s *stream) shouldSendFin() bool {
	s.mutex.Lock()
	res := atomic.LoadInt32(&s.closed) != 0 && !s.finSent && s.err == nil && s.dataForWriting == nil
	s.mutex.Unlock()
	return res
}

func (s *stream) sentFin() {
	s.mutex.Lock()
	s.finSent = true
	s.mutex.Unlock()
}

// AddStreamFrame adds a new stream frame
func (s *stream) AddStreamFrame(frame *frames.StreamFrame) error {
	maxOffset := frame.Offset + frame.DataLen()
	err := s.flowControlManager.UpdateHighestReceived(s.streamID, maxOffset)

	if err == flowcontrol.ErrStreamFlowControlViolation {
		return qerr.FlowControlReceivedTooMuchData
	}
	if err == flowcontrol.ErrConnectionFlowControlViolation {
		return qerr.FlowControlReceivedTooMuchData
	}
	if err != nil {
		return err
	}

	s.mutex.Lock()
	defer s.mutex.Unlock()
	err = s.frameQueue.Push(frame)
	if err != nil && err != errDuplicateStreamData {
		return err
	}
	s.newFrameOrErrCond.Signal()
	return nil
}

// CloseRemote makes the stream receive a "virtual" FIN stream frame at a given offset
func (s *stream) CloseRemote(offset protocol.ByteCount) {
	s.AddStreamFrame(&frames.StreamFrame{FinBit: true, Offset: offset})
}

// RegisterError is called by session to indicate that an error occurred and the
// stream should be closed.
func (s *stream) RegisterError(err error) {
	atomic.StoreInt32(&s.closed, 1)
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if s.err != nil { // s.err must not be changed!
		return
	}
	s.err = err
	s.doneWritingOrErrCond.Signal()
	s.newFrameOrErrCond.Signal()
}

func (s *stream) finishedReading() bool {
	return atomic.LoadInt32(&s.eof) != 0
}

func (s *stream) finishedWriting() bool {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	return s.err != nil || (atomic.LoadInt32(&s.closed) != 0 && s.finSent)
}

func (s *stream) finished() bool {
	return s.finishedReading() && s.finishedWriting()
}

func (s *stream) StreamID() protocol.StreamID {
	return s.streamID
}
<commit_msg>do some consistency checks before accessing slices in stream<commit_after>package quic

import (
	"fmt"
	"io"
	"sync"
	"sync/atomic"

	"github.com/lucas-clemente/quic-go/flowcontrol"
	"github.com/lucas-clemente/quic-go/frames"
	"github.com/lucas-clemente/quic-go/protocol"
	"github.com/lucas-clemente/quic-go/qerr"
	"github.com/lucas-clemente/quic-go/utils"
)

// A Stream assembles the data from StreamFrames and provides a super-convenient Read-Interface
//
// Read() and Write() may be called concurrently, but multiple calls to Read() or Write() individually must be synchronized manually.
type stream struct {
	streamID protocol.StreamID
	onData   func()

	readPosInFrame int
	writeOffset    protocol.ByteCount
	readOffset     protocol.ByteCount

	// Once set, err must not be changed!
	err   error
	mutex sync.Mutex

	// eof is set if we are finished reading
	eof int32 // really a bool
	// closed is set when we are finished writing
	closed int32 // really a bool

	frameQueue        *streamFrameSorter
	newFrameOrErrCond sync.Cond

	dataForWriting       []byte
	finSent              bool
	doneWritingOrErrCond sync.Cond

	flowControlManager flowcontrol.FlowControlManager
}

// newStream creates a new Stream
func newStream(StreamID protocol.StreamID, onData func(), flowControlManager flowcontrol.FlowControlManager) (*stream, error) {
	s := &stream{
		onData:             onData,
		streamID:           StreamID,
		flowControlManager: flowControlManager,
		frameQueue:         newStreamFrameSorter(),
	}

	s.newFrameOrErrCond.L = &s.mutex
	s.doneWritingOrErrCond.L = &s.mutex

	return s, nil
}

// Read implements io.Reader. It is not thread safe!
func (s *stream) Read(p []byte) (int, error) {
	if atomic.LoadInt32(&s.eof) != 0 {
		return 0, io.EOF
	}

	bytesRead := 0
	for bytesRead < len(p) {
		s.mutex.Lock()
		frame := s.frameQueue.Head()

		if frame == nil && bytesRead > 0 {
			s.mutex.Unlock()
			return bytesRead, s.err
		}

		var err error
		for {
			// Stop waiting on errors
			if s.err != nil {
				err = s.err
				break
			}
			if frame != nil {
				s.readPosInFrame = int(s.readOffset - frame.Offset)
				break
			}
			s.newFrameOrErrCond.Wait()
			frame = s.frameQueue.Head()
		}
		s.mutex.Unlock()
		// Here, either frame != nil xor err != nil

		if frame == nil {
			atomic.StoreInt32(&s.eof, 1)
			// We have an err and no data, return the error
			return bytesRead, err
		}

		m := utils.Min(len(p)-bytesRead, int(frame.DataLen())-s.readPosInFrame)

		if bytesRead > len(p) {
			return bytesRead, fmt.Errorf("BUG: bytesRead (%d) > len(p) (%d) in stream.Read", bytesRead, len(p))
		}
		if s.readPosInFrame > int(frame.DataLen()) {
			return bytesRead, fmt.Errorf("BUG: readPosInFrame (%d) > frame.DataLen (%d) in stream.Read", s.readPosInFrame, frame.DataLen())
		}
		copy(p[bytesRead:], frame.Data[s.readPosInFrame:])

		s.readPosInFrame += m
		bytesRead += m
		s.readOffset += protocol.ByteCount(m)

		s.flowControlManager.AddBytesRead(s.streamID, protocol.ByteCount(m))
		s.onData() // so that a possible WINDOW_UPDATE is sent

		if s.readPosInFrame >= int(frame.DataLen()) {
			fin := frame.FinBit
			s.mutex.Lock()
			s.frameQueue.Pop()
			s.mutex.Unlock()
			if fin {
				atomic.StoreInt32(&s.eof, 1)
				return bytesRead, io.EOF
			}
		}
	}

	return bytesRead, nil
}

// ReadByte implements io.ByteReader
func (s *stream) ReadByte() (byte, error) {
	p := make([]byte, 1)
	_, err := io.ReadFull(s, p)
	return p[0], err
}

func (s *stream) Write(p []byte) (int, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	if s.err != nil {
		return 0, s.err
	}

	if len(p) == 0 {
		return 0, nil
	}

	s.dataForWriting = make([]byte, len(p))
	copy(s.dataForWriting, p)

	s.onData()

	for s.dataForWriting != nil && s.err == nil {
		s.doneWritingOrErrCond.Wait()
	}

	if s.err != nil {
		return 0, s.err
	}

	return len(p), nil
}

func (s *stream) lenOfDataForWriting() protocol.ByteCount {
	s.mutex.Lock()
	l := protocol.ByteCount(len(s.dataForWriting))
	s.mutex.Unlock()
	return l
}

func (s *stream) getDataForWriting(maxBytes protocol.ByteCount) []byte {
	s.mutex.Lock()
	if s.dataForWriting == nil {
		s.mutex.Unlock()
		return nil
	}
	var ret []byte
	if protocol.ByteCount(len(s.dataForWriting)) > maxBytes {
		ret = s.dataForWriting[:maxBytes]
		s.dataForWriting = s.dataForWriting[maxBytes:]
	} else {
		ret = s.dataForWriting
		s.dataForWriting = nil
		s.doneWritingOrErrCond.Signal()
	}
	s.writeOffset += protocol.ByteCount(len(ret))
	s.mutex.Unlock()
	return ret
}

// Close implements io.Closer
func (s *stream) Close() error {
	atomic.StoreInt32(&s.closed, 1)
	s.onData()
	return nil
}

func (s *stream) shouldSendFin() bool {
	s.mutex.Lock()
	res := atomic.LoadInt32(&s.closed) != 0 && !s.finSent && s.err == nil && s.dataForWriting == nil
	s.mutex.Unlock()
	return res
}

func (s *stream) sentFin() {
	s.mutex.Lock()
	s.finSent = true
	s.mutex.Unlock()
}

// AddStreamFrame adds a new stream frame
func (s *stream) AddStreamFrame(frame *frames.StreamFrame) error {
	maxOffset := frame.Offset + frame.DataLen()
	err := s.flowControlManager.UpdateHighestReceived(s.streamID, maxOffset)

	if err == flowcontrol.ErrStreamFlowControlViolation {
		return qerr.FlowControlReceivedTooMuchData
	}
	if err == flowcontrol.ErrConnectionFlowControlViolation {
		return qerr.FlowControlReceivedTooMuchData
	}
	if err != nil {
		return err
	}

	s.mutex.Lock()
	defer s.mutex.Unlock()
	err = s.frameQueue.Push(frame)
	if err != nil && err != errDuplicateStreamData {
		return err
	}
	s.newFrameOrErrCond.Signal()
	return nil
}

// CloseRemote makes the stream receive a "virtual" FIN stream frame at a given offset
func (s *stream) CloseRemote(offset protocol.ByteCount) {
	s.AddStreamFrame(&frames.StreamFrame{FinBit: true, Offset: offset})
}

// RegisterError is called by session to indicate that an error occurred and the
// stream should be closed.
func (s *stream) RegisterError(err error) {
	atomic.StoreInt32(&s.closed, 1)
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if s.err != nil { // s.err must not be changed!
		return
	}
	s.err = err
	s.doneWritingOrErrCond.Signal()
	s.newFrameOrErrCond.Signal()
}

func (s *stream) finishedReading() bool {
	return atomic.LoadInt32(&s.eof) != 0
}

func (s *stream) finishedWriting() bool {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	return s.err != nil || (atomic.LoadInt32(&s.closed) != 0 && s.finSent)
}

func (s *stream) finished() bool {
	return s.finishedReading() && s.finishedWriting()
}

func (s *stream) StreamID() protocol.StreamID {
	return s.streamID
}
<|endoftext|>


<commit_before>package check

import (
	"regexp"
	"strings"
)

// MinChar validates that a string must have a length minimum of its constraint
type MinChar struct {
	Constraint int
}

// Validate check value against constraint
func (validator MinChar) Validate(v interface{}) Error {
	if len(v.(string)) < validator.Constraint {
		return NewValidationError("minChar", validator.Constraint)
	}

	return nil
}

// MaxChar validates that a string must have a length maximum of its constraint
type MaxChar struct {
	Constraint int
}

// Validate check value against constraint
func (validator MaxChar) Validate(v interface{}) Error {
	if len(v.(string)) > validator.Constraint {
		return NewValidationError("maxChar", validator.Constraint)
	}

	return nil
}

// Email is a constraint to do a simple validation for email addresses, it only check if the string contains "@"
// and that it is not in the first or last character of the string
type Email struct{}

// Validate email addresses
func (validator Email) Validate(v interface{}) Error {
	if !strings.Contains(v.(string), "@") || string(v.(string)[0]) == "@" || string(v.(string)[len(v.(string))-1]) == "@" {
		return NewValidationError("email", v)
	}

	return nil
}

// Regex allow validation usig regular expressions
type Regex struct {
	Constraint string
}

// Validate using regex
func (validator Regex) Validate(v interface{}) Error {
	regex, err := regexp.Compile(validator.Constraint)
	if err != nil {
		panic(err)
	}

	if !regex.MatchString(v.(string)) {
		return NewValidationError("regex", v, validator.Constraint)
	}

	return nil
}

// UUID verify a string in the UUID format xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
type UUID struct{}

// Validate checks a string as correct UUID format
func (validator UUID) Validate(v interface{}) Error {
	regex := regexp.MustCompile("^[a-z0-9]{8}-[a-z0-9]{4}-[1-5][a-z0-9]{3}-[a-z0-9]{4}-[a-z0-9]{12}$")

	if !regex.MatchString(v.(string)) {
		return NewValidationError("uuid", v)
	}

	return nil
}
<commit_msg>Improve email validation<commit_after>package check

import (
	"regexp"
	"strings"
)

// MinChar validates that a string must have a length minimum of its constraint
type MinChar struct {
	Constraint int
}

// Validate check value against constraint
func (validator MinChar) Validate(v interface{}) Error {
	if len(v.(string)) < validator.Constraint {
		return NewValidationError("minChar", validator.Constraint)
	}

	return nil
}

// MaxChar validates that a string must have a length maximum of its constraint
type MaxChar struct {
	Constraint int
}

// Validate check value against constraint
func (validator MaxChar) Validate(v interface{}) Error {
	if len(v.(string)) > validator.Constraint {
		return NewValidationError("maxChar", validator.Constraint)
	}

	return nil
}

// Email is a constraint to do a simple validation for email addresses, it only check if the string contains "@"
// and that it is not in the first or last character of the string. Also if there is only one "@" and if there is a "." in the string after the "@".
type Email struct{}

// Validate email addresses
func (validator Email) Validate(v interface{}) Error {
	if !strings.Contains(v.(string), "@") || string(v.(string)[0]) == "@" || string(v.(string)[len(v.(string))-1]) == "@" || string(v.(string)[len(v.(string))-1]) == "." || len(strings.Split(v.(string), "@")) != 2 || !strings.Contains(strings.Split(v.(string), "@")[1], ".") || string(v.(string)[len(v.(string))-1]) == "." {
		return NewValidationError("email", v)
	}

	return nil
}

// Regex allow validation usig regular expressions
type Regex struct {
	Constraint string
}

// Validate using regex
func (validator Regex) Validate(v interface{}) Error {
	regex, err := regexp.Compile(validator.Constraint)
	if err != nil {
		panic(err)
	}

	if !regex.MatchString(v.(string)) {
		return NewValidationError("regex", v, validator.Constraint)
	}

	return nil
}

// UUID verify a string in the UUID format xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
type UUID struct{}

// Validate checks a string as correct UUID format
func (validator UUID) Validate(v interface{}) Error {
	regex := regexp.MustCompile("^[a-z0-9]{8}-[a-z0-9]{4}-[1-5][a-z0-9]{3}-[a-z0-9]{4}-[a-z0-9]{12}$")

	if !regex.MatchString(v.(string)) {
		return NewValidationError("uuid", v)
	}

	return nil
}
<|endoftext|>


<commit_before>package capnp

// Struct is a pointer to a struct.
type Struct struct {
	seg        *Segment
	off        address
	size       ObjectSize
	depthLimit uint
	flags      structFlags
}

// NewStruct creates a new struct, preferring placement in s.
func NewStruct(s *Segment, sz ObjectSize) (Struct, error) {
	if !sz.isValid() {
		return Struct{}, newError("new struct: invalid size")
	}
	sz.DataSize = sz.DataSize.padToWord()
	seg, addr, err := alloc(s, sz.totalSize())
	if err != nil {
		return Struct{}, annotate(err).errorf("new struct")
	}
	return Struct{
		seg:        seg,
		off:        addr,
		size:       sz,
		depthLimit: maxDepth,
	}, nil
}

// NewRootStruct creates a new struct, preferring placement in s, then sets the
// message's root to the new struct.
func NewRootStruct(s *Segment, sz ObjectSize) (Struct, error) {
	st, err := NewStruct(s, sz)
	if err != nil {
		return st, err
	}
	if err := s.msg.SetRoot(st.ToPtr()); err != nil {
		return st, err
	}
	return st, nil
}

// ToPtr converts the struct to a generic pointer.
func (p Struct) ToPtr() Ptr {
	return Ptr{
		seg:        p.seg,
		off:        p.off,
		size:       p.size,
		depthLimit: p.depthLimit,
		flags:      structPtrFlag(p.flags),
	}
}

// Segment returns the segment the referenced struct is stored in or nil
// if the pointer is invalid.
func (p Struct) Segment() *Segment {
	return p.seg
}

// Message returns the message the referenced struct is stored in or nil
// if the pointer is invalid.
func (p Struct) Message() *Message {
	if p.seg == nil {
		return nil
	}
	return p.seg.msg
}

// IsValid returns whether the struct is valid.
func (p Struct) IsValid() bool {
	return p.seg != nil
}

// Size returns the size of the struct.
func (p Struct) Size() ObjectSize {
	return p.size
}

// CopyFrom copies content from another struct.  If the other struct's
// sections are larger than this struct's, the extra data is not copied,
// meaning there is a risk of data loss when copying from messages built
// with future versions of the protocol.
func (p Struct) CopyFrom(other Struct) error {
	if err := copyStruct(p, other); err != nil {
		return annotate(err).errorf("copy struct")
	}
	return nil
}

// readSize returns the struct's size for the purposes of read limit
// accounting.
func (p Struct) readSize() Size {
	if p.seg == nil {
		return 0
	}
	return p.size.totalSize()
}

// Ptr returns the i'th pointer in the struct.
func (p Struct) Ptr(i uint16) (Ptr, error) {
	if p.seg == nil || i >= p.size.PointerCount {
		return Ptr{}, nil
	}
	return p.seg.readPtr(p.pointerAddress(i), p.depthLimit)
}

// HasPtr reports whether the i'th pointer in the struct is non-null.
// It does not affect the read limit.
func (p Struct) HasPtr(i uint16) bool {
	if p.seg == nil || i >= p.size.PointerCount {
		return false
	}
	return p.seg.readRawPointer(p.pointerAddress(i)) != 0
}

// SetPtr sets the i'th pointer in the struct to src.
func (p Struct) SetPtr(i uint16, src Ptr) error {
	if p.seg == nil || i >= p.size.PointerCount {
		panic("capnp: set field outside struct boundaries")
	}
	return p.seg.writePtr(p.pointerAddress(i), src, false)
}

// SetText sets the i'th pointer to a newly allocated text or null if v is empty.
func (p Struct) SetText(i uint16, v string) error {
	if v == "" {
		return p.SetPtr(i, Ptr{})
	}
	return p.SetNewText(i, v)
}

// SetNewText sets the i'th pointer to a newly allocated text.
func (p Struct) SetNewText(i uint16, v string) error {
	t, err := NewText(p.seg, v)
	if err != nil {
		return err
	}
	return p.SetPtr(i, t.List.ToPtr())
}

// SetTextFromBytes sets the i'th pointer to a newly allocated text or null if v is nil.
func (p Struct) SetTextFromBytes(i uint16, v []byte) error {
	if v == nil {
		return p.SetPtr(i, Ptr{})
	}
	t, err := NewTextFromBytes(p.seg, v)
	if err != nil {
		return err
	}
	return p.SetPtr(i, t.List.ToPtr())
}

// SetData sets the i'th pointer to a newly allocated data or null if v is nil.
func (p Struct) SetData(i uint16, v []byte) error {
	if v == nil {
		return p.SetPtr(i, Ptr{})
	}
	d, err := NewData(p.seg, v)
	if err != nil {
		return err
	}
	return p.SetPtr(i, d.List.ToPtr())
}

func (p Struct) pointerAddress(i uint16) address {
	// Struct already had bounds check
	ptrStart, _ := p.off.addSize(p.size.DataSize)
	a, _ := ptrStart.element(int32(i), wordSize)
	return a
}

// bitInData reports whether bit is inside p's data section.
func (p Struct) bitInData(bit BitOffset) bool {
	return p.seg != nil && bit < BitOffset(p.size.DataSize*8)
}

// Bit returns the bit that is n bits from the start of the struct.
func (p Struct) Bit(n BitOffset) bool {
	if !p.bitInData(n) {
		return false
	}
	addr := p.off.addOffset(n.offset())
	return p.seg.readUint8(addr)&n.mask() != 0
}

// SetBit sets the bit that is n bits from the start of the struct to v.
func (p Struct) SetBit(n BitOffset, v bool) {
	if !p.bitInData(n) {
		panic("capnp: set field outside struct boundaries")
	}
	addr := p.off.addOffset(n.offset())
	b := p.seg.readUint8(addr)
	if v {
		b |= n.mask()
	} else {
		b &^= n.mask()
	}
	p.seg.writeUint8(addr, b)
}

func (p Struct) dataAddress(off DataOffset, sz Size) (addr address, ok bool) {
	if p.seg == nil || Size(off)+sz > p.size.DataSize {
		return 0, false
	}
	return p.off.addOffset(off), true
}

// Uint8 returns an 8-bit integer from the struct's data section.
func (p Struct) Uint8(off DataOffset) uint8 {
	addr, ok := p.dataAddress(off, 1)
	if !ok {
		return 0
	}
	return p.seg.readUint8(addr)
}

// Uint16 returns a 16-bit integer from the struct's data section.
func (p Struct) Uint16(off DataOffset) uint16 {
	addr, ok := p.dataAddress(off, 2)
	if !ok {
		return 0
	}
	return p.seg.readUint16(addr)
}

// Uint32 returns a 32-bit integer from the struct's data section.
func (p Struct) Uint32(off DataOffset) uint32 {
	addr, ok := p.dataAddress(off, 4)
	if !ok {
		return 0
	}
	return p.seg.readUint32(addr)
}

// Uint64 returns a 64-bit integer from the struct's data section.
func (p Struct) Uint64(off DataOffset) uint64 {
	addr, ok := p.dataAddress(off, 8)
	if !ok {
		return 0
	}
	return p.seg.readUint64(addr)
}

// SetUint8 sets the 8-bit integer that is off bytes from the start of the struct to v.
func (p Struct) SetUint8(off DataOffset, v uint8) {
	addr, ok := p.dataAddress(off, 1)
	if !ok {
		panic("capnp: set field outside struct boundaries")
	}
	p.seg.writeUint8(addr, v)
}

// SetUint16 sets the 16-bit integer that is off bytes from the start of the struct to v.
func (p Struct) SetUint16(off DataOffset, v uint16) {
	addr, ok := p.dataAddress(off, 2)
	if !ok {
		panic("capnp: set field outside struct boundaries")
	}
	p.seg.writeUint16(addr, v)
}

// SetUint32 sets the 32-bit integer that is off bytes from the start of the struct to v.
func (p Struct) SetUint32(off DataOffset, v uint32) {
	addr, ok := p.dataAddress(off, 4)
	if !ok {
		panic("capnp: set field outside struct boundaries")
	}
	p.seg.writeUint32(addr, v)
}

// SetUint64 sets the 64-bit integer that is off bytes from the start of the struct to v.
func (p Struct) SetUint64(off DataOffset, v uint64) {
	addr, ok := p.dataAddress(off, 8)
	if !ok {
		panic("capnp: set field outside struct boundaries")
	}
	p.seg.writeUint64(addr, v)
}

// structFlags is a bitmask of flags for a pointer.
type structFlags uint8

// Pointer flags.
const (
	isListMember structFlags = 1 << iota
)

// copyStruct makes a deep copy of src into dst.
func copyStruct(dst, src Struct) error {
	if dst.seg == nil {
		return nil
	}

	// Q: how does version handling happen here, when the
	//    destination toData[] slice can be bigger or smaller
	//    than the source data slice, which is in
	//    src.seg.Data[src.off:src.off+src.size.DataSize] ?
	//
	// A: Newer fields only come *after* old fields. Note that
	//    copy only copies min(len(src), len(dst)) size,
	//    and then we manually zero the rest in the for loop
	//    that writes toData[j] = 0.
	//

	// data section:
	srcData := src.seg.slice(src.off, src.size.DataSize)
	dstData := dst.seg.slice(dst.off, dst.size.DataSize)
	copyCount := copy(dstData, srcData)
	dstData = dstData[copyCount:]
	for j := range dstData {
		dstData[j] = 0
	}

	// ptrs section:

	// version handling: we ignore any extra-newer-pointers in src,
	// i.e. the case when srcPtrSize > dstPtrSize, by only
	// running j over the size of dstPtrSize, the destination size.
	srcPtrSect, _ := src.off.addSize(src.size.DataSize)
	dstPtrSect, _ := dst.off.addSize(dst.size.DataSize)
	numSrcPtrs := src.size.PointerCount
	numDstPtrs := dst.size.PointerCount
	for j := uint16(0); j < numSrcPtrs && j < numDstPtrs; j++ {
		srcAddr, _ := srcPtrSect.element(int32(j), wordSize)
		dstAddr, _ := dstPtrSect.element(int32(j), wordSize)
		m, err := src.seg.readPtr(srcAddr, src.depthLimit)
		if err != nil {
			return annotate(err).errorf("copy struct pointer %d", j)
		}
		err = dst.seg.writePtr(dstAddr, m, true)
		if err != nil {
			return annotate(err).errorf("copy struct pointer %d", j)
		}
	}
	for j := numSrcPtrs; j < numDstPtrs; j++ {
		// destination p is a newer version than source so these extra new pointer fields in p must be zeroed.
		addr, _ := dstPtrSect.element(int32(j), wordSize)
		dst.seg.writeRawPointer(addr, 0)
	}
	// Nothing more here: so any other pointers in srcPtrSize beyond
	// those in dstPtrSize are ignored and discarded.

	return nil
}
<commit_msg>capnp: no-op copyStruct for invalid src and panic for invalid dst<commit_after>package capnp

// Struct is a pointer to a struct.
type Struct struct {
	seg        *Segment
	off        address
	size       ObjectSize
	depthLimit uint
	flags      structFlags
}

// NewStruct creates a new struct, preferring placement in s.
func NewStruct(s *Segment, sz ObjectSize) (Struct, error) {
	if !sz.isValid() {
		return Struct{}, newError("new struct: invalid size")
	}
	sz.DataSize = sz.DataSize.padToWord()
	seg, addr, err := alloc(s, sz.totalSize())
	if err != nil {
		return Struct{}, annotate(err).errorf("new struct")
	}
	return Struct{
		seg:        seg,
		off:        addr,
		size:       sz,
		depthLimit: maxDepth,
	}, nil
}

// NewRootStruct creates a new struct, preferring placement in s, then sets the
// message's root to the new struct.
func NewRootStruct(s *Segment, sz ObjectSize) (Struct, error) {
	st, err := NewStruct(s, sz)
	if err != nil {
		return st, err
	}
	if err := s.msg.SetRoot(st.ToPtr()); err != nil {
		return st, err
	}
	return st, nil
}

// ToPtr converts the struct to a generic pointer.
func (p Struct) ToPtr() Ptr {
	return Ptr{
		seg:        p.seg,
		off:        p.off,
		size:       p.size,
		depthLimit: p.depthLimit,
		flags:      structPtrFlag(p.flags),
	}
}

// Segment returns the segment the referenced struct is stored in or nil
// if the pointer is invalid.
func (p Struct) Segment() *Segment {
	return p.seg
}

// Message returns the message the referenced struct is stored in or nil
// if the pointer is invalid.
func (p Struct) Message() *Message {
	if p.seg == nil {
		return nil
	}
	return p.seg.msg
}

// IsValid returns whether the struct is valid.
func (p Struct) IsValid() bool {
	return p.seg != nil
}

// Size returns the size of the struct.
func (p Struct) Size() ObjectSize {
	return p.size
}

// CopyFrom copies content from another struct.  If the other struct's
// sections are larger than this struct's, the extra data is not copied,
// meaning there is a risk of data loss when copying from messages built
// with future versions of the protocol.
func (p Struct) CopyFrom(other Struct) error {
	if err := copyStruct(p, other); err != nil {
		return annotate(err).errorf("copy struct")
	}
	return nil
}

// readSize returns the struct's size for the purposes of read limit
// accounting.
func (p Struct) readSize() Size {
	if p.seg == nil {
		return 0
	}
	return p.size.totalSize()
}

// Ptr returns the i'th pointer in the struct.
func (p Struct) Ptr(i uint16) (Ptr, error) {
	if p.seg == nil || i >= p.size.PointerCount {
		return Ptr{}, nil
	}
	return p.seg.readPtr(p.pointerAddress(i), p.depthLimit)
}

// HasPtr reports whether the i'th pointer in the struct is non-null.
// It does not affect the read limit.
func (p Struct) HasPtr(i uint16) bool {
	if p.seg == nil || i >= p.size.PointerCount {
		return false
	}
	return p.seg.readRawPointer(p.pointerAddress(i)) != 0
}

// SetPtr sets the i'th pointer in the struct to src.
func (p Struct) SetPtr(i uint16, src Ptr) error {
	if p.seg == nil || i >= p.size.PointerCount {
		panic("capnp: set field outside struct boundaries")
	}
	return p.seg.writePtr(p.pointerAddress(i), src, false)
}

// SetText sets the i'th pointer to a newly allocated text or null if v is empty.
func (p Struct) SetText(i uint16, v string) error {
	if v == "" {
		return p.SetPtr(i, Ptr{})
	}
	return p.SetNewText(i, v)
}

// SetNewText sets the i'th pointer to a newly allocated text.
func (p Struct) SetNewText(i uint16, v string) error {
	t, err := NewText(p.seg, v)
	if err != nil {
		return err
	}
	return p.SetPtr(i, t.List.ToPtr())
}

// SetTextFromBytes sets the i'th pointer to a newly allocated text or null if v is nil.
func (p Struct) SetTextFromBytes(i uint16, v []byte) error {
	if v == nil {
		return p.SetPtr(i, Ptr{})
	}
	t, err := NewTextFromBytes(p.seg, v)
	if err != nil {
		return err
	}
	return p.SetPtr(i, t.List.ToPtr())
}

// SetData sets the i'th pointer to a newly allocated data or null if v is nil.
func (p Struct) SetData(i uint16, v []byte) error {
	if v == nil {
		return p.SetPtr(i, Ptr{})
	}
	d, err := NewData(p.seg, v)
	if err != nil {
		return err
	}
	return p.SetPtr(i, d.List.ToPtr())
}

func (p Struct) pointerAddress(i uint16) address {
	// Struct already had bounds check
	ptrStart, _ := p.off.addSize(p.size.DataSize)
	a, _ := ptrStart.element(int32(i), wordSize)
	return a
}

// bitInData reports whether bit is inside p's data section.
func (p Struct) bitInData(bit BitOffset) bool {
	return p.seg != nil && bit < BitOffset(p.size.DataSize*8)
}

// Bit returns the bit that is n bits from the start of the struct.
func (p Struct) Bit(n BitOffset) bool {
	if !p.bitInData(n) {
		return false
	}
	addr := p.off.addOffset(n.offset())
	return p.seg.readUint8(addr)&n.mask() != 0
}

// SetBit sets the bit that is n bits from the start of the struct to v.
func (p Struct) SetBit(n BitOffset, v bool) {
	if !p.bitInData(n) {
		panic("capnp: set field outside struct boundaries")
	}
	addr := p.off.addOffset(n.offset())
	b := p.seg.readUint8(addr)
	if v {
		b |= n.mask()
	} else {
		b &^= n.mask()
	}
	p.seg.writeUint8(addr, b)
}

func (p Struct) dataAddress(off DataOffset, sz Size) (addr address, ok bool) {
	if p.seg == nil || Size(off)+sz > p.size.DataSize {
		return 0, false
	}
	return p.off.addOffset(off), true
}

// Uint8 returns an 8-bit integer from the struct's data section.
func (p Struct) Uint8(off DataOffset) uint8 {
	addr, ok := p.dataAddress(off, 1)
	if !ok {
		return 0
	}
	return p.seg.readUint8(addr)
}

// Uint16 returns a 16-bit integer from the struct's data section.
func (p Struct) Uint16(off DataOffset) uint16 {
	addr, ok := p.dataAddress(off, 2)
	if !ok {
		return 0
	}
	return p.seg.readUint16(addr)
}

// Uint32 returns a 32-bit integer from the struct's data section.
func (p Struct) Uint32(off DataOffset) uint32 {
	addr, ok := p.dataAddress(off, 4)
	if !ok {
		return 0
	}
	return p.seg.readUint32(addr)
}

// Uint64 returns a 64-bit integer from the struct's data section.
func (p Struct) Uint64(off DataOffset) uint64 {
	addr, ok := p.dataAddress(off, 8)
	if !ok {
		return 0
	}
	return p.seg.readUint64(addr)
}

// SetUint8 sets the 8-bit integer that is off bytes from the start of the struct to v.
func (p Struct) SetUint8(off DataOffset, v uint8) {
	addr, ok := p.dataAddress(off, 1)
	if !ok {
		panic("capnp: set field outside struct boundaries")
	}
	p.seg.writeUint8(addr, v)
}

// SetUint16 sets the 16-bit integer that is off bytes from the start of the struct to v.
func (p Struct) SetUint16(off DataOffset, v uint16) {
	addr, ok := p.dataAddress(off, 2)
	if !ok {
		panic("capnp: set field outside struct boundaries")
	}
	p.seg.writeUint16(addr, v)
}

// SetUint32 sets the 32-bit integer that is off bytes from the start of the struct to v.
func (p Struct) SetUint32(off DataOffset, v uint32) {
	addr, ok := p.dataAddress(off, 4)
	if !ok {
		panic("capnp: set field outside struct boundaries")
	}
	p.seg.writeUint32(addr, v)
}

// SetUint64 sets the 64-bit integer that is off bytes from the start of the struct to v.
func (p Struct) SetUint64(off DataOffset, v uint64) {
	addr, ok := p.dataAddress(off, 8)
	if !ok {
		panic("capnp: set field outside struct boundaries")
	}
	p.seg.writeUint64(addr, v)
}

// structFlags is a bitmask of flags for a pointer.
type structFlags uint8

// Pointer flags.
const (
	isListMember structFlags = 1 << iota
)

// copyStruct makes a deep copy of src into dst.
func copyStruct(dst, src Struct) error {
	if dst.seg == nil {
		panic("copy struct into invalid pointer")
	}
	if src.seg == nil {
		return nil
	}

	// Q: how does version handling happen here, when the
	//    destination toData[] slice can be bigger or smaller
	//    than the source data slice, which is in
	//    src.seg.Data[src.off:src.off+src.size.DataSize] ?
	//
	// A: Newer fields only come *after* old fields. Note that
	//    copy only copies min(len(src), len(dst)) size,
	//    and then we manually zero the rest in the for loop
	//    that writes toData[j] = 0.
	//

	// data section:
	srcData := src.seg.slice(src.off, src.size.DataSize)
	dstData := dst.seg.slice(dst.off, dst.size.DataSize)
	copyCount := copy(dstData, srcData)
	dstData = dstData[copyCount:]
	for j := range dstData {
		dstData[j] = 0
	}

	// ptrs section:

	// version handling: we ignore any extra-newer-pointers in src,
	// i.e. the case when srcPtrSize > dstPtrSize, by only
	// running j over the size of dstPtrSize, the destination size.
	srcPtrSect, _ := src.off.addSize(src.size.DataSize)
	dstPtrSect, _ := dst.off.addSize(dst.size.DataSize)
	numSrcPtrs := src.size.PointerCount
	numDstPtrs := dst.size.PointerCount
	for j := uint16(0); j < numSrcPtrs && j < numDstPtrs; j++ {
		srcAddr, _ := srcPtrSect.element(int32(j), wordSize)
		dstAddr, _ := dstPtrSect.element(int32(j), wordSize)
		m, err := src.seg.readPtr(srcAddr, src.depthLimit)
		if err != nil {
			return annotate(err).errorf("copy struct pointer %d", j)
		}
		err = dst.seg.writePtr(dstAddr, m, true)
		if err != nil {
			return annotate(err).errorf("copy struct pointer %d", j)
		}
	}
	for j := numSrcPtrs; j < numDstPtrs; j++ {
		// destination p is a newer version than source so these extra new pointer fields in p must be zeroed.
		addr, _ := dstPtrSect.element(int32(j), wordSize)
		dst.seg.writeRawPointer(addr, 0)
	}
	// Nothing more here: so any other pointers in srcPtrSize beyond
	// those in dstPtrSize are ignored and discarded.

	return nil
}
<|endoftext|>


<commit_before>package gen

import (
	"fmt"
	"strings"

	"github.com/go-clang/clang-v3.9/clang"
)

// Struct represents a generation struct
type Struct struct {
	api *API

	IncludeFiles includeFiles

	Name           string
	CName          string
	CNameIsTypeDef bool
	Receiver       Receiver
	Comment        string

	IsPointerComposition bool

	Members []*StructMember
	Methods []interface{}
}

type StructMember struct {
	CName   string
	Comment string

	Type Type
}

func handleStructCursor(cursor clang.Cursor, cname string, cnameIsTypeDef bool) *Struct {
	s := &Struct{
		CName:          cname,
		CNameIsTypeDef: cnameIsTypeDef,
		Comment:        CleanDoxygenComment(cursor.RawCommentText()),

		IncludeFiles: newIncludeFiles(),
	}

	s.Name = TrimLanguagePrefix(s.CName)
	s.Receiver.Name = commonReceiverName(s.Name)

	cursor.Visit(func(cursor, parent clang.Cursor) clang.ChildVisitResult {
		switch cursor.Kind() {
		case clang.Cursor_FieldDecl:
			typ, err := typeFromClangType(cursor.Type())
			if err != nil {
				panic(fmt.Errorf("unexpected error: %w, cursor.Type(): %#v", err, cursor.Type()))
			}

			if typ.IsFunctionPointer {
				return clang.ChildVisit_Continue
			}

			s.Members = append(s.Members, &StructMember{
				CName:   cursor.DisplayName(),
				Comment: CleanDoxygenComment(cursor.RawCommentText()),

				Type: typ,
			})
		}

		return clang.ChildVisit_Continue
	})

	return s
}

func (s *Struct) ContainsMethod(name string) bool {
	for _, m := range s.Methods {
		switch m := m.(type) {
		case *Function:
			if m.Name == name {
				return true
			}
		case string:
			if strings.Contains(m, ") "+name+"()") {
				return true
			}
		}
	}

	return false
}

func (s *Struct) generate() error {
	f := newFile(strings.ToLower(s.Name))
	f.Structs = append(f.Structs, s)

	return f.generate()
}

func (s *Struct) addMemberGetters() error {
	if s.api.PrepareStructMembers != nil {
		s.api.PrepareStructMembers(s)
	}

	// Generate the getters we can handle
	for _, m := range s.Members {
		if s.api.FilterStructMemberGetter != nil && !s.api.FilterStructMemberGetter(m) {
			continue
		}

		if m.Type.CGoName == "void" || m.Type.CGoName == "uintptr_t" {
			continue
		}

		if m.Type.IsArray { // TODO generate arrays with the correct size and type https://github.com/go-clang/gen/issues/48
			continue
		}

		f := newFunction(m.CName, s.CName, m.Comment, m.CName, m.Type)

		if !s.ContainsMethod(f.Name) {
			s.Methods = append(s.Methods, f)
		}
	}

	return nil
}
<commit_msg>gen: remove unused arg from handleStructCursor<commit_after>package gen

import (
	"fmt"
	"strings"

	"github.com/go-clang/clang-v3.9/clang"
)

// Struct represents a generation struct
type Struct struct {
	api *API

	IncludeFiles includeFiles

	Name           string
	CName          string
	CNameIsTypeDef bool
	Receiver       Receiver
	Comment        string

	IsPointerComposition bool

	Members []*StructMember
	Methods []interface{}
}

type StructMember struct {
	CName   string
	Comment string

	Type Type
}

func handleStructCursor(cursor clang.Cursor, cname string, cnameIsTypeDef bool) *Struct {
	s := &Struct{
		CName:          cname,
		CNameIsTypeDef: cnameIsTypeDef,
		Comment:        CleanDoxygenComment(cursor.RawCommentText()),

		IncludeFiles: newIncludeFiles(),
	}

	s.Name = TrimLanguagePrefix(s.CName)
	s.Receiver.Name = commonReceiverName(s.Name)

	cursor.Visit(func(cursor, _ clang.Cursor) clang.ChildVisitResult {
		switch cursor.Kind() {
		case clang.Cursor_FieldDecl:
			typ, err := typeFromClangType(cursor.Type())
			if err != nil {
				panic(fmt.Errorf("unexpected error: %w, cursor.Type(): %#v", err, cursor.Type()))
			}

			if typ.IsFunctionPointer {
				return clang.ChildVisit_Continue
			}

			s.Members = append(s.Members, &StructMember{
				CName:   cursor.DisplayName(),
				Comment: CleanDoxygenComment(cursor.RawCommentText()),

				Type: typ,
			})
		}

		return clang.ChildVisit_Continue
	})

	return s
}

func (s *Struct) ContainsMethod(name string) bool {
	for _, m := range s.Methods {
		switch m := m.(type) {
		case *Function:
			if m.Name == name {
				return true
			}
		case string:
			if strings.Contains(m, ") "+name+"()") {
				return true
			}
		}
	}

	return false
}

func (s *Struct) generate() error {
	f := newFile(strings.ToLower(s.Name))
	f.Structs = append(f.Structs, s)

	return f.generate()
}

func (s *Struct) addMemberGetters() error {
	if s.api.PrepareStructMembers != nil {
		s.api.PrepareStructMembers(s)
	}

	// Generate the getters we can handle
	for _, m := range s.Members {
		if s.api.FilterStructMemberGetter != nil && !s.api.FilterStructMemberGetter(m) {
			continue
		}

		if m.Type.CGoName == "void" || m.Type.CGoName == "uintptr_t" {
			continue
		}

		if m.Type.IsArray { // TODO generate arrays with the correct size and type https://github.com/go-clang/gen/issues/48
			continue
		}

		f := newFunction(m.CName, s.CName, m.Comment, m.CName, m.Type)

		if !s.ContainsMethod(f.Name) {
			s.Methods = append(s.Methods, f)
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package definitions

import (
	"fmt"
	"strings"

	"github.com/cihangir/gene/generators/common"
	"github.com/cihangir/schema"
)

// DefineConstraints creates constraints definition for tables
func DefineConstraints(context *common.Context, settings schema.Generator, s *schema.Schema) ([]byte, error) {
	primaryKeyConstraint := ""
	primaryKey := settings.Get("primaryKey")
	if primaryKey != nil {
		pmi := primaryKey.([]interface{})
		if len(pmi) > 0 {
			sl := make([]string, len(pmi))
			for i, pm := range pmi {
				sl[i] = context.FieldNameFunc(pm.(string))
			}

			primaryKeyConstraint = fmt.Sprintf(
				"ALTER TABLE %q.%q ADD PRIMARY KEY (%q) NOT DEFERRABLE INITIALLY IMMEDIATE;\n",
				settings.Get("schemaName"),
				settings.Get("tableName"),
				strings.Join(sl, ", "),
			)
			primaryKeyConstraint = fmt.Sprintf("-------------------------------\n--  Primary key structure for table %s\n-- ----------------------------\n%s",
				settings.Get("tableName"),
				primaryKeyConstraint,
			)
		}
	}

	uniqueKeyConstraints := ""
	uniqueKeys := settings.Get("uniqueKeys")
	if uniqueKeys != nil {
		ukci := uniqueKeys.([]interface{})
		if len(ukci) > 0 {
			for _, ukc := range ukci {
				ukcs := ukc.([]interface{})
				ukcsps := make([]string, len(ukcs))
				for i, ukc := range ukcs {
					ukcsps[i] = context.FieldNameFunc(ukc.(string))
				}
				keyName := fmt.Sprintf(
					"%s_%s_%s",
					context.FieldNameFunc("key"),
					context.FieldNameFunc(settings.Get("tableName").(string)),
					strings.Join(ukcsps, "_"),
				)
				uniqueKeyConstraints += fmt.Sprintf(
					"ALTER TABLE %q.%q ADD CONSTRAINT %q UNIQUE (\"%s\") NOT DEFERRABLE INITIALLY IMMEDIATE;\n",
					settings.Get("schemaName"),
					settings.Get("tableName"),
					keyName,
					strings.Join(ukcsps, "\", \""),
				)

			}
			uniqueKeyConstraints = fmt.Sprintf("-------------------------------\n--  Unique key structure for table %s\n-- ----------------------------\n%s",
				settings.Get("tableName"),
				uniqueKeyConstraints,
			)

		}
	}

	foreignKeyConstraints := ""
	foreignKeys := settings.Get("foreignKeys")
	if foreignKeys != nil {
		ukci := foreignKeys.([]interface{})
		if len(ukci) > 0 {
			for _, fkc := range ukci {
				fkcs := fkc.([]interface{})
				localField := context.FieldNameFunc(fkcs[0].(string))
				refFields := strings.Split(fkcs[1].(string), ".")
				if len(refFields) != 3 {
					return nil, fmt.Errorf("need schemaName.tableName.fieldName")
				}
				keyName := fmt.Sprintf(
					"%s_%s_%s",
					context.FieldNameFunc("fkey"),
					context.FieldNameFunc(settings.Get("tableName").(string)),
					localField,
				)

				foreignKeyConstraints += fmt.Sprintf(
					"ALTER TABLE %q.%q ADD CONSTRAINT %q FOREIGN KEY (\"%s\") REFERENCES %s.%s (%s) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE;\n",
					settings.Get("schemaName"),
					settings.Get("tableName"),
					keyName,
					localField,
					context.FieldNameFunc(refFields[0]), // first item schema name
					context.FieldNameFunc(refFields[1]), // second item table name
					context.FieldNameFunc(refFields[2]), // third item field name

				)

				foreignKeyConstraints = fmt.Sprintf("-------------------------------\n--  Foreign keys structure for table %s\n-- ----------------------------\n%s",
					settings.Get("tableName"),
					foreignKeyConstraints,
				)
			}
		}
	}

	return clean([]byte(primaryKeyConstraint + uniqueKeyConstraints + foreignKeyConstraints)), nil
}
<commit_msg>Gene: change var name<commit_after>package definitions

import (
	"fmt"
	"strings"

	"github.com/cihangir/gene/generators/common"
	"github.com/cihangir/schema"
)

// DefineConstraints creates constraints definition for tables
func DefineConstraints(context *common.Context, settings schema.Generator, s *schema.Schema) ([]byte, error) {
	primaryKeyConstraint := ""
	primaryKey := settings.Get("primaryKey")
	if primaryKey != nil {
		pmi := primaryKey.([]interface{})
		if len(pmi) > 0 {
			sl := make([]string, len(pmi))
			for i, pm := range pmi {
				sl[i] = context.FieldNameFunc(pm.(string))
			}

			primaryKeyConstraint = fmt.Sprintf(
				"ALTER TABLE %q.%q ADD PRIMARY KEY (%q) NOT DEFERRABLE INITIALLY IMMEDIATE;\n",
				settings.Get("schemaName"),
				settings.Get("tableName"),
				strings.Join(sl, ", "),
			)
			primaryKeyConstraint = fmt.Sprintf("-------------------------------\n--  Primary key structure for table %s\n-- ----------------------------\n%s",
				settings.Get("tableName"),
				primaryKeyConstraint,
			)
		}
	}

	uniqueKeyConstraints := ""
	uniqueKeys := settings.Get("uniqueKeys")
	if uniqueKeys != nil {
		ukci := uniqueKeys.([]interface{})
		if len(ukci) > 0 {
			for _, ukc := range ukci {
				ukcs := ukc.([]interface{})
				ukcsps := make([]string, len(ukcs))
				for i, ukc := range ukcs {
					ukcsps[i] = context.FieldNameFunc(ukc.(string))
				}
				keyName := fmt.Sprintf(
					"%s_%s_%s",
					context.FieldNameFunc("key"),
					context.FieldNameFunc(settings.Get("tableName").(string)),
					strings.Join(ukcsps, "_"),
				)
				uniqueKeyConstraints += fmt.Sprintf(
					"ALTER TABLE %q.%q ADD CONSTRAINT %q UNIQUE (\"%s\") NOT DEFERRABLE INITIALLY IMMEDIATE;\n",
					settings.Get("schemaName"),
					settings.Get("tableName"),
					keyName,
					strings.Join(ukcsps, "\", \""),
				)

			}
			uniqueKeyConstraints = fmt.Sprintf("-------------------------------\n--  Unique key structure for table %s\n-- ----------------------------\n%s",
				settings.Get("tableName"),
				uniqueKeyConstraints,
			)

		}
	}

	foreignKeyConstraints := ""
	foreignKeys := settings.Get("foreignKeys")
	if foreignKeys != nil {
		fkci := foreignKeys.([]interface{})
		if len(fkci) > 0 {
			for _, fkc := range fkci {
				fkcs := fkc.([]interface{})
				localField := context.FieldNameFunc(fkcs[0].(string))
				refFields := strings.Split(fkcs[1].(string), ".")
				if len(refFields) != 3 {
					return nil, fmt.Errorf("need schemaName.tableName.fieldName")
				}
				keyName := fmt.Sprintf(
					"%s_%s_%s",
					context.FieldNameFunc("fkey"),
					context.FieldNameFunc(settings.Get("tableName").(string)),
					localField,
				)

				foreignKeyConstraints += fmt.Sprintf(
					"ALTER TABLE %q.%q ADD CONSTRAINT %q FOREIGN KEY (\"%s\") REFERENCES %s.%s (%s) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE;\n",
					settings.Get("schemaName"),
					settings.Get("tableName"),
					keyName,
					localField,
					context.FieldNameFunc(refFields[0]), // first item schema name
					context.FieldNameFunc(refFields[1]), // second item table name
					context.FieldNameFunc(refFields[2]), // third item field name

				)

				foreignKeyConstraints = fmt.Sprintf("-------------------------------\n--  Foreign keys structure for table %s\n-- ----------------------------\n%s",
					settings.Get("tableName"),
					foreignKeyConstraints,
				)
			}
		}
	}

	return clean([]byte(primaryKeyConstraint + uniqueKeyConstraints + foreignKeyConstraints)), nil
}
<|endoftext|>


<commit_before>package cover

import (
	"fmt"
	"log"
	"math"
	"sort"
)

// Builds a constraint matrix for a sudoku of the given dimension.
// The constraint matrix can then be used by the DLX algorithm.
func SudokuConstraintMatrix(dim int) (matrix [][]int, headers []string) {
	// small dim, 3 for classic sudoku
	sdim := int(math.Sqrt(float64(dim)))
	// big dim, 81 for classic sudoku
	bdim := dim * dim
	rowCount := bdim * dim
	colCount := bdim * 4
	log.Printf("Building sparse matrix of %dx%d\n", rowCount, colCount)
	// constraint matrix headers
	// constraint order is existence, row, col, block
	headers = make([]string, colCount)
	for i, j := 0, 0; i < colCount; i++ {
		j = i % bdim
		if i < bdim {
			// constraint 1: existence
			headers[i] = fmt.Sprintf("%v,%v", i/dim, i%dim)
		} else if i < 2*bdim {
			// constraint 2: row
			headers[i] = fmt.Sprintf("%vr%v", j%dim+1, j/dim)
		} else if i < 3*bdim {
			// constraint 3: column
			headers[i] = fmt.Sprintf("%vc%v", j%dim+1, j/dim)
		} else {
			// constraint 4: block
			headers[i] = fmt.Sprintf("%vb%v", j%dim+1, j/dim)
		}
	}
	// constraint matrix
	matrix = make([][]int, rowCount)
	for i := 0; i < rowCount; i++ {
		matrix[i] = make([]int, colCount)
		digit := i%dim + 1
		dcell := i / dim
		drow := i / bdim
		dcol := (i / dim) % dim
		dblock := drow/sdim*sdim + dcol/sdim
		matrix[i][dcell] = digit
		matrix[i][bdim+drow*dim+i%dim] = digit
		matrix[i][bdim+bdim+i%bdim] = digit
		matrix[i][bdim+bdim+bdim+dblock*dim+i%dim] = digit
	}
	return
}

type SudokuSolver struct {
	*Solver
}

// Since the constraint matrix for a sudoku only depends on its size, this constructor
// encapsulate the matrix creation so that only the sudoku size is needed.
func NewSudokuSolver(dim int) *SudokuSolver {
	m, h := SudokuConstraintMatrix(dim)
	log.Println(len(h), h)
	log.Println(len(m))
	s := SudokuSolver{&Solver{matrix: NewSparseMatrix(m, h)}}
	return &s
}

// Translates the initial grid to a map of digit => cells.
// This enables the solver to safely initialize the matrix before
// actually running the DLX algorithm.
// The trick is to search only in the columns of the 1st constraint (existence)
// and start from the biggest digit. This way, the number of steps to find the correct
// row does not change and the digit can be found in a single column.
func (s *SudokuSolver) gridToCover(sudoku [][]int) map[int][]string {
	dim := len(sudoku)
	init := map[int][]string{}
	for i := 0; i < dim; i++ {
		for j := 0; j < dim; j++ {
			digit := sudoku[i][j]
			if digit > 0 {
				_, ok := init[digit]
				if !ok {
					init[digit] = make([]string, 0)
				}
				init[digit] = append(init[digit], fmt.Sprintf("%v,%v", i, j))
			}
		}
	}
	return init
}
func (s *SudokuSolver) Solve(sudoku [][]int) *Solution {
	partial := s.gridToCover(sudoku)
	// Iterate through the digits from biggest to smallest.
	keys := make([]int, 0, len(partial))
	for key, _ := range partial {
		keys = append(keys, key)
	}
	sort.Sort(sort.Reverse(sort.IntSlice(keys)))
	log.Println("Initial config is", partial)
	O := new(Solution)
	k := 0
	m := s.matrix
	for _, digit := range keys {
		for _, c := range partial[digit] {
			// Find the column for existence constraint, so that all the digits are available inside.
			n := m.Col(c)
			n.Cover()
			// Move down by <digit> nodes to find the row to include in the solution.
			for j := 0; j < digit; j++ {
				n = n.Down
			}
			O.Set(k, n)
			for o := n.Right; o != n; o = o.Right {
				o.Col.Cover()
			}
			k++
		}
	}
	fmt.Printf("Initial solution is\n%v", O)
	s.matrix.Search(O, k, s)
	return O
}
<commit_msg>Improve sudoku stuff to print a useable solution.<commit_after>package cover

import (
	"fmt"
	"log"
	"math"
	"sort"
	"strconv"
	"strings"
)

// Builds a constraint matrix for a sudoku of the given dimension.
// The constraint matrix can then be used by the DLX algorithm.
func SudokuConstraintMatrix(dim int) (matrix [][]int, headers []string) {
	// small dim, 3 for classic sudoku
	sdim := int(math.Sqrt(float64(dim)))
	// big dim, 81 for classic sudoku
	bdim := dim * dim
	rowCount := bdim * dim
	colCount := bdim * 4
	log.Printf("Building sparse matrix of %dx%d\n", rowCount, colCount)
	// constraint matrix headers
	// constraint order is existence, row, col, block
	headers = make([]string, colCount)
	for i, j := 0, 0; i < colCount; i++ {
		j = i % bdim
		if i < bdim {
			// constraint 1: existence
			headers[i] = fmt.Sprintf("%v,%v", i/dim, i%dim)
		} else if i < 2*bdim {
			// constraint 2: row
			headers[i] = fmt.Sprintf("%vr%v", j%dim+1, j/dim)
		} else if i < 3*bdim {
			// constraint 3: column
			headers[i] = fmt.Sprintf("%vc%v", j%dim+1, j/dim)
		} else {
			// constraint 4: block
			headers[i] = fmt.Sprintf("%vb%v", j%dim+1, j/dim)
		}
	}
	// constraint matrix
	matrix = make([][]int, rowCount)
	for i := 0; i < rowCount; i++ {
		matrix[i] = make([]int, colCount)
		digit := i%dim + 1
		dcell := i / dim
		drow := i / bdim
		dcol := (i / dim) % dim
		dblock := drow/sdim*sdim + dcol/sdim
		matrix[i][dcell] = digit
		matrix[i][bdim+drow*dim+i%dim] = digit
		matrix[i][bdim+bdim+i%bdim] = digit
		matrix[i][bdim+bdim+bdim+dblock*dim+i%dim] = digit
	}
	return
}

type SudokuSolver struct {
	*Solver
	Dim int
}

// Since the constraint matrix for a sudoku only depends on its size, this constructor
// encapsulate the matrix creation so that only the sudoku size is needed.
func NewSudokuSolver(dim int) *SudokuSolver {
	m, h := SudokuConstraintMatrix(dim)
	s := SudokuSolver{&Solver{matrix: NewSparseMatrix(m, h)}, dim}
	return &s
}

// Translates the initial grid to a map of digit => cells.
// This enables the solver to safely initialize the matrix before
// actually running the DLX algorithm.
// The trick is to search only in the columns of the 1st constraint (existence)
// and start from the biggest digit. This way, the number of steps to find the correct
// row does not change and the digit can be found in a single column.
func (s *SudokuSolver) gridToCover(sudoku [][]int) map[int][]string {
	dim := len(sudoku)
	init := map[int][]string{}
	for i := 0; i < dim; i++ {
		for j := 0; j < dim; j++ {
			digit := sudoku[i][j]
			if digit > 0 {
				_, ok := init[digit]
				if !ok {
					init[digit] = make([]string, 0)
				}
				init[digit] = append(init[digit], fmt.Sprintf("%v,%v", i, j))
			}
		}
	}
	return init
}
func (s *SudokuSolver) coverToGrid(nodes []*Node) (x int, y int, digit int) {
	for _, n := range nodes {
		if n != nil {
			if strings.ContainsAny(n.Col.Name, "r & c & b") {
				digit, _ = strconv.Atoi(fmt.Sprintf("%c", n.Col.Name[0]))
			} else {
				xy := strings.Split(n.Col.Name, ",")
				x, _ = strconv.Atoi(xy[0])
				y, _ = strconv.Atoi(xy[1])
			}
		}
	}
	return
}
func (s *SudokuSolver) Eureka(O *Solution) {
	grid := make([][]int, s.Dim)
	for i := 0; i < s.Dim; i++ {
		grid[i] = make([]int, s.Dim)
	}
	for _, n := range *O {
		nodes := make([]*Node, 4)
		nodes = append(nodes, n)
		for m := n.Right; n != m; m = m.Right {
			nodes = append(nodes, m)
		}
		x, y, digit := s.coverToGrid(nodes)
		grid[x][y] = digit
	}
	sdim := int(math.Sqrt(float64(s.Dim)))
	delim := "+" + strings.Repeat(strings.Repeat("-", sdim*2+1)+"+", sdim)
	for i, line := range grid {
		if i%sdim == 0 {
			fmt.Println(delim)
		}
		for j, cell := range line {
			if j%sdim == 0 {
				if j > 0 {
					fmt.Print(" ")
				}
				fmt.Print("|")
			}
			fmt.Print(" ", cell)
		}
		fmt.Print(" |\n")
	}
	fmt.Println(delim)
}
func (s *SudokuSolver) Solve(sudoku [][]int) *Solution {
	partial := s.gridToCover(sudoku)
	// Iterate through the digits from biggest to smallest.
	keys := make([]int, 0, len(partial))
	for key, _ := range partial {
		keys = append(keys, key)
	}
	sort.Sort(sort.Reverse(sort.IntSlice(keys)))
	// log.Println("Initial config is", partial)
	O := new(Solution)
	k := 0
	m := s.matrix
	for _, digit := range keys {
		for _, c := range partial[digit] {
			// Find the column for existence constraint, so that all the digits are available inside.
			n := m.Col(c)
			n.Cover()
			// Move down by <digit> nodes to find the row to include in the solution.
			for j := 0; j < digit; j++ {
				n = n.Down
			}
			O.Set(k, n)
			for o := n.Right; o != n; o = o.Right {
				o.Col.Cover()
			}
			k++
		}
	}
	// fmt.Printf("Initial solution is\n%v", O)
	s.matrix.Search(O, k, s)
	return O
}
<|endoftext|>


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

package src

import (
	"errors"
	"fmt"
	"io"
)

const bufsize = 8192

const (
	scanIllegalToken = iota
	scanBeginObject
	scanEndObject
	scanBeginArray
	scanEndArray
	scanIntLit
	scanStringLit
	scanBoolLit
	scanNumberLit
	scanNullVal
	scanComma
)

type scanner struct {
	r   io.Reader
	err error

	row int64
	col int64

	buf []byte
	pos int // position inside the buffer; must be -1 by default

	eof bool // true when the reader has been reached
}

func newScanner(r io.Reader) *scanner {
	return &scanner{r: r, buf: make([]byte, bufsize), pos: -1}
}

func (scan *scanner) nextKey() (string, error) {
	if err := scan.ignoreWhitespaces(); err != nil {
		if err == io.EOF {
			return "", errors.New("expected key, found EOF")
		}
		return "", err
	}

	if c, err := scan.read(); err != nil {
		return "", err
	} else if c != '"' {
		return "", fmt.Errorf("expected '\"', found '%c'", c)
	}

	var key string
	origPos := scan.pos
	for {
		c, err := scan.read()
		if err == io.EOF {
			return "", errors.New("expected key, found EOF")
		} else if err != nil {
			return "", err
		}

		// TODO: check character

		if c == '"' {
			break
		}

		if scan.pos >= len(scan.buf)-1 {
			key += string(scan.buf[origPos:])
			origPos = 0
		}
	}

	key += string(scan.buf[origPos:scan.pos])

	if err := scan.ignoreWhitespaces(); err != nil {
		if err == io.EOF {
			return "", errors.New("expected ':', found EOF")
		}
		return "", err
	}

	if c, err := scan.read(); err == io.EOF {
		return "", errors.New("expected ':', found EOF")
	} else if err != nil {
		return "", err
	} else if c != ':' {
		return "", fmt.Errorf("expected ':', found '%c'", c)
	}

	return key, nil
}

func (scan *scanner) nextValue() (val []byte, tok int, err error) {
	if err := scan.ignoreWhitespaces(); err != nil {
		if err == io.EOF {
			return nil, 0, errors.New("expected value, found EOF")
		}
		return nil, 0, err
	}

	c, err := scan.read()
	if err != nil {
		if err == io.EOF {
			return nil, 0, errors.New("expected value, found EOF")
		}
		return nil, 0, err
	}

	switch {
	case isDigit(c):
		// TODO: read digit
	case c == '{': // beginning of an object literal
		return nil, scanBeginObject, nil
	case c == '}': // ending of an object literal
		return nil, scanEndObject, nil
	case c == '[': // beginning of an array literal
		return nil, scanBeginArray, nil
	case c == ']': // ending of an array literal
		return nil, scanEndArray, nil
	case c == '"': // beginning or ending of a string literal
		// TODO: read string
	case c == 'n': // null
		// TODO: read null
	case c == ',':
		return nil, scanComma, nil
	}
	return nil, scanIllegalToken, fmt.Errorf("illegal value '%c'", c)
}

// peek reads the next value without consuming it.
func (scan *scanner) peek() (byte, error) {
	c, err := scan.read()
	if err != nil {
		return 0, err
	}
	scan.back()
	return c, nil
}

func (scan *scanner) read() (byte, error) {
	if scan.pos == -1 || (scan.pos > len(scan.buf)-1 && !scan.eof) {
		n, err := scan.r.Read(scan.buf)
		if err != nil {
			if err != io.EOF {
				return 0, err
			}
			scan.eof = true
		}
		if n < bufsize {
			scan.buf = scan.buf[:n]
		}
		scan.pos = 0
	}
	if scan.pos >= len(scan.buf) {
		return 0, io.EOF
	}
	b := scan.buf[scan.pos]
	scan.pos++
	return b, nil
}

func (scan *scanner) back() {
	if scan.pos > 0 {
		scan.pos--
	}
}

// ignoreWhitespaces consumes all whitespaces.
func (scan *scanner) ignoreWhitespaces() error {
	var c byte
	var err error
	// XXX: refactor when the tests pass
	for {
		if c, err = scan.read(); err != nil || !isWhitespace(c) {
			break
		}
		// Nothing, we just skip whitespaces.
	}

	// Since a non-whitespace has been read, we have to put it back to the
	// buffer so that it can be read again.
	scan.back()

	if err != io.EOF {
		return err
	}
	return nil
}

func isWhitespace(c byte) bool {
	return c == ' ' || c == '\n' || c == '\t' || c == '\r'
}

func isDigit(c byte) bool {
	return c >= '0' && c <= '9'
}

// TODO: implement
func isUnicodeChar(c byte) bool {
	return false
}
<commit_msg>src: add case for boolean in the scanner<commit_after>// Copyright 2014-2015 The project AUTHORS. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package src

import (
	"errors"
	"fmt"
	"io"
)

const bufsize = 8192

const (
	scanIllegalToken = iota
	scanBeginObject
	scanEndObject
	scanBeginArray
	scanEndArray
	scanIntLit
	scanStringLit
	scanBoolLit
	scanNumberLit
	scanNullVal
	scanComma
)

type scanner struct {
	r   io.Reader
	err error

	row int64
	col int64

	buf []byte
	pos int // position inside the buffer; must be -1 by default

	eof bool // true when the reader has been reached
}

func newScanner(r io.Reader) *scanner {
	return &scanner{r: r, buf: make([]byte, bufsize), pos: -1}
}

func (scan *scanner) nextKey() (string, error) {
	if err := scan.ignoreWhitespaces(); err != nil {
		if err == io.EOF {
			return "", errors.New("expected key, found EOF")
		}
		return "", err
	}

	if c, err := scan.read(); err != nil {
		return "", err
	} else if c != '"' {
		return "", fmt.Errorf("expected '\"', found '%c'", c)
	}

	var key string
	origPos := scan.pos
	for {
		c, err := scan.read()
		if err == io.EOF {
			return "", errors.New("expected key, found EOF")
		} else if err != nil {
			return "", err
		}

		// TODO: check character

		if c == '"' {
			break
		}

		if scan.pos >= len(scan.buf)-1 {
			key += string(scan.buf[origPos:])
			origPos = 0
		}
	}

	key += string(scan.buf[origPos:scan.pos])

	if err := scan.ignoreWhitespaces(); err != nil {
		if err == io.EOF {
			return "", errors.New("expected ':', found EOF")
		}
		return "", err
	}

	if c, err := scan.read(); err == io.EOF {
		return "", errors.New("expected ':', found EOF")
	} else if err != nil {
		return "", err
	} else if c != ':' {
		return "", fmt.Errorf("expected ':', found '%c'", c)
	}

	return key, nil
}

func (scan *scanner) nextValue() (val []byte, tok int, err error) {
	if err := scan.ignoreWhitespaces(); err != nil {
		if err == io.EOF {
			return nil, 0, errors.New("expected value, found EOF")
		}
		return nil, 0, err
	}

	c, err := scan.read()
	if err != nil {
		if err == io.EOF {
			return nil, 0, errors.New("expected value, found EOF")
		}
		return nil, 0, err
	}

	switch {
	case isDigit(c):
		// TODO: read digit
	case c == 't' || c == 'f':
		// TODO: read bool
	case c == '{': // beginning of an object literal
		return nil, scanBeginObject, nil
	case c == '}': // ending of an object literal
		return nil, scanEndObject, nil
	case c == '[': // beginning of an array literal
		return nil, scanBeginArray, nil
	case c == ']': // ending of an array literal
		return nil, scanEndArray, nil
	case c == '"': // beginning or ending of a string literal
		// TODO: read string
	case c == 'n': // null
		// TODO: read null
	case c == ',':
		return nil, scanComma, nil
	}
	return nil, scanIllegalToken, fmt.Errorf("illegal value '%c'", c)
}

// peek reads the next value without consuming it.
func (scan *scanner) peek() (byte, error) {
	c, err := scan.read()
	if err != nil {
		return 0, err
	}
	scan.back()
	return c, nil
}

func (scan *scanner) read() (byte, error) {
	if scan.pos == -1 || (scan.pos > len(scan.buf)-1 && !scan.eof) {
		n, err := scan.r.Read(scan.buf)
		if err != nil {
			if err != io.EOF {
				return 0, err
			}
			scan.eof = true
		}
		if n < bufsize {
			scan.buf = scan.buf[:n]
		}
		scan.pos = 0
	}
	if scan.pos >= len(scan.buf) {
		return 0, io.EOF
	}
	b := scan.buf[scan.pos]
	scan.pos++
	return b, nil
}

func (scan *scanner) back() {
	if scan.pos > 0 {
		scan.pos--
	}
}

// ignoreWhitespaces consumes all whitespaces.
func (scan *scanner) ignoreWhitespaces() error {
	var c byte
	var err error
	// XXX: refactor when the tests pass
	for {
		if c, err = scan.read(); err != nil || !isWhitespace(c) {
			break
		}
		// Nothing, we just skip whitespaces.
	}

	// Since a non-whitespace has been read, we have to put it back to the
	// buffer so that it can be read again.
	scan.back()

	if err != io.EOF {
		return err
	}
	return nil
}

func isWhitespace(c byte) bool {
	return c == ' ' || c == '\n' || c == '\t' || c == '\r'
}

func isDigit(c byte) bool {
	return c >= '0' && c <= '9'
}

// TODO: implement
func isUnicodeChar(c byte) bool {
	return false
}
<|endoftext|>