<commit_before>/*
   Copyright 2017 GitHub Inc.

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

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

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

package remote

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"github.com/github/orchestrator/go/config"
	"github.com/github/orchestrator/go/inst"
	orcos "github.com/github/orchestrator/go/os"
	"github.com/github/orchestrator/go/process"
	"github.com/outbrain/golib/log"
)

func TestRemoteCommandOnInstance(instanceKey *inst.InstanceKey) error {
	sudoCommand := ""
	if config.Config.RemoteSSHCommandUseSudo {
		sudoCommand = "sudo -i"
	}

	tempFile, err := ioutil.TempFile("", "orchestrator-remote-test-")
	if err != nil {
		return err
	}
	defer os.Remove(tempFile.Name())

	randomToken := process.NewToken()

	command := config.Config.RemoteSSHCommand
	command = strings.Replace(command, "{hostname}", instanceKey.Hostname, -1)
	command = fmt.Sprintf("%s '%s echo %s' > %s", command, sudoCommand, randomToken.Hash, tempFile.Name())
	if err := orcos.CommandRun(command, orcos.EmptyEnv); err != nil {
		return err
	}
	bytes, err := ioutil.ReadFile(tempFile.Name())
	if err != nil {
		return err
	}
	if content := strings.TrimSpace(string(bytes)); content != randomToken.Hash {
		return fmt.Errorf("TestRemoteCommandOnInstance: expected %s, got %s", randomToken.Hash, content)
	}
	return nil
}

// AlignViaRelaylogCorrelation will align siblings by applying relaylogs from one to the other, via remote SSH
func AlignViaRelaylogCorrelation(instance, fromInstance *inst.Instance) (*inst.Instance, error) {
	if config.Config.RemoteSSHCommand == "" {
		return instance, fmt.Errorf("RemoteSSHCommand not configured")
	}
	log.Debugf("Testing SSH on %+v", instance.Key)
	if err := TestRemoteCommandOnInstance(&instance.Key); err != nil {
		return instance, err
	}

	if instance.ReplicaRunning() {
		return instance, log.Errorf("AlignViaRelaylogCorrelation: replication on %+v must not run", instance.Key)
	}
	if fromInstance.ReplicaRunning() {
		return instance, log.Errorf("AlignViaRelaylogCorrelation: replication on %+v must not run", fromInstance.Key)
	}

	log.Debugf("AlignViaRelaylogCorrelation: correlating coordinates of %+v on %+v", instance.Key, fromInstance.Key)
	_, _, nextCoordinates, found, err := inst.CorrelateRelaylogCoordinates(instance, nil, fromInstance)
	if err != nil {
		return instance, err
	}
	if !found {
		return instance, err
	}
	log.Debugf("AlignViaRelaylogCorrelation: correlated next-coordinates are %+v", *nextCoordinates)

	// We now have the correlation info needed to proceed with remote calls
	sudoCommand := ""
	if config.Config.RemoteSSHCommandUseSudo {
		sudoCommand = "sudo -i"
	}

	// Write get-relaylogs script locally
	getRelayLogContentsScriptFile, err := ioutil.TempFile("", "orchestrator-remote-get-relaylogs-content-")
	if err != nil {
		return instance, err
	}
	{
		//	defer os.Remove(getRelayLogContentsScriptFile.Name())
		script := GetRelayLogContentsScript
		script = strings.Replace(script, "$MAGIC_FIRST_RELAYLOG_FILE", nextCoordinates.LogFile, -1)
		script = strings.Replace(script, "$MAGIC_START_POSITION", fmt.Sprintf("%d", nextCoordinates.LogPos), -1)
		script = strings.Replace(script, "$MAGIC_STOP_POSITION", fmt.Sprintf("%d", fromInstance.ReadBinlogCoordinates.LogPos), -1)
		log.Debugf("------ MAGIC_START_POSITION=%+v, MAGIC_STOP_POSITION=%+v", fmt.Sprintf("%d", nextCoordinates.LogPos), fmt.Sprintf("%d", fromInstance.ReadBinlogCoordinates.LogPos))
		if err := ioutil.WriteFile(getRelayLogContentsScriptFile.Name(), []byte(script), 0640); err != nil {
			return instance, err
		}
	}
	log.Debugf("getRelayLogContentsScriptFile: %+v", getRelayLogContentsScriptFile.Name())

	// Get relay log contents, save locally
	localRelayLogContentsFile, err := ioutil.TempFile("", "orchestrator-remote-relaylogs-content-")
	if err != nil {
		return instance, err
	}
	defer os.Remove(localRelayLogContentsFile.Name())
	localRelayLogContentsCopyFileName := fmt.Sprintf("%s.copy", localRelayLogContentsFile.Name())
	{
		command := config.Config.RemoteSSHCommand
		command = strings.Replace(command, "{hostname}", fromInstance.Key.Hostname, -1)
		command = fmt.Sprintf("cat %s | %s '%s' > %s", getRelayLogContentsScriptFile.Name(), command, sudoCommand, localRelayLogContentsFile.Name())
		if err := orcos.CommandRun(command, orcos.EmptyEnv); err != nil {
			return instance, err
		}
	}
	log.Debugf("Have fetched relay logs from %s, output file is %s", fromInstance.Key.Hostname, localRelayLogContentsFile.Name())
	// Copy local relay log contents to target host:
	{
		command := config.Config.RemoteSSHCommand
		command = strings.Replace(command, "{hostname}", instance.Key.Hostname, -1)
		command = fmt.Sprintf("cat %s | %s '%s cat - > %s'", localRelayLogContentsFile.Name(), command, sudoCommand, localRelayLogContentsCopyFileName)
		if err := orcos.CommandRun(command, orcos.EmptyEnv); err != nil {
			return instance, err
		}
	}
	log.Debugf("Have copied contents file to %s, output file is %s", instance.Key.Hostname, localRelayLogContentsFile.Name())

	// Generate the apply-relaylogs script, locally
	applyRelayLogContentsScriptFile, err := ioutil.TempFile("", "orchestrator-remote-apply-relaylogs-content-")
	if err != nil {
		return instance, err
	}
	{
		defer os.Remove(applyRelayLogContentsScriptFile.Name())
		script := ApplyRelayLogContentsScript
		script = strings.Replace(script, "$MAGIC_MYSQL_COMMAND", "", -1)
		script = strings.Replace(script, "$MAGIC_CONTENTS_FILE", localRelayLogContentsCopyFileName, -1)

		if err := ioutil.WriteFile(applyRelayLogContentsScriptFile.Name(), []byte(script), 0640); err != nil {
			return instance, err
		}
	}
	log.Debugf("applyRelayLogContentsScriptFile: %+v", applyRelayLogContentsScriptFile.Name())

	if *config.RuntimeCLIFlags.Noop {
		return instance, fmt.Errorf("noop: Not really applying scripts onto %+v; signalling error but nothing went wrong", instance.Key)
	}

	// apply relaylog contents on target host:
	{
		command := config.Config.RemoteSSHCommand
		command = strings.Replace(command, "{hostname}", instance.Key.Hostname, -1)
		command = fmt.Sprintf("cat %s | %s '%s'", applyRelayLogContentsScriptFile.Name(), command, sudoCommand)
		if err := orcos.CommandRun(command, orcos.EmptyEnv); err != nil {
			return instance, err
		}
	}
	log.Debugf("Have successfully applied relay logs on %s", instance.Key.Hostname)

	instance, err = inst.ChangeMasterTo(&instance.Key, &fromInstance.MasterKey, &fromInstance.ExecBinlogCoordinates, false, inst.GTIDHintNeutral)
	if err != nil {
		return instance, err
	}
	inst.AuditOperation("align-via-relaylogs-remote", &instance.Key, fmt.Sprintf("aligned %+v by relaylogs from %+v", instance.Key, fromInstance.Key))
	return instance, err
}

func SyncReplicasRelayLogs(masterKey *inst.InstanceKey, postponedFunctionsContainer *inst.PostponedFunctionsContainer) (
	syncedReplicas, failedReplicas, postponedReplicas [](*inst.Instance), err error,
) {
	var replicas [](*inst.Instance)
	if replicas, err = inst.GetSortedReplicas(masterKey, true); err != nil {
		return syncedReplicas, replicas, postponedReplicas, err
	}
	if len(replicas) <= 1 {
		// Nothing to be done
		return syncedReplicas, replicas, postponedReplicas, err
	}
	applyFromReplica := replicas[0]
	applyToReplicas := replicas[1:]

	log.Debugf("Testing SSH on %+v", applyFromReplica.Key)
	if err := TestRemoteCommandOnInstance(&applyFromReplica.Key); err != nil {
		return syncedReplicas, replicas, postponedReplicas, err
	}

	barrier := make(chan *inst.InstanceKey, len(applyToReplicas))
	allErrors := make(chan error, len(applyToReplicas))
	synchedReplicasChan := make(chan *inst.Instance, len(applyToReplicas))
	failedReplicasChan := make(chan *inst.Instance, len(applyToReplicas))

	applyToReplicaFunc := func(applyToReplica *inst.Instance) error {
		defer func() { barrier <- &applyToReplica.Key }()

		if _, err := AlignViaRelaylogCorrelation(applyToReplica, applyFromReplica); err == nil {
			synchedReplicasChan <- applyToReplica
		} else {
			failedReplicasChan <- applyToReplica
			allErrors <- err
		}
		return err
	}

	log.Debugf("Applying relay logs on %+v replicas", len(applyToReplicas))
	countImmediateApply := 0
	for _, applyToReplica := range applyToReplicas {
		applyToReplica := applyToReplica

		if postponedFunctionsContainer != nil &&
			config.Config.PostponeReplicaRecoveryOnLagMinutes > 0 &&
			applyToReplica.SQLDelay > config.Config.PostponeReplicaRecoveryOnLagMinutes*60 {
			postponedReplicas = append(postponedReplicas, applyToReplica)
			(*postponedFunctionsContainer).AddPostponedFunction(func() error { return applyToReplicaFunc(applyToReplica) })
		} else {
			countImmediateApply++
			go applyToReplicaFunc(applyToReplica)
		}
	}
	for i := 0; i < countImmediateApply; i++ {
		<-barrier
	}
	syncedReplicas = append(syncedReplicas, applyFromReplica)
	for len(synchedReplicasChan) > 0 {
		syncedReplicas = append(syncedReplicas, <-synchedReplicasChan)
	}
	for len(failedReplicasChan) > 0 {
		failedReplicas = append(failedReplicas, <-failedReplicasChan)
	}
	countErrors := len(allErrors)
	for len(allErrors) > 0 {
		log.Errore(<-allErrors)
	}
	inst.AuditOperation("sync-replicas-relaylogs", masterKey, fmt.Sprintf("aligned %+v replicas by relaylogs from %+v, got %+v errors", len(applyToReplicas), applyFromReplica.Key, countErrors))
	return syncedReplicas, failedReplicas, postponedReplicas, err
}
<commit_msg>restore script file cleanup<commit_after>/*
   Copyright 2017 GitHub Inc.

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

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

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

package remote

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"github.com/github/orchestrator/go/config"
	"github.com/github/orchestrator/go/inst"
	orcos "github.com/github/orchestrator/go/os"
	"github.com/github/orchestrator/go/process"
	"github.com/outbrain/golib/log"
)

func TestRemoteCommandOnInstance(instanceKey *inst.InstanceKey) error {
	sudoCommand := ""
	if config.Config.RemoteSSHCommandUseSudo {
		sudoCommand = "sudo -i"
	}

	tempFile, err := ioutil.TempFile("", "orchestrator-remote-test-")
	if err != nil {
		return err
	}
	defer os.Remove(tempFile.Name())

	randomToken := process.NewToken()

	command := config.Config.RemoteSSHCommand
	command = strings.Replace(command, "{hostname}", instanceKey.Hostname, -1)
	command = fmt.Sprintf("%s '%s echo %s' > %s", command, sudoCommand, randomToken.Hash, tempFile.Name())
	if err := orcos.CommandRun(command, orcos.EmptyEnv); err != nil {
		return err
	}
	bytes, err := ioutil.ReadFile(tempFile.Name())
	if err != nil {
		return err
	}
	if content := strings.TrimSpace(string(bytes)); content != randomToken.Hash {
		return fmt.Errorf("TestRemoteCommandOnInstance: expected %s, got %s", randomToken.Hash, content)
	}
	return nil
}

// AlignViaRelaylogCorrelation will align siblings by applying relaylogs from one to the other, via remote SSH
func AlignViaRelaylogCorrelation(instance, fromInstance *inst.Instance) (*inst.Instance, error) {
	if config.Config.RemoteSSHCommand == "" {
		return instance, fmt.Errorf("RemoteSSHCommand not configured")
	}
	log.Debugf("Testing SSH on %+v", instance.Key)
	if err := TestRemoteCommandOnInstance(&instance.Key); err != nil {
		return instance, err
	}

	if instance.ReplicaRunning() {
		return instance, log.Errorf("AlignViaRelaylogCorrelation: replication on %+v must not run", instance.Key)
	}
	if fromInstance.ReplicaRunning() {
		return instance, log.Errorf("AlignViaRelaylogCorrelation: replication on %+v must not run", fromInstance.Key)
	}

	log.Debugf("AlignViaRelaylogCorrelation: correlating coordinates of %+v on %+v", instance.Key, fromInstance.Key)
	_, _, nextCoordinates, found, err := inst.CorrelateRelaylogCoordinates(instance, nil, fromInstance)
	if err != nil {
		return instance, err
	}
	if !found {
		return instance, err
	}
	log.Debugf("AlignViaRelaylogCorrelation: correlated next-coordinates are %+v", *nextCoordinates)

	// We now have the correlation info needed to proceed with remote calls
	sudoCommand := ""
	if config.Config.RemoteSSHCommandUseSudo {
		sudoCommand = "sudo -i"
	}

	// Write get-relaylogs script locally
	getRelayLogContentsScriptFile, err := ioutil.TempFile("", "orchestrator-remote-get-relaylogs-content-")
	if err != nil {
		return instance, err
	}
	{
		defer os.Remove(getRelayLogContentsScriptFile.Name())
		script := GetRelayLogContentsScript
		script = strings.Replace(script, "$MAGIC_FIRST_RELAYLOG_FILE", nextCoordinates.LogFile, -1)
		script = strings.Replace(script, "$MAGIC_START_POSITION", fmt.Sprintf("%d", nextCoordinates.LogPos), -1)
		script = strings.Replace(script, "$MAGIC_STOP_POSITION", fmt.Sprintf("%d", fromInstance.ReadBinlogCoordinates.LogPos), -1)
		if err := ioutil.WriteFile(getRelayLogContentsScriptFile.Name(), []byte(script), 0640); err != nil {
			return instance, err
		}
	}
	log.Debugf("getRelayLogContentsScriptFile: %+v", getRelayLogContentsScriptFile.Name())

	// Get relay log contents, save locally
	localRelayLogContentsFile, err := ioutil.TempFile("", "orchestrator-remote-relaylogs-content-")
	if err != nil {
		return instance, err
	}
	defer os.Remove(localRelayLogContentsFile.Name())
	localRelayLogContentsCopyFileName := fmt.Sprintf("%s.copy", localRelayLogContentsFile.Name())
	{
		command := config.Config.RemoteSSHCommand
		command = strings.Replace(command, "{hostname}", fromInstance.Key.Hostname, -1)
		command = fmt.Sprintf("cat %s | %s '%s' > %s", getRelayLogContentsScriptFile.Name(), command, sudoCommand, localRelayLogContentsFile.Name())
		if err := orcos.CommandRun(command, orcos.EmptyEnv); err != nil {
			return instance, err
		}
	}
	log.Debugf("Have fetched relay logs from %s, output file is %s", fromInstance.Key.Hostname, localRelayLogContentsFile.Name())
	// Copy local relay log contents to target host:
	{
		command := config.Config.RemoteSSHCommand
		command = strings.Replace(command, "{hostname}", instance.Key.Hostname, -1)
		command = fmt.Sprintf("cat %s | %s '%s cat - > %s'", localRelayLogContentsFile.Name(), command, sudoCommand, localRelayLogContentsCopyFileName)
		if err := orcos.CommandRun(command, orcos.EmptyEnv); err != nil {
			return instance, err
		}
	}
	log.Debugf("Have copied contents file to %s, output file is %s", instance.Key.Hostname, localRelayLogContentsFile.Name())

	// Generate the apply-relaylogs script, locally
	applyRelayLogContentsScriptFile, err := ioutil.TempFile("", "orchestrator-remote-apply-relaylogs-content-")
	if err != nil {
		return instance, err
	}
	{
		defer os.Remove(applyRelayLogContentsScriptFile.Name())
		script := ApplyRelayLogContentsScript
		script = strings.Replace(script, "$MAGIC_MYSQL_COMMAND", "", -1)
		script = strings.Replace(script, "$MAGIC_CONTENTS_FILE", localRelayLogContentsCopyFileName, -1)

		if err := ioutil.WriteFile(applyRelayLogContentsScriptFile.Name(), []byte(script), 0640); err != nil {
			return instance, err
		}
	}
	log.Debugf("applyRelayLogContentsScriptFile: %+v", applyRelayLogContentsScriptFile.Name())

	if *config.RuntimeCLIFlags.Noop {
		return instance, fmt.Errorf("noop: Not really applying scripts onto %+v; signalling error but nothing went wrong", instance.Key)
	}

	// apply relaylog contents on target host:
	{
		command := config.Config.RemoteSSHCommand
		command = strings.Replace(command, "{hostname}", instance.Key.Hostname, -1)
		command = fmt.Sprintf("cat %s | %s '%s'", applyRelayLogContentsScriptFile.Name(), command, sudoCommand)
		if err := orcos.CommandRun(command, orcos.EmptyEnv); err != nil {
			return instance, err
		}
	}
	log.Debugf("Have successfully applied relay logs on %s", instance.Key.Hostname)

	instance, err = inst.ChangeMasterTo(&instance.Key, &fromInstance.MasterKey, &fromInstance.ExecBinlogCoordinates, false, inst.GTIDHintNeutral)
	if err != nil {
		return instance, err
	}
	inst.AuditOperation("align-via-relaylogs-remote", &instance.Key, fmt.Sprintf("aligned %+v by relaylogs from %+v", instance.Key, fromInstance.Key))
	return instance, err
}

func SyncReplicasRelayLogs(masterKey *inst.InstanceKey, postponedFunctionsContainer *inst.PostponedFunctionsContainer) (
	syncedReplicas, failedReplicas, postponedReplicas [](*inst.Instance), err error,
) {
	var replicas [](*inst.Instance)
	if replicas, err = inst.GetSortedReplicas(masterKey, true); err != nil {
		return syncedReplicas, replicas, postponedReplicas, err
	}
	if len(replicas) <= 1 {
		// Nothing to be done
		return syncedReplicas, replicas, postponedReplicas, err
	}
	applyFromReplica := replicas[0]
	applyToReplicas := replicas[1:]

	log.Debugf("Testing SSH on %+v", applyFromReplica.Key)
	if err := TestRemoteCommandOnInstance(&applyFromReplica.Key); err != nil {
		return syncedReplicas, replicas, postponedReplicas, err
	}

	barrier := make(chan *inst.InstanceKey, len(applyToReplicas))
	allErrors := make(chan error, len(applyToReplicas))
	synchedReplicasChan := make(chan *inst.Instance, len(applyToReplicas))
	failedReplicasChan := make(chan *inst.Instance, len(applyToReplicas))

	applyToReplicaFunc := func(applyToReplica *inst.Instance) error {
		defer func() { barrier <- &applyToReplica.Key }()

		if _, err := AlignViaRelaylogCorrelation(applyToReplica, applyFromReplica); err == nil {
			synchedReplicasChan <- applyToReplica
		} else {
			failedReplicasChan <- applyToReplica
			allErrors <- err
		}
		return err
	}

	log.Debugf("Applying relay logs on %+v replicas", len(applyToReplicas))
	countImmediateApply := 0
	for _, applyToReplica := range applyToReplicas {
		applyToReplica := applyToReplica

		if postponedFunctionsContainer != nil &&
			config.Config.PostponeReplicaRecoveryOnLagMinutes > 0 &&
			applyToReplica.SQLDelay > config.Config.PostponeReplicaRecoveryOnLagMinutes*60 {
			postponedReplicas = append(postponedReplicas, applyToReplica)
			(*postponedFunctionsContainer).AddPostponedFunction(func() error { return applyToReplicaFunc(applyToReplica) })
		} else {
			countImmediateApply++
			go applyToReplicaFunc(applyToReplica)
		}
	}
	for i := 0; i < countImmediateApply; i++ {
		<-barrier
	}
	syncedReplicas = append(syncedReplicas, applyFromReplica)
	for len(synchedReplicasChan) > 0 {
		syncedReplicas = append(syncedReplicas, <-synchedReplicasChan)
	}
	for len(failedReplicasChan) > 0 {
		failedReplicas = append(failedReplicas, <-failedReplicasChan)
	}
	countErrors := len(allErrors)
	for len(allErrors) > 0 {
		log.Errore(<-allErrors)
	}
	inst.AuditOperation("sync-replicas-relaylogs", masterKey, fmt.Sprintf("aligned %+v replicas by relaylogs from %+v, got %+v errors", len(applyToReplicas), applyFromReplica.Key, countErrors))
	return syncedReplicas, failedReplicas, postponedReplicas, err
}
<|endoftext|>


<commit_before>package main

import (
  "fmt"
  "io/ioutil"
  "strings"
  "strconv"
)

type Operation struct {
  Name string
  Cells [4] int
}

func checkError(e error) {
  if e != nil {
    panic(e)
  }
}

func paintRow(matrix *[][] int, operations *[]Operation, spr int, spc int, ROWS int, COLS int) int {
  var op Operation
  rowLength := 0
  for i:=0; ((spc + i) < COLS) && ((*matrix)[spr][spc + i] == 1); i++ {
    rowLength++
  }

  if rowLength == 0 {
    op = Operation {
      Name: "PAINT_SQUARE",
      Cells: [4] int {spr, spc, 0, 0},
    }
  } else {
    op = Operation {
      Name: "PAINT_LINE",
      Cells: [4] int {spr, spc, spr, spc + rowLength},
    }
  }
  (*operations) = append(*operations, op)
  for i:=spc; i <= (spc + rowLength); i++ {
    (*matrix)[spr][spc] = 0
  }
  return rowLength
}

func paintByLines(matrix *[][]int, operations *[]Operation, ROWS int, COLS int) {
  for row,_ := range (*matrix) {
    for col,_ := range (*matrix)[row] {
      if (*matrix)[row][col] == 1 {
        paintRow(matrix, operations, row, col, ROWS, COLS)
      }
    }
  }
}

func main() {
  operations := [] Operation {}
  inputFile := "inputs/logo.in"
  // Read the file and check for errors
  dat, err := ioutil.ReadFile(inputFile)
  checkError(err)
  fileString := string(dat)
  // Lines array
  lines := strings.Split(fileString, "\n")
  specs := lines[0]
  rows_cols := strings.Split(specs, " ")
  ROWS, err := strconv.Atoi(rows_cols[0])
  checkError(err)
  COLS, err := strconv.Atoi(rows_cols[1])
  checkError(err)
  lines = lines[1:]
  matrix := [][] int {}
  for _,line := range lines {
    lineToAppend := [] int {}
    for _, el := range line {
      var a int = 0
      if strings.Compare(string(el), ".") == 0 {
        a = 0
      } else if strings.Compare(string(el), "#") == 0 {
        a = 1
      } else {
        panic("unexpected char")
      }
      lineToAppend = append(lineToAppend, a)
    }
    matrix = append(matrix, lineToAppend)
  }
  paintByLines(&matrix, &operations, ROWS, COLS)
  fmt.Println(len(operations))
  i := 0
  for _,value := range operations {
    fmt.Println(value)
    i++
  }
  fmt.Println(i)
  // for _,line := range matrix {
  //   fmt.Println(line)
  // }
}<commit_msg>working print by rows<commit_after>package main

import (
  "fmt"
  "io/ioutil"
  "strings"
  "strconv"
)

type Operation struct {
  Name string
  Cells [4] int
}

func checkError(e error) {
  if e != nil {
    panic(e)
  }
}

func paintRow(matrix [][] int, operations []Operation, spr int, spc int, ROWS int, COLS int) ([][]int, []Operation) {
  var op Operation
  rowLength := 0
  for i:=0; ((spc + i) < COLS) && (matrix[spr][spc + i] == 1); i++ {
    rowLength++
  }

  if rowLength == 1 {
    op = Operation {
      Name: "PAINT_SQUARE",
      Cells: [4] int {spr, spc, 0, 0},
    }
  } else {
    op = Operation {
      Name: "PAINT_LINE",
      Cells: [4] int {spr, spc, spr, spc + rowLength},
    }
  }
  operations = append(operations, op)
  for i := spc; i < (spc + rowLength); i++ {
    matrix[spr][i] = 0
  }
  return matrix, operations
}

func paintByLines(matrix [][]int, operations []Operation, ROWS int, COLS int) ([][]int, []Operation){
  for row,_ := range matrix {
    for col,_ := range matrix[row] {
      if matrix[row][col] == 1 {
        matrix, operations = paintRow(matrix, operations, row, col, ROWS, COLS)
      }
    }
  }
  return matrix, operations
}

func main() {
  operations := [] Operation {}
  inputFile := "inputs/logo.in"
  // Read the file and check for errors
  dat, err := ioutil.ReadFile(inputFile)
  checkError(err)
  fileString := string(dat)
  // Lines array
  lines := strings.Split(fileString, "\n")
  specs := lines[0]
  rows_cols := strings.Split(specs, " ")
  ROWS, err := strconv.Atoi(rows_cols[0])
  checkError(err)
  COLS, err := strconv.Atoi(rows_cols[1])
  checkError(err)
  lines = lines[1:]
  matrix := [][] int {}
  for _,line := range lines {
    lineToAppend := [] int {}
    for _, el := range line {
      var a int = 0
      if strings.Compare(string(el), ".") == 0 {
        a = 0
      } else if strings.Compare(string(el), "#") == 0 {
        a = 1
      } else {
        panic("unexpected char")
      }
      lineToAppend = append(lineToAppend, a)
    }
    matrix = append(matrix, lineToAppend)
  }
  matrix, operations = paintByLines(matrix, operations, ROWS, COLS)
  fmt.Println(len(operations))
  i := 0
  for _,value := range operations {
    fmt.Println(value)
    i++
  }
  fmt.Println(i)
  // for _,line := range matrix {
  //   fmt.Println(line)
  // }
}<|endoftext|>


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

package backups

import (
	"compress/gzip"
	"crypto/sha1"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/juju/errors"
	"github.com/juju/utils/hash"
	"github.com/juju/utils/tar"

	"github.com/juju/juju/state/backups/archive"
)

// TODO(ericsnow) One concern is files that get out of date by the time
// backup finishes running.  This is particularly a problem with log
// files.

const (
	tempPrefix   = "jujuBackup-"
	tempFilename = "juju-backup.tar.gz"
)

type dumper interface {
	Dump(dumpDir string) error
}

type createArgs struct {
	filesToBackUp []string
	db            dumper
}

type createResult struct {
	archiveFile io.ReadCloser
	size        int64
	checksum    string
}

// create builds a new backup archive file and returns it.  It also
// updates the metadata with the file info.
func create(args *createArgs) (*createResult, error) {
	// Prepare the backup builder.
	builder, err := newBuilder(args.filesToBackUp, args.db)
	if err != nil {
		return nil, errors.Trace(err)
	}
	defer builder.cleanUp()

	// Build the backup.
	if err := builder.buildAll(); err != nil {
		return nil, errors.Trace(err)
	}

	// Get the result.
	result, err := builder.result()
	if err != nil {
		return nil, errors.Trace(err)
	}

	// Return the result.  Note that the entire build workspace will be
	// deleted at the end of this function.  This includes the backup
	// archive file we built.  However, the handle to that file in the
	// result will still be open and readable.
	return result, nil
}

// builder exposes the machinery for creating a backup of juju's state.
type builder struct {
	// archive is the backups archive summary.
	archive *archive.Archive
	// checksum is the checksum of the archive file.
	checksum string
	// filesToBackUp is the paths to every file to include in the archive.
	filesToBackUp []string
	// db is the wrapper around the DB dump command and args.
	db dumper
	// archiveFile is the backup archive file.
	archiveFile *os.File
	// bundleFile is the inner archive file containing all the juju
	// state-related files gathered during backup.
	bundleFile *os.File
}

// newBuilder returns a new backup archive builder.  It creates the temp
// directories which backup uses as its staging area while building the
// archive.  It also creates the archive
// (temp root, tarball root, DB dumpdir), along with any error.
func newBuilder(filesToBackUp []string, db dumper) (*builder, error) {
	b := builder{
		filesToBackUp: filesToBackUp,
		db:            db,
	}

	// Create the backups workspace root directory.
	rootDir, err := ioutil.TempDir("", tempPrefix)
	if err != nil {
		return nil, errors.Annotate(err, "error making backups workspace")
	}
	filename := filepath.Join(rootDir, tempFilename)
	b.archive = &archive.Archive{filename, rootDir}

	// Create all the direcories we need.  We go with user-only
	// permissions on principle; the directories are short-lived so in
	// practice it shouldn't matter much.
	err = os.MkdirAll(b.archive.DBDumpDir(), 0700)
	if err != nil {
		b.cleanUp()
		return nil, errors.Annotate(err, "error creating temp directories")
	}

	// Create the archive files.  We do so here to fail as early as
	// possible.
	b.archiveFile, err = os.Create(filename)
	if err != nil {
		b.cleanUp()
		return nil, errors.Annotate(err, "error creating archive file")
	}

	b.bundleFile, err = os.Create(b.archive.FilesBundle())
	if err != nil {
		b.cleanUp()
		return nil, errors.Annotate(err, `error creating bundle file`)
	}

	return &b, nil
}

func (b *builder) closeArchiveFile() error {
	if b.archiveFile == nil {
		return nil
	}

	if err := b.archiveFile.Close(); err != nil {
		return errors.Annotate(err, "error closing archive file")
	}

	b.archiveFile = nil
	return nil
}

func (b *builder) closeBundleFile() error {
	if b.bundleFile == nil {
		return nil
	}

	if err := b.bundleFile.Close(); err != nil {
		return errors.Annotate(err, `error closing "bundle" file`)
	}

	b.bundleFile = nil
	return nil
}

func (b *builder) removeRootDir() error {
	if b.archive == nil || b.archive.UnpackedRootDir == "" {
		return nil
	}

	if err := os.RemoveAll(b.archive.UnpackedRootDir); err != nil {
		return errors.Annotate(err, "error removing backups temp dir")
	}

	return nil
}

func (b *builder) cleanUp() error {
	var failed int

	funcs := [](func() error){
		b.closeBundleFile,
		b.closeArchiveFile,
		b.removeRootDir,
	}
	for _, cleanupFunc := range funcs {
		if err := cleanupFunc(); err != nil {
			logger.Errorf(err.Error())
			failed++
		}
	}

	if failed > 0 {
		return errors.Errorf("%d errors during cleanup (see logs)", failed)
	}
	return nil
}

func (b *builder) buildFilesBundle() error {
	logger.Infof("dumping juju state-related files")
	if b.filesToBackUp == nil {
		logger.Infof("nothing to do")
		return nil
	}
	if b.bundleFile == nil {
		return errors.New("missing bundleFile")
	}

	stripPrefix := string(os.PathSeparator)
	_, err := tar.TarFiles(b.filesToBackUp, b.bundleFile, stripPrefix)
	if err != nil {
		return errors.Annotate(err, "cannot backup configuration files")
	}

	return nil
}

func (b *builder) buildDBDump() error {
	logger.Infof("dumping database")
	if b.db == nil {
		logger.Infof("nothing to do")
		return nil
	}

	dumpDir := b.archive.DBDumpDir()
	if err := b.db.Dump(dumpDir); err != nil {
		return errors.Annotate(err, "error dumping juju state database")
	}

	return nil
}

func (b *builder) buildArchive(outFile io.Writer) error {
	tarball := gzip.NewWriter(outFile)
	defer tarball.Close()

	// We add a trailing slash (or whatever) to root so that everything
	// in the path up to and including that slash is stripped off when
	// each file is added to the tar file.
	stripPrefix := b.archive.UnpackedRootDir + string(os.PathSeparator)
	filenames := []string{b.archive.ContentDir()}
	if _, err := tar.TarFiles(filenames, tarball, stripPrefix); err != nil {
		return errors.Annotate(err, "error bundling final archive")
	}

	return nil
}

func (b *builder) buildArchiveAndChecksum() error {
	logger.Infof("building archive file (%s)", b.archive.Filename)
	if b.archiveFile == nil {
		return errors.New("missing archiveFile")
	}

	// Build the tarball, writing out to both the archive file and a
	// SHA1 hash.  The hash will correspond to the gzipped file rather
	// than to the uncompressed contents of the tarball.  This is so
	// that users can compare the published checksum against the
	// checksum of the file without having to decompress it first.
	hasher := hash.NewHashingWriter(b.archiveFile, sha1.New())
	if err := b.buildArchive(hasher); err != nil {
		return errors.Trace(err)
	}

	// Save the SHA1 checksum.
	// Gzip writers may buffer what they're writing so we must call
	// Close() on the writer *before* getting the checksum from the
	// hasher.
	b.checksum = hasher.Base64Sum()

	return nil
}

func (b *builder) buildAll() error {
	// Dump the files.
	if err := b.buildFilesBundle(); err != nil {
		return errors.Trace(err)
	}

	// Dump the database.
	if err := b.buildDBDump(); err != nil {
		return errors.Trace(err)
	}

	// Bundle it all into a tarball.
	if err := b.buildArchiveAndChecksum(); err != nil {
		return errors.Trace(err)
	}

	return nil
}

func (b *builder) result() (*createResult, error) {
	// Open the file in read-only mode.
	file, err := os.Open(b.archive.Filename)
	if err != nil {
		return nil, errors.Annotate(err, "error opening archive file")
	}

	// Get the size.
	stat, err := file.Stat()
	if err != nil {
		return nil, errors.Annotate(err, "error reading archive file info")
	}
	size := stat.Size()

	// Get the checksum.
	checksum := b.checksum

	// Return the result.
	result := createResult{
		archiveFile: file,
		size:        size,
		checksum:    checksum,
	}
	return &result, nil
}
<commit_msg>Make a note about deleting open files on Windows.<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package backups

import (
	"compress/gzip"
	"crypto/sha1"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/juju/errors"
	"github.com/juju/utils/hash"
	"github.com/juju/utils/tar"

	"github.com/juju/juju/state/backups/archive"
)

// TODO(ericsnow) One concern is files that get out of date by the time
// backup finishes running.  This is particularly a problem with log
// files.

const (
	tempPrefix   = "jujuBackup-"
	tempFilename = "juju-backup.tar.gz"
)

type dumper interface {
	Dump(dumpDir string) error
}

type createArgs struct {
	filesToBackUp []string
	db            dumper
}

type createResult struct {
	archiveFile io.ReadCloser
	size        int64
	checksum    string
}

// create builds a new backup archive file and returns it.  It also
// updates the metadata with the file info.
func create(args *createArgs) (*createResult, error) {
	// Prepare the backup builder.
	builder, err := newBuilder(args.filesToBackUp, args.db)
	if err != nil {
		return nil, errors.Trace(err)
	}
	defer builder.cleanUp()

	// Build the backup.
	if err := builder.buildAll(); err != nil {
		return nil, errors.Trace(err)
	}

	// Get the result.
	result, err := builder.result()
	if err != nil {
		return nil, errors.Trace(err)
	}

	// Return the result.  Note that the entire build workspace will be
	// deleted at the end of this function.  This includes the backup
	// archive file we built.  However, the handle to that file in the
	// result will still be open and readable.
	// If we ever support state machines on Windows, this will need to
	// change (you can't delete open files on Windows).
	return result, nil
}

// builder exposes the machinery for creating a backup of juju's state.
type builder struct {
	// archive is the backups archive summary.
	archive *archive.Archive
	// checksum is the checksum of the archive file.
	checksum string
	// filesToBackUp is the paths to every file to include in the archive.
	filesToBackUp []string
	// db is the wrapper around the DB dump command and args.
	db dumper
	// archiveFile is the backup archive file.
	archiveFile *os.File
	// bundleFile is the inner archive file containing all the juju
	// state-related files gathered during backup.
	bundleFile *os.File
}

// newBuilder returns a new backup archive builder.  It creates the temp
// directories which backup uses as its staging area while building the
// archive.  It also creates the archive
// (temp root, tarball root, DB dumpdir), along with any error.
func newBuilder(filesToBackUp []string, db dumper) (*builder, error) {
	b := builder{
		filesToBackUp: filesToBackUp,
		db:            db,
	}

	// Create the backups workspace root directory.
	rootDir, err := ioutil.TempDir("", tempPrefix)
	if err != nil {
		return nil, errors.Annotate(err, "error making backups workspace")
	}
	filename := filepath.Join(rootDir, tempFilename)
	b.archive = &archive.Archive{filename, rootDir}

	// Create all the direcories we need.  We go with user-only
	// permissions on principle; the directories are short-lived so in
	// practice it shouldn't matter much.
	err = os.MkdirAll(b.archive.DBDumpDir(), 0700)
	if err != nil {
		b.cleanUp()
		return nil, errors.Annotate(err, "error creating temp directories")
	}

	// Create the archive files.  We do so here to fail as early as
	// possible.
	b.archiveFile, err = os.Create(filename)
	if err != nil {
		b.cleanUp()
		return nil, errors.Annotate(err, "error creating archive file")
	}

	b.bundleFile, err = os.Create(b.archive.FilesBundle())
	if err != nil {
		b.cleanUp()
		return nil, errors.Annotate(err, `error creating bundle file`)
	}

	return &b, nil
}

func (b *builder) closeArchiveFile() error {
	if b.archiveFile == nil {
		return nil
	}

	if err := b.archiveFile.Close(); err != nil {
		return errors.Annotate(err, "error closing archive file")
	}

	b.archiveFile = nil
	return nil
}

func (b *builder) closeBundleFile() error {
	if b.bundleFile == nil {
		return nil
	}

	if err := b.bundleFile.Close(); err != nil {
		return errors.Annotate(err, `error closing "bundle" file`)
	}

	b.bundleFile = nil
	return nil
}

func (b *builder) removeRootDir() error {
	if b.archive == nil || b.archive.UnpackedRootDir == "" {
		return nil
	}

	if err := os.RemoveAll(b.archive.UnpackedRootDir); err != nil {
		return errors.Annotate(err, "error removing backups temp dir")
	}

	return nil
}

func (b *builder) cleanUp() error {
	var failed int

	funcs := [](func() error){
		b.closeBundleFile,
		b.closeArchiveFile,
		b.removeRootDir,
	}
	for _, cleanupFunc := range funcs {
		if err := cleanupFunc(); err != nil {
			logger.Errorf(err.Error())
			failed++
		}
	}

	if failed > 0 {
		return errors.Errorf("%d errors during cleanup (see logs)", failed)
	}
	return nil
}

func (b *builder) buildFilesBundle() error {
	logger.Infof("dumping juju state-related files")
	if b.filesToBackUp == nil {
		logger.Infof("nothing to do")
		return nil
	}
	if b.bundleFile == nil {
		return errors.New("missing bundleFile")
	}

	stripPrefix := string(os.PathSeparator)
	_, err := tar.TarFiles(b.filesToBackUp, b.bundleFile, stripPrefix)
	if err != nil {
		return errors.Annotate(err, "cannot backup configuration files")
	}

	return nil
}

func (b *builder) buildDBDump() error {
	logger.Infof("dumping database")
	if b.db == nil {
		logger.Infof("nothing to do")
		return nil
	}

	dumpDir := b.archive.DBDumpDir()
	if err := b.db.Dump(dumpDir); err != nil {
		return errors.Annotate(err, "error dumping juju state database")
	}

	return nil
}

func (b *builder) buildArchive(outFile io.Writer) error {
	tarball := gzip.NewWriter(outFile)
	defer tarball.Close()

	// We add a trailing slash (or whatever) to root so that everything
	// in the path up to and including that slash is stripped off when
	// each file is added to the tar file.
	stripPrefix := b.archive.UnpackedRootDir + string(os.PathSeparator)
	filenames := []string{b.archive.ContentDir()}
	if _, err := tar.TarFiles(filenames, tarball, stripPrefix); err != nil {
		return errors.Annotate(err, "error bundling final archive")
	}

	return nil
}

func (b *builder) buildArchiveAndChecksum() error {
	logger.Infof("building archive file (%s)", b.archive.Filename)
	if b.archiveFile == nil {
		return errors.New("missing archiveFile")
	}

	// Build the tarball, writing out to both the archive file and a
	// SHA1 hash.  The hash will correspond to the gzipped file rather
	// than to the uncompressed contents of the tarball.  This is so
	// that users can compare the published checksum against the
	// checksum of the file without having to decompress it first.
	hasher := hash.NewHashingWriter(b.archiveFile, sha1.New())
	if err := b.buildArchive(hasher); err != nil {
		return errors.Trace(err)
	}

	// Save the SHA1 checksum.
	// Gzip writers may buffer what they're writing so we must call
	// Close() on the writer *before* getting the checksum from the
	// hasher.
	b.checksum = hasher.Base64Sum()

	return nil
}

func (b *builder) buildAll() error {
	// Dump the files.
	if err := b.buildFilesBundle(); err != nil {
		return errors.Trace(err)
	}

	// Dump the database.
	if err := b.buildDBDump(); err != nil {
		return errors.Trace(err)
	}

	// Bundle it all into a tarball.
	if err := b.buildArchiveAndChecksum(); err != nil {
		return errors.Trace(err)
	}

	return nil
}

func (b *builder) result() (*createResult, error) {
	// Open the file in read-only mode.
	file, err := os.Open(b.archive.Filename)
	if err != nil {
		return nil, errors.Annotate(err, "error opening archive file")
	}

	// Get the size.
	stat, err := file.Stat()
	if err != nil {
		return nil, errors.Annotate(err, "error reading archive file info")
	}
	size := stat.Size()

	// Get the checksum.
	checksum := b.checksum

	// Return the result.
	result := createResult{
		archiveFile: file,
		size:        size,
		checksum:    checksum,
	}
	return &result, nil
}
<|endoftext|>


<commit_before>package metrics

import (
	"context"

	"go.opencensus.io/stats"
	"go.opencensus.io/stats/view"
)

// Recorder is our backend-independent metrics recorder.
// This should be created with NewRecorder().
type Recorder struct {
	startPomCount   *stats.Int64Measure
	runningPomCount *stats.Int64Measure
	serverCount     *stats.Int64Measure
}

// NewRecorder creates a Recorder with its metrics initialized.
func NewRecorder() (*Recorder, error) {
	recorder := &Recorder{
		startPomCount:   stats.Int64("pomodoros_started", "Count of Pomodoros started", stats.UnitDimensionless),
		runningPomCount: stats.Int64("pomodoros_running", "Current number of Pomodoros running", stats.UnitDimensionless),
		serverCount:     stats.Int64("connected_servers", "Current number of connected servers", stats.UnitDimensionless),
	}

	startView := &view.View{
		Name:        "pomodoros_started_count",
		Measure:     recorder.startPomCount,
		Description: "The number of Pomodoros started",
		Aggregation: view.Count(),
	}

	runningView := &view.View{
		Name:        "pomodoros_running_value",
		Measure:     recorder.runningPomCount,
		Description: "The number of Pomodoros running",
		Aggregation: view.LastValue(),
	}

	serverView := &view.View{
		Name:        "connected_servers_value",
		Measure:     recorder.serverCount,
		Description: "The number of connected servers",
		Aggregation: view.LastValue(),
	}

	return recorder, view.Register(startView, runningView, serverView)
}

// RecordStartPom records the start of a pomodoro.
func (r *Recorder) RecordStartPom() {
	stats.Record(context.Background(), r.startPomCount.M(1))
}

// RecordRunningPoms records the number of currently running pomodoros.
func (r *Recorder) RecordRunningPoms(count int64) {
	stats.Record(context.Background(), r.runningPomCount.M(count))
}

// RecordConnectedServers records the number of currently connected servers (guilds).
func (r *Recorder) RecordConnectedServers(count int64) {
	stats.Record(context.Background(), r.serverCount.M(count))
}
<commit_msg>Added package comments for metrics<commit_after>// Package metrics handles the aggregated stats that can be reported to a metrics exporter for
// bot monitoring. This only contains functionality for initializing and managing the stats
// themselves - the user is expected to set up an OpenCensus exporter.
package metrics

import (
	"context"

	"go.opencensus.io/stats"
	"go.opencensus.io/stats/view"
)

// Recorder is our backend-independent metrics recorder.
// This should be created with NewRecorder().
type Recorder struct {
	startPomCount   *stats.Int64Measure
	runningPomCount *stats.Int64Measure
	serverCount     *stats.Int64Measure
}

// NewRecorder creates a Recorder with its metrics initialized.
func NewRecorder() (*Recorder, error) {
	recorder := &Recorder{
		startPomCount:   stats.Int64("pomodoros_started", "Count of Pomodoros started", stats.UnitDimensionless),
		runningPomCount: stats.Int64("pomodoros_running", "Current number of Pomodoros running", stats.UnitDimensionless),
		serverCount:     stats.Int64("connected_servers", "Current number of connected servers", stats.UnitDimensionless),
	}

	startView := &view.View{
		Name:        "pomodoros_started_count",
		Measure:     recorder.startPomCount,
		Description: "The number of Pomodoros started",
		Aggregation: view.Count(),
	}

	runningView := &view.View{
		Name:        "pomodoros_running_value",
		Measure:     recorder.runningPomCount,
		Description: "The number of Pomodoros running",
		Aggregation: view.LastValue(),
	}

	serverView := &view.View{
		Name:        "connected_servers_value",
		Measure:     recorder.serverCount,
		Description: "The number of connected servers",
		Aggregation: view.LastValue(),
	}

	return recorder, view.Register(startView, runningView, serverView)
}

// RecordStartPom records the start of a pomodoro.
func (r *Recorder) RecordStartPom() {
	stats.Record(context.Background(), r.startPomCount.M(1))
}

// RecordRunningPoms records the number of currently running pomodoros.
func (r *Recorder) RecordRunningPoms(count int64) {
	stats.Record(context.Background(), r.runningPomCount.M(count))
}

// RecordConnectedServers records the number of currently connected servers (guilds).
func (r *Recorder) RecordConnectedServers(count int64) {
	stats.Record(context.Background(), r.serverCount.M(count))
}
<|endoftext|>


<commit_before>package stream

import (
	"encoding/xml"
)

type ElementHandlerAction func(ElementHandler)

type ElementHandler interface {
	HandleElement(*Wrapper)
}

type InnerXMLHandler interface {
	HandleInnerXML(*Wrapper) []ElementHandler
}

type InnerXML struct {
	InnerXML    []byte `xml:",innerxml"`
	Registrator ElementHandlerRegistrator
}

func (self *InnerXML) HandleInnerXML(sw *Wrapper) []ElementHandler {
	sw.InnerDecoder.PutXML(self.InnerXML)
	handlers := make([]ElementHandler, 0)

	processStreamElements(sw.InnerDecoder.Decoder, self.Registrator, func(handler ElementHandler) {
		handlers = append(handlers, handler)
	})

	return handlers
}

func processStreamElements(decoder *xml.Decoder, registry ElementHandlerRegistrator, elementAction ElementHandlerAction) {
	for token, terr := decoder.Token(); terr == nil; token, terr = decoder.Token() {
		switch element := token.(type) {
		case *xml.StartElement:
			var handler ElementHandler
			var err error
			if handler, err = registry.GetHandler(element.Name.Space + " " + element.Name.Local); err != nil {
				// TODO: added logging here
				continue
			}

			if err = decoder.DecodeElement(handler, element); err != nil {
				// TODO: added logging here
				continue
			}

			elementAction(handler)
		}
	}
}

func (self *InnerXML) HandleElement(sw *Wrapper) {
	for _, element := range self.HandleInnerXML(sw) {
		element.HandleElement(sw)
	}
}
<commit_msg>Fixed type switch<commit_after>package stream

import (
	"encoding/xml"
)

type ElementHandlerAction func(ElementHandler)

type ElementHandler interface {
	HandleElement(*Wrapper)
}

type InnerXMLHandler interface {
	HandleInnerXML(*Wrapper) []ElementHandler
}

type InnerXML struct {
	InnerXML    []byte `xml:",innerxml"`
	Registrator ElementHandlerRegistrator
}

func (self *InnerXML) HandleInnerXML(sw *Wrapper) []ElementHandler {
	sw.InnerDecoder.PutXML(self.InnerXML)
	handlers := make([]ElementHandler, 0)

	processStreamElements(sw.InnerDecoder.Decoder, self.Registrator, func(handler ElementHandler) {
		handlers = append(handlers, handler)
	})

	return handlers
}

func processStreamElements(decoder *xml.Decoder, registry ElementHandlerRegistrator, elementAction ElementHandlerAction) {
	for token, terr := decoder.Token(); terr == nil; token, terr = decoder.Token() {
		switch element := token.(type) {
		case xml.StartElement:
			var handler ElementHandler
			var err error
			if handler, err = registry.GetHandler(element.Name.Space + " " + element.Name.Local); err != nil {
				// TODO: added logging here
				continue
			}

			if err = decoder.DecodeElement(handler, &element); err != nil {
				// TODO: added logging here
				continue
			}

			elementAction(handler)
		}
	}
}

func (self *InnerXML) HandleElement(sw *Wrapper) {
	for _, element := range self.HandleInnerXML(sw) {
		element.HandleElement(sw)
	}
}
<|endoftext|>


<commit_before>package models

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/ninjasphere/go-ninja/config"
	"github.com/ninjasphere/go-ninja/model"
	"github.com/ninjasphere/redigo/redis"
)

type SiteModel struct {
	baseModel
}

func NewSiteModel() *SiteModel {
	return &SiteModel{
		baseModel: newBaseModel("site", model.Site{}),
	}
}

func (m *SiteModel) Fetch(id string, conn redis.Conn) (*model.Site, error) {
	m.syncing.Wait()

	if id == "here" {
		id = config.MustString("siteId")
	}

	site := &model.Site{}

	if err := m.fetch(id, site, false, conn); err != nil {
		return nil, err
	}

	return site, nil
}

func (m *SiteModel) FetchAll(conn redis.Conn) (*[]*model.Site, error) {
	m.syncing.Wait()

	ids, err := m.fetchIds(conn)

	if err != nil {
		return nil, err
	}

	sites := make([]*model.Site, len(ids))

	for i, id := range ids {
		sites[i], err = m.Fetch(id, conn)
		if err != nil {
			return nil, err
		}
	}

	return &sites, nil
}

func (m *SiteModel) Create(site *model.Site, conn redis.Conn) error {
	m.syncing.Wait()
	//defer m.sync()

	if site.ID == "here" {
		site.ID = config.MustString("siteId")
	}

	m.log.Debugf("Saving site %s", site.ID)

	updated, err := m.save(site.ID, site, conn)

	m.log.Debugf("Site was updated? %t", updated)

	return err
}

func (m *SiteModel) Delete(id string, conn redis.Conn) error {
	m.syncing.Wait()
	//defer m.sync()

	if id == "here" {
		id = config.MustString("siteId")
	}

	return m.delete(id, conn)
}

func (m *SiteModel) Update(id string, site *model.Site, conn redis.Conn) error {
	m.syncing.Wait()
	//defer m.sync()

	if id == "here" {
		id = config.MustString("siteId")
	}

	oldSite := &model.Site{}

	if err := m.fetch(id, oldSite, false, conn); err != nil {
		return fmt.Errorf("Failed to fetch site (id:%s): %s", id, err)
	}

	oldSite.Name = site.Name
	oldSite.Type = site.Type
	oldSite.SitePreferences = site.SitePreferences
	oldSite.DefaultRoomID = site.DefaultRoomID

	if (oldSite.Latitude == nil || oldSite.Longitude == nil) || (*oldSite.Latitude != *site.Latitude || *oldSite.Longitude != *site.Longitude) {
		oldSite.Latitude = site.Latitude
		oldSite.Longitude = site.Longitude

		tz, err := getTimezone(*site.Latitude, *site.Longitude)
		if err != nil {
			return fmt.Errorf("Failed to get timezone: %s", err)
		}

		oldSite.TimeZoneID = tz.TimeZoneID
		oldSite.TimeZoneName = tz.TimeZoneName
		oldSite.TimeZoneOffset = tz.RawOffset // TODO: Not handling DST. Worth even having?
	}

	if _, err := m.save(id, oldSite, conn); err != nil {
		return fmt.Errorf("Failed to update site (id:%s): %s", id, err)
	}

	return nil
}

type googleTimezone struct {
	DstOffset    *int    `json:"dstOffset,omitempty"`
	RawOffset    *int    `json:"rawOffset,omitempty"`
	Status       *string `json:"status,omitempty"`
	TimeZoneID   *string `json:"timeZoneId,omitempty"`
	TimeZoneName *string `json:"timeZoneName,omitempty"`
}

func getTimezone(latitude, longitude float64) (*googleTimezone, error) {

	// TODO: Send proper timestamp to get the dst... or...?
	url := fmt.Sprintf("https://maps.googleapis.com/maps/api/timezone/json?location=%f,%f&timestamp=1414645501", latitude, longitude)

	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode != http.StatusOK {
		return nil, errors.New("Could not access schema " + resp.Status)
	}

	bodyBuff, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var tz googleTimezone
	err = json.Unmarshal(bodyBuff, &tz)
	if err != nil {
		return nil, err
	}

	if *tz.Status != "OK" {
		return nil, fmt.Errorf("Failed to get timezone: %s", *tz.Status)
	}

	/*

	   req := &geocode.Request{
	     Region:   "us",
	     Provider: geocode.GOOGLE,
	     Location: &geocode.Point{-33.86, 151.20},
	   }*/

	return &tz, nil
}
<commit_msg>Add nil pointer checks.<commit_after>package models

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/ninjasphere/go-ninja/config"
	"github.com/ninjasphere/go-ninja/model"
	"github.com/ninjasphere/redigo/redis"
)

type SiteModel struct {
	baseModel
}

func NewSiteModel() *SiteModel {
	return &SiteModel{
		baseModel: newBaseModel("site", model.Site{}),
	}
}

func (m *SiteModel) Fetch(id string, conn redis.Conn) (*model.Site, error) {
	m.syncing.Wait()

	if id == "here" {
		id = config.MustString("siteId")
	}

	site := &model.Site{}

	if err := m.fetch(id, site, false, conn); err != nil {
		return nil, err
	}

	return site, nil
}

func (m *SiteModel) FetchAll(conn redis.Conn) (*[]*model.Site, error) {
	m.syncing.Wait()

	ids, err := m.fetchIds(conn)

	if err != nil {
		return nil, err
	}

	sites := make([]*model.Site, len(ids))

	for i, id := range ids {
		sites[i], err = m.Fetch(id, conn)
		if err != nil {
			return nil, err
		}
	}

	return &sites, nil
}

func (m *SiteModel) Create(site *model.Site, conn redis.Conn) error {
	m.syncing.Wait()
	//defer m.sync()

	if site.ID == "here" {
		site.ID = config.MustString("siteId")
	}

	m.log.Debugf("Saving site %s", site.ID)

	updated, err := m.save(site.ID, site, conn)

	m.log.Debugf("Site was updated? %t", updated)

	return err
}

func (m *SiteModel) Delete(id string, conn redis.Conn) error {
	m.syncing.Wait()
	//defer m.sync()

	if id == "here" {
		id = config.MustString("siteId")
	}

	return m.delete(id, conn)
}

func (m *SiteModel) Update(id string, site *model.Site, conn redis.Conn) error {
	m.syncing.Wait()
	//defer m.sync()

	if id == "here" {
		id = config.MustString("siteId")
	}

	oldSite := &model.Site{}

	if err := m.fetch(id, oldSite, false, conn); err != nil {
		return fmt.Errorf("Failed to fetch site (id:%s): %s", id, err)
	}

	oldSite.Name = site.Name
	oldSite.Type = site.Type
	oldSite.SitePreferences = site.SitePreferences
	oldSite.DefaultRoomID = site.DefaultRoomID

	if site.Latitude != nil &&
		site.Longitude != nil &&
		((oldSite.Latitude == nil || oldSite.Longitude == nil) ||
			(*oldSite.Latitude != *site.Latitude || *oldSite.Longitude != *site.Longitude)) {
		oldSite.Latitude = site.Latitude
		oldSite.Longitude = site.Longitude

		tz, err := getTimezone(*site.Latitude, *site.Longitude)
		if err != nil {
			return fmt.Errorf("Failed to get timezone: %s", err)
		}

		oldSite.TimeZoneID = tz.TimeZoneID
		oldSite.TimeZoneName = tz.TimeZoneName
		oldSite.TimeZoneOffset = tz.RawOffset // TODO: Not handling DST. Worth even having?
	}

	if _, err := m.save(id, oldSite, conn); err != nil {
		return fmt.Errorf("Failed to update site (id:%s): %s", id, err)
	}

	return nil
}

type googleTimezone struct {
	DstOffset    *int    `json:"dstOffset,omitempty"`
	RawOffset    *int    `json:"rawOffset,omitempty"`
	Status       *string `json:"status,omitempty"`
	TimeZoneID   *string `json:"timeZoneId,omitempty"`
	TimeZoneName *string `json:"timeZoneName,omitempty"`
}

func getTimezone(latitude, longitude float64) (*googleTimezone, error) {

	// TODO: Send proper timestamp to get the dst... or...?
	url := fmt.Sprintf("https://maps.googleapis.com/maps/api/timezone/json?location=%f,%f&timestamp=1414645501", latitude, longitude)

	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode != http.StatusOK {
		return nil, errors.New("Could not access schema " + resp.Status)
	}

	bodyBuff, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var tz googleTimezone
	err = json.Unmarshal(bodyBuff, &tz)
	if err != nil {
		return nil, err
	}

	if *tz.Status != "OK" {
		return nil, fmt.Errorf("Failed to get timezone: %s", *tz.Status)
	}

	/*

	   req := &geocode.Request{
	     Region:   "us",
	     Provider: geocode.GOOGLE,
	     Location: &geocode.Point{-33.86, 151.20},
	   }*/

	return &tz, nil
}
<|endoftext|>


<commit_before>package models

import (
	"errors"
	"fmt"
	"testing"

	"github.com/taironas/gonawin/helpers"

	"appengine/aetest"
)

type testUser struct {
	email    string
	username string
	name     string
	alias    string
	isAdmin  bool
	auth     string
}

// TestCreateUser tests that you can create a user.
//
func TestCreateUser(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tests := []struct {
		title string
		user  testUser
	}{
		{"can create user", testUser{"foo@bar.com", "john.snow", "john snow", "crow", false, ""}},
	}

	for i, test := range tests {
		t.Log(test.title)
		var got *User
		if got, err = CreateUser(c, test.user.email, test.user.username, test.user.name, test.user.alias, test.user.isAdmin, test.user.auth); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkUser(got, test.user); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkUserInvertedIndex(t, c, got); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

// TestUserById tests that you can get a user by its ID.
//
func TestUserById(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		user  testUser
	}{
		"can get user by ID", testUser{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
	}

	t.Log(test.title)
	var got *User
	if got, err = CreateUser(c, test.user.email, test.user.username, test.user.name, test.user.alias, test.user.isAdmin, test.user.auth); err != nil {
		t.Errorf("Error: %v", err)
	}

	var u *User

	// Test non existing user
	if u, err = UserById(c, got.Id+50); u != nil {
		t.Errorf("Error: no user should have been found")
	}

	if err == nil {
		t.Errorf("Error: an error should have been returned in case of non existing user")
	}

	// Test existing user
	if u, err = UserById(c, got.Id); u == nil {
		t.Errorf("Error: user not found")
	}

	if err = checkUser(got, test.user); err != nil {
		t.Errorf("Error: want user == %v, got %v", test.user, got)
	}
}

// TestUsersByIds tests that you can get a list of users by their IDs.
//
func TestUsersByIds(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		users []testUser
	}{
		"can get users by IDs",
		[]testUser{
			{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
			{"foo@bar.com", "robb.stark", "robb stark", "king in the north", false, ""},
			{"foo@bar.com", "jamie.lannister", "jamie lannister", "kingslayer", false, ""},
		},
	}

	t.Log(test.title)
	var gotIDs []int64
	var got *User
	for _, user := range test.users {
		if got, err = CreateUser(c, user.email, user.username, user.name, user.alias, user.isAdmin, user.auth); err != nil {
			t.Errorf("Error: %v", err)
		}

		gotIDs = append(gotIDs, got.Id)
	}

	var users []*User

	// Test non existing users
	var nonExistingIDs []int64
	for _, ID := range gotIDs {
		nonExistingIDs = append(nonExistingIDs, ID+50)
	}

	if users, err = UsersByIds(c, nonExistingIDs); users != nil {
		t.Errorf("Error: no users should have been found")
	}

	// Test existing users
	if users, err = UsersByIds(c, gotIDs); users == nil {
		t.Errorf("Error: users not found")
	}

	for i, user := range test.users {
		if err = checkUser(users[i], user); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

// TestDestroyUser tests that you can destroy a user.
//
func TestDestroyUser(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		user  testUser
	}{
		"can destroy user", testUser{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
	}

	t.Log(test.title)
	var got *User
	if got, err = CreateUser(c, test.user.email, test.user.username, test.user.name, test.user.alias, test.user.isAdmin, test.user.auth); err != nil {
		t.Errorf("Error: %v", err)
	}

	if err = got.Destroy(c); err != nil {
		t.Errorf("Error: %v", err)
	}

	var u *User
	if u, err = UserById(c, got.Id); u != nil {
		t.Errorf("Error: user found, not properly destroyed")
	}
	if err = checkUserInvertedIndex(t, c, got); err == nil {
		t.Errorf("Error: user found in database")
	}
}

// TestFindUser tests that you can find a user.
//
func TestFindUser(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		user  testUser
	}{
		"can find user", testUser{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
	}

	t.Log(test.title)

	if _, err = CreateUser(c, test.user.email, test.user.username, test.user.name, test.user.alias, test.user.isAdmin, test.user.auth); err != nil {
		t.Errorf("Error: %v", err)
	}

	var got *User
	if got = FindUser(c, "Username", "john.snow"); got == nil {
		t.Errorf("Error: user not found by Username")
	}

	if got = FindUser(c, "Name", "john snow"); got == nil {
		t.Errorf("Error: user not found by Name")
	}

	if got = FindUser(c, "Alias", "crow"); got == nil {
		t.Errorf("Error: user not found by Alias")
	}
}

// TestFindAllUsers tests that you can find all the users.
//
func TestFindAllUsers(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		users []testUser
	}{
		"can find users",
		[]testUser{
			{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
			{"foo@bar.com", "robb.stark", "robb stark", "king in the north", false, ""},
			{"foo@bar.com", "jamie.lannister", "jamie lannister", "kingslayer", false, ""},
		},
	}

	t.Log(test.title)

	for _, user := range test.users {
		if _, err = CreateUser(c, user.email, user.username, user.name, user.alias, user.isAdmin, user.auth); err != nil {
			t.Errorf("Error: %v", err)
		}
	}

	var got []*User
	if got = FindAllUsers(c); got == nil {
		t.Errorf("Error: users not found")
	}

	if len(got) != len(test.users) {
		t.Errorf("Error: want users count == %s, got %s", len(test.users), len(got))
	}

	for i, user := range test.users {
		if err = checkUser(got[i], user); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

func checkUser(got *User, want testUser) error {
	var s string
	if got.Email != want.email {
		s = fmt.Sprintf("want Email == %s, got %s", want.email, got.Email)
	} else if got.Username != want.username {
		s = fmt.Sprintf("want Username == %s, got %s", want.username, got.Username)
	} else if got.Name != want.name {
		s = fmt.Sprintf("want Name == %s, got %s", want.name, got.Name)
	} else if got.Alias != want.alias {
		s = fmt.Sprintf("want Name == %s, got %s", want.alias, got.Alias)
	} else if got.IsAdmin != want.isAdmin {
		s = fmt.Sprintf("want isAdmin == %t, got %t", want.isAdmin, got.IsAdmin)
	} else if got.Auth != want.auth {
		s = fmt.Sprintf("want auth == %s, got %s", want.auth, got.Auth)
	} else {
		return nil
	}
	return errors.New(s)
}

func checkUserInvertedIndex(t *testing.T, c aetest.Context, got *User) error {

	var ids []int64
	var err error
	words := helpers.SetOfStrings("john")
	if ids, err = GetUserInvertedIndexes(c, words); err != nil {
		s := fmt.Sprintf("failed calling GetUserInvertedIndexes %v", err)
		return errors.New(s)
	}
	for _, id := range ids {
		if id == got.Id {
			return nil
		}
	}

	return errors.New("user not found")

}
<commit_msg>Revert "add test User.UsersByIds"<commit_after>package models

import (
	"errors"
	"fmt"
	"testing"

	"github.com/taironas/gonawin/helpers"

	"appengine/aetest"
)

type testUser struct {
	email    string
	username string
	name     string
	alias    string
	isAdmin  bool
	auth     string
}

// TestCreateUser tests that you can create a user.
//
func TestCreateUser(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	tests := []struct {
		title string
		user  testUser
	}{
		{"can create user", testUser{"foo@bar.com", "john.snow", "john snow", "crow", false, ""}},
	}

	for i, test := range tests {
		t.Log(test.title)
		var got *User
		if got, err = CreateUser(c, test.user.email, test.user.username, test.user.name, test.user.alias, test.user.isAdmin, test.user.auth); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkUser(got, test.user); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
		if err = checkUserInvertedIndex(t, c, got); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

// TestDestroyUser tests that you can destroy a user.
//
func TestDestroyUser(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		user  testUser
	}{
		"can destroy user", testUser{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
	}

	t.Log(test.title)
	var got *User
	if got, err = CreateUser(c, test.user.email, test.user.username, test.user.name, test.user.alias, test.user.isAdmin, test.user.auth); err != nil {
		t.Errorf("Error: %v", err)
	}

	if err = got.Destroy(c); err != nil {
		t.Errorf("Error: %v", err)
	}

	var u *User
	if u, err = UserById(c, got.Id); u != nil {
		t.Errorf("Error: user found, not properly destroyed")
	}
	if err = checkUserInvertedIndex(t, c, got); err == nil {
		t.Errorf("Error: user found in database")
	}
}

// TestFindUser tests that you can find a user.
//
func TestFindUser(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		user  testUser
	}{
		"can find user", testUser{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
	}

	t.Log(test.title)

	if _, err = CreateUser(c, test.user.email, test.user.username, test.user.name, test.user.alias, test.user.isAdmin, test.user.auth); err != nil {
		t.Errorf("Error: %v", err)
	}

	var got *User
	if got = FindUser(c, "Username", "john.snow"); got == nil {
		t.Errorf("Error: user not found by Username")
	}

	if got = FindUser(c, "Name", "john snow"); got == nil {
		t.Errorf("Error: user not found by Name")
	}

	if got = FindUser(c, "Alias", "crow"); got == nil {
		t.Errorf("Error: user not found by Alias")
	}
}

// TestFindAllUsers tests that you can find all the users.
//
func TestFindAllUsers(t *testing.T) {
	var c aetest.Context
	var err error
	options := aetest.Options{StronglyConsistentDatastore: true}

	if c, err = aetest.NewContext(&options); err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	test := struct {
		title string
		users []testUser
	}{
		"can find users",
		[]testUser{
			{"foo@bar.com", "john.snow", "john snow", "crow", false, ""},
			{"foo@bar.com", "robb.stark", "robb stark", "king in the north", false, ""},
			{"foo@bar.com", "jamie.lannister", "jamie lannister", "kingslayer", false, ""},
		},
	}

	t.Log(test.title)

	for _, user := range test.users {
		if _, err = CreateUser(c, user.email, user.username, user.name, user.alias, user.isAdmin, user.auth); err != nil {
			t.Errorf("Error: %v", err)
		}
	}

	var got []*User
	if got = FindAllUsers(c); got == nil {
		t.Errorf("Error: users not found")
	}

	if len(got) != len(test.users) {
		t.Errorf("Error: want users count == %s, got %s", len(test.users), len(got))
	}

	for i, user := range test.users {
		if err = checkUser(got[i], user); err != nil {
			t.Errorf("test %v - Error: %v", i, err)
		}
	}
}

func checkUser(got *User, want testUser) error {
	var s string
	if got.Email != want.email {
		s = fmt.Sprintf("want Email == %s, got %s", want.email, got.Email)
	} else if got.Username != want.username {
		s = fmt.Sprintf("want Username == %s, got %s", want.username, got.Username)
	} else if got.Name != want.name {
		s = fmt.Sprintf("want Name == %s, got %s", want.name, got.Name)
	} else if got.Alias != want.alias {
		s = fmt.Sprintf("want Name == %s, got %s", want.alias, got.Alias)
	} else if got.IsAdmin != want.isAdmin {
		s = fmt.Sprintf("want isAdmin == %t, got %t", want.isAdmin, got.IsAdmin)
	} else if got.Auth != want.auth {
		s = fmt.Sprintf("want auth == %s, got %s", want.auth, got.Auth)
	} else {
		return nil
	}
	return errors.New(s)
}

func checkUserInvertedIndex(t *testing.T, c aetest.Context, got *User) error {

	var ids []int64
	var err error
	words := helpers.SetOfStrings("john")
	if ids, err = GetUserInvertedIndexes(c, words); err != nil {
		s := fmt.Sprintf("failed calling GetUserInvertedIndexes %v", err)
		return errors.New(s)
	}
	for _, id := range ids {
		if id == got.Id {
			return nil
		}
	}

	return errors.New("user not found")

}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"github.com/dcu/mongodb_exporter/collector"
	"github.com/dcu/mongodb_exporter/shared"
	"github.com/prometheus/client_golang/prometheus"
	"net/http"
	//"github.com/golang/glog"
)

var (
	listenAddressFlag = flag.String("web.listen-address", ":9001", "Address on which to expose metrics and web interface.")
	metricsPathFlag   = flag.String("web.metrics-path", "/metrics", "Path under which to expose metrics.")

	mongodbUriFlag    = flag.String("mongodb.uri", "mongodb://localhost:27017", "Mongodb URI, format: [mongodb://][user:pass@]host1[:port1][,host2[:port2],...][/database][?options]")
	enabledGroupsFlag = flag.String("groups.enabled", "asserts,durability,background_flushing,connections,extra_info,global_lock,index_counters,network,op_counters,op_counters_repl,memory,locks,metrics", "Comma-separated list of groups to use, for more info see: docs.mongodb.org/manual/reference/command/serverStatus/")
	//printCollectors   = flag.Bool("collectors.print", false, "If true, print available collectors and exit.")
	authUserFlag = flag.String("auth.user", "", "Username for basic auth.")
	authPassFlag = flag.String("auth.pass", "", "Password for basic auth.")
)

type basicAuthHandler struct {
	handler  http.HandlerFunc
	user     string
	password string
}

func (h *basicAuthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	user, password, ok := r.BasicAuth()
	if !ok || password != h.password || user != h.user {
		w.Header().Set("WWW-Authenticate", "Basic realm=\"metrics\"")
		http.Error(w, "Invalid username or password", http.StatusUnauthorized)
		return
	}
	h.handler(w, r)
	return
}

func hasUserAndPassword() bool {
	return *authUserFlag != "" && *authPassFlag != ""
}

func prometheusHandler() http.Handler {
	handler := prometheus.Handler()
	if hasUserAndPassword() {
		handler = &basicAuthHandler{
			handler:  prometheus.Handler().ServeHTTP,
			user:     *authUserFlag,
			password: *authPassFlag,
		}
	}

	return handler
}

func startWebServer() {
	handler := prometheusHandler()

	http.Handle(*metricsPathFlag, handler)
	err := http.ListenAndServe(*listenAddressFlag, nil)

	if err != nil {
		panic(err)
	}
}

func main() {
	flag.Parse()
	shared.LoadGroupsDesc()
	shared.ParseEnabledGroups(*enabledGroupsFlag)

	mongodbCollector := collector.NewMongodbCollector(collector.MongodbCollectorOpts{
		URI: *mongodbUriFlag,
	})
	prometheus.MustRegister(mongodbCollector)

	startWebServer()
}
<commit_msg>Print the listening address on the screen.<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/dcu/mongodb_exporter/collector"
	"github.com/dcu/mongodb_exporter/shared"
	"github.com/prometheus/client_golang/prometheus"
	"net/http"
)

var (
	listenAddressFlag = flag.String("web.listen-address", ":9001", "Address on which to expose metrics and web interface.")
	metricsPathFlag   = flag.String("web.metrics-path", "/metrics", "Path under which to expose metrics.")

	mongodbUriFlag    = flag.String("mongodb.uri", "mongodb://localhost:27017", "Mongodb URI, format: [mongodb://][user:pass@]host1[:port1][,host2[:port2],...][/database][?options]")
	enabledGroupsFlag = flag.String("groups.enabled", "asserts,durability,background_flushing,connections,extra_info,global_lock,index_counters,network,op_counters,op_counters_repl,memory,locks,metrics", "Comma-separated list of groups to use, for more info see: docs.mongodb.org/manual/reference/command/serverStatus/")
	//printCollectors   = flag.Bool("collectors.print", false, "If true, print available collectors and exit.")
	authUserFlag = flag.String("auth.user", "", "Username for basic auth.")
	authPassFlag = flag.String("auth.pass", "", "Password for basic auth.")
)

type basicAuthHandler struct {
	handler  http.HandlerFunc
	user     string
	password string
}

func (h *basicAuthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	user, password, ok := r.BasicAuth()
	if !ok || password != h.password || user != h.user {
		w.Header().Set("WWW-Authenticate", "Basic realm=\"metrics\"")
		http.Error(w, "Invalid username or password", http.StatusUnauthorized)
		return
	}
	h.handler(w, r)
	return
}

func hasUserAndPassword() bool {
	return *authUserFlag != "" && *authPassFlag != ""
}

func prometheusHandler() http.Handler {
	handler := prometheus.Handler()
	if hasUserAndPassword() {
		handler = &basicAuthHandler{
			handler:  prometheus.Handler().ServeHTTP,
			user:     *authUserFlag,
			password: *authPassFlag,
		}
	}

	return handler
}

func startWebServer() {
	fmt.Printf("Listening on %s\n", *listenAddressFlag)
	handler := prometheusHandler()

	http.Handle(*metricsPathFlag, handler)
	err := http.ListenAndServe(*listenAddressFlag, nil)

	if err != nil {
		panic(err)
	}
}

func main() {
	flag.Parse()
	shared.LoadGroupsDesc()
	shared.ParseEnabledGroups(*enabledGroupsFlag)

	mongodbCollector := collector.NewMongodbCollector(collector.MongodbCollectorOpts{
		URI: *mongodbUriFlag,
	})
	prometheus.MustRegister(mongodbCollector)

	startWebServer()
}
<|endoftext|>


<commit_before>package container

import (
	"fmt"
	"github.com/labstack/gommon/log"
	"reflect"
)

type singletonContainer struct {
	values map[string]interface{}
}

var instance *singletonContainer

func init() {
	instance = &singletonContainer{
		make(map[string]interface{}),
	}
}

func Set(val interface{}) {
	var key string
	if reflect.TypeOf(val).Kind() == reflect.Ptr {
		key = reflect.Indirect(reflect.ValueOf(val)).Type().String()
	} else {
		key = reflect.ValueOf(val).Type().String()
	}

	log.Info(fmt.Sprintf("added %s to components container.", key))
	instance.values[key] = val
}

func Get(ptr interface{}) {
	val := reflect.ValueOf(ptr)
	key := reflect.Indirect(val).Type().String()
	component := instance.values[key]
	if component == nil {
		log.Warn(fmt.Sprintf("component not found. such type of %s.", key))
		return
	}
	log.Info(fmt.Sprintf("found component of %s .", key))

	elm := reflect.ValueOf(ptr).Elem()
	if reflect.TypeOf(component).Kind() == reflect.Ptr {
		elm.Set(reflect.Indirect(reflect.ValueOf(component)))
	} else {
		elm.Set(reflect.ValueOf(component))
	}
}
<commit_msg>Change log level<commit_after>package container

import (
	"fmt"
	"github.com/labstack/gommon/log"
	"reflect"
)

type singletonContainer struct {
	values map[string]interface{}
}

var instance *singletonContainer

func init() {
	instance = &singletonContainer{
		make(map[string]interface{}),
	}
}

func Set(val interface{}) {
	var key string
	if reflect.TypeOf(val).Kind() == reflect.Ptr {
		key = reflect.Indirect(reflect.ValueOf(val)).Type().String()
	} else {
		key = reflect.ValueOf(val).Type().String()
	}

	log.Debug(fmt.Sprintf("added %s to components container.", key))
	instance.values[key] = val
}

func Get(ptr interface{}) {
	val := reflect.ValueOf(ptr)
	key := reflect.Indirect(val).Type().String()
	component := instance.values[key]
	if component == nil {
		log.Warn(fmt.Sprintf("component not found. such type of %s.", key))
		return
	}
	log.Debug(fmt.Sprintf("found component of %s .", key))

	elm := reflect.ValueOf(ptr).Elem()
	if reflect.TypeOf(component).Kind() == reflect.Ptr {
		elm.Set(reflect.Indirect(reflect.ValueOf(component)))
	} else {
		elm.Set(reflect.ValueOf(component))
	}
}
<|endoftext|>


<commit_before>package commands

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"time"

	humanize "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/dustin/go-humanize"

	cmds "github.com/ipfs/go-ipfs/commands"
	metrics "gx/ipfs/QmYgaiNVVL7f2nydijAwpDRunRkmxfu3PoK87Y3pH84uAW/go-libp2p/p2p/metrics"
	protocol "gx/ipfs/QmYgaiNVVL7f2nydijAwpDRunRkmxfu3PoK87Y3pH84uAW/go-libp2p/p2p/protocol"
	u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
	peer "gx/ipfs/QmZwZjMVGss5rqYsJVGy18gNbkTJffFyq2x1uJ4e4p3ZAt/go-libp2p-peer"
)

var StatsCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline:          "Query IPFS statistics.",
		ShortDescription: ``,
	},

	Subcommands: map[string]*cmds.Command{
		"bw": statBwCmd,
	},
}

var statBwCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline:          "Print ipfs bandwidth information.",
		ShortDescription: ``,
	},
	Options: []cmds.Option{
		cmds.StringOption("peer", "p", "Specify a peer to print bandwidth for."),
		cmds.StringOption("proto", "t", "Specify a protocol to print bandwidth for."),
		cmds.BoolOption("poll", "Print bandwidth at an interval. Default: false."),
		cmds.StringOption("interval", "i", "Time interval to wait between updating output."),
	},

	Run: func(req cmds.Request, res cmds.Response) {
		nd, err := req.InvocContext().GetNode()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		// Must be online!
		if !nd.OnlineMode() {
			res.SetError(errNotOnline, cmds.ErrClient)
			return
		}

		pstr, pfound, err := req.Option("peer").String()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		tstr, tfound, err := req.Option("proto").String()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
		if pfound && tfound {
			res.SetError(errors.New("please only specify peer OR protocol"), cmds.ErrClient)
			return
		}

		var pid peer.ID
		if pfound {
			checkpid, err := peer.IDB58Decode(pstr)
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}
			pid = checkpid
		}

		interval := time.Second
		timeS, found, err := req.Option("interval").String()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
		if found {
			v, err := time.ParseDuration(timeS)
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}
			interval = v
		}

		doPoll, _, err := req.Option("poll").Bool()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		out := make(chan interface{})
		res.SetOutput((<-chan interface{})(out))

		go func() {
			defer close(out)
			for {
				if pfound {
					stats := nd.Reporter.GetBandwidthForPeer(pid)
					out <- &stats
				} else if tfound {
					protoId := protocol.ID(tstr)
					stats := nd.Reporter.GetBandwidthForProtocol(protoId)
					out <- &stats
				} else {
					totals := nd.Reporter.GetBandwidthTotals()
					out <- &totals
				}
				if !doPoll {
					return
				}
				select {
				case <-time.After(interval):
				case <-req.Context().Done():
					return
				}
			}
		}()
	},
	Type: metrics.Stats{},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) (io.Reader, error) {
			outCh, ok := res.Output().(<-chan interface{})
			if !ok {
				return nil, u.ErrCast()
			}

			polling, _, err := res.Request().Option("poll").Bool()
			if err != nil {
				return nil, err
			}

			first := true
			marshal := func(v interface{}) (io.Reader, error) {
				bs, ok := v.(*metrics.Stats)
				if !ok {
					return nil, u.ErrCast()
				}
				out := new(bytes.Buffer)
				if !polling {
					printStats(out, bs)
				} else {
					if first {
						fmt.Fprintln(out, "Total Up\t Total Down\t Rate Up\t Rate Down")
						first = false
					}
					fmt.Fprint(out, "\r")
					fmt.Fprintf(out, "%s \t\t", humanize.Bytes(uint64(bs.TotalOut)))
					fmt.Fprintf(out, " %s \t\t", humanize.Bytes(uint64(bs.TotalIn)))
					fmt.Fprintf(out, " %s/s   \t", humanize.Bytes(uint64(bs.RateOut)))
					fmt.Fprintf(out, " %s/s     ", humanize.Bytes(uint64(bs.RateIn)))
				}
				return out, nil

			}

			return &cmds.ChannelMarshaler{
				Channel:   outCh,
				Marshaler: marshal,
				Res:       res,
			}, nil
		},
	},
}

func printStats(out io.Writer, bs *metrics.Stats) {
	fmt.Fprintln(out, "Bandwidth")
	fmt.Fprintf(out, "TotalIn: %s\n", humanize.Bytes(uint64(bs.TotalIn)))
	fmt.Fprintf(out, "TotalOut: %s\n", humanize.Bytes(uint64(bs.TotalOut)))
	fmt.Fprintf(out, "RateIn: %s/s\n", humanize.Bytes(uint64(bs.RateIn)))
	fmt.Fprintf(out, "RateOut: %s/s\n", humanize.Bytes(uint64(bs.RateOut)))
}
<commit_msg>Added note to ipfs stats bw interval option<commit_after>package commands

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"time"

	humanize "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/dustin/go-humanize"

	cmds "github.com/ipfs/go-ipfs/commands"
	metrics "gx/ipfs/QmYgaiNVVL7f2nydijAwpDRunRkmxfu3PoK87Y3pH84uAW/go-libp2p/p2p/metrics"
	protocol "gx/ipfs/QmYgaiNVVL7f2nydijAwpDRunRkmxfu3PoK87Y3pH84uAW/go-libp2p/p2p/protocol"
	u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
	peer "gx/ipfs/QmZwZjMVGss5rqYsJVGy18gNbkTJffFyq2x1uJ4e4p3ZAt/go-libp2p-peer"
)

var StatsCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline:          "Query IPFS statistics.",
		ShortDescription: ``,
	},

	Subcommands: map[string]*cmds.Command{
		"bw": statBwCmd,
	},
}

var statBwCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline:          "Print ipfs bandwidth information.",
		ShortDescription: ``,
	},
	Options: []cmds.Option{
		cmds.StringOption("peer", "p", "Specify a peer to print bandwidth for."),
		cmds.StringOption("proto", "t", "Specify a protocol to print bandwidth for."),
		cmds.BoolOption("poll", "Print bandwidth at an interval. Default: false."),
		cmds.StringOption("interval", "i", "Time interval to wait between updating output, if 'poll' is true."),
	},

	Run: func(req cmds.Request, res cmds.Response) {
		nd, err := req.InvocContext().GetNode()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		// Must be online!
		if !nd.OnlineMode() {
			res.SetError(errNotOnline, cmds.ErrClient)
			return
		}

		pstr, pfound, err := req.Option("peer").String()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		tstr, tfound, err := req.Option("proto").String()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
		if pfound && tfound {
			res.SetError(errors.New("please only specify peer OR protocol"), cmds.ErrClient)
			return
		}

		var pid peer.ID
		if pfound {
			checkpid, err := peer.IDB58Decode(pstr)
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}
			pid = checkpid
		}

		interval := time.Second
		timeS, found, err := req.Option("interval").String()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
		if found {
			v, err := time.ParseDuration(timeS)
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}
			interval = v
		}

		doPoll, _, err := req.Option("poll").Bool()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		out := make(chan interface{})
		res.SetOutput((<-chan interface{})(out))

		go func() {
			defer close(out)
			for {
				if pfound {
					stats := nd.Reporter.GetBandwidthForPeer(pid)
					out <- &stats
				} else if tfound {
					protoId := protocol.ID(tstr)
					stats := nd.Reporter.GetBandwidthForProtocol(protoId)
					out <- &stats
				} else {
					totals := nd.Reporter.GetBandwidthTotals()
					out <- &totals
				}
				if !doPoll {
					return
				}
				select {
				case <-time.After(interval):
				case <-req.Context().Done():
					return
				}
			}
		}()
	},
	Type: metrics.Stats{},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) (io.Reader, error) {
			outCh, ok := res.Output().(<-chan interface{})
			if !ok {
				return nil, u.ErrCast()
			}

			polling, _, err := res.Request().Option("poll").Bool()
			if err != nil {
				return nil, err
			}

			first := true
			marshal := func(v interface{}) (io.Reader, error) {
				bs, ok := v.(*metrics.Stats)
				if !ok {
					return nil, u.ErrCast()
				}
				out := new(bytes.Buffer)
				if !polling {
					printStats(out, bs)
				} else {
					if first {
						fmt.Fprintln(out, "Total Up\t Total Down\t Rate Up\t Rate Down")
						first = false
					}
					fmt.Fprint(out, "\r")
					fmt.Fprintf(out, "%s \t\t", humanize.Bytes(uint64(bs.TotalOut)))
					fmt.Fprintf(out, " %s \t\t", humanize.Bytes(uint64(bs.TotalIn)))
					fmt.Fprintf(out, " %s/s   \t", humanize.Bytes(uint64(bs.RateOut)))
					fmt.Fprintf(out, " %s/s     ", humanize.Bytes(uint64(bs.RateIn)))
				}
				return out, nil

			}

			return &cmds.ChannelMarshaler{
				Channel:   outCh,
				Marshaler: marshal,
				Res:       res,
			}, nil
		},
	},
}

func printStats(out io.Writer, bs *metrics.Stats) {
	fmt.Fprintln(out, "Bandwidth")
	fmt.Fprintf(out, "TotalIn: %s\n", humanize.Bytes(uint64(bs.TotalIn)))
	fmt.Fprintf(out, "TotalOut: %s\n", humanize.Bytes(uint64(bs.TotalOut)))
	fmt.Fprintf(out, "RateIn: %s/s\n", humanize.Bytes(uint64(bs.RateIn)))
	fmt.Fprintf(out, "RateOut: %s/s\n", humanize.Bytes(uint64(bs.RateOut)))
}
<|endoftext|>


<commit_before>package ipfs2dir

import "log"
import "sync/atomic"

type statDataType uint64

const (
	SeenEntityCount      statDataType = iota
	SeenFileCount        statDataType = iota
	ProcessedEntityCount statDataType = iota
	SkippedEntityCount   statDataType = iota
	// The next line is needed for the array size in the StatData type
	numberOfDataPoints statDataType = iota
)

type StatData struct {
	data [numberOfDataPoints]uint64
}

func (s *StatData) Increment(whatToIncrement statDataType) {
	atomic.AddUint64(&s.data[whatToIncrement], 1)
}

func (s *StatData) Print() {
	log.Print("Seen entity count:")
	log.Print(atomic.LoadUint64(&s.data[SeenEntityCount]))
	log.Print("Seen file count:")
	log.Print(atomic.LoadUint64(&s.data[SeenFileCount]))
	log.Print("Overwritten file count:")
	log.Print(atomic.LoadUint64(&s.data[ProcessedEntityCount]))
	log.Print("Skipped (already up-to-date) file count:")
	log.Print(atomic.LoadUint64(&s.data[SkippedEntityCount]))
}
<commit_msg>cleaner stat<commit_after>package ipfs2dir

import "log"
import "sync/atomic"

type statDataType uint64

const (
	SeenEntityCount      statDataType = iota
	SeenFileCount                     = iota
	ProcessedEntityCount              = iota
	SkippedEntityCount                = iota
	// The next line is needed for the array size in the StatData type
	numberOfDataPoints = iota
)

type StatData struct {
	data [numberOfDataPoints]uint64
}

func (s *StatData) Increment(whatToIncrement statDataType) {
	atomic.AddUint64(&s.data[whatToIncrement], 1)
}

func (s *StatData) Read(whatToRead statDataType) uint64 {
	return atomic.LoadUint64(&s.data[whatToRead])
}

func (s *StatData) Print() {
	log.Print("Seen entity count:")
	log.Print(s.Read(SeenEntityCount))
	log.Print("Seen file count:")
	log.Print(s.Read(SeenFileCount))
	log.Print("Overwritten file count:")
	log.Print(s.Read(ProcessedEntityCount))
	log.Print("Skipped (already up-to-date) file count:")
	log.Print(s.Read(SkippedEntityCount))
}
<|endoftext|>