<commit_before>// Copyright 2014 Marc-Antoine Ruel. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

// This file defines all the interfaces to be used by the wi editor and to be
// accessable by plugins.

package wiCore

import (
	"fmt"
)

// UI

// DockingType defines the relative position of a Window relative to its parent.
type DockingType int

// Available docking options.
const (
	// DockingUnknown is an invalid value.
	DockingUnknown DockingType = iota

	// DockingFill means the Window uses all the available space.

	DockingFill
	// DockingFloating means the Window is not constrained by the parent window
	// size and location.
	DockingFloating

	DockingLeft
	DockingRight
	DockingTop
	DockingBottom
)

func (d DockingType) String() string {
	switch d {
	case DockingFill:
		return "DockingFill"
	case DockingFloating:
		return "DockingFloating"
	case DockingLeft:
		return "DockingLeft"
	case DockingRight:
		return "DockingRight"
	case DockingTop:
		return "DockingTop"
	case DockingBottom:
		return "DockingBottom"
	default:
		return "Unknown DockingType"
	}
}

// StringToDockingType converts a string back to a DockingType.
func StringToDockingType(s string) DockingType {
	switch s {
	case "fill":
		return DockingFill
	case "floating":
		return DockingFloating
	case "left":
		return DockingLeft
	case "right":
		return DockingRight
	case "top":
		return DockingTop
	case "bottom":
		return DockingBottom
	default:
		return DockingUnknown
	}
}

// BorderType defines the type of border for a Window.
type BorderType int

const (
	// BorderNone means width is 0.
	BorderNone BorderType = iota
	// BorderSingle means width is 1.
	BorderSingle
	// BorderDouble means width is 1 despite its name, only the glyph is
	// different.
	BorderDouble
)

func (b BorderType) String() string {
	switch b {
	case BorderNone:
		return "BorderNone"
	case BorderSingle:
		return "BorderSingle"
	case BorderDouble:
		return "BorderDouble"
	default:
		return "Unknown BorderType"
	}
}

// CommandCategory is used to put commands into sections for help purposes.
type CommandCategory int

const (
	// UnknownCategory means the command couldn't be categorized.
	UnknownCategory CommandCategory = iota
	// WindowCategory are commands relating to manipuling windows and UI in
	// general.
	WindowCategory
	// CommandsCategory are commands relating to manipulating commands, aliases,
	// keybindings.
	CommandsCategory
	// EditorCategory are commands relating to the editor lifetime.
	EditorCategory
	// DebugCategory are commands relating to debugging the app itself or plugins.
	DebugCategory

	// TODO(maruel): Add other categories.
)

func (c CommandCategory) String() string {
	switch c {
	case UnknownCategory:
		return "UnknownCategory"
	case WindowCategory:
		return "WindowCategory"
	case CommandsCategory:
		return "CommandsCategory"
	case DebugCategory:
		return "DebugCategory"
	default:
		return "Unknown CommandCategory"
	}
}

// KeyboardMode defines the keyboard mapping (input mode) to use.
type KeyboardMode int

const (
	// CommandMode is the mode where typing letters results in commands, not
	// content editing.
	CommandMode KeyboardMode = iota + 1
	// EditMode is the mode where typing letters results in content, not commands.
	EditMode
	// AllMode is to bind keys independent of the current mode. It is useful for
	// function keys, Ctrl-<letter>, arrow keys, etc.
	AllMode
)

// CommandID describes a command in the queue.
type CommandID struct {
	ProcessID    int
	CommandIndex int
}

func (c CommandID) String() string {
	return fmt.Sprintf("%d:%d", c.ProcessID, c.CommandIndex)
}

// CommandDispatcher owns the command queue. Use this interface to enqueue
// commands for execution.
type CommandDispatcher interface {
	// PostCommands appends several Command calls at the end of the queue. Using
	// this function guarantees that all the commands will be executed in order
	// without commands interfering.
	//
	// `callback` is called synchronously after the command is executed.
	PostCommands(cmds [][]string, callback func()) CommandID
}

// ViewFactory returns a new View.
type ViewFactory func(args ...string) View

// CommandDispatcherFull is a superset of CommandDispatcher for internal use.
type CommandDispatcherFull interface {
	CommandDispatcher

	// ExecuteCommand executes a command now. This is only meant to run a command
	// reentrantly; e.g. running a command triggers another one. This usually
	// happens for key binding, command aliases, when a command triggers an error.
	ExecuteCommand(w Window, cmdName string, args ...string)

	// ActiveWindow returns the current active Window.
	ActiveWindow() Window

	// RegisterViewFactory makes a nwe view available by name.
	RegisterViewFactory(name string, viewFactory ViewFactory) bool

	CurrentLanguage() LanguageMode
}

// Editor is the output device and the main process context. It shows the root
// window which covers the whole screen estate.
type Editor interface {
	CommandDispatcherFull

	KeyboardMode() KeyboardMode

	// Version returns the version number of this build of wi.
	Version() string
}

// Window is a View container. It defines the position, Z-ordering via
// hierarchy and decoration. It can have multiple child windows. The child
// windows are not bounded by the parent window if DockingFloating is used. The
// Window itself doesn't interact with the user, since it only has a non-client
// area (the border). All the client area is covered by the View.
//
// Split view is not supported. A 4-way merge setup can be created with the
// following Window setup as 4 child Window of the root Window:
//
//    +-----------+-----------+------------+
//    |  Remote   |Merge Base*|   Local    |
//    |DockingLeft|DockingFill|DockingRight|
//    |           |           |            |
//    +-----------+-----------+------------+
//    |              Result                |
//    |           DockingBottom            |
//    |                                    |
//    +------------------------------------+
//
// * The Merge Base View can be either:
//   - The root Window's View that is constained.
//   - A child Window set as DockingFill. In this case, the root Window View is
//     not visible.
//
// The end result is that this use case doesn't require any "split" support.
// Further subdivision can be done via Window containment.
//
// The Window interface exists for synchronous query but modifications
// (creation, closing, moving) are done asynchronously via commands. A set of
// privileged commands starting with the prefix "window_" can modify Window
// instances, designating the actual Window by its .ID() method.
type Window interface {
	fmt.Stringer
	CommandDispatcher

	// ID returns the unique id for this Window. The id is guaranteed to be
	// unique through the process lifetime of the editor.
	ID() string

	// Tree returns a textual representation of the Window hierarchy. It is only
	// for debugging purpose.
	// TODO(maruel): Remove.
	Tree() string

	// Parent returns the parent Window.
	Parent() Window
	// ChildrenWindows returns a copy of the slice of children windows.
	ChildrenWindows() []Window

	// Rect returns the position based on the parent Window area, except if
	// Docking() is DockingFloating.
	Rect() Rect

	// Docking returns where this Window is docked relative to the parent Window.
	// A DockingFloating window is effectively starting a new independent Rect.
	Docking() DockingType

	// View returns the View contained by this Window. There is exactly one.
	View() View
}

// View is content presented in a Window. For example it can be a TextBuffer or
// a command box. View define the key binding and commands supported so it
// responds to user input.
type View interface {
	// Commands returns the commands registered for this specific view. For
	// example a text window will have commands specific to the file type
	// enabled.
	Commands() Commands

	// KeyBindings returns the key bindings registered for this specific key. For
	// example the 'command' view has different behavior on up/down arrow keys
	// than a text editor view.
	KeyBindings() KeyBindings

	// Title is View's title, which can be the current file name or any other
	// relevant detail.
	Title() string

	// IsDisabled returns false if the View can be activated to receive user
	// inputs at all.
	IsDisabled() bool

	// Buffer returns the display buffer for this Window.
	Buffer() *Buffer

	// NaturalSize returns the natural size of the content. It can be -1 for as
	// long/large as possible, 0 if indeterminate. The return value of this
	// function is not affected by SetSize().
	NaturalSize() (width, height int)
	// SetSize resets the View Buffer size.
	SetSize(x, y int)

	// OnAttach is called by the Window after it was attached.
	// TODO(maruel): Maybe split in ViewFull?
	OnAttach(w Window)

	// DefaultFormat returns the default coloring for this View. If this View has
	// an CellFormat.Empty()==true format, it will uses whatever parent Window's
	// View DefaultFormat().
	DefaultFormat() CellFormat
}

// Document represents an open document. It can be accessed by zero, one or
// multiple View. For example the document may not be visible at all as a 'back
// buffer', may be loaded in a View or in multiple View, each having their own
// coloring and cursor position.
type Document interface {
	// RenderInto renders a view of a document.
	//
	// TODO(maruel): Likely return a new Buffer instance instead, for RPC
	// friendlyness. To be decided.
	RenderInto(buffer *Buffer, view View, offsetLine, offsetColumn int)

	// IsDirty is true if the content should be saved before quitting.
	IsDirty() bool
}

// Config

// Config is the configuration manager.
type Config interface {
	GetInt(name string) int
	GetString(name string) string
	Save()
}

// Control

// CommandHandler executes the command cmd on the Window w.
type CommandHandler func(cd CommandDispatcherFull, w Window, args ...string)

// Command describes a registered command that can be triggered directly at the
// command prompt, via a keybinding or a plugin.
type Command interface {
	// Name is the name of the command.
	Name() string
	// Handle executes the command.
	Handle(cd CommandDispatcherFull, w Window, args ...string)
	// Category returns the category the command should be bucketed in, for help
	// documentation purpose.
	Category(cd CommandDispatcherFull, w Window) CommandCategory
	// ShortDesc returns a short description of the command in the language
	// requested. It defaults to English if the description was not translated in
	// this language.
	ShortDesc(cd CommandDispatcherFull, w Window) string
	// LongDesc returns a long explanation of the command in the language
	// requested. It defaults to English if the description was not translated in
	// this language.
	LongDesc(cd CommandDispatcherFull, w Window) string
}

// Commands stores the known commands. This is where plugins can add new
// commands. Each View contains its own Commands.
type Commands interface {
	// Register registers a command so it can be executed later. In practice
	// commands should normally be registered on startup. Returns false if a
	// command was already registered and was lost.
	Register(cmd Command) bool

	// Get returns a command if registered, nil otherwise.
	Get(cmdName string) Command
}

// KeyBindings stores the mapping between keyboard entry and commands. This
// includes what can be considered "macros" as much as casual things like arrow
// keys.
type KeyBindings interface {
	// Set registers a keyboard mapping. In practice keyboard mappings
	// should normally be registered on startup. Returns false if a key mapping
	// was already registered and was lost. Set cmdName to "" to remove a key
	// binding.
	Set(mode KeyboardMode, key KeyPress, cmdName string) bool

	// Get returns a command if registered, nil otherwise.
	Get(mode KeyboardMode, key KeyPress) string
}

// EventType is the type of the event being flowed through the Window hierarchy
// and plugins. EventListener receive these.
//
// TODO(maruel): Dedupe from editor/terminal.go, testing.
type EventType string

// TODO(maruel): Dedupe from editor/terminal.go, testing.
//
// TODO(maruel): Use int or string? int is faster, string is likely more
// "extendable".
const (
	EventKey                 EventType = "key"
	EventResize                        = "resize"
	EventWindowCreated                 = "window_created"
	EventViewCreated                   = "view_created"
	EventDocumentCreated               = "document_created"
	EventDocumentCursorMoved           = "document_cursor_moved"

// Etc.
)

// EventListener are called on events.
// TODO(maruel): Experimenting with the idea.
type EventListener interface {
	OnEvent(t EventType, i interface{})
}

// Utility functions.

// PostCommand appends a Command at the end of the queue.
// It is a shortcut to cd.PostCommands([][]string{[]string{cmdName, args...}},
// callback). Sadly, using `...string` means that callback cannot be the last
// parameter.
func PostCommand(cd CommandDispatcher, callback func(), cmdName string, args ...string) CommandID {
	line := make([]string, len(args)+1)
	line[0] = cmdName
	copy(line[1:], args)
	return cd.PostCommands([][]string{line}, callback)
}

// GetCommand traverses the Window hierarchy tree to find a View that has
// the command cmd in its Commands mapping. If Window is nil, it starts with
// the Editor's active Window.
func GetCommand(cd CommandDispatcherFull, w Window, cmdName string) Command {
	if w == nil {
		w = cd.ActiveWindow()
	}
	for {
		cmd := w.View().Commands().Get(cmdName)
		if cmd != nil {
			return cmd
		}
		w = w.Parent()
		if w == nil {
			return nil
		}
	}
}

// GetKeyBindingCommand traverses the Editor's Window tree to find a View that
// has the key binding in its Keyboard mapping.
func GetKeyBindingCommand(e Editor, mode KeyboardMode, key KeyPress) string {
	active := e.ActiveWindow()
	for {
		cmdName := active.View().KeyBindings().Get(mode, key)
		if cmdName != "" {
			return cmdName
		}
		active = active.Parent()
		if active == nil {
			return ""
		}
	}
}

// RootWindow returns the root Window when given any Window in the tree.
func RootWindow(w Window) Window {
	for {
		if w.Parent() == nil {
			return w
		}
		w = w.Parent()
	}
}

// PositionOnScreen returns the exact position on screen of a Window.
func PositionOnScreen(w Window) Rect {
	out := w.Rect()
	if w.Docking() == DockingFloating {
		return out
	}
	for {
		w = w.Parent()
		if w == nil {
			break
		}
		// Take in account the parent Window position.
		r := w.Rect()
		out.X += r.X
		out.Y += r.Y
		if w.Docking() == DockingFloating {
			break
		}
	}
	return out
}
<commit_msg>Sort event entries<commit_after>// Copyright 2014 Marc-Antoine Ruel. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

// This file defines all the interfaces to be used by the wi editor and to be
// accessable by plugins.

package wiCore

import (
	"fmt"
)

// UI

// DockingType defines the relative position of a Window relative to its parent.
type DockingType int

// Available docking options.
const (
	// DockingUnknown is an invalid value.
	DockingUnknown DockingType = iota

	// DockingFill means the Window uses all the available space.

	DockingFill
	// DockingFloating means the Window is not constrained by the parent window
	// size and location.
	DockingFloating

	DockingLeft
	DockingRight
	DockingTop
	DockingBottom
)

func (d DockingType) String() string {
	switch d {
	case DockingFill:
		return "DockingFill"
	case DockingFloating:
		return "DockingFloating"
	case DockingLeft:
		return "DockingLeft"
	case DockingRight:
		return "DockingRight"
	case DockingTop:
		return "DockingTop"
	case DockingBottom:
		return "DockingBottom"
	default:
		return "Unknown DockingType"
	}
}

// StringToDockingType converts a string back to a DockingType.
func StringToDockingType(s string) DockingType {
	switch s {
	case "fill":
		return DockingFill
	case "floating":
		return DockingFloating
	case "left":
		return DockingLeft
	case "right":
		return DockingRight
	case "top":
		return DockingTop
	case "bottom":
		return DockingBottom
	default:
		return DockingUnknown
	}
}

// BorderType defines the type of border for a Window.
type BorderType int

const (
	// BorderNone means width is 0.
	BorderNone BorderType = iota
	// BorderSingle means width is 1.
	BorderSingle
	// BorderDouble means width is 1 despite its name, only the glyph is
	// different.
	BorderDouble
)

func (b BorderType) String() string {
	switch b {
	case BorderNone:
		return "BorderNone"
	case BorderSingle:
		return "BorderSingle"
	case BorderDouble:
		return "BorderDouble"
	default:
		return "Unknown BorderType"
	}
}

// CommandCategory is used to put commands into sections for help purposes.
type CommandCategory int

const (
	// UnknownCategory means the command couldn't be categorized.
	UnknownCategory CommandCategory = iota
	// WindowCategory are commands relating to manipuling windows and UI in
	// general.
	WindowCategory
	// CommandsCategory are commands relating to manipulating commands, aliases,
	// keybindings.
	CommandsCategory
	// EditorCategory are commands relating to the editor lifetime.
	EditorCategory
	// DebugCategory are commands relating to debugging the app itself or plugins.
	DebugCategory

	// TODO(maruel): Add other categories.
)

func (c CommandCategory) String() string {
	switch c {
	case UnknownCategory:
		return "UnknownCategory"
	case WindowCategory:
		return "WindowCategory"
	case CommandsCategory:
		return "CommandsCategory"
	case DebugCategory:
		return "DebugCategory"
	default:
		return "Unknown CommandCategory"
	}
}

// KeyboardMode defines the keyboard mapping (input mode) to use.
type KeyboardMode int

const (
	// CommandMode is the mode where typing letters results in commands, not
	// content editing.
	CommandMode KeyboardMode = iota + 1
	// EditMode is the mode where typing letters results in content, not commands.
	EditMode
	// AllMode is to bind keys independent of the current mode. It is useful for
	// function keys, Ctrl-<letter>, arrow keys, etc.
	AllMode
)

// CommandID describes a command in the queue.
type CommandID struct {
	ProcessID    int
	CommandIndex int
}

func (c CommandID) String() string {
	return fmt.Sprintf("%d:%d", c.ProcessID, c.CommandIndex)
}

// CommandDispatcher owns the command queue. Use this interface to enqueue
// commands for execution.
type CommandDispatcher interface {
	// PostCommands appends several Command calls at the end of the queue. Using
	// this function guarantees that all the commands will be executed in order
	// without commands interfering.
	//
	// `callback` is called synchronously after the command is executed.
	PostCommands(cmds [][]string, callback func()) CommandID
}

// ViewFactory returns a new View.
type ViewFactory func(args ...string) View

// CommandDispatcherFull is a superset of CommandDispatcher for internal use.
type CommandDispatcherFull interface {
	CommandDispatcher

	// ExecuteCommand executes a command now. This is only meant to run a command
	// reentrantly; e.g. running a command triggers another one. This usually
	// happens for key binding, command aliases, when a command triggers an error.
	ExecuteCommand(w Window, cmdName string, args ...string)

	// ActiveWindow returns the current active Window.
	ActiveWindow() Window

	// RegisterViewFactory makes a nwe view available by name.
	RegisterViewFactory(name string, viewFactory ViewFactory) bool

	CurrentLanguage() LanguageMode
}

// Editor is the output device and the main process context. It shows the root
// window which covers the whole screen estate.
type Editor interface {
	CommandDispatcherFull

	KeyboardMode() KeyboardMode

	// Version returns the version number of this build of wi.
	Version() string
}

// Window is a View container. It defines the position, Z-ordering via
// hierarchy and decoration. It can have multiple child windows. The child
// windows are not bounded by the parent window if DockingFloating is used. The
// Window itself doesn't interact with the user, since it only has a non-client
// area (the border). All the client area is covered by the View.
//
// Split view is not supported. A 4-way merge setup can be created with the
// following Window setup as 4 child Window of the root Window:
//
//    +-----------+-----------+------------+
//    |  Remote   |Merge Base*|   Local    |
//    |DockingLeft|DockingFill|DockingRight|
//    |           |           |            |
//    +-----------+-----------+------------+
//    |              Result                |
//    |           DockingBottom            |
//    |                                    |
//    +------------------------------------+
//
// * The Merge Base View can be either:
//   - The root Window's View that is constained.
//   - A child Window set as DockingFill. In this case, the root Window View is
//     not visible.
//
// The end result is that this use case doesn't require any "split" support.
// Further subdivision can be done via Window containment.
//
// The Window interface exists for synchronous query but modifications
// (creation, closing, moving) are done asynchronously via commands. A set of
// privileged commands starting with the prefix "window_" can modify Window
// instances, designating the actual Window by its .ID() method.
type Window interface {
	fmt.Stringer
	CommandDispatcher

	// ID returns the unique id for this Window. The id is guaranteed to be
	// unique through the process lifetime of the editor.
	ID() string

	// Tree returns a textual representation of the Window hierarchy. It is only
	// for debugging purpose.
	// TODO(maruel): Remove.
	Tree() string

	// Parent returns the parent Window.
	Parent() Window
	// ChildrenWindows returns a copy of the slice of children windows.
	ChildrenWindows() []Window

	// Rect returns the position based on the parent Window area, except if
	// Docking() is DockingFloating.
	Rect() Rect

	// Docking returns where this Window is docked relative to the parent Window.
	// A DockingFloating window is effectively starting a new independent Rect.
	Docking() DockingType

	// View returns the View contained by this Window. There is exactly one.
	View() View
}

// View is content presented in a Window. For example it can be a TextBuffer or
// a command box. View define the key binding and commands supported so it
// responds to user input.
type View interface {
	// Commands returns the commands registered for this specific view. For
	// example a text window will have commands specific to the file type
	// enabled.
	Commands() Commands

	// KeyBindings returns the key bindings registered for this specific key. For
	// example the 'command' view has different behavior on up/down arrow keys
	// than a text editor view.
	KeyBindings() KeyBindings

	// Title is View's title, which can be the current file name or any other
	// relevant detail.
	Title() string

	// IsDisabled returns false if the View can be activated to receive user
	// inputs at all.
	IsDisabled() bool

	// Buffer returns the display buffer for this Window.
	Buffer() *Buffer

	// NaturalSize returns the natural size of the content. It can be -1 for as
	// long/large as possible, 0 if indeterminate. The return value of this
	// function is not affected by SetSize().
	NaturalSize() (width, height int)
	// SetSize resets the View Buffer size.
	SetSize(x, y int)

	// OnAttach is called by the Window after it was attached.
	// TODO(maruel): Maybe split in ViewFull?
	OnAttach(w Window)

	// DefaultFormat returns the default coloring for this View. If this View has
	// an CellFormat.Empty()==true format, it will uses whatever parent Window's
	// View DefaultFormat().
	DefaultFormat() CellFormat
}

// Document represents an open document. It can be accessed by zero, one or
// multiple View. For example the document may not be visible at all as a 'back
// buffer', may be loaded in a View or in multiple View, each having their own
// coloring and cursor position.
type Document interface {
	// RenderInto renders a view of a document.
	//
	// TODO(maruel): Likely return a new Buffer instance instead, for RPC
	// friendlyness. To be decided.
	RenderInto(buffer *Buffer, view View, offsetLine, offsetColumn int)

	// IsDirty is true if the content should be saved before quitting.
	IsDirty() bool
}

// Config

// Config is the configuration manager.
type Config interface {
	GetInt(name string) int
	GetString(name string) string
	Save()
}

// Control

// CommandHandler executes the command cmd on the Window w.
type CommandHandler func(cd CommandDispatcherFull, w Window, args ...string)

// Command describes a registered command that can be triggered directly at the
// command prompt, via a keybinding or a plugin.
type Command interface {
	// Name is the name of the command.
	Name() string
	// Handle executes the command.
	Handle(cd CommandDispatcherFull, w Window, args ...string)
	// Category returns the category the command should be bucketed in, for help
	// documentation purpose.
	Category(cd CommandDispatcherFull, w Window) CommandCategory
	// ShortDesc returns a short description of the command in the language
	// requested. It defaults to English if the description was not translated in
	// this language.
	ShortDesc(cd CommandDispatcherFull, w Window) string
	// LongDesc returns a long explanation of the command in the language
	// requested. It defaults to English if the description was not translated in
	// this language.
	LongDesc(cd CommandDispatcherFull, w Window) string
}

// Commands stores the known commands. This is where plugins can add new
// commands. Each View contains its own Commands.
type Commands interface {
	// Register registers a command so it can be executed later. In practice
	// commands should normally be registered on startup. Returns false if a
	// command was already registered and was lost.
	Register(cmd Command) bool

	// Get returns a command if registered, nil otherwise.
	Get(cmdName string) Command
}

// KeyBindings stores the mapping between keyboard entry and commands. This
// includes what can be considered "macros" as much as casual things like arrow
// keys.
type KeyBindings interface {
	// Set registers a keyboard mapping. In practice keyboard mappings
	// should normally be registered on startup. Returns false if a key mapping
	// was already registered and was lost. Set cmdName to "" to remove a key
	// binding.
	Set(mode KeyboardMode, key KeyPress, cmdName string) bool

	// Get returns a command if registered, nil otherwise.
	Get(mode KeyboardMode, key KeyPress) string
}

// EventType is the type of the event being flowed through the Window hierarchy
// and plugins. EventListener receive these.
//
// TODO(maruel): Dedupe from editor/terminal.go, testing.
type EventType string

// TODO(maruel): Dedupe from editor/terminal.go, testing.
//
// TODO(maruel): Use int or string? int is faster, string is likely more
// "extendable".
const (
	EventDocumentCreated     EventType = "document_created"
	EventDocumentCursorMoved           = "document_cursor_moved"
	EventTerminalResized               = "terminal_resized"
	EventTerminalKeyPressed            = "terminal_key_pressed"
	EventViewCreated                   = "view_created"
	EventWindowCreated                 = "window_created"
	EventWindowResized                 = "window_resized"

// Etc.
)

// EventListener are called on events.
//
// TODO(maruel): Experimenting with the idea.
type EventListener interface {
	OnEvent(t EventType, i interface{})
}

// Utility functions.

// PostCommand appends a Command at the end of the queue.
// It is a shortcut to cd.PostCommands([][]string{[]string{cmdName, args...}},
// callback). Sadly, using `...string` means that callback cannot be the last
// parameter.
func PostCommand(cd CommandDispatcher, callback func(), cmdName string, args ...string) CommandID {
	line := make([]string, len(args)+1)
	line[0] = cmdName
	copy(line[1:], args)
	return cd.PostCommands([][]string{line}, callback)
}

// GetCommand traverses the Window hierarchy tree to find a View that has
// the command cmd in its Commands mapping. If Window is nil, it starts with
// the Editor's active Window.
func GetCommand(cd CommandDispatcherFull, w Window, cmdName string) Command {
	if w == nil {
		w = cd.ActiveWindow()
	}
	for {
		cmd := w.View().Commands().Get(cmdName)
		if cmd != nil {
			return cmd
		}
		w = w.Parent()
		if w == nil {
			return nil
		}
	}
}

// GetKeyBindingCommand traverses the Editor's Window tree to find a View that
// has the key binding in its Keyboard mapping.
func GetKeyBindingCommand(e Editor, mode KeyboardMode, key KeyPress) string {
	active := e.ActiveWindow()
	for {
		cmdName := active.View().KeyBindings().Get(mode, key)
		if cmdName != "" {
			return cmdName
		}
		active = active.Parent()
		if active == nil {
			return ""
		}
	}
}

// RootWindow returns the root Window when given any Window in the tree.
func RootWindow(w Window) Window {
	for {
		if w.Parent() == nil {
			return w
		}
		w = w.Parent()
	}
}

// PositionOnScreen returns the exact position on screen of a Window.
func PositionOnScreen(w Window) Rect {
	out := w.Rect()
	if w.Docking() == DockingFloating {
		return out
	}
	for {
		w = w.Parent()
		if w == nil {
			break
		}
		// Take in account the parent Window position.
		r := w.Rect()
		out.X += r.X
		out.Y += r.Y
		if w.Docking() == DockingFloating {
			break
		}
	}
	return out
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsEbsSnapshot() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsEbsSnapshotCreate,
		Read:   resourceAwsEbsSnapshotRead,
		Delete: resourceAwsEbsSnapshotDelete,

		Schema: map[string]*schema.Schema{
			"volume_id": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"description": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"owner_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"owner_alias": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"encrypted": {
				Type:     schema.TypeBool,
				Computed: true,
			},
			"volume_size": {
				Type:     schema.TypeInt,
				Computed: true,
			},
			"kms_key_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"data_encryption_key_id": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"tags": {
				Type:     schema.TypeMap,
				Optional: true,
				ForceNew: true,
			},
		},
	}
}

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

	request := &ec2.CreateSnapshotInput{
		VolumeId: aws.String(d.Get("volume_id").(string)),
	}
	if v, ok := d.GetOk("description"); ok {
		request.Description = aws.String(v.(string))
	}

	res, err := conn.CreateSnapshot(request)
	if err != nil {
		return err
	}

	d.SetId(*res.SnapshotId)

	err = resourceAwsEbsSnapshotWaitForAvailable(d.Id(), conn)
	if err != nil {
		return err
	}

	if err := setTags(conn, d); err != nil {
		log.Printf("[WARN] error setting tags: %s", err)
	}

	return resourceAwsEbsSnapshotRead(d, meta)
}

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

	req := &ec2.DescribeSnapshotsInput{
		SnapshotIds: []*string{aws.String(d.Id())},
	}
	res, err := conn.DescribeSnapshots(req)
	if err != nil {
		if isAWSErr(err, "InvalidSnapshot.NotFound", "") {
			log.Printf("[WARN] Snapshot %q Not found - removing from state", d.Id())
			d.SetId("")
			return nil
		}
		return err
	}

	if len(res.Snapshots) == 0 {
		d.SetId("")
		return nil
	}

	snapshot := res.Snapshots[0]

	d.Set("description", snapshot.Description)
	d.Set("owner_id", snapshot.OwnerId)
	d.Set("encrypted", snapshot.Encrypted)
	d.Set("owner_alias", snapshot.OwnerAlias)
	d.Set("volume_id", snapshot.VolumeId)
	d.Set("data_encryption_key_id", snapshot.DataEncryptionKeyId)
	d.Set("kms_key_id", snapshot.KmsKeyId)
	d.Set("volume_size", snapshot.VolumeSize)

	if err := d.Set("tags", tagsToMap(snapshot.Tags)); err != nil {
		log.Printf("[WARN] error saving tags to state: %s", err)
	}

	return nil
}

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

	return resource.Retry(5*time.Minute, func() *resource.RetryError {
		request := &ec2.DeleteSnapshotInput{
			SnapshotId: aws.String(d.Id()),
		}
		_, err := conn.DeleteSnapshot(request)
		if err == nil {
			return nil
		}

		ebsErr, ok := err.(awserr.Error)
		if ebsErr.Code() == "SnapshotInUse" {
			return resource.RetryableError(fmt.Errorf("EBS SnapshotInUse - trying again while it detaches"))
		}

		if !ok {
			return resource.NonRetryableError(err)
		}

		return resource.NonRetryableError(err)
	})
}

func resourceAwsEbsSnapshotWaitForAvailable(id string, conn *ec2.EC2) error {
	log.Printf("Waiting for Snapshot %s to become available...", id)

	req := &ec2.DescribeSnapshotsInput{
		SnapshotIds: []*string{aws.String(id)},
	}
	err := conn.WaitUntilSnapshotCompleted(req)
	return err
}
<commit_msg>resource/aws_ebs_snapshot: Allow retries for `SnapshotCreationPerVolumeRateExceeded` errors on creation<commit_after>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsEbsSnapshot() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsEbsSnapshotCreate,
		Read:   resourceAwsEbsSnapshotRead,
		Delete: resourceAwsEbsSnapshotDelete,

		Schema: map[string]*schema.Schema{
			"volume_id": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"description": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},
			"owner_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"owner_alias": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"encrypted": {
				Type:     schema.TypeBool,
				Computed: true,
			},
			"volume_size": {
				Type:     schema.TypeInt,
				Computed: true,
			},
			"kms_key_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"data_encryption_key_id": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"tags": {
				Type:     schema.TypeMap,
				Optional: true,
				ForceNew: true,
			},
		},
	}
}

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

	request := &ec2.CreateSnapshotInput{
		VolumeId: aws.String(d.Get("volume_id").(string)),
	}
	if v, ok := d.GetOk("description"); ok {
		request.Description = aws.String(v.(string))
	}

	var res *ec2.Snapshot
	err := resource.Retry(1*time.Minute, func() *resource.RetryError {
		var err error
		res, err = conn.CreateSnapshot(request)

		if isAWSErr(err, "SnapshotCreationPerVolumeRateExceeded", "The maximum per volume CreateSnapshot request rate has been exceeded") {
			return resource.RetryableError(err)
		}

		if err != nil {
			return resource.NonRetryableError(err)
		}

		return nil
	})

	if err != nil {
		return fmt.Errorf("error creating EC2 EBS Snapshot: %s", err)
	}

	d.SetId(*res.SnapshotId)

	err = resourceAwsEbsSnapshotWaitForAvailable(d.Id(), conn)
	if err != nil {
		return err
	}

	if err := setTags(conn, d); err != nil {
		log.Printf("[WARN] error setting tags: %s", err)
	}

	return resourceAwsEbsSnapshotRead(d, meta)
}

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

	req := &ec2.DescribeSnapshotsInput{
		SnapshotIds: []*string{aws.String(d.Id())},
	}
	res, err := conn.DescribeSnapshots(req)
	if err != nil {
		if isAWSErr(err, "InvalidSnapshot.NotFound", "") {
			log.Printf("[WARN] Snapshot %q Not found - removing from state", d.Id())
			d.SetId("")
			return nil
		}
		return err
	}

	if len(res.Snapshots) == 0 {
		d.SetId("")
		return nil
	}

	snapshot := res.Snapshots[0]

	d.Set("description", snapshot.Description)
	d.Set("owner_id", snapshot.OwnerId)
	d.Set("encrypted", snapshot.Encrypted)
	d.Set("owner_alias", snapshot.OwnerAlias)
	d.Set("volume_id", snapshot.VolumeId)
	d.Set("data_encryption_key_id", snapshot.DataEncryptionKeyId)
	d.Set("kms_key_id", snapshot.KmsKeyId)
	d.Set("volume_size", snapshot.VolumeSize)

	if err := d.Set("tags", tagsToMap(snapshot.Tags)); err != nil {
		log.Printf("[WARN] error saving tags to state: %s", err)
	}

	return nil
}

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

	return resource.Retry(5*time.Minute, func() *resource.RetryError {
		request := &ec2.DeleteSnapshotInput{
			SnapshotId: aws.String(d.Id()),
		}
		_, err := conn.DeleteSnapshot(request)
		if err == nil {
			return nil
		}

		ebsErr, ok := err.(awserr.Error)
		if ebsErr.Code() == "SnapshotInUse" {
			return resource.RetryableError(fmt.Errorf("EBS SnapshotInUse - trying again while it detaches"))
		}

		if !ok {
			return resource.NonRetryableError(err)
		}

		return resource.NonRetryableError(err)
	})
}

func resourceAwsEbsSnapshotWaitForAvailable(id string, conn *ec2.EC2) error {
	log.Printf("Waiting for Snapshot %s to become available...", id)

	req := &ec2.DescribeSnapshotsInput{
		SnapshotIds: []*string{aws.String(id)},
	}
	err := conn.WaitUntilSnapshotCompleted(req)
	return err
}
<|endoftext|>


<commit_before>// Copyright (C) 2015  Arista Networks, Inc.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the COPYING file.

package test

import (
	"fmt"
	"os"
	"reflect"
	"sort"
	"strconv"

	"github.com/aristanetworks/goarista/areflect"
)

// PrettyPrint tries to display a human readable version of an interface
func PrettyPrint(v interface{}) string {
	return PrettyPrintWithDepth(v, prettyPrintDepth)
}

// PrettyPrintWithDepth tries to display a human readable version of an interface
// and allows to define the depth of the print
func PrettyPrintWithDepth(v interface{}, depth int) string {
	return prettyPrint(reflect.ValueOf(v), ptrSet{}, depth)
}

var prettyPrintDepth = 8

func init() {
	d := os.Getenv("PPDEPTH")
	if d, ok := strconv.Atoi(d); ok == nil && d >= 0 {
		prettyPrintDepth = d
	}
}

type ptrSet map[uintptr]struct{}

func prettyPrint(v reflect.Value, done ptrSet, depth int) string {
	return prettyPrintWithType(v, done, depth, true)
}

func prettyPrintWithType(v reflect.Value, done ptrSet, depth int, showType bool) string {
	if depth < 0 {
		return "<max_depth>"
	}
	switch v.Kind() {
	case reflect.Invalid:
		return "nil"
	case reflect.Bool:
		return fmt.Sprintf("%t", v.Bool())
	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
		reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Float32, reflect.Float64,
		reflect.Int, reflect.Uint, reflect.Uintptr,
		reflect.Complex64, reflect.Complex128:
		i := areflect.ForceExport(v).Interface()
		if showType {
			return fmt.Sprintf("%s(%v)", v.Type().Name(), i)
		}
		return fmt.Sprintf("%v", i)
	case reflect.String:
		return fmt.Sprintf("%q", v.String())
	case reflect.Ptr:
		return "*" + prettyPrintWithType(v.Elem(), done, depth-1, showType)
	case reflect.Interface:
		return prettyPrintWithType(v.Elem(), done, depth-1, showType)
	case reflect.Map:
		var r []byte
		r = append(r, []byte(v.Type().String())...)
		r = append(r, '{')
		var elems mapEntries
		for _, k := range v.MapKeys() {
			elem := &mapEntry{
				k: prettyPrint(k, done, depth-1),
				v: prettyPrint(v.MapIndex(k), done, depth-1),
			}
			elems.entries = append(elems.entries, elem)
		}
		sort.Sort(&elems)
		for i, e := range elems.entries {
			if i > 0 {
				r = append(r, []byte(", ")...)
			}
			r = append(r, []byte(e.k)...)
			r = append(r, ':')
			r = append(r, []byte(e.v)...)
		}
		r = append(r, '}')
		return string(r)
	case reflect.Struct:
		// Circular dependency?
		if v.CanAddr() {
			ptr := v.UnsafeAddr()
			if _, ok := done[ptr]; ok {
				return fmt.Sprintf("%s{<circular dependency>}", v.Type().String())
			}
			done[ptr] = struct{}{}
		}
		var r []byte
		r = append(r, []byte(v.Type().String())...)
		r = append(r, '{')
		for i := 0; i < v.NumField(); i++ {
			if i > 0 {
				r = append(r, []byte(", ")...)
			}
			sf := v.Type().Field(i)
			r = append(r, sf.Name...)
			r = append(r, ':')
			r = append(r, prettyPrint(v.Field(i), done, depth-1)...)
		}
		r = append(r, '}')
		return string(r)
	case reflect.Chan:
		var ptr, bufsize string
		if v.Pointer() == 0 {
			ptr = "nil"
		} else {
			ptr = fmt.Sprintf("0x%x", v.Pointer())
		}
		if v.Cap() > 0 {
			bufsize = fmt.Sprintf("[%d]", v.Cap())
		}
		return fmt.Sprintf("(%s)(%s)%s", v.Type().String(), ptr, bufsize)
	case reflect.Func:
		return "func(...)"
	case reflect.Array, reflect.Slice:
		l := v.Len()
		var r []byte
		if v.Type().Elem().Kind() == reflect.Uint8 && v.Kind() != reflect.Array {
			b := areflect.ForceExport(v).Interface().([]byte)
			r = append(r, []byte(`[]byte(`)...)
			if b == nil {
				r = append(r, []byte("nil")...)
			} else {
				r = append(r, []byte(fmt.Sprintf("%q", b))...)
			}
			r = append(r, ')')
			return string(r)
		}
		r = append(r, []byte(v.Type().String())...)
		r = append(r, '{')
		for i := 0; i < l; i++ {
			if i > 0 {
				r = append(r, []byte(", ")...)
			}
			r = append(r, prettyPrintWithType(v.Index(i), done, depth-1, false)...)
		}
		r = append(r, '}')
		return string(r)
	case reflect.UnsafePointer:
		var ptr string
		if v.Pointer() == 0 {
			ptr = "nil"
		} else {
			ptr = fmt.Sprintf("0x%x", v.Pointer())
		}
		if showType {
			ptr = fmt.Sprintf("(unsafe.Pointer)(%s)", ptr)
		}
		return ptr
	default:
		panic(fmt.Errorf("Unhandled kind of reflect.Value: %v", v.Kind()))
	}
}

// IsNilCheck checks if the two values can compare to nil
// if checked == false, deep equal should continue
func IsNilCheck(a, b interface{}) (bool /*checked*/, string) {
	return isNilCheck(reflect.ValueOf(a), reflect.ValueOf(b))
}
<commit_msg>test: Delete unused/useless exported function.<commit_after>// Copyright (C) 2015  Arista Networks, Inc.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the COPYING file.

package test

import (
	"fmt"
	"os"
	"reflect"
	"sort"
	"strconv"

	"github.com/aristanetworks/goarista/areflect"
)

// PrettyPrint tries to display a human readable version of an interface
func PrettyPrint(v interface{}) string {
	return PrettyPrintWithDepth(v, prettyPrintDepth)
}

// PrettyPrintWithDepth tries to display a human readable version of an interface
// and allows to define the depth of the print
func PrettyPrintWithDepth(v interface{}, depth int) string {
	return prettyPrint(reflect.ValueOf(v), ptrSet{}, depth)
}

var prettyPrintDepth = 8

func init() {
	d := os.Getenv("PPDEPTH")
	if d, ok := strconv.Atoi(d); ok == nil && d >= 0 {
		prettyPrintDepth = d
	}
}

type ptrSet map[uintptr]struct{}

func prettyPrint(v reflect.Value, done ptrSet, depth int) string {
	return prettyPrintWithType(v, done, depth, true)
}

func prettyPrintWithType(v reflect.Value, done ptrSet, depth int, showType bool) string {
	if depth < 0 {
		return "<max_depth>"
	}
	switch v.Kind() {
	case reflect.Invalid:
		return "nil"
	case reflect.Bool:
		return fmt.Sprintf("%t", v.Bool())
	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
		reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Float32, reflect.Float64,
		reflect.Int, reflect.Uint, reflect.Uintptr,
		reflect.Complex64, reflect.Complex128:
		i := areflect.ForceExport(v).Interface()
		if showType {
			return fmt.Sprintf("%s(%v)", v.Type().Name(), i)
		}
		return fmt.Sprintf("%v", i)
	case reflect.String:
		return fmt.Sprintf("%q", v.String())
	case reflect.Ptr:
		return "*" + prettyPrintWithType(v.Elem(), done, depth-1, showType)
	case reflect.Interface:
		return prettyPrintWithType(v.Elem(), done, depth-1, showType)
	case reflect.Map:
		var r []byte
		r = append(r, []byte(v.Type().String())...)
		r = append(r, '{')
		var elems mapEntries
		for _, k := range v.MapKeys() {
			elem := &mapEntry{
				k: prettyPrint(k, done, depth-1),
				v: prettyPrint(v.MapIndex(k), done, depth-1),
			}
			elems.entries = append(elems.entries, elem)
		}
		sort.Sort(&elems)
		for i, e := range elems.entries {
			if i > 0 {
				r = append(r, []byte(", ")...)
			}
			r = append(r, []byte(e.k)...)
			r = append(r, ':')
			r = append(r, []byte(e.v)...)
		}
		r = append(r, '}')
		return string(r)
	case reflect.Struct:
		// Circular dependency?
		if v.CanAddr() {
			ptr := v.UnsafeAddr()
			if _, ok := done[ptr]; ok {
				return fmt.Sprintf("%s{<circular dependency>}", v.Type().String())
			}
			done[ptr] = struct{}{}
		}
		var r []byte
		r = append(r, []byte(v.Type().String())...)
		r = append(r, '{')
		for i := 0; i < v.NumField(); i++ {
			if i > 0 {
				r = append(r, []byte(", ")...)
			}
			sf := v.Type().Field(i)
			r = append(r, sf.Name...)
			r = append(r, ':')
			r = append(r, prettyPrint(v.Field(i), done, depth-1)...)
		}
		r = append(r, '}')
		return string(r)
	case reflect.Chan:
		var ptr, bufsize string
		if v.Pointer() == 0 {
			ptr = "nil"
		} else {
			ptr = fmt.Sprintf("0x%x", v.Pointer())
		}
		if v.Cap() > 0 {
			bufsize = fmt.Sprintf("[%d]", v.Cap())
		}
		return fmt.Sprintf("(%s)(%s)%s", v.Type().String(), ptr, bufsize)
	case reflect.Func:
		return "func(...)"
	case reflect.Array, reflect.Slice:
		l := v.Len()
		var r []byte
		if v.Type().Elem().Kind() == reflect.Uint8 && v.Kind() != reflect.Array {
			b := areflect.ForceExport(v).Interface().([]byte)
			r = append(r, []byte(`[]byte(`)...)
			if b == nil {
				r = append(r, []byte("nil")...)
			} else {
				r = append(r, []byte(fmt.Sprintf("%q", b))...)
			}
			r = append(r, ')')
			return string(r)
		}
		r = append(r, []byte(v.Type().String())...)
		r = append(r, '{')
		for i := 0; i < l; i++ {
			if i > 0 {
				r = append(r, []byte(", ")...)
			}
			r = append(r, prettyPrintWithType(v.Index(i), done, depth-1, false)...)
		}
		r = append(r, '}')
		return string(r)
	case reflect.UnsafePointer:
		var ptr string
		if v.Pointer() == 0 {
			ptr = "nil"
		} else {
			ptr = fmt.Sprintf("0x%x", v.Pointer())
		}
		if showType {
			ptr = fmt.Sprintf("(unsafe.Pointer)(%s)", ptr)
		}
		return ptr
	default:
		panic(fmt.Errorf("Unhandled kind of reflect.Value: %v", v.Kind()))
	}
}
<|endoftext|>


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

package sqlite

/*
#include <sqlite3.h>
#include <stdlib.h>

int goSqlite3CreateModule(sqlite3 *db, const char *zName, void *pClientData);
*/
import "C"

import (
	"fmt"
	"reflect"
	"unsafe"
)

type sqliteModule struct {
	c      *Conn
	name   string
	module Module
	vts    map[*sqliteVTab]bool
}

type sqliteVTab struct {
	module *sqliteModule
	vTab   VTab
	vtcs   map[*sqliteVTabCursor]bool
}

type sqliteVTabCursor struct {
	vTab       *sqliteVTab
	vTabCursor VTabCursor
}

//export goMInit
func goMInit(db, pClientData unsafe.Pointer, argc int, argv **C.char, pzErr **C.char, isCreate int) unsafe.Pointer {
	m := (*sqliteModule)(pClientData)
	if m.c.db != (*C.sqlite3)(db) {
		*pzErr = mPrintf("%s", "Inconsistent db handles")
		return nil
	}
	args := make([]string, argc)
	var A []*C.char
	slice := reflect.SliceHeader{uintptr(unsafe.Pointer(argv)), argc, argc}
	a := reflect.NewAt(reflect.TypeOf(A), unsafe.Pointer(&slice)).Elem().Interface()
	for i, s := range a.([]*C.char) {
		args[i] = C.GoString(s)
	}
	var vTab VTab
	var err error
	if isCreate == 1 {
		vTab, err = m.module.Create(m.c, args)
	} else {
		vTab, err = m.module.Connect(m.c, args)
	}

	if err != nil {
		*pzErr = mPrintf("%s", err.Error())
		return nil
	}
	vt := &sqliteVTab{m, vTab, nil}
	// prevents 'vt' from being gced
	if m.vts == nil {
		m.vts = make(map[*sqliteVTab]bool)
	}
	m.vts[vt] = true
	*pzErr = nil
	return unsafe.Pointer(vt)
}

//export goVRelease
func goVRelease(pVTab unsafe.Pointer, isDestroy int) *C.char {
	vt := (*sqliteVTab)(pVTab)
	var err error
	if isDestroy == 1 {
		err = vt.vTab.Destroy()
	} else {
		err = vt.vTab.Disconnect()
	}
	if err != nil {
		return mPrintf("%s", err.Error())
	}
	// TODO Check vt.vtcs is empty
	vt.vtcs = nil
	delete(vt.module.vts, vt)
	return nil
}

//export goVOpen
func goVOpen(pVTab unsafe.Pointer, pzErr **C.char) unsafe.Pointer {
	vt := (*sqliteVTab)(pVTab)
	vTabCursor, err := vt.vTab.Open()
	if err != nil {
		*pzErr = mPrintf("%s", err.Error())
		return nil
	}
	// prevents 'vt' from being gced
	vtc := &sqliteVTabCursor{vt, vTabCursor}
	if vt.vtcs == nil {
		vt.vtcs = make(map[*sqliteVTabCursor]bool)
	}
	vt.vtcs[vtc] = true
	*pzErr = nil
	return unsafe.Pointer(vtc)
}

//export goVClose
func goVClose(pCursor unsafe.Pointer) *C.char {
	vtc := (*sqliteVTabCursor)(pCursor)
	err := vtc.vTabCursor.Close()
	if err != nil {
		return mPrintf("%s", err.Error())
	}
	delete(vtc.vTab.vtcs, vtc)
	return nil
}

//export goMDestroy
func goMDestroy(pClientData unsafe.Pointer) {
	m := (*sqliteModule)(pClientData)
	m.module.Destroy()
	// TODO Check m.vts is empty
	m.vts = nil
	delete(m.c.modules, m.name)
}

//export goVFilter
func goVFilter(pCursor unsafe.Pointer) *C.char {
	vtc := (*sqliteVTabCursor)(pCursor)
	err := vtc.vTabCursor.Filter()
	if err != nil {
		return mPrintf("%s", err.Error())
	}
	return nil
}

//export goVNext
func goVNext(pCursor unsafe.Pointer) *C.char {
	vtc := (*sqliteVTabCursor)(pCursor)
	err := vtc.vTabCursor.Next()
	if err != nil {
		return mPrintf("%s", err.Error())
	}
	return nil
}

//export goVEof
func goVEof(pCursor unsafe.Pointer) C.int {
	vtc := (*sqliteVTabCursor)(pCursor)
	return btocint(vtc.vTabCursor.Eof())
}

//export goVColumn
func goVColumn(pCursor, cp unsafe.Pointer, col int) *C.char {
	vtc := (*sqliteVTabCursor)(pCursor)
	c := &Context{(*C.sqlite3_context)(cp)} // TODO how to avoid building a Context at each invocation?
	err := vtc.vTabCursor.Column(c, col)
	if err != nil {
		return mPrintf("%s", err.Error())
	}
	return nil
}

//export goVRowid
func goVRowid(pCursor unsafe.Pointer, pRowid *C.sqlite3_int64) *C.char {
	vtc := (*sqliteVTabCursor)(pCursor)
	rowid, err := vtc.vTabCursor.Rowid()
	if err != nil {
		return mPrintf("%s", err.Error())
	}
	*pRowid = C.sqlite3_int64(rowid)
	return nil
}

type Module interface {
	Create(c *Conn, args []string) (VTab, error)  // See http://sqlite.org/vtab.html#xcreate
	Connect(c *Conn, args []string) (VTab, error) // See http://sqlite.org/vtab.html#xconnect
	Destroy()                                     // See http://sqlite.org/c3ref/create_module.html
}

// (See http://sqlite.org/c3ref/vtab.html)
type VTab interface {
	BestIndex( /*sqlite3_index_info**/) error // See http://sqlite.org/vtab.html#xbestindex
	Disconnect() error                        // See http://sqlite.org/vtab.html#xdisconnect
	Destroy() error                           // See http://sqlite.org/vtab.html#sqlite3_module.xDestroy
	Open() (VTabCursor, error)                // See http://sqlite.org/vtab.html#xopen
}

// (See http://sqlite.org/c3ref/vtab.html)
type VTabExtended interface {
	VTab
	Update( /*int argc, sqlite3_value **argv, */ rowid int64) error

	Begin() error
	Sync() error
	Commit() error
	Rollback() error

	//FindFunction(nArg int, name string /*, void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), void **ppArg*/) error
	Rename(newName string) error

	Savepoint(i int) error
	Release(i int) error
	RollbackTo(i int) error
}

// (See http://sqlite.org/c3ref/vtab_cursor.html)
type VTabCursor interface {
	Close() error                                                                // See http://sqlite.org/vtab.html#xclose
	Filter( /*idxNum int, idxStr string, int argc, sqlite3_value **argv*/) error // See http://sqlite.org/vtab.html#xfilter
	Next() error                                                                 // See http://sqlite.org/vtab.html#xnext
	Eof() bool                                                                   // See http://sqlite.org/vtab.html#xeof
	// col is zero-based so the first column is numbered 0
	Column(c *Context, col int) error // See http://sqlite.org/vtab.html#xcolumn
	Rowid() (int64, error)            // See http://sqlite.org/vtab.html#xrowid
}

// DeclareVTab declares the Schema of a virtual table.
// (See http://sqlite.org/c3ref/declare_vtab.html)
func (c *Conn) DeclareVTab(sql string) error {
	zSQL := C.CString(sql)
	defer C.free(unsafe.Pointer(zSQL))
	return c.error(C.sqlite3_declare_vtab(c.db, zSQL), fmt.Sprintf("Conn.DeclareVTab(%q)", sql))
}

// CreateModule registers a virtual table implementation.
// (See http://sqlite.org/c3ref/create_module.html)
func (c *Conn) CreateModule(moduleName string, module Module) error {
	mname := C.CString(moduleName)
	defer C.free(unsafe.Pointer(mname))
	// To make sure it is not gced, keep a reference in the connection.
	udm := &sqliteModule{c, moduleName, module, nil}
	if len(c.modules) == 0 {
		c.modules = make(map[string]*sqliteModule)
	}
	c.modules[moduleName] = udm // FIXME What happens if different modules are registered with the same name?
	return c.error(C.goSqlite3CreateModule(c.db, mname, unsafe.Pointer(udm)),
		fmt.Sprintf("Conn.CreateModule(%q)", moduleName))
}

/*
GO                                                   C
CreateModule(                       int sqlite3_create_module_v2(
 |- c *Conn                          |- sqlite3 *db
 |- moduleName string                |- const char *zName
 |- goModule                         |- const sqlite3_module *p (~) Methods for the module
 |- *sqliteModule                    |- void *pClientData () Client data for xCreate/xConnect
 \- goVDestroy                       \- void(*xDestroy)(void*) () Client data destructor function
)                                   )

goModule                            sqlite3_module {
                                     |- int iVersion
goMInit                              |- int (*xCreate)(sqlite3*, void *pAux, int argc, char **argv, sqlite3_vtab **ppVTab,
                                             char **pzErr)
goMInit                              |- int (*xConnect)(sqlite3*, void *pAux, int argc, char **argv, sqlite3_vtab **ppVTab,
                                             char **pzErr)
x                                    |- int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*)
goVRelease                           |- int (*xDisconnect)(sqlite3_vtab *pVTab)
goVRelease                           |- int (*xDestroy)(sqlite3_vtab *pVTab)
goVOpen                              |- int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor)
goVClose                             |- int (*xClose)(sqlite3_vtab_cursor*)
x                                    |- int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, int argc,
                                             sqlite3_value **argv)
x                                    |- int (*xNext)(sqlite3_vtab_cursor*)
x                                    |- int (*xEof)(sqlite3_vtab_cursor*)
x                                    |- int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int)
x                                    |- int (*xRowid)(sqlite3_vtab_cursor*, sqlite_int64 *pRowid)
o                                    |- int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite_int64 *)
o                                    |- int (*xBegin)(sqlite3_vtab *pVTab)
o                                    |- int (*xSync)(sqlite3_vtab *pVTab)
o                                    |- int (*xCommit)(sqlite3_vtab *pVTab)
o                                    |- int (*xRollback)(sqlite3_vtab *pVTab)
o                                    |- int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
                                             void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), void **ppArg)
x                                    |- int (*xRename)(sqlite3_vtab *pVtab, const char *zNew)
o                                    |- int (*xSavepoint)(sqlite3_vtab *pVTab, int)
o                                    |- int (*xRelease)(sqlite3_vtab *pVTab, int)
o                                    \- int (*xRollbackTo)(sqlite3_vtab *pVTab, int)
                                    }

                                    int sqlite3_declare_vtab( (Called in xCreate/xConnect)
                                     |- sqlite3 *db,
                                     \- const char *zCreateTable
                                    )

sqliteVTab                          sqlite3_vtab { (Created by xCreate/xConnect)
                                     |- const sqlite3_module *pModule
                                     |- int nRef
                                     |- char *zErrMsg
                                     \- ...
                                    }

?                                   sqlite3_vtab_cursor { (Created by xOpen)
                                     |- sqlite3_vtab *pVtab
                                     \- ...
                                    }

*/
<commit_msg>Fix go vet warning.<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sqlite

/*
#include <sqlite3.h>
#include <stdlib.h>

int goSqlite3CreateModule(sqlite3 *db, const char *zName, void *pClientData);
*/
import "C"

import (
	"fmt"
	"reflect"
	"unsafe"
)

type sqliteModule struct {
	c      *Conn
	name   string
	module Module
	vts    map[*sqliteVTab]bool
}

type sqliteVTab struct {
	module *sqliteModule
	vTab   VTab
	vtcs   map[*sqliteVTabCursor]bool
}

type sqliteVTabCursor struct {
	vTab       *sqliteVTab
	vTabCursor VTabCursor
}

//export goMInit
func goMInit(db, pClientData unsafe.Pointer, argc int, argv **C.char, pzErr **C.char, isCreate int) unsafe.Pointer {
	m := (*sqliteModule)(pClientData)
	if m.c.db != (*C.sqlite3)(db) {
		*pzErr = mPrintf("%s", "Inconsistent db handles")
		return nil
	}
	args := make([]string, argc)
	var A []*C.char
	slice := reflect.SliceHeader{Data: uintptr(unsafe.Pointer(argv)), Len: argc, Cap: argc}
	a := reflect.NewAt(reflect.TypeOf(A), unsafe.Pointer(&slice)).Elem().Interface()
	for i, s := range a.([]*C.char) {
		args[i] = C.GoString(s)
	}
	var vTab VTab
	var err error
	if isCreate == 1 {
		vTab, err = m.module.Create(m.c, args)
	} else {
		vTab, err = m.module.Connect(m.c, args)
	}

	if err != nil {
		*pzErr = mPrintf("%s", err.Error())
		return nil
	}
	vt := &sqliteVTab{m, vTab, nil}
	// prevents 'vt' from being gced
	if m.vts == nil {
		m.vts = make(map[*sqliteVTab]bool)
	}
	m.vts[vt] = true
	*pzErr = nil
	return unsafe.Pointer(vt)
}

//export goVRelease
func goVRelease(pVTab unsafe.Pointer, isDestroy int) *C.char {
	vt := (*sqliteVTab)(pVTab)
	var err error
	if isDestroy == 1 {
		err = vt.vTab.Destroy()
	} else {
		err = vt.vTab.Disconnect()
	}
	if err != nil {
		return mPrintf("%s", err.Error())
	}
	// TODO Check vt.vtcs is empty
	vt.vtcs = nil
	delete(vt.module.vts, vt)
	return nil
}

//export goVOpen
func goVOpen(pVTab unsafe.Pointer, pzErr **C.char) unsafe.Pointer {
	vt := (*sqliteVTab)(pVTab)
	vTabCursor, err := vt.vTab.Open()
	if err != nil {
		*pzErr = mPrintf("%s", err.Error())
		return nil
	}
	// prevents 'vt' from being gced
	vtc := &sqliteVTabCursor{vt, vTabCursor}
	if vt.vtcs == nil {
		vt.vtcs = make(map[*sqliteVTabCursor]bool)
	}
	vt.vtcs[vtc] = true
	*pzErr = nil
	return unsafe.Pointer(vtc)
}

//export goVClose
func goVClose(pCursor unsafe.Pointer) *C.char {
	vtc := (*sqliteVTabCursor)(pCursor)
	err := vtc.vTabCursor.Close()
	if err != nil {
		return mPrintf("%s", err.Error())
	}
	delete(vtc.vTab.vtcs, vtc)
	return nil
}

//export goMDestroy
func goMDestroy(pClientData unsafe.Pointer) {
	m := (*sqliteModule)(pClientData)
	m.module.Destroy()
	// TODO Check m.vts is empty
	m.vts = nil
	delete(m.c.modules, m.name)
}

//export goVFilter
func goVFilter(pCursor unsafe.Pointer) *C.char {
	vtc := (*sqliteVTabCursor)(pCursor)
	err := vtc.vTabCursor.Filter()
	if err != nil {
		return mPrintf("%s", err.Error())
	}
	return nil
}

//export goVNext
func goVNext(pCursor unsafe.Pointer) *C.char {
	vtc := (*sqliteVTabCursor)(pCursor)
	err := vtc.vTabCursor.Next()
	if err != nil {
		return mPrintf("%s", err.Error())
	}
	return nil
}

//export goVEof
func goVEof(pCursor unsafe.Pointer) C.int {
	vtc := (*sqliteVTabCursor)(pCursor)
	return btocint(vtc.vTabCursor.Eof())
}

//export goVColumn
func goVColumn(pCursor, cp unsafe.Pointer, col int) *C.char {
	vtc := (*sqliteVTabCursor)(pCursor)
	c := &Context{(*C.sqlite3_context)(cp)} // TODO how to avoid building a Context at each invocation?
	err := vtc.vTabCursor.Column(c, col)
	if err != nil {
		return mPrintf("%s", err.Error())
	}
	return nil
}

//export goVRowid
func goVRowid(pCursor unsafe.Pointer, pRowid *C.sqlite3_int64) *C.char {
	vtc := (*sqliteVTabCursor)(pCursor)
	rowid, err := vtc.vTabCursor.Rowid()
	if err != nil {
		return mPrintf("%s", err.Error())
	}
	*pRowid = C.sqlite3_int64(rowid)
	return nil
}

type Module interface {
	Create(c *Conn, args []string) (VTab, error)  // See http://sqlite.org/vtab.html#xcreate
	Connect(c *Conn, args []string) (VTab, error) // See http://sqlite.org/vtab.html#xconnect
	Destroy()                                     // See http://sqlite.org/c3ref/create_module.html
}

// (See http://sqlite.org/c3ref/vtab.html)
type VTab interface {
	BestIndex( /*sqlite3_index_info**/) error // See http://sqlite.org/vtab.html#xbestindex
	Disconnect() error                        // See http://sqlite.org/vtab.html#xdisconnect
	Destroy() error                           // See http://sqlite.org/vtab.html#sqlite3_module.xDestroy
	Open() (VTabCursor, error)                // See http://sqlite.org/vtab.html#xopen
}

// (See http://sqlite.org/c3ref/vtab.html)
type VTabExtended interface {
	VTab
	Update( /*int argc, sqlite3_value **argv, */ rowid int64) error

	Begin() error
	Sync() error
	Commit() error
	Rollback() error

	//FindFunction(nArg int, name string /*, void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), void **ppArg*/) error
	Rename(newName string) error

	Savepoint(i int) error
	Release(i int) error
	RollbackTo(i int) error
}

// (See http://sqlite.org/c3ref/vtab_cursor.html)
type VTabCursor interface {
	Close() error                                                                // See http://sqlite.org/vtab.html#xclose
	Filter( /*idxNum int, idxStr string, int argc, sqlite3_value **argv*/) error // See http://sqlite.org/vtab.html#xfilter
	Next() error                                                                 // See http://sqlite.org/vtab.html#xnext
	Eof() bool                                                                   // See http://sqlite.org/vtab.html#xeof
	// col is zero-based so the first column is numbered 0
	Column(c *Context, col int) error // See http://sqlite.org/vtab.html#xcolumn
	Rowid() (int64, error)            // See http://sqlite.org/vtab.html#xrowid
}

// DeclareVTab declares the Schema of a virtual table.
// (See http://sqlite.org/c3ref/declare_vtab.html)
func (c *Conn) DeclareVTab(sql string) error {
	zSQL := C.CString(sql)
	defer C.free(unsafe.Pointer(zSQL))
	return c.error(C.sqlite3_declare_vtab(c.db, zSQL), fmt.Sprintf("Conn.DeclareVTab(%q)", sql))
}

// CreateModule registers a virtual table implementation.
// (See http://sqlite.org/c3ref/create_module.html)
func (c *Conn) CreateModule(moduleName string, module Module) error {
	mname := C.CString(moduleName)
	defer C.free(unsafe.Pointer(mname))
	// To make sure it is not gced, keep a reference in the connection.
	udm := &sqliteModule{c, moduleName, module, nil}
	if len(c.modules) == 0 {
		c.modules = make(map[string]*sqliteModule)
	}
	c.modules[moduleName] = udm // FIXME What happens if different modules are registered with the same name?
	return c.error(C.goSqlite3CreateModule(c.db, mname, unsafe.Pointer(udm)),
		fmt.Sprintf("Conn.CreateModule(%q)", moduleName))
}

/*
GO                                                   C
CreateModule(                       int sqlite3_create_module_v2(
 |- c *Conn                          |- sqlite3 *db
 |- moduleName string                |- const char *zName
 |- goModule                         |- const sqlite3_module *p (~) Methods for the module
 |- *sqliteModule                    |- void *pClientData () Client data for xCreate/xConnect
 \- goVDestroy                       \- void(*xDestroy)(void*) () Client data destructor function
)                                   )

goModule                            sqlite3_module {
                                     |- int iVersion
goMInit                              |- int (*xCreate)(sqlite3*, void *pAux, int argc, char **argv, sqlite3_vtab **ppVTab,
                                             char **pzErr)
goMInit                              |- int (*xConnect)(sqlite3*, void *pAux, int argc, char **argv, sqlite3_vtab **ppVTab,
                                             char **pzErr)
x                                    |- int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*)
goVRelease                           |- int (*xDisconnect)(sqlite3_vtab *pVTab)
goVRelease                           |- int (*xDestroy)(sqlite3_vtab *pVTab)
goVOpen                              |- int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor)
goVClose                             |- int (*xClose)(sqlite3_vtab_cursor*)
x                                    |- int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, int argc,
                                             sqlite3_value **argv)
x                                    |- int (*xNext)(sqlite3_vtab_cursor*)
x                                    |- int (*xEof)(sqlite3_vtab_cursor*)
x                                    |- int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int)
x                                    |- int (*xRowid)(sqlite3_vtab_cursor*, sqlite_int64 *pRowid)
o                                    |- int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite_int64 *)
o                                    |- int (*xBegin)(sqlite3_vtab *pVTab)
o                                    |- int (*xSync)(sqlite3_vtab *pVTab)
o                                    |- int (*xCommit)(sqlite3_vtab *pVTab)
o                                    |- int (*xRollback)(sqlite3_vtab *pVTab)
o                                    |- int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
                                             void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), void **ppArg)
x                                    |- int (*xRename)(sqlite3_vtab *pVtab, const char *zNew)
o                                    |- int (*xSavepoint)(sqlite3_vtab *pVTab, int)
o                                    |- int (*xRelease)(sqlite3_vtab *pVTab, int)
o                                    \- int (*xRollbackTo)(sqlite3_vtab *pVTab, int)
                                    }

                                    int sqlite3_declare_vtab( (Called in xCreate/xConnect)
                                     |- sqlite3 *db,
                                     \- const char *zCreateTable
                                    )

sqliteVTab                          sqlite3_vtab { (Created by xCreate/xConnect)
                                     |- const sqlite3_module *pModule
                                     |- int nRef
                                     |- char *zErrMsg
                                     \- ...
                                    }

?                                   sqlite3_vtab_cursor { (Created by xOpen)
                                     |- sqlite3_vtab *pVtab
                                     \- ...
                                    }

*/
<|endoftext|>


<commit_before>package operation

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"mime"
	"mime/multipart"
	"net/http"
	"net/textproto"
	"path/filepath"
	"runtime/debug"
	"strings"
	"time"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/security"
	"github.com/chrislusf/seaweedfs/weed/util"
	"github.com/valyala/bytebufferpool"
)

type UploadResult struct {
	Name       string `json:"name,omitempty"`
	Size       uint32 `json:"size,omitempty"`
	Error      string `json:"error,omitempty"`
	ETag       string `json:"eTag,omitempty"`
	CipherKey  []byte `json:"cipherKey,omitempty"`
	Mime       string `json:"mime,omitempty"`
	Gzip       uint32 `json:"gzip,omitempty"`
	ContentMd5 string `json:"contentMd5,omitempty"`
}

func (uploadResult *UploadResult) ToPbFileChunk(fileId string, offset int64) *filer_pb.FileChunk {
	fid, _ := filer_pb.ToFileIdObject(fileId)
	return &filer_pb.FileChunk{
		FileId:       fileId,
		Offset:       offset,
		Size:         uint64(uploadResult.Size),
		Mtime:        time.Now().UnixNano(),
		ETag:         uploadResult.ETag,
		CipherKey:    uploadResult.CipherKey,
		IsCompressed: uploadResult.Gzip > 0,
		Fid:          fid,
	}
}

// HTTPClient interface for testing
type HTTPClient interface {
	Do(req *http.Request) (*http.Response, error)
}

var (
	HttpClient HTTPClient
)

func init() {
	HttpClient = &http.Client{Transport: &http.Transport{
		MaxIdleConnsPerHost: 1024,
	}}
}

var fileNameEscaper = strings.NewReplacer("\\", "\\\\", "\"", "\\\"")

// Upload sends a POST request to a volume server to upload the content with adjustable compression level
func UploadData(uploadUrl string, filename string, cipher bool, data []byte, isInputCompressed bool, mtype string, pairMap map[string]string, jwt security.EncodedJwt) (uploadResult *UploadResult, err error) {
	uploadResult, err = retriedUploadData(uploadUrl, filename, cipher, data, isInputCompressed, mtype, pairMap, jwt)
	return
}

// Upload sends a POST request to a volume server to upload the content with fast compression
func Upload(uploadUrl string, filename string, cipher bool, reader io.Reader, isInputCompressed bool, mtype string, pairMap map[string]string, jwt security.EncodedJwt) (uploadResult *UploadResult, err error, data []byte) {
	uploadResult, err, data = doUpload(uploadUrl, filename, cipher, reader, isInputCompressed, mtype, pairMap, jwt)
	return
}

func doUpload(uploadUrl string, filename string, cipher bool, reader io.Reader, isInputCompressed bool, mtype string, pairMap map[string]string, jwt security.EncodedJwt) (uploadResult *UploadResult, err error, data []byte) {
	bytesReader, ok := reader.(*util.BytesReader)
	if ok {
		data = bytesReader.Bytes
	} else {
		buf := bytebufferpool.Get()
		_, err = buf.ReadFrom(reader)
		defer bytebufferpool.Put(buf)
		if err != nil {
			err = fmt.Errorf("read input: %v", err)
			return
		}
		data = buf.Bytes()
	}
	uploadResult, uploadErr := retriedUploadData(uploadUrl, filename, cipher, data, isInputCompressed, mtype, pairMap, jwt)
	return uploadResult, uploadErr, data
}

func retriedUploadData(uploadUrl string, filename string, cipher bool, data []byte, isInputCompressed bool, mtype string, pairMap map[string]string, jwt security.EncodedJwt) (uploadResult *UploadResult, err error) {
	for i := 0; i < 1; i++ {
		uploadResult, err = doUploadData(uploadUrl, filename, cipher, data, isInputCompressed, mtype, pairMap, jwt)
		if err == nil {
			return
		} else {
			glog.Warningf("uploading to %s: %v", uploadUrl, err)
		}
	}
	return
}

func doUploadData(uploadUrl string, filename string, cipher bool, data []byte, isInputCompressed bool, mtype string, pairMap map[string]string, jwt security.EncodedJwt) (uploadResult *UploadResult, err error) {
	contentIsGzipped := isInputCompressed
	shouldGzipNow := false
	if !isInputCompressed {
		if mtype == "" {
			mtype = http.DetectContentType(data)
			// println("detect1 mimetype to", mtype)
			if mtype == "application/octet-stream" {
				mtype = ""
			}
		}
		if shouldBeCompressed, iAmSure := util.IsCompressableFileType(filepath.Base(filename), mtype); iAmSure && shouldBeCompressed {
			shouldGzipNow = true
		} else if !iAmSure && mtype == "" && len(data) > 128 {
			var compressed []byte
			compressed, err = util.GzipData(data[0:128])
			shouldGzipNow = len(compressed)*10 < 128*9 // can not compress to less than 90%
		}
	}

	var clearDataLen int

	// gzip if possible
	// this could be double copying
	clearDataLen = len(data)
	if shouldGzipNow {
		compressed, compressErr := util.GzipData(data)
		// fmt.Printf("data is compressed from %d ==> %d\n", len(data), len(compressed))
		if compressErr == nil {
			data = compressed
			contentIsGzipped = true
		}
	} else if isInputCompressed {
		// just to get the clear data length
		clearData, err := util.DecompressData(data)
		if err == nil {
			clearDataLen = len(clearData)
		}
	}

	if cipher {
		// encrypt(gzip(data))

		// encrypt
		cipherKey := util.GenCipherKey()
		encryptedData, encryptionErr := util.Encrypt(data, cipherKey)
		if encryptionErr != nil {
			err = fmt.Errorf("encrypt input: %v", encryptionErr)
			return
		}

		// upload data
		uploadResult, err = upload_content(uploadUrl, func(w io.Writer) (err error) {
			_, err = w.Write(encryptedData)
			return
		}, "", false, len(encryptedData), "", nil, jwt)
		if uploadResult != nil {
			uploadResult.Name = filename
			uploadResult.Mime = mtype
			uploadResult.CipherKey = cipherKey
		}
	} else {
		// upload data
		uploadResult, err = upload_content(uploadUrl, func(w io.Writer) (err error) {
			_, err = w.Write(data)
			return
		}, filename, contentIsGzipped, 0, mtype, pairMap, jwt)
	}

	if uploadResult == nil {
		return
	}

	uploadResult.Size = uint32(clearDataLen)
	if contentIsGzipped {
		uploadResult.Gzip = 1
	}

	return uploadResult, err
}

func upload_content(uploadUrl string, fillBufferFunction func(w io.Writer) error, filename string, isGzipped bool, originalDataSize int, mtype string, pairMap map[string]string, jwt security.EncodedJwt) (*UploadResult, error) {
	body_buf := bytes.NewBufferString("")
	body_writer := multipart.NewWriter(body_buf)
	h := make(textproto.MIMEHeader)
	h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="file"; filename="%s"`, fileNameEscaper.Replace(filename)))
	if mtype == "" {
		mtype = mime.TypeByExtension(strings.ToLower(filepath.Ext(filename)))
	}
	if mtype != "" {
		h.Set("Content-Type", mtype)
	}
	if isGzipped {
		h.Set("Content-Encoding", "gzip")
	}

	file_writer, cp_err := body_writer.CreatePart(h)
	if cp_err != nil {
		glog.V(0).Infoln("error creating form file", cp_err.Error())
		return nil, cp_err
	}
	if err := fillBufferFunction(file_writer); err != nil {
		glog.V(0).Infoln("error copying data", err)
		return nil, err
	}
	content_type := body_writer.FormDataContentType()
	if err := body_writer.Close(); err != nil {
		glog.V(0).Infoln("error closing body", err)
		return nil, err
	}

	req, postErr := http.NewRequest("POST", uploadUrl, body_buf)
	if postErr != nil {
		glog.V(1).Infof("create upload request %s: %v", uploadUrl, postErr)
		return nil, fmt.Errorf("create upload request %s: %v", uploadUrl, postErr)
	}
	req.Header.Set("Content-Type", content_type)
	for k, v := range pairMap {
		req.Header.Set(k, v)
	}
	if jwt != "" {
		req.Header.Set("Authorization", "BEARER "+string(jwt))
	}
	resp, post_err := HttpClient.Do(req)
	if post_err != nil {
		glog.Errorf("upload %s %d bytes to %v: %v", filename, originalDataSize, uploadUrl, post_err)
		debug.PrintStack()
		return nil, fmt.Errorf("upload %s %d bytes to %v: %v", filename, originalDataSize, uploadUrl, post_err)
	}
	defer util.CloseResponse(resp)

	var ret UploadResult
	etag := getEtag(resp)
	if resp.StatusCode == http.StatusNoContent {
		ret.ETag = etag
		return &ret, nil
	}

	resp_body, ra_err := ioutil.ReadAll(resp.Body)
	if ra_err != nil {
		return nil, fmt.Errorf("read response body %v: %v", uploadUrl, ra_err)
	}

	unmarshal_err := json.Unmarshal(resp_body, &ret)
	if unmarshal_err != nil {
		glog.Errorf("unmarshal %s: %v", uploadUrl, string(resp_body))
		return nil, fmt.Errorf("unmarshal %v: %v", uploadUrl, unmarshal_err)
	}
	if ret.Error != "" {
		return nil, fmt.Errorf("unmarshalled error %v: %v", uploadUrl, ret.Error)
	}
	ret.ETag = etag
	ret.ContentMd5 = resp.Header.Get("Content-MD5")
	return &ret, nil
}

func getEtag(r *http.Response) (etag string) {
	etag = r.Header.Get("ETag")
	if strings.HasPrefix(etag, "\"") && strings.HasSuffix(etag, "\"") {
		etag = etag[1 : len(etag)-1]
	}
	return
}
<commit_msg>byte buffer for uploading<commit_after>package operation

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"mime"
	"mime/multipart"
	"net/http"
	"net/textproto"
	"path/filepath"
	"runtime/debug"
	"strings"
	"time"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/security"
	"github.com/chrislusf/seaweedfs/weed/util"
	"github.com/valyala/bytebufferpool"
)

type UploadResult struct {
	Name       string `json:"name,omitempty"`
	Size       uint32 `json:"size,omitempty"`
	Error      string `json:"error,omitempty"`
	ETag       string `json:"eTag,omitempty"`
	CipherKey  []byte `json:"cipherKey,omitempty"`
	Mime       string `json:"mime,omitempty"`
	Gzip       uint32 `json:"gzip,omitempty"`
	ContentMd5 string `json:"contentMd5,omitempty"`
}

func (uploadResult *UploadResult) ToPbFileChunk(fileId string, offset int64) *filer_pb.FileChunk {
	fid, _ := filer_pb.ToFileIdObject(fileId)
	return &filer_pb.FileChunk{
		FileId:       fileId,
		Offset:       offset,
		Size:         uint64(uploadResult.Size),
		Mtime:        time.Now().UnixNano(),
		ETag:         uploadResult.ETag,
		CipherKey:    uploadResult.CipherKey,
		IsCompressed: uploadResult.Gzip > 0,
		Fid:          fid,
	}
}

// HTTPClient interface for testing
type HTTPClient interface {
	Do(req *http.Request) (*http.Response, error)
}

var (
	HttpClient HTTPClient
)

func init() {
	HttpClient = &http.Client{Transport: &http.Transport{
		MaxIdleConnsPerHost: 1024,
	}}
}

var fileNameEscaper = strings.NewReplacer("\\", "\\\\", "\"", "\\\"")

// Upload sends a POST request to a volume server to upload the content with adjustable compression level
func UploadData(uploadUrl string, filename string, cipher bool, data []byte, isInputCompressed bool, mtype string, pairMap map[string]string, jwt security.EncodedJwt) (uploadResult *UploadResult, err error) {
	uploadResult, err = retriedUploadData(uploadUrl, filename, cipher, data, isInputCompressed, mtype, pairMap, jwt)
	return
}

// Upload sends a POST request to a volume server to upload the content with fast compression
func Upload(uploadUrl string, filename string, cipher bool, reader io.Reader, isInputCompressed bool, mtype string, pairMap map[string]string, jwt security.EncodedJwt) (uploadResult *UploadResult, err error, data []byte) {
	uploadResult, err, data = doUpload(uploadUrl, filename, cipher, reader, isInputCompressed, mtype, pairMap, jwt)
	return
}

func doUpload(uploadUrl string, filename string, cipher bool, reader io.Reader, isInputCompressed bool, mtype string, pairMap map[string]string, jwt security.EncodedJwt) (uploadResult *UploadResult, err error, data []byte) {
	bytesReader, ok := reader.(*util.BytesReader)
	if ok {
		data = bytesReader.Bytes
	} else {
		buf := bytebufferpool.Get()
		_, err = buf.ReadFrom(reader)
		defer bytebufferpool.Put(buf)
		if err != nil {
			err = fmt.Errorf("read input: %v", err)
			return
		}
		data = buf.Bytes()
	}
	uploadResult, uploadErr := retriedUploadData(uploadUrl, filename, cipher, data, isInputCompressed, mtype, pairMap, jwt)
	return uploadResult, uploadErr, data
}

func retriedUploadData(uploadUrl string, filename string, cipher bool, data []byte, isInputCompressed bool, mtype string, pairMap map[string]string, jwt security.EncodedJwt) (uploadResult *UploadResult, err error) {
	for i := 0; i < 1; i++ {
		uploadResult, err = doUploadData(uploadUrl, filename, cipher, data, isInputCompressed, mtype, pairMap, jwt)
		if err == nil {
			return
		} else {
			glog.Warningf("uploading to %s: %v", uploadUrl, err)
		}
	}
	return
}

func doUploadData(uploadUrl string, filename string, cipher bool, data []byte, isInputCompressed bool, mtype string, pairMap map[string]string, jwt security.EncodedJwt) (uploadResult *UploadResult, err error) {
	contentIsGzipped := isInputCompressed
	shouldGzipNow := false
	if !isInputCompressed {
		if mtype == "" {
			mtype = http.DetectContentType(data)
			// println("detect1 mimetype to", mtype)
			if mtype == "application/octet-stream" {
				mtype = ""
			}
		}
		if shouldBeCompressed, iAmSure := util.IsCompressableFileType(filepath.Base(filename), mtype); iAmSure && shouldBeCompressed {
			shouldGzipNow = true
		} else if !iAmSure && mtype == "" && len(data) > 128 {
			var compressed []byte
			compressed, err = util.GzipData(data[0:128])
			shouldGzipNow = len(compressed)*10 < 128*9 // can not compress to less than 90%
		}
	}

	var clearDataLen int

	// gzip if possible
	// this could be double copying
	clearDataLen = len(data)
	if shouldGzipNow {
		compressed, compressErr := util.GzipData(data)
		// fmt.Printf("data is compressed from %d ==> %d\n", len(data), len(compressed))
		if compressErr == nil {
			data = compressed
			contentIsGzipped = true
		}
	} else if isInputCompressed {
		// just to get the clear data length
		clearData, err := util.DecompressData(data)
		if err == nil {
			clearDataLen = len(clearData)
		}
	}

	if cipher {
		// encrypt(gzip(data))

		// encrypt
		cipherKey := util.GenCipherKey()
		encryptedData, encryptionErr := util.Encrypt(data, cipherKey)
		if encryptionErr != nil {
			err = fmt.Errorf("encrypt input: %v", encryptionErr)
			return
		}

		// upload data
		uploadResult, err = upload_content(uploadUrl, func(w io.Writer) (err error) {
			_, err = w.Write(encryptedData)
			return
		}, "", false, len(encryptedData), "", nil, jwt)
		if uploadResult != nil {
			uploadResult.Name = filename
			uploadResult.Mime = mtype
			uploadResult.CipherKey = cipherKey
		}
	} else {
		// upload data
		uploadResult, err = upload_content(uploadUrl, func(w io.Writer) (err error) {
			_, err = w.Write(data)
			return
		}, filename, contentIsGzipped, 0, mtype, pairMap, jwt)
	}

	if uploadResult == nil {
		return
	}

	uploadResult.Size = uint32(clearDataLen)
	if contentIsGzipped {
		uploadResult.Gzip = 1
	}

	return uploadResult, err
}

func upload_content(uploadUrl string, fillBufferFunction func(w io.Writer) error, filename string, isGzipped bool, originalDataSize int, mtype string, pairMap map[string]string, jwt security.EncodedJwt) (*UploadResult, error) {
	buf := bytebufferpool.Get()
	defer bytebufferpool.Put(buf)
	body_writer := multipart.NewWriter(buf)
	h := make(textproto.MIMEHeader)
	h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="file"; filename="%s"`, fileNameEscaper.Replace(filename)))
	if mtype == "" {
		mtype = mime.TypeByExtension(strings.ToLower(filepath.Ext(filename)))
	}
	if mtype != "" {
		h.Set("Content-Type", mtype)
	}
	if isGzipped {
		h.Set("Content-Encoding", "gzip")
	}

	file_writer, cp_err := body_writer.CreatePart(h)
	if cp_err != nil {
		glog.V(0).Infoln("error creating form file", cp_err.Error())
		return nil, cp_err
	}
	if err := fillBufferFunction(file_writer); err != nil {
		glog.V(0).Infoln("error copying data", err)
		return nil, err
	}
	content_type := body_writer.FormDataContentType()
	if err := body_writer.Close(); err != nil {
		glog.V(0).Infoln("error closing body", err)
		return nil, err
	}

	req, postErr := http.NewRequest("POST", uploadUrl, bytes.NewReader(buf.Bytes()))
	if postErr != nil {
		glog.V(1).Infof("create upload request %s: %v", uploadUrl, postErr)
		return nil, fmt.Errorf("create upload request %s: %v", uploadUrl, postErr)
	}
	req.Header.Set("Content-Type", content_type)
	for k, v := range pairMap {
		req.Header.Set(k, v)
	}
	if jwt != "" {
		req.Header.Set("Authorization", "BEARER "+string(jwt))
	}
	resp, post_err := HttpClient.Do(req)
	if post_err != nil {
		glog.Errorf("upload %s %d bytes to %v: %v", filename, originalDataSize, uploadUrl, post_err)
		debug.PrintStack()
		return nil, fmt.Errorf("upload %s %d bytes to %v: %v", filename, originalDataSize, uploadUrl, post_err)
	}
	defer util.CloseResponse(resp)

	var ret UploadResult
	etag := getEtag(resp)
	if resp.StatusCode == http.StatusNoContent {
		ret.ETag = etag
		return &ret, nil
	}

	resp_body, ra_err := ioutil.ReadAll(resp.Body)
	if ra_err != nil {
		return nil, fmt.Errorf("read response body %v: %v", uploadUrl, ra_err)
	}

	unmarshal_err := json.Unmarshal(resp_body, &ret)
	if unmarshal_err != nil {
		glog.Errorf("unmarshal %s: %v", uploadUrl, string(resp_body))
		return nil, fmt.Errorf("unmarshal %v: %v", uploadUrl, unmarshal_err)
	}
	if ret.Error != "" {
		return nil, fmt.Errorf("unmarshalled error %v: %v", uploadUrl, ret.Error)
	}
	ret.ETag = etag
	ret.ContentMd5 = resp.Header.Get("Content-MD5")
	return &ret, nil
}

func getEtag(r *http.Response) (etag string) {
	etag = r.Header.Get("ETag")
	if strings.HasPrefix(etag, "\"") && strings.HasSuffix(etag, "\"") {
		etag = etag[1 : len(etag)-1]
	}
	return
}
<|endoftext|>


<commit_before><commit_msg>Build assets<commit_after><|endoftext|>


<commit_before>package vkapi

const (
	PostTypePost     = "post"
	PostTypeCopy     = "copy"
	PostTypeReply    = "reply"
	PostTypePostpone = "postpone"
	PostTypeSuggest  = "suggest"
)

type Wall struct {
	ID           int64         `json:"id"`
	OwnerID      int64         `json:"owner_id"`
	FromID       int64         `json:"from_id"`
	Date         int64         `json:"date"`
	Text         string        `json:"text"`
	ReplyOwnerID int64         `json:"reply_owner_id"`
	ReplyPostID  int64         `json:"reply_post_id"`
	FriendsOnly  int           `json:"friends_only"`
	Comments     *Comments     `json:"comments"`
	Likes        *Likes        `json:"likes"`
	Reposts      *Reposts      `json:"reposts"`
	Views        *Views        `json:"views"`
	PostType     string        `json:"post_type"`
	PostSource   *PostSource   `json:"post_source"`
	Attachments  *[]Attachment `json:"attachments"`
	Geo          *Geo          `json:"geo"`
	SingerID     int64         `json:"singer_id"`
	CopyHistory  *[]Wall       `json:"copy_history"`
	CanPin       int           `json:"can_pin"`
	CanDelete    int           `json:"can_delete"`
	CanEdit      int           `json:"can_edit"`
	IsPinned     int           `json:"is_pinned"`
	MarkedAsAds  int           `json:"marked_as_ads"`
}

type Comments struct {
	Count   int `json:"count"`
	CanPost int `json:"can_post"`
}

type Likes struct {
	Count      int `json:"count"`
	UserLikes  int `json:"user_likes"`
	CanLike    int `json:"can_like"`
	CanPublish int `json:"can_publish"`
}

type Reposts struct {
	Count        int `json:"count"`
	UserReposted int `json:"user_reposted"`
}

type Views struct {
	Count int `json:"count"`
}

type PostSource struct {
	Type     string `json:"type"`
	Platform string `json:"platform"`
	Data     string `json:"data"`
	URL      string `json:"url"`
}

type Geo struct {
	Type        string `json:"type"`
	Coordinates string `json:"coordinates"`
	Place       struct {
		ID         int64  `json:"id"`
		Title      string `json:"title"`
		Latitude   int    `json:"latitude"`
		Longitude  int    `json:"longitude"`
		Created    int64  `json:"created"`
		Icon       string `json:"icon"`
		Country    string `json:"country"`
		City       string `json:"city"`
		Type       int    `json:"type"`
		GroupID    int64  `json:"group_id"`
		GroupPhoto int64  `json:"group_photo"`
		Checkins   int64  `json:"checkins"`
		Updated    int64  `json:"updated"`
		Address    int64  `json:"address"`
	} `json:"place"`
}
<commit_msg>Added get.wall method<commit_after>package vkapi

import (
	"net/url"
	"strings"
)

const (
	PostTypePost     = "post"
	PostTypeCopy     = "copy"
	PostTypeReply    = "reply"
	PostTypePostpone = "postpone"
	PostTypeSuggest  = "suggest"
)

type Wall struct {
	ID           int64         `json:"id"`
	OwnerID      int64         `json:"owner_id"`
	FromID       int64         `json:"from_id"`
	Date         int64         `json:"date"`
	Text         string        `json:"text"`
	ReplyOwnerID int64         `json:"reply_owner_id"`
	ReplyPostID  int64         `json:"reply_post_id"`
	FriendsOnly  int           `json:"friends_only"`
	Comments     *Comments     `json:"comments"`
	Likes        *Likes        `json:"likes"`
	Reposts      *Reposts      `json:"reposts"`
	Views        *Views        `json:"views"`
	PostType     string        `json:"post_type"`
	PostSource   *PostSource   `json:"post_source"`
	Attachments  *[]Attachment `json:"attachments"`
	Geo          *Geo          `json:"geo"`
	SingerID     int64         `json:"singer_id"`
	CopyHistory  *[]Wall       `json:"copy_history"`
	CanPin       int           `json:"can_pin"`
	CanDelete    int           `json:"can_delete"`
	CanEdit      int           `json:"can_edit"`
	IsPinned     int           `json:"is_pinned"`
	MarkedAsAds  int           `json:"marked_as_ads"`
}

func (client *Client) GetWall(dst Destination, count int64, offset int64, filter string, extended bool, fields ...string) (int64, []Wall, []Users, []Group, *Error) {
	values := url.Values{}
	switch {
	case dst.UserID != 0:
		values.Set("owner_id", ConcatInt64ToString(dst.UserID))
	case dst.GroupID != 0:
		values.Set("owner_id", ConcatInt64ToString(-dst.GroupID))
	case dst.Domain != "":
		values.Set("domain", dst.Domain)
	}

	values.Set("count", ConcatInt64ToString(count))
	values.Set("offset", ConcatInt64ToString(offset))
	values.Set("filter", filter)

	if extended {
		values.Set("extended", "1")
		values.Set("fields", strings.Join(fields, ","))
	}

	res, err := client.Do(NewRequest("wall.get", "", values))
	if err != nil {
		return 0, []Wall{}, []Users{}, []Group{}, err
	}

	Answer := struct {
		Count    int64   `json:"count"`
		Items    []Wall  `json:"items"`
		Profiles []Users `json:"profiles"`
		Groups   []Group `json:"groups"`
	}{}

	if err := res.To(&Answer); err != nil {
		return 0, []Wall{}, []Users{}, []Group{}, NewError(ErrBadCode, err.Error())
	}

	return Answer.Count, Answer.Items, Answer.Profiles, Answer.Groups, nil
}

type Comments struct {
	Count   int `json:"count"`
	CanPost int `json:"can_post"`
}

type Likes struct {
	Count      int `json:"count"`
	UserLikes  int `json:"user_likes"`
	CanLike    int `json:"can_like"`
	CanPublish int `json:"can_publish"`
}

type Reposts struct {
	Count        int `json:"count"`
	UserReposted int `json:"user_reposted"`
}

type Views struct {
	Count int `json:"count"`
}

type PostSource struct {
	Type     string `json:"type"`
	Platform string `json:"platform"`
	Data     string `json:"data"`
	URL      string `json:"url"`
}

type Geo struct {
	Type        string `json:"type"`
	Coordinates string `json:"coordinates"`
	Place       struct {
		ID         int64  `json:"id"`
		Title      string `json:"title"`
		Latitude   int    `json:"latitude"`
		Longitude  int    `json:"longitude"`
		Created    int64  `json:"created"`
		Icon       string `json:"icon"`
		Country    string `json:"country"`
		City       string `json:"city"`
		Type       int    `json:"type"`
		GroupID    int64  `json:"group_id"`
		GroupPhoto int64  `json:"group_photo"`
		Checkins   int64  `json:"checkins"`
		Updated    int64  `json:"updated"`
		Address    int64  `json:"address"`
	} `json:"place"`
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/organizations"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/helper/validation"
	"log"
)

func resourceAwsOrganization() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsOrganizationCreate,
		Read:   resourceAwsOrganizationRead,
		Delete: resourceAwsOrganizationDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"master_account_arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"master_account_email": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"master_account_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"feature_set": {
				Type:         schema.TypeString,
				Optional:     true,
				ForceNew:     true,
				Default:      organizations.OrganizationFeatureSetAll,
				ValidateFunc: validation.StringInSlice([]string{organizations.OrganizationFeatureSetAll, organizations.OrganizationFeatureSetConsolidatedBilling}, true),
			},
		},
	}
}

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

	createOpts := &organizations.CreateOrganizationInput{
		FeatureSet: aws.String(d.Get("feature_set").(string)),
	}
	log.Printf("[DEBUG] Creating Organization: %#v", createOpts)

	resp, err := conn.CreateOrganization(createOpts)
	if err != nil {
		return fmt.Errorf("Error creating organization: %s", err)
	}

	org := resp.Organization
	d.SetId(*org.Id)

	return resourceAwsOrganizationRead(d, meta)
}

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

	log.Printf("[INFO] Reading Organization: %s", d.Id())
	org, err := conn.DescribeOrganization(&organizations.DescribeOrganizationInput{})
	if err != nil {
		if isAWSErr(err, organizations.ErrCodeAWSOrganizationsNotInUseException, "") {
			log.Printf("[WARN] Organization does not exist, removing from state: %s", d.Id())
			d.SetId("")
			return nil
		}
		return err
	}

	d.Set("arn", org.Organization.Arn)
	d.Set("feature_set", org.Organization.FeatureSet)
	d.Set("master_account_arn", org.Organization.MasterAccountArn)
	d.Set("master_account_email", org.Organization.MasterAccountEmail)
	d.Set("master_account_id", org.Organization.MasterAccountId)
	return nil
}

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

	log.Printf("[INFO] Deleting Organization: %s", d.Id())

	_, err := conn.DeleteOrganization(&organizations.DeleteOrganizationInput{})
	if err != nil {
		return fmt.Errorf("Error deleting Organization: %s", err)
	}

	return nil
}
<commit_msg>Use goimports.<commit_after>package aws

import (
	"fmt"
	"log"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/organizations"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/helper/validation"
)

func resourceAwsOrganization() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsOrganizationCreate,
		Read:   resourceAwsOrganizationRead,
		Delete: resourceAwsOrganizationDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"master_account_arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"master_account_email": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"master_account_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"feature_set": {
				Type:         schema.TypeString,
				Optional:     true,
				ForceNew:     true,
				Default:      organizations.OrganizationFeatureSetAll,
				ValidateFunc: validation.StringInSlice([]string{organizations.OrganizationFeatureSetAll, organizations.OrganizationFeatureSetConsolidatedBilling}, true),
			},
		},
	}
}

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

	createOpts := &organizations.CreateOrganizationInput{
		FeatureSet: aws.String(d.Get("feature_set").(string)),
	}
	log.Printf("[DEBUG] Creating Organization: %#v", createOpts)

	resp, err := conn.CreateOrganization(createOpts)
	if err != nil {
		return fmt.Errorf("Error creating organization: %s", err)
	}

	org := resp.Organization
	d.SetId(*org.Id)

	return resourceAwsOrganizationRead(d, meta)
}

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

	log.Printf("[INFO] Reading Organization: %s", d.Id())
	org, err := conn.DescribeOrganization(&organizations.DescribeOrganizationInput{})
	if err != nil {
		if isAWSErr(err, organizations.ErrCodeAWSOrganizationsNotInUseException, "") {
			log.Printf("[WARN] Organization does not exist, removing from state: %s", d.Id())
			d.SetId("")
			return nil
		}
		return err
	}

	d.Set("arn", org.Organization.Arn)
	d.Set("feature_set", org.Organization.FeatureSet)
	d.Set("master_account_arn", org.Organization.MasterAccountArn)
	d.Set("master_account_email", org.Organization.MasterAccountEmail)
	d.Set("master_account_id", org.Organization.MasterAccountId)
	return nil
}

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

	log.Printf("[INFO] Deleting Organization: %s", d.Id())

	_, err := conn.DeleteOrganization(&organizations.DeleteOrganizationInput{})
	if err != nil {
		return fmt.Errorf("Error deleting Organization: %s", err)
	}

	return nil
}
<|endoftext|>