<commit_before>// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*
Package raft provides an implementation of the raft consensus algorithm.

Raft is a protocol by which a cluster of nodes can maintain a replicated state machine.
The state machine is kept in sync through the use of a replicated log.
For more details on Raft, you can read In Search of an Understandable Consensus Algorithm
(https://ramcloud.stanford.edu/raft.pdf) by Diego Ongaro and John Ousterhout.

Usage

The primary object in raft is a Node. You either start a Node from scratch
using raft.StartNode or start a Node from some initial state using raft.RestartNode.

To start a node from scratch:

  storage := raft.NewMemoryStorage()
  c := &Config{
    ID:              0x01,
    ElectionTick:    10,
    HeartbeatTick:   1,
    Storage:         storage,
    MaxSizePerMsg:   4096,
    MaxInflightMsgs: 256,
  }
  n := raft.StartNode(c, []raft.Peer{{ID: 0x02}, {ID: 0x03}})

To restart a node from previous state:

  storage := raft.NewMemoryStorage()

  // recover the in-memory storage from persistent
  // snapshot, state and entries.
  storage.ApplySnapshot(snapshot)
  storage.SetHardState(state)
  storage.Append(entries)

  c := &Config{
    ID:              0x01,
    ElectionTick:    10,
    HeartbeatTick:   1,
    Storage:         storage,
    MaxSizePerMsg:   4096,
    MaxInflightMsgs: 256,
  }

  // restart raft without peer information.
  // peer information is already included in the storage.
  n := raft.RestartNode(c)

Now that you are holding onto a Node you have a few responsibilities:

First, you must read from the Node.Ready() channel and process the updates
it contains. These steps may be performed in parallel, except as noted in step
2.

1. Write HardState, Entries, and Snapshot to persistent storage if they are
not empty. Note that when writing an Entry with Index i, any
previously-persisted entries with Index >= i must be discarded.

2. Send all Messages to the nodes named in the To field. It is important that
no messages be sent until after the latest HardState has been persisted to disk,
and all Entries written by any previous Ready batch (Messages may be sent while
entries from the same batch are being persisted). If any Message has type MsgSnap,
call Node.ReportSnapshot() after it has been sent (these messages may be large).

3. Apply Snapshot (if any) and CommittedEntries to the state machine.
If any committed Entry has Type EntryConfChange, call Node.ApplyConfChange()
to apply it to the node. The configuration change may be cancelled at this point
by setting the NodeID field to zero before calling ApplyConfChange
(but ApplyConfChange must be called one way or the other, and the decision to cancel
must be based solely on the state machine and not external information such as
the observed health of the node).

4. Call Node.Advance() to signal readiness for the next batch of updates.
This may be done at any time after step 1, although all updates must be processed
in the order they were returned by Ready.

Second, all persisted log entries must be made available via an
implementation of the Storage interface. The provided MemoryStorage
type can be used for this (if you repopulate its state upon a
restart), or you can supply your own disk-backed implementation.

Third, when you receive a message from another node, pass it to Node.Step:

	func recvRaftRPC(ctx context.Context, m raftpb.Message) {
		n.Step(ctx, m)
	}

Finally, you need to call Node.Tick() at regular intervals (probably
via a time.Ticker). Raft has two important timeouts: heartbeat and the
election timeout. However, internally to the raft package time is
represented by an abstract "tick".

The total state machine handling loop will look something like this:

  for {
    select {
    case <-s.Ticker:
      n.Tick()
    case rd := <-s.Node.Ready():
      saveToStorage(rd.State, rd.Entries, rd.Snapshot)
      send(rd.Messages)
      if !raft.IsEmptySnap(rd.Snapshot) {
        processSnapshot(rd.Snapshot)
      }
      for _, entry := range rd.CommittedEntries {
        process(entry)
        if entry.Type == raftpb.EntryConfChange {
          var cc raftpb.ConfChange
          cc.Unmarshal(entry.Data)
          s.Node.ApplyConfChange(cc)
        }
      s.Node.Advance()
    case <-s.done:
      return
    }
  }

To propose changes to the state machine from your node take your application
data, serialize it into a byte slice and call:

	n.Propose(ctx, data)

If the proposal is committed, data will appear in committed entries with type
raftpb.EntryNormal. There is no guarantee that a proposed command will be
committed; you may have to re-propose after a timeout.

To add or remove node in a cluster, build ConfChange struct 'cc' and call:

	n.ProposeConfChange(ctx, cc)

After config change is committed, some committed entry with type
raftpb.EntryConfChange will be returned. You must apply it to node through:

	var cc raftpb.ConfChange
	cc.Unmarshal(data)
	n.ApplyConfChange(cc)

Note: An ID represents a unique node in a cluster for all time. A
given ID MUST be used only once even if the old node has been removed.
This means that for example IP addresses make poor node IDs since they
may be reused. Node IDs must be non-zero.

Implementation notes

This implementation is up to date with the final Raft thesis
(https://ramcloud.stanford.edu/~ongaro/thesis.pdf), although our
implementation of the membership change protocol differs somewhat from
that described in chapter 4. The key invariant that membership changes
happen one node at a time is preserved, but in our implementation the
membership change takes effect when its entry is applied, not when it
is added to the log (so the entry is committed under the old
membership instead of the new). This is equivalent in terms of safety,
since the old and new configurations are guaranteed to overlap.

To ensure that we do not attempt to commit two membership changes at
once by matching log positions (which would be unsafe since they
should have different quorum requirements), we simply disallow any
proposed membership change while any uncommitted change appears in
the leader's log.

This approach introduces a problem when you try to remove a member
from a two-member cluster: If one of the members dies before the
other one receives the commit of the confchange entry, then the member
cannot be removed any more since the cluster cannot make progress.
For this reason it is highly recommended to use three or more nodes in
every cluster.

*/
package raft
<commit_msg>raft: add raftexample to the docs<commit_after>// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*
Package raft provides an implementation of the raft consensus algorithm.

Raft is a protocol by which a cluster of nodes can maintain a replicated state machine.
The state machine is kept in sync through the use of a replicated log.
For more details on Raft, you can read In Search of an Understandable Consensus Algorithm
(https://ramcloud.stanford.edu/raft.pdf) by Diego Ongaro and John Ousterhout.

A simple example application called, raftexample, is also avialable to help illustrate how to use this package in practice:
https://github.com/coreos/etcd/tree/master/contrib/raftexample

Usage

The primary object in raft is a Node. You either start a Node from scratch
using raft.StartNode or start a Node from some initial state using raft.RestartNode.

To start a node from scratch:

  storage := raft.NewMemoryStorage()
  c := &Config{
    ID:              0x01,
    ElectionTick:    10,
    HeartbeatTick:   1,
    Storage:         storage,
    MaxSizePerMsg:   4096,
    MaxInflightMsgs: 256,
  }
  n := raft.StartNode(c, []raft.Peer{{ID: 0x02}, {ID: 0x03}})

To restart a node from previous state:

  storage := raft.NewMemoryStorage()

  // recover the in-memory storage from persistent
  // snapshot, state and entries.
  storage.ApplySnapshot(snapshot)
  storage.SetHardState(state)
  storage.Append(entries)

  c := &Config{
    ID:              0x01,
    ElectionTick:    10,
    HeartbeatTick:   1,
    Storage:         storage,
    MaxSizePerMsg:   4096,
    MaxInflightMsgs: 256,
  }

  // restart raft without peer information.
  // peer information is already included in the storage.
  n := raft.RestartNode(c)

Now that you are holding onto a Node you have a few responsibilities:

First, you must read from the Node.Ready() channel and process the updates
it contains. These steps may be performed in parallel, except as noted in step
2.

1. Write HardState, Entries, and Snapshot to persistent storage if they are
not empty. Note that when writing an Entry with Index i, any
previously-persisted entries with Index >= i must be discarded.

2. Send all Messages to the nodes named in the To field. It is important that
no messages be sent until after the latest HardState has been persisted to disk,
and all Entries written by any previous Ready batch (Messages may be sent while
entries from the same batch are being persisted). If any Message has type MsgSnap,
call Node.ReportSnapshot() after it has been sent (these messages may be large).

3. Apply Snapshot (if any) and CommittedEntries to the state machine.
If any committed Entry has Type EntryConfChange, call Node.ApplyConfChange()
to apply it to the node. The configuration change may be cancelled at this point
by setting the NodeID field to zero before calling ApplyConfChange
(but ApplyConfChange must be called one way or the other, and the decision to cancel
must be based solely on the state machine and not external information such as
the observed health of the node).

4. Call Node.Advance() to signal readiness for the next batch of updates.
This may be done at any time after step 1, although all updates must be processed
in the order they were returned by Ready.

Second, all persisted log entries must be made available via an
implementation of the Storage interface. The provided MemoryStorage
type can be used for this (if you repopulate its state upon a
restart), or you can supply your own disk-backed implementation.

Third, when you receive a message from another node, pass it to Node.Step:

	func recvRaftRPC(ctx context.Context, m raftpb.Message) {
		n.Step(ctx, m)
	}

Finally, you need to call Node.Tick() at regular intervals (probably
via a time.Ticker). Raft has two important timeouts: heartbeat and the
election timeout. However, internally to the raft package time is
represented by an abstract "tick".

The total state machine handling loop will look something like this:

  for {
    select {
    case <-s.Ticker:
      n.Tick()
    case rd := <-s.Node.Ready():
      saveToStorage(rd.State, rd.Entries, rd.Snapshot)
      send(rd.Messages)
      if !raft.IsEmptySnap(rd.Snapshot) {
        processSnapshot(rd.Snapshot)
      }
      for _, entry := range rd.CommittedEntries {
        process(entry)
        if entry.Type == raftpb.EntryConfChange {
          var cc raftpb.ConfChange
          cc.Unmarshal(entry.Data)
          s.Node.ApplyConfChange(cc)
        }
      s.Node.Advance()
    case <-s.done:
      return
    }
  }

To propose changes to the state machine from your node take your application
data, serialize it into a byte slice and call:

	n.Propose(ctx, data)

If the proposal is committed, data will appear in committed entries with type
raftpb.EntryNormal. There is no guarantee that a proposed command will be
committed; you may have to re-propose after a timeout.

To add or remove node in a cluster, build ConfChange struct 'cc' and call:

	n.ProposeConfChange(ctx, cc)

After config change is committed, some committed entry with type
raftpb.EntryConfChange will be returned. You must apply it to node through:

	var cc raftpb.ConfChange
	cc.Unmarshal(data)
	n.ApplyConfChange(cc)

Note: An ID represents a unique node in a cluster for all time. A
given ID MUST be used only once even if the old node has been removed.
This means that for example IP addresses make poor node IDs since they
may be reused. Node IDs must be non-zero.

Implementation notes

This implementation is up to date with the final Raft thesis
(https://ramcloud.stanford.edu/~ongaro/thesis.pdf), although our
implementation of the membership change protocol differs somewhat from
that described in chapter 4. The key invariant that membership changes
happen one node at a time is preserved, but in our implementation the
membership change takes effect when its entry is applied, not when it
is added to the log (so the entry is committed under the old
membership instead of the new). This is equivalent in terms of safety,
since the old and new configurations are guaranteed to overlap.

To ensure that we do not attempt to commit two membership changes at
once by matching log positions (which would be unsafe since they
should have different quorum requirements), we simply disallow any
proposed membership change while any uncommitted change appears in
the leader's log.

This approach introduces a problem when you try to remove a member
from a two-member cluster: If one of the members dies before the
other one receives the commit of the confchange entry, then the member
cannot be removed any more since the cluster cannot make progress.
For this reason it is highly recommended to use three or more nodes in
every cluster.

*/
package raft
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/options"
	"v.io/v23/security"
	"v.io/v23/vdl"

	"mojom/v23proxy"

	"mojo/public/go/application"
	"mojo/public/go/bindings"
	"mojo/public/go/system"
	"mojo/public/interfaces/bindings/mojom_types"

	"v.io/x/mojo/transcoder"
	_ "v.io/x/ref/runtime/factories/static"
)

//#include "mojo/public/c/system/types.h"
import "C"

func init() {
	flag.String("child-connection-id", "", "")
	flag.String("mojo-platform-channel-handle", "", "")
}

type v23HeaderReceiver struct {
	delegate    *V23ServerDelegate
	v23Name     string
	ifaceSig    mojom_types.MojomInterface
	desc        map[string]mojom_types.UserDefinedType
	serviceName string
	handle      system.MessagePipeHandle
}

func (r *v23HeaderReceiver) SetupProxy(v23Name string, ifaceSig mojom_types.MojomInterface, desc map[string]mojom_types.UserDefinedType, serviceName string, handle system.MessagePipeHandle) (err error) {
	log.Printf("[server] In SetupProxy(%s, %v, %v, %s, %v)\n", v23Name, ifaceSig, desc, serviceName, handle)
	r.v23Name = v23Name
	r.ifaceSig = ifaceSig
	r.desc = desc
	r.serviceName = serviceName
	r.handle = handle

	go func() {
		connector := bindings.NewConnector(r.handle, bindings.GetAsyncWaiter())

		// Read generic calls in a loop
		stub := &genericStub{
			header:    r,
			ctx:       r.delegate.ctx,
			connector: connector,
		}
		bindingStub := bindings.NewStub(connector, stub)
		for {
			if err := bindingStub.ServeRequest(); err != nil {
				connectionError, ok := err.(*bindings.ConnectionError)
				if !ok || !connectionError.Closed() {
					log.Println(err)
				}
				break
			}
		}
		r.delegate.stubs = append(r.delegate.stubs, bindingStub)
	}()
	return nil
}

// TODO(alexfandrianto): This assumes that bindings.Encoder has the method
// WriteRawBytes. See the comment block below.
// type byteCopyingPayload []byte

// func (bcp byteCopyingPayload) Encode(encoder *bindings.Encoder) error {
// 	encoder.WriteRawBytes(bcp)
// 	return nil
// }

// func (bcp byteCopyingPayload) Decode(decoder *bindings.Decoder) error {
// 	panic("not supported")
// }

type genericStub struct {
	header    *v23HeaderReceiver
	ctx       *context.T
	connector *bindings.Connector
}

func (s *genericStub) Accept(message *bindings.Message) (err error) {
	if _, ok := s.header.ifaceSig.Methods[message.Header.Type]; !ok {
		return fmt.Errorf("Method had index %d, but interface only has %d methods",
			message.Header.Type, len(s.header.ifaceSig.Methods))
	}

	methodSig := s.header.ifaceSig.Methods[message.Header.Type]
	methodName := *methodSig.DeclData.ShortName
	// Should we perform validation of flags like generated methods?
	// Does this handle 0-arg methods?

	messageBytes := message.Payload

	response, err := s.Call(s.header.v23Name, methodName, messageBytes, methodSig.Parameters, methodSig.ResponseParams)
	if err != nil {
		return err
	}

	// TODO(alexfandrianto): This assumes that bindings.Encoder has the method
	// WriteRawBytes. We will need to add this to Mojo ourselves.
	// func (e *Encoder) WriteRawBytes(data []byte) {
	// 	first := e.end
	// 	e.claimData(align(len(data), defaultAlignment))
	// 	copy(e.buf[first:], data)
	// }
	//
	// See: https://codereview.chromium.org/1416433002/

	responseHeader := bindings.MessageHeader{
		Type:      message.Header.Type,
		Flags:     bindings.MessageIsResponseFlag,
		RequestId: message.Header.RequestId,
	}
	// responseMessage, err := bindings.EncodeMessage(responseHeader, byteCopyingPayload(response))
	// if err != nil {
	// 	return err
	// }
	// return s.connector.WriteMessage(responseMessage)

	// TODO(alexfandrianto): Replace this block with the above.
	encoder := bindings.NewEncoder()
	if err := responseHeader.Encode(encoder); err != nil {
		return err
	}
	if bytes, handles, err := encoder.Data(); err != nil {
		return err
	} else {
		// response is our payload; append to the end of our slice.
		bytes = append(bytes, response...)

		// This is analogous to bindings.newMessage
		responseMessage := &bindings.Message{
			Header:  responseHeader,
			Bytes:   bytes,
			Handles: handles,
			Payload: response,
		}
		return s.connector.WriteMessage(responseMessage)
	}
}

func (s *genericStub) Call(name, method string, value []byte, inParamsType mojom_types.MojomStruct, outParamsType *mojom_types.MojomStruct) ([]byte, error) {
	log.Printf("server: %s.%s: %#v", name, method, inParamsType)

	inVType := transcoder.MojomStructToVDLType(inParamsType, s.header.desc)
	var outVType *vdl.Type
	if outParamsType != nil {
		outVType = transcoder.MojomStructToVDLType(*outParamsType, s.header.desc)
	}

	// Decode the vdl.Value from the mojom bytes and mojom type.
	var inVdlValue *vdl.Value
	if err := transcoder.MojomToVdl(value, inVType, &inVdlValue); err != nil {
		return nil, fmt.Errorf("transcoder.MojoToVom failed: %v", err)
	}

	// inVdlValue is a struct, but we need to send []interface.
	inargs := splitVdlValueByMojomType(inVdlValue, inVType)
	inargsIfc := make([]interface{}, len(inargs))
	for i := range inargs {
		inargsIfc[i] = inargs[i]
	}

	// We know that the v23proxy (on the other side) will give us back a bunch of
	// data in []interface{}. so we'll want to decode them into *vdl.Value.
	log.Printf("%s %v\n", method, outParamsType)
	outargs := make([]*vdl.Value, len(outParamsType.Fields))
	outptrs := make([]interface{}, len(outargs))
	for i := range outargs {
		outptrs[i] = &outargs[i]
	}

	// Now, run the call without any authorization.
	if err := v23.GetClient(s.ctx).Call(s.ctx, name, method, inargsIfc, outptrs, options.ServerAuthorizer{security.AllowEveryone()}); err != nil {
		return nil, err
	}

	// Now convert the []interface{} into a *vdl.Value (struct).
	outVdlValue := combineVdlValueByMojomType(outargs, outVType)

	// Finally, encode this *vdl.Value (struct) into mojom bytes and send the response.
	result, err := transcoder.VdlToMojom(outVdlValue)
	if err != nil {
		return nil, fmt.Errorf("transcoder.Encode failed: %v", err)
	}
	return result, nil
}

type V23ServerDelegate struct {
	ctx      *context.T
	stubs    []*bindings.Stub
	shutdown v23.Shutdown
}

func (delegate *V23ServerDelegate) Initialize(context application.Context) {
	log.Printf("V23ServerDelegate.Initialize...")

	// Start up v23 whenever a v23proxy is begun.
	// This is done regardless of whether we are initializing this v23proxy for use
	// as a client or as a server.
	ctx, shutdown := v23.Init()
	delegate.ctx = ctx
	delegate.shutdown = shutdown

	// TODO(alexfandrianto): Does Mojo stop us from creating too many v23proxy?
	// Is it 1 per shell? Ideally, each device will only serve 1 of these v23proxy,
	// but it is not problematic to have extra.
	/*s := MakeServer(ctx)
	err := s.ServeDispatcher("", &V23ProxyDispatcher{
		appctx: context,
	})*/
	_, s, err := v23.WithNewDispatchingServer(ctx, "", &V23ProxyDispatcher{
		appctx: context,
	})
	if err != nil {
		log.Panic("Error serving service: ", err)
	}

	endpoints := s.Status().Endpoints
	fmt.Printf("Listening at: /%v\n", endpoints[0])
}

/*func MakeServer(ctx *context.T) rpc.Server {
	s, err := v23.NewServer(ctx)
	if err != nil {
		log.Panic("Failure creating server: ", err)
	}

	endpoints, err := s.Listen(v23.GetListenSpec(ctx))
	if err != nil {
		log.Panic("Error listening to service: ", err)
	}
	fmt.Printf("Listening at: /%v\n", endpoints[0])
	return s
}*/

type V23ProxyDispatcher struct {
	appctx application.Context
}

func (v23pd *V23ProxyDispatcher) Lookup(ctx *context.T, suffix string) (interface{}, security.Authorizer, error) {
	log.Printf("Dispatcher: %s", suffix)
	return fakeService{
		appctx: v23pd.appctx,
		suffix: suffix,
		ids:    bindings.NewCounter(),
	}, security.AllowEveryone(), nil
}

func (delegate *V23ServerDelegate) Create(request v23proxy.V23_Request) {
	headerReceiver := &v23HeaderReceiver{delegate: delegate}
	v23Stub := v23proxy.NewV23Stub(request, headerReceiver, bindings.GetAsyncWaiter())
	delegate.stubs = append(delegate.stubs, v23Stub)

	go func() {
		// Read header message
		if err := v23Stub.ServeRequest(); err != nil {
			connectionError, ok := err.(*bindings.ConnectionError)
			if !ok || !connectionError.Closed() {
				log.Println(err)
			}
			return
		}
	}()
}

func (delegate *V23ServerDelegate) AcceptConnection(connection *application.Connection) {
	log.Printf("V23ServerDelegate.AcceptConnection...")
	connection.ProvideServices(&v23proxy.V23_ServiceFactory{delegate})
}

func (delegate *V23ServerDelegate) Quit() {
	log.Printf("V23ServerDelegate.Quit...")
	for _, stub := range delegate.stubs {
		stub.Close()
	}

	delegate.shutdown()
}

//export MojoMain
func MojoMain(handle C.MojoHandle) C.MojoResult {
	application.Run(&V23ServerDelegate{}, system.MojoHandle(handle))
	return C.MOJO_RESULT_OK
}

func main() {
}
<commit_msg>mojo/v23proxy: : v.io/c/17574 follow up<commit_after>package main

import (
	"fmt"
	"log"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/options"
	"v.io/v23/security"
	"v.io/v23/vdl"

	"mojom/v23proxy"

	"mojo/public/go/application"
	"mojo/public/go/bindings"
	"mojo/public/go/system"
	"mojo/public/interfaces/bindings/mojom_types"

	"v.io/x/mojo/transcoder"
	_ "v.io/x/ref/runtime/factories/static"
)

//#include "mojo/public/c/system/types.h"
import "C"

type v23HeaderReceiver struct {
	delegate    *V23ServerDelegate
	v23Name     string
	ifaceSig    mojom_types.MojomInterface
	desc        map[string]mojom_types.UserDefinedType
	serviceName string
	handle      system.MessagePipeHandle
}

func (r *v23HeaderReceiver) SetupProxy(v23Name string, ifaceSig mojom_types.MojomInterface, desc map[string]mojom_types.UserDefinedType, serviceName string, handle system.MessagePipeHandle) (err error) {
	log.Printf("[server] In SetupProxy(%s, %v, %v, %s, %v)\n", v23Name, ifaceSig, desc, serviceName, handle)
	r.v23Name = v23Name
	r.ifaceSig = ifaceSig
	r.desc = desc
	r.serviceName = serviceName
	r.handle = handle

	go func() {
		connector := bindings.NewConnector(r.handle, bindings.GetAsyncWaiter())

		// Read generic calls in a loop
		stub := &genericStub{
			header:    r,
			ctx:       r.delegate.ctx,
			connector: connector,
		}
		bindingStub := bindings.NewStub(connector, stub)
		for {
			if err := bindingStub.ServeRequest(); err != nil {
				connectionError, ok := err.(*bindings.ConnectionError)
				if !ok || !connectionError.Closed() {
					log.Println(err)
				}
				break
			}
		}
		r.delegate.stubs = append(r.delegate.stubs, bindingStub)
	}()
	return nil
}

// TODO(alexfandrianto): This assumes that bindings.Encoder has the method
// WriteRawBytes. See the comment block below.
// type byteCopyingPayload []byte

// func (bcp byteCopyingPayload) Encode(encoder *bindings.Encoder) error {
// 	encoder.WriteRawBytes(bcp)
// 	return nil
// }

// func (bcp byteCopyingPayload) Decode(decoder *bindings.Decoder) error {
// 	panic("not supported")
// }

type genericStub struct {
	header    *v23HeaderReceiver
	ctx       *context.T
	connector *bindings.Connector
}

func (s *genericStub) Accept(message *bindings.Message) (err error) {
	if _, ok := s.header.ifaceSig.Methods[message.Header.Type]; !ok {
		return fmt.Errorf("Method had index %d, but interface only has %d methods",
			message.Header.Type, len(s.header.ifaceSig.Methods))
	}

	methodSig := s.header.ifaceSig.Methods[message.Header.Type]
	methodName := *methodSig.DeclData.ShortName
	// Should we perform validation of flags like generated methods?
	// Does this handle 0-arg methods?

	messageBytes := message.Payload

	response, err := s.Call(s.header.v23Name, methodName, messageBytes, methodSig.Parameters, methodSig.ResponseParams)
	if err != nil {
		return err
	}

	// TODO(alexfandrianto): This assumes that bindings.Encoder has the method
	// WriteRawBytes. We will need to add this to Mojo ourselves.
	// func (e *Encoder) WriteRawBytes(data []byte) {
	// 	first := e.end
	// 	e.claimData(align(len(data), defaultAlignment))
	// 	copy(e.buf[first:], data)
	// }
	//
	// See: https://codereview.chromium.org/1416433002/

	responseHeader := bindings.MessageHeader{
		Type:      message.Header.Type,
		Flags:     bindings.MessageIsResponseFlag,
		RequestId: message.Header.RequestId,
	}
	// responseMessage, err := bindings.EncodeMessage(responseHeader, byteCopyingPayload(response))
	// if err != nil {
	// 	return err
	// }
	// return s.connector.WriteMessage(responseMessage)

	// TODO(alexfandrianto): Replace this block with the above.
	encoder := bindings.NewEncoder()
	if err := responseHeader.Encode(encoder); err != nil {
		return err
	}
	if bytes, handles, err := encoder.Data(); err != nil {
		return err
	} else {
		// response is our payload; append to the end of our slice.
		bytes = append(bytes, response...)

		// This is analogous to bindings.newMessage
		responseMessage := &bindings.Message{
			Header:  responseHeader,
			Bytes:   bytes,
			Handles: handles,
			Payload: response,
		}
		return s.connector.WriteMessage(responseMessage)
	}
}

func (s *genericStub) Call(name, method string, value []byte, inParamsType mojom_types.MojomStruct, outParamsType *mojom_types.MojomStruct) ([]byte, error) {
	log.Printf("server: %s.%s: %#v", name, method, inParamsType)

	inVType := transcoder.MojomStructToVDLType(inParamsType, s.header.desc)
	var outVType *vdl.Type
	if outParamsType != nil {
		outVType = transcoder.MojomStructToVDLType(*outParamsType, s.header.desc)
	}

	// Decode the vdl.Value from the mojom bytes and mojom type.
	var inVdlValue *vdl.Value
	if err := transcoder.MojomToVdl(value, inVType, &inVdlValue); err != nil {
		return nil, fmt.Errorf("transcoder.MojoToVom failed: %v", err)
	}

	// inVdlValue is a struct, but we need to send []interface.
	inargs := splitVdlValueByMojomType(inVdlValue, inVType)
	inargsIfc := make([]interface{}, len(inargs))
	for i := range inargs {
		inargsIfc[i] = inargs[i]
	}

	// We know that the v23proxy (on the other side) will give us back a bunch of
	// data in []interface{}. so we'll want to decode them into *vdl.Value.
	log.Printf("%s %v\n", method, outParamsType)
	outargs := make([]*vdl.Value, len(outParamsType.Fields))
	outptrs := make([]interface{}, len(outargs))
	for i := range outargs {
		outptrs[i] = &outargs[i]
	}

	// Now, run the call without any authorization.
	if err := v23.GetClient(s.ctx).Call(s.ctx, name, method, inargsIfc, outptrs, options.ServerAuthorizer{security.AllowEveryone()}); err != nil {
		return nil, err
	}

	// Now convert the []interface{} into a *vdl.Value (struct).
	outVdlValue := combineVdlValueByMojomType(outargs, outVType)

	// Finally, encode this *vdl.Value (struct) into mojom bytes and send the response.
	result, err := transcoder.VdlToMojom(outVdlValue)
	if err != nil {
		return nil, fmt.Errorf("transcoder.Encode failed: %v", err)
	}
	return result, nil
}

type V23ServerDelegate struct {
	ctx      *context.T
	stubs    []*bindings.Stub
	shutdown v23.Shutdown
}

func (delegate *V23ServerDelegate) Initialize(context application.Context) {
	log.Printf("V23ServerDelegate.Initialize...")

	// Start up v23 whenever a v23proxy is begun.
	// This is done regardless of whether we are initializing this v23proxy for use
	// as a client or as a server.
	ctx, shutdown := v23.Init(context)
	delegate.ctx = ctx
	delegate.shutdown = shutdown

	// TODO(alexfandrianto): Does Mojo stop us from creating too many v23proxy?
	// Is it 1 per shell? Ideally, each device will only serve 1 of these v23proxy,
	// but it is not problematic to have extra.
	/*s := MakeServer(ctx)
	err := s.ServeDispatcher("", &V23ProxyDispatcher{
		appctx: context,
	})*/
	_, s, err := v23.WithNewDispatchingServer(ctx, "", &V23ProxyDispatcher{
		appctx: context,
	})
	if err != nil {
		log.Panic("Error serving service: ", err)
	}

	endpoints := s.Status().Endpoints
	fmt.Printf("Listening at: /%v\n", endpoints[0])
}

/*func MakeServer(ctx *context.T) rpc.Server {
	s, err := v23.NewServer(ctx)
	if err != nil {
		log.Panic("Failure creating server: ", err)
	}

	endpoints, err := s.Listen(v23.GetListenSpec(ctx))
	if err != nil {
		log.Panic("Error listening to service: ", err)
	}
	fmt.Printf("Listening at: /%v\n", endpoints[0])
	return s
}*/

type V23ProxyDispatcher struct {
	appctx application.Context
}

func (v23pd *V23ProxyDispatcher) Lookup(ctx *context.T, suffix string) (interface{}, security.Authorizer, error) {
	log.Printf("Dispatcher: %s", suffix)
	return fakeService{
		appctx: v23pd.appctx,
		suffix: suffix,
		ids:    bindings.NewCounter(),
	}, security.AllowEveryone(), nil
}

func (delegate *V23ServerDelegate) Create(request v23proxy.V23_Request) {
	headerReceiver := &v23HeaderReceiver{delegate: delegate}
	v23Stub := v23proxy.NewV23Stub(request, headerReceiver, bindings.GetAsyncWaiter())
	delegate.stubs = append(delegate.stubs, v23Stub)

	go func() {
		// Read header message
		if err := v23Stub.ServeRequest(); err != nil {
			connectionError, ok := err.(*bindings.ConnectionError)
			if !ok || !connectionError.Closed() {
				log.Println(err)
			}
			return
		}
	}()
}

func (delegate *V23ServerDelegate) AcceptConnection(connection *application.Connection) {
	log.Printf("V23ServerDelegate.AcceptConnection...")
	connection.ProvideServices(&v23proxy.V23_ServiceFactory{delegate})
}

func (delegate *V23ServerDelegate) Quit() {
	log.Printf("V23ServerDelegate.Quit...")
	for _, stub := range delegate.stubs {
		stub.Close()
	}

	delegate.shutdown()
}

//export MojoMain
func MojoMain(handle C.MojoHandle) C.MojoResult {
	application.Run(&V23ServerDelegate{}, system.MojoHandle(handle))
	return C.MOJO_RESULT_OK
}

func main() {
}
<|endoftext|>


<commit_before>// Copyright 2017 The casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package casbin

import (
	"github.com/casbin/casbin/v2/errors"
	"github.com/casbin/casbin/v2/util"
)

// GetRolesForUser gets the roles that a user has.
func (e *Enforcer) GetRolesForUser(name string, domain ...string) ([]string, error) {
	res, err := e.model["g"]["g"].RM.GetRoles(name, domain...)
	return res, err
}

// GetUsersForRole gets the users that has a role.
func (e *Enforcer) GetUsersForRole(name string, domain ...string) ([]string, error) {
	res, err := e.model["g"]["g"].RM.GetUsers(name, domain...)
	return res, err
}

// HasRoleForUser determines whether a user has a role.
func (e *Enforcer) HasRoleForUser(name string, role string, domain ...string) (bool, error) {
	roles, err := e.GetRolesForUser(name,domain ...)
	if err != nil {
		return false, err
	}
	hasRole := false
	for _, r := range roles {
		if r == role {
			hasRole = true
			break
		}
	}

	return hasRole, nil
}

// AddRoleForUser adds a role for a user.
// Returns false if the user already has the role (aka not affected).
func (e *Enforcer) AddRoleForUser(user string, role string, domain ...string) (bool, error) {
	if len(domain) ==0 {
		return e.AddGroupingPolicy(user, role)
	}else if len(domain) > 1 {
		return false, errors.ERR_DOMAIN_PARAMETER
	}
	return e.AddGroupingPolicy(user, role, domain[0])
}

// AddRolesForUser adds roles for a user.
// Returns false if the user already has the roles (aka not affected).
func (e *Enforcer) AddRolesForUser(user string, roles []string) (bool, error) {
	f := false
	for _, r := range roles {
		b, err := e.AddGroupingPolicy(user, r)
		if err != nil {
			return false, err
		}
		if b {
			f = true
		}
	}
	return f, nil
}

// DeleteRoleForUser deletes a role for a user.
// Returns false if the user does not have the role (aka not affected).
func (e *Enforcer) DeleteRoleForUser(user string, role string) (bool, error) {
	return e.RemoveGroupingPolicy(user, role)
}

// DeleteRolesForUser deletes all roles for a user.
// Returns false if the user does not have any roles (aka not affected).
func (e *Enforcer) DeleteRolesForUser(user string) (bool, error) {
	return e.RemoveFilteredGroupingPolicy(0, user)
}

// DeleteUser deletes a user.
// Returns false if the user does not exist (aka not affected).
func (e *Enforcer) DeleteUser(user string) (bool, error) {
	var err error
	res1, err := e.RemoveFilteredGroupingPolicy(0, user)
	if err != nil {
		return res1, err
	}

	res2, err := e.RemoveFilteredPolicy(0, user)
	return res1 || res2, err
}

// DeleteRole deletes a role.
// Returns false if the role does not exist (aka not affected).
func (e *Enforcer) DeleteRole(role string) (bool, error) {
	var err error
	res1, err := e.RemoveFilteredGroupingPolicy(1, role)
	if err != nil {
		return res1, err
	}

	res2, err := e.RemoveFilteredPolicy(0, role)
	return res1 || res2, err
}

// DeletePermission deletes a permission.
// Returns false if the permission does not exist (aka not affected).
func (e *Enforcer) DeletePermission(permission ...string) (bool, error) {
	return e.RemoveFilteredPolicy(1, permission...)
}

// AddPermissionForUser adds a permission for a user or role.
// Returns false if the user or role already has the permission (aka not affected).
func (e *Enforcer) AddPermissionForUser(user string, permission ...string) (bool, error) {
	return e.AddPolicy(util.JoinSlice(user, permission...))
}

// DeletePermissionForUser deletes a permission for a user or role.
// Returns false if the user or role does not have the permission (aka not affected).
func (e *Enforcer) DeletePermissionForUser(user string, permission ...string) (bool, error) {
	return e.RemovePolicy(util.JoinSlice(user, permission...))
}

// DeletePermissionsForUser deletes permissions for a user or role.
// Returns false if the user or role does not have any permissions (aka not affected).
func (e *Enforcer) DeletePermissionsForUser(user string) (bool, error) {
	return e.RemoveFilteredPolicy(0, user)
}

// GetPermissionsForUser gets permissions for a user or role.
func (e *Enforcer) GetPermissionsForUser(user string) [][]string {
	return e.GetFilteredPolicy(0, user)
}

// HasPermissionForUser determines whether a user has a permission.
func (e *Enforcer) HasPermissionForUser(user string, permission ...string) bool {
	return e.HasPolicy(util.JoinSlice(user, permission...))
}

// GetImplicitRolesForUser gets implicit roles that a user has.
// Compared to GetRolesForUser(), this function retrieves indirect roles besides direct roles.
// For example:
// g, alice, role:admin
// g, role:admin, role:user
//
// GetRolesForUser("alice") can only get: ["role:admin"].
// But GetImplicitRolesForUser("alice") will get: ["role:admin", "role:user"].
func (e *Enforcer) GetImplicitRolesForUser(name string, domain ...string) ([]string, error) {
	res := []string{}
	roleSet := make(map[string]bool)
	roleSet[name] = true

	q := make([]string, 0)
	q = append(q, name)

	for len(q) > 0 {
		name := q[0]
		q = q[1:]

		roles, err := e.rm.GetRoles(name, domain...)
		if err != nil {
			return nil, err
		}
		for _, r := range roles {
			if _, ok := roleSet[r]; !ok {
				res = append(res, r)
				q = append(q, r)
				roleSet[r] = true
			}
		}
	}

	return res, nil
}

// GetImplicitPermissionsForUser gets implicit permissions for a user or role.
// Compared to GetPermissionsForUser(), this function retrieves permissions for inherited roles.
// For example:
// p, admin, data1, read
// p, alice, data2, read
// g, alice, admin
//
// GetPermissionsForUser("alice") can only get: [["alice", "data2", "read"]].
// But GetImplicitPermissionsForUser("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]].
func (e *Enforcer) GetImplicitPermissionsForUser(user string, domain ...string) ([][]string, error) {
	roles, err := e.GetImplicitRolesForUser(user, domain...)
	if err != nil {
		return nil, err
	}

	roles = append([]string{user}, roles...)

	withDomain := false
	if len(domain) == 1 {
		withDomain = true
	} else if len(domain) > 1 {
		return nil, errors.ERR_DOMAIN_PARAMETER
	}

	var res [][]string
	var permissions [][]string
	for _, role := range roles {
		if withDomain {
			permissions = e.GetPermissionsForUserInDomain(role, domain[0])
		} else {
			permissions = e.GetPermissionsForUser(role)
		}
		res = append(res, permissions...)
	}

	return res, nil
}

// GetImplicitUsersForPermission gets implicit users for a permission.
// For example:
// p, admin, data1, read
// p, bob, data1, read
// g, alice, admin
//
// GetImplicitUsersForPermission("data1", "read") will get: ["alice", "bob"].
// Note: only users will be returned, roles (2nd arg in "g") will be excluded.
func (e *Enforcer) GetImplicitUsersForPermission(permission ...string) ([]string, error) {
	pSubjects := e.GetAllSubjects()
	gInherit := e.model.GetValuesForFieldInPolicyAllTypes("g", 1)
	gSubjects := e.model.GetValuesForFieldInPolicyAllTypes("g", 0)

	subjects := append(pSubjects, gSubjects...)
	util.ArrayRemoveDuplicates(&subjects)

	res := []string{}
	for _, user := range subjects {
		req := util.JoinSliceAny(user, permission...)
		allowed, err := e.Enforce(req...)
		if err != nil {
			return nil, err
		}

		if allowed {
			res = append(res, user)
		}
	}

	res = util.SetSubtract(res, gInherit)

	return res, nil
}
<commit_msg>feat: Add domain in AddRolesForUser<commit_after>// Copyright 2017 The casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package casbin

import (
	"github.com/casbin/casbin/v2/errors"
	"github.com/casbin/casbin/v2/util"
)

// GetRolesForUser gets the roles that a user has.
func (e *Enforcer) GetRolesForUser(name string, domain ...string) ([]string, error) {
	res, err := e.model["g"]["g"].RM.GetRoles(name, domain...)
	return res, err
}

// GetUsersForRole gets the users that has a role.
func (e *Enforcer) GetUsersForRole(name string, domain ...string) ([]string, error) {
	res, err := e.model["g"]["g"].RM.GetUsers(name, domain...)
	return res, err
}

// HasRoleForUser determines whether a user has a role.
func (e *Enforcer) HasRoleForUser(name string, role string, domain ...string) (bool, error) {
	roles, err := e.GetRolesForUser(name,domain ...)
	if err != nil {
		return false, err
	}
	hasRole := false
	for _, r := range roles {
		if r == role {
			hasRole = true
			break
		}
	}

	return hasRole, nil
}

// AddRoleForUser adds a role for a user.
// Returns false if the user already has the role (aka not affected).
func (e *Enforcer) AddRoleForUser(user string, role string, domain ...string) (bool, error) {
	if len(domain) ==0 {
		return e.AddGroupingPolicy(user, role)
	}else if len(domain) > 1 {
		return false, errors.ERR_DOMAIN_PARAMETER
	}
	return e.AddGroupingPolicy(user, role, domain[0])
}

// AddRolesForUser adds roles for a user.
// Returns false if the user already has the roles (aka not affected).
func (e *Enforcer) AddRolesForUser(user string, roles []string, domain ...string) (bool, error) {
	f := false
	if len(domain) == 0 {
		for _, r := range roles {
			b, err := e.AddGroupingPolicy(user, r)
			if err != nil {
				return false, err
			}
			if b {
				f = true
			}
		}
	}else if len(domain) > 1 {
		return false,errors.ERR_DOMAIN_PARAMETER
	}else {
		for _, r := range roles {
			b, err := e.AddGroupingPolicy(user, r, domain[0])
			if err != nil {
				return false, err
			}
			if b {
				f = true
			}
		}
	}
	return f, nil
}

// DeleteRoleForUser deletes a role for a user.
// Returns false if the user does not have the role (aka not affected).
func (e *Enforcer) DeleteRoleForUser(user string, role string) (bool, error) {
	return e.RemoveGroupingPolicy(user, role)
}

// DeleteRolesForUser deletes all roles for a user.
// Returns false if the user does not have any roles (aka not affected).
func (e *Enforcer) DeleteRolesForUser(user string) (bool, error) {
	return e.RemoveFilteredGroupingPolicy(0, user)
}

// DeleteUser deletes a user.
// Returns false if the user does not exist (aka not affected).
func (e *Enforcer) DeleteUser(user string) (bool, error) {
	var err error
	res1, err := e.RemoveFilteredGroupingPolicy(0, user)
	if err != nil {
		return res1, err
	}

	res2, err := e.RemoveFilteredPolicy(0, user)
	return res1 || res2, err
}

// DeleteRole deletes a role.
// Returns false if the role does not exist (aka not affected).
func (e *Enforcer) DeleteRole(role string) (bool, error) {
	var err error
	res1, err := e.RemoveFilteredGroupingPolicy(1, role)
	if err != nil {
		return res1, err
	}

	res2, err := e.RemoveFilteredPolicy(0, role)
	return res1 || res2, err
}

// DeletePermission deletes a permission.
// Returns false if the permission does not exist (aka not affected).
func (e *Enforcer) DeletePermission(permission ...string) (bool, error) {
	return e.RemoveFilteredPolicy(1, permission...)
}

// AddPermissionForUser adds a permission for a user or role.
// Returns false if the user or role already has the permission (aka not affected).
func (e *Enforcer) AddPermissionForUser(user string, permission ...string) (bool, error) {
	return e.AddPolicy(util.JoinSlice(user, permission...))
}

// DeletePermissionForUser deletes a permission for a user or role.
// Returns false if the user or role does not have the permission (aka not affected).
func (e *Enforcer) DeletePermissionForUser(user string, permission ...string) (bool, error) {
	return e.RemovePolicy(util.JoinSlice(user, permission...))
}

// DeletePermissionsForUser deletes permissions for a user or role.
// Returns false if the user or role does not have any permissions (aka not affected).
func (e *Enforcer) DeletePermissionsForUser(user string) (bool, error) {
	return e.RemoveFilteredPolicy(0, user)
}

// GetPermissionsForUser gets permissions for a user or role.
func (e *Enforcer) GetPermissionsForUser(user string) [][]string {
	return e.GetFilteredPolicy(0, user)
}

// HasPermissionForUser determines whether a user has a permission.
func (e *Enforcer) HasPermissionForUser(user string, permission ...string) bool {
	return e.HasPolicy(util.JoinSlice(user, permission...))
}

// GetImplicitRolesForUser gets implicit roles that a user has.
// Compared to GetRolesForUser(), this function retrieves indirect roles besides direct roles.
// For example:
// g, alice, role:admin
// g, role:admin, role:user
//
// GetRolesForUser("alice") can only get: ["role:admin"].
// But GetImplicitRolesForUser("alice") will get: ["role:admin", "role:user"].
func (e *Enforcer) GetImplicitRolesForUser(name string, domain ...string) ([]string, error) {
	res := []string{}
	roleSet := make(map[string]bool)
	roleSet[name] = true

	q := make([]string, 0)
	q = append(q, name)

	for len(q) > 0 {
		name := q[0]
		q = q[1:]

		roles, err := e.rm.GetRoles(name, domain...)
		if err != nil {
			return nil, err
		}
		for _, r := range roles {
			if _, ok := roleSet[r]; !ok {
				res = append(res, r)
				q = append(q, r)
				roleSet[r] = true
			}
		}
	}

	return res, nil
}

// GetImplicitPermissionsForUser gets implicit permissions for a user or role.
// Compared to GetPermissionsForUser(), this function retrieves permissions for inherited roles.
// For example:
// p, admin, data1, read
// p, alice, data2, read
// g, alice, admin
//
// GetPermissionsForUser("alice") can only get: [["alice", "data2", "read"]].
// But GetImplicitPermissionsForUser("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]].
func (e *Enforcer) GetImplicitPermissionsForUser(user string, domain ...string) ([][]string, error) {
	roles, err := e.GetImplicitRolesForUser(user, domain...)
	if err != nil {
		return nil, err
	}

	roles = append([]string{user}, roles...)

	withDomain := false
	if len(domain) == 1 {
		withDomain = true
	} else if len(domain) > 1 {
		return nil, errors.ERR_DOMAIN_PARAMETER
	}

	var res [][]string
	var permissions [][]string
	for _, role := range roles {
		if withDomain {
			permissions = e.GetPermissionsForUserInDomain(role, domain[0])
		} else {
			permissions = e.GetPermissionsForUser(role)
		}
		res = append(res, permissions...)
	}

	return res, nil
}

// GetImplicitUsersForPermission gets implicit users for a permission.
// For example:
// p, admin, data1, read
// p, bob, data1, read
// g, alice, admin
//
// GetImplicitUsersForPermission("data1", "read") will get: ["alice", "bob"].
// Note: only users will be returned, roles (2nd arg in "g") will be excluded.
func (e *Enforcer) GetImplicitUsersForPermission(permission ...string) ([]string, error) {
	pSubjects := e.GetAllSubjects()
	gInherit := e.model.GetValuesForFieldInPolicyAllTypes("g", 1)
	gSubjects := e.model.GetValuesForFieldInPolicyAllTypes("g", 0)

	subjects := append(pSubjects, gSubjects...)
	util.ArrayRemoveDuplicates(&subjects)

	res := []string{}
	for _, user := range subjects {
		req := util.JoinSliceAny(user, permission...)
		allowed, err := e.Enforce(req...)
		if err != nil {
			return nil, err
		}

		if allowed {
			res = append(res, user)
		}
	}

	res = util.SetSubtract(res, gInherit)

	return res, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
)

func main() {
	if len(os.Args) == 1 {
		fmt.Println("bad args")
		return
	}
}
<commit_msg>Read hand and start card from command line<commit_after>package main

import (
	"fmt"
	"os"
	"strconv"
)

func main() {
	if len(os.Args) == 1 {
		fmt.Println("bad args")
		return
	}
	handRaw := make([]string, len(os.Args)-1)
	copy(handRaw, os.Args[1:])

	startCard := Card{
		suit: ToSuit(pop(&handRaw)),
		rank: ToRank(pop(&handRaw)),
	}

	var hand Hand
	for len(handRaw) > 0 {
		hand = append(hand, Card{
			suit: ToSuit(pop(&handRaw)),
			rank: ToRank(pop(&handRaw)),
		})
	}
	fmt.Println(startCard)
	fmt.Println(hand)

}

type Hand []Card

func (h Hand) Len() int           { return len(h) }
func (h Hand) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
func (h Hand) Less(i, j int) bool { return h[i].rank < h[j].rank }

func (h Hand) String() string {
	var ret string
	for _, c := range h {
		ret += c.String() + " "
	}
	return ret
}

type Card struct {
	rank Rank
	suit Suit
}

func (c Card) String() string {
	return fmt.Sprintf("%v%v", c.rank, c.suit)
}

type Rank int

func (r Rank) String() string {
	switch r {
	case 13:
		return "K"
	case 12:
		return "Q"
	case 11:
		return "J"
	default:
		return strconv.Itoa(int(r))
	}
}

func ToRank(a string) Rank {
	r, err := strconv.Atoi(a)
	if err != nil {
		panic(err)
	}
	return Rank(r)
}

type Suit byte

func (s Suit) String() string {
	return string([]byte{byte(s)})
}

func ToSuit(a string) Suit {
	return Suit(a[0])
}

func pop(a *[]string) string {
	val := (*a)[len(*a)-1]
	*a = (*a)[:len(*a)-1]
	return val
}
<|endoftext|>


<commit_before>package instance

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

	"github.com/hashicorp/packer/packer"
)

func testConfig() map[string]interface{} {
	tf, err := ioutil.TempFile("", "packer")
	if err != nil {
		panic(err)
	}

	return map[string]interface{}{
		"account_id":       "foo",
		"ami_name":         "foo",
		"instance_type":    "m1.small",
		"region":           "us-east-1",
		"s3_bucket":        "foo",
		"source_ami":       "foo",
		"ssh_username":     "bob",
		"x509_cert_path":   tf.Name(),
		"x509_key_path":    tf.Name(),
		"x509_upload_path": "/foo",
	}
}

func TestBuilder_ImplementsBuilder(t *testing.T) {
	var raw interface{}
	raw = &Builder{}
	if _, ok := raw.(packer.Builder); !ok {
		t.Fatalf("Builder should be a builder")
	}
}

func TestBuilderPrepare_AccountId(t *testing.T) {
	b := &Builder{}
	config := testConfig()

	config["account_id"] = ""
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	config["account_id"] = "foo"
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Errorf("err: %s", err)
	}

	config["account_id"] = "0123-0456-7890"
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	if b.config.AccountId != "012304567890" {
		t.Errorf("should strip hyphens: %s", b.config.AccountId)
	}
}

func TestBuilderPrepare_AMIName(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test good
	config["ami_name"] = "foo"
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	// Test bad
	config["ami_name"] = "foo {{"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	// Test bad
	delete(config, "ami_name")
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}
}

func TestBuilderPrepare_BundleDestination(t *testing.T) {
	b := &Builder{}
	config := testConfig()

	config["bundle_destination"] = ""
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	if b.config.BundleDestination != "/tmp" {
		t.Fatalf("bad: %s", b.config.BundleDestination)
	}
}

func TestBuilderPrepare_BundlePrefix(t *testing.T) {
	b := &Builder{}
	config := testConfig()

	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	if b.config.BundlePrefix == "" {
		t.Fatalf("bad: %s", b.config.BundlePrefix)
	}
}

func TestBuilderPrepare_InvalidKey(t *testing.T) {
	var b Builder
	config := testConfig()

	// Add a random key
	config["i_should_not_be_valid"] = true
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}
}

func TestBuilderPrepare_S3Bucket(t *testing.T) {
	b := &Builder{}
	config := testConfig()

	config["s3_bucket"] = ""
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	config["s3_bucket"] = "foo"
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Errorf("err: %s", err)
	}
}

func TestBuilderPrepare_X509CertPath(t *testing.T) {
	b := &Builder{}
	config := testConfig()

	config["x509_cert_path"] = ""
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	config["x509_cert_path"] = "i/am/a/file/that/doesnt/exist"
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Error("should have error")
	}

	tf, err := ioutil.TempFile("", "packer")
	if err != nil {
		t.Fatalf("error tempfile: %s", err)
	}
	defer os.Remove(tf.Name())

	config["x509_cert_path"] = tf.Name()
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}
}

func TestBuilderPrepare_X509KeyPath(t *testing.T) {
	b := &Builder{}
	config := testConfig()

	config["x509_key_path"] = ""
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	config["x509_key_path"] = "i/am/a/file/that/doesnt/exist"
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Error("should have error")
	}

	tf, err := ioutil.TempFile("", "packer")
	if err != nil {
		t.Fatalf("error tempfile: %s", err)
	}
	defer os.Remove(tf.Name())

	config["x509_key_path"] = tf.Name()
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}
}

func TestBuilderPrepare_X509UploadPath(t *testing.T) {
	b := &Builder{}
	config := testConfig()

	config["x509_upload_path"] = ""
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}
}
<commit_msg>Remove tmp files created by builder/amazon/instance tests<commit_after>package instance

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

	"github.com/hashicorp/packer/packer"
)

func testConfig() (config map[string]interface{}, tf *os.File) {
	tf, err := ioutil.TempFile("", "packer")
	if err != nil {
		panic(err)
	}

	config = map[string]interface{}{
		"account_id":       "foo",
		"ami_name":         "foo",
		"instance_type":    "m1.small",
		"region":           "us-east-1",
		"s3_bucket":        "foo",
		"source_ami":       "foo",
		"ssh_username":     "bob",
		"x509_cert_path":   tf.Name(),
		"x509_key_path":    tf.Name(),
		"x509_upload_path": "/foo",
	}

	return config, tf
}

func TestBuilder_ImplementsBuilder(t *testing.T) {
	var raw interface{}
	raw = &Builder{}
	if _, ok := raw.(packer.Builder); !ok {
		t.Fatalf("Builder should be a builder")
	}
}

func TestBuilderPrepare_AccountId(t *testing.T) {
	b := &Builder{}
	config, tempfile := testConfig()
	defer os.Remove(tempfile.Name())
	defer tempfile.Close()

	config["account_id"] = ""
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	config["account_id"] = "foo"
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Errorf("err: %s", err)
	}

	config["account_id"] = "0123-0456-7890"
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	if b.config.AccountId != "012304567890" {
		t.Errorf("should strip hyphens: %s", b.config.AccountId)
	}
}

func TestBuilderPrepare_AMIName(t *testing.T) {
	var b Builder
	config, tempfile := testConfig()
	defer os.Remove(tempfile.Name())
	defer tempfile.Close()

	// Test good
	config["ami_name"] = "foo"
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	// Test bad
	config["ami_name"] = "foo {{"
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	// Test bad
	delete(config, "ami_name")
	b = Builder{}
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}
}

func TestBuilderPrepare_BundleDestination(t *testing.T) {
	b := &Builder{}
	config, tempfile := testConfig()
	defer os.Remove(tempfile.Name())
	defer tempfile.Close()

	config["bundle_destination"] = ""
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	if b.config.BundleDestination != "/tmp" {
		t.Fatalf("bad: %s", b.config.BundleDestination)
	}
}

func TestBuilderPrepare_BundlePrefix(t *testing.T) {
	b := &Builder{}
	config, tempfile := testConfig()
	defer os.Remove(tempfile.Name())
	defer tempfile.Close()

	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	if b.config.BundlePrefix == "" {
		t.Fatalf("bad: %s", b.config.BundlePrefix)
	}
}

func TestBuilderPrepare_InvalidKey(t *testing.T) {
	var b Builder
	config, tempfile := testConfig()
	defer os.Remove(tempfile.Name())
	defer tempfile.Close()

	// Add a random key
	config["i_should_not_be_valid"] = true
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}
}

func TestBuilderPrepare_S3Bucket(t *testing.T) {
	b := &Builder{}
	config, tempfile := testConfig()
	defer os.Remove(tempfile.Name())
	defer tempfile.Close()

	config["s3_bucket"] = ""
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	config["s3_bucket"] = "foo"
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Errorf("err: %s", err)
	}
}

func TestBuilderPrepare_X509CertPath(t *testing.T) {
	b := &Builder{}
	config, tempfile := testConfig()
	defer os.Remove(tempfile.Name())
	defer tempfile.Close()

	config["x509_cert_path"] = ""
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	config["x509_cert_path"] = "i/am/a/file/that/doesnt/exist"
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Error("should have error")
	}

	tf, err := ioutil.TempFile("", "packer")
	if err != nil {
		t.Fatalf("error tempfile: %s", err)
	}
	defer os.Remove(tf.Name())
	defer tf.Close()

	config["x509_cert_path"] = tf.Name()
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}
}

func TestBuilderPrepare_X509KeyPath(t *testing.T) {
	b := &Builder{}
	config, tempfile := testConfig()
	defer os.Remove(tempfile.Name())
	defer tempfile.Close()

	config["x509_key_path"] = ""
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	config["x509_key_path"] = "i/am/a/file/that/doesnt/exist"
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err == nil {
		t.Error("should have error")
	}

	tf, err := ioutil.TempFile("", "packer")
	if err != nil {
		t.Fatalf("error tempfile: %s", err)
	}
	defer os.Remove(tf.Name())
	defer tf.Close()

	config["x509_key_path"] = tf.Name()
	warnings, err = b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}
}

func TestBuilderPrepare_X509UploadPath(t *testing.T) {
	b := &Builder{}
	config, tempfile := testConfig()
	defer os.Remove(tempfile.Name())
	defer tempfile.Close()

	config["x509_upload_path"] = ""
	warnings, err := b.Prepare(config)
	if len(warnings) > 0 {
		t.Fatalf("bad: %#v", warnings)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}
}
<|endoftext|>


<commit_before>package transit

import (
	"encoding/json"
	"fmt"
	"sync"

	"github.com/hashicorp/vault/logical"
)

const (
	shared    = false
	exclusive = true
)

type lockManager struct {
	// A lock for each named key
	locks map[string]*sync.RWMutex

	// A mutex for the map itself
	lockMutex sync.RWMutex

	// If caching is enabled, the map of name to in-memory policy cache
	cache map[string]*Policy

	// Used for global locking, and as the cache map mutex
	globalMutex sync.RWMutex
}

func newLockManager(cacheDisabled bool) *lockManager {
	lm := &lockManager{
		locks: map[string]*sync.RWMutex{},
	}
	if !cacheDisabled {
		lm.cache = map[string]*Policy{}
	}
	return lm
}

func (lm *lockManager) CacheActive() bool {
	return lm.cache != nil
}

func (lm *lockManager) LockAll(name string) {
	lm.globalMutex.Lock()
	lm.LockPolicy(name, exclusive)
}

func (lm *lockManager) UnlockAll(name string) {
	lm.UnlockPolicy(name, exclusive)
	lm.globalMutex.Unlock()
}

func (lm *lockManager) LockPolicy(name string, writeLock bool) {
	lm.lockMutex.RLock()
	lock := lm.locks[name]
	if lock != nil {
		// We want to give this up before locking the lock, but it's safe --
		// the only time we ever write to a value in this map is the first time
		// we access the value, so it won't be changing out from under us
		lm.lockMutex.RUnlock()
		if writeLock {
			lock.Lock()
		} else {
			lock.RLock()
		}
		return
	}

	lm.lockMutex.RUnlock()
	lm.lockMutex.Lock()

	// Don't defer the unlock call because if we get a valid lock below we want
	// to release the lock mutex right away to avoid the possibility of
	// deadlock by trying to grab the second lock

	// Check to make sure it hasn't been created since
	lock = lm.locks[name]
	if lock != nil {
		lm.lockMutex.Unlock()
		if writeLock {
			lock.Lock()
		} else {
			lock.RLock()
		}
		return
	}

	lock = &sync.RWMutex{}
	lm.locks[name] = lock
	lm.lockMutex.Unlock()
	if writeLock {
		lock.Lock()
	} else {
		lock.RLock()
	}
}

func (lm *lockManager) UnlockPolicy(name string, writeLock bool) {
	lm.lockMutex.RLock()
	lock := lm.locks[name]
	lm.lockMutex.RUnlock()

	if writeLock {
		lock.Unlock()
	} else {
		lock.RUnlock()
	}
}

func (lm *lockManager) GetPolicy(storage logical.Storage, name string) (*Policy, bool, error) {
	p, lt, _, err := lm.getPolicyCommon(storage, name, false, false)
	return p, lt, err
}

func (lm *lockManager) GetPolicyUpsert(storage logical.Storage, name string, derived bool) (*Policy, bool, bool, error) {
	return lm.getPolicyCommon(storage, name, true, derived)
}

// When the function returns, a lock will be held on the policy if err == nil.
// The type of lock will be indicated by the return value. It is the caller's
// responsibility to unlock.
func (lm *lockManager) getPolicyCommon(storage logical.Storage, name string, upsert, derived bool) (p *Policy, lockType bool, upserted bool, err error) {
	// If we are using a cache, lock it now to avoid having to do really
	// complicated lock juggling as we call various functions. We'll also defer
	// the store into the cache.
	lockType = shared
	lm.LockPolicy(name, shared)

	if lm.CacheActive() {
		lm.globalMutex.RLock()
		p = lm.cache[name]
		if p != nil {
			defer lm.globalMutex.RUnlock()
			return
		}
		lm.globalMutex.RUnlock()

		// When we return, since we didn't have the policy in the cache, if
		// there was no error, write the value in.
		defer func() {
			if err == nil {
				lm.globalMutex.Lock()
				defer lm.globalMutex.Unlock()
				// Make sure a policy didn't appear
				exp := lm.cache[name]
				if exp != nil {
					p = exp
					return
				}

				lm.cache[name] = p
			}
		}()
	}

	p, err = lm.getStoredPolicy(storage, name)
	if err != nil {
		defer lm.UnlockPolicy(name, shared)
		return
	}

	if p == nil {
		if !upsert {
			defer lm.UnlockPolicy(name, shared)
			return
		}

		// Get an exlusive lock; on success, check again to ensure that no
		// policy exists. Note that if we are using a cache we will already be
		// serializing this entire code path and it's currently the only one
		// that generates policies, so we don't need to check the cache here;
		// simply checking the disk again is sufficient.
		lm.UnlockPolicy(name, shared)
		lockType = exclusive
		lm.LockPolicy(name, exclusive)

		p, err = lm.getStoredPolicy(storage, name)
		if err != nil {
			defer lm.UnlockPolicy(name, exclusive)
			return
		}
		if p != nil {
			return
		}

		upserted = true

		p = &Policy{
			Name:       name,
			CipherMode: "aes-gcm",
			Derived:    derived,
		}
		if derived {
			p.KDFMode = kdfMode
		}

		err = p.rotate(storage)
		if err != nil {
			defer lm.UnlockPolicy(name, exclusive)
			p = nil
		}

		// We don't need to worry about upgrading since it will be a new policy
		return
	}

	if p.needsUpgrade() {
		lm.UnlockPolicy(name, shared)
		lockType = exclusive
		lm.LockPolicy(name, exclusive)

		// Reload the policy with the write lock to ensure we still need the upgrade
		p, err = lm.getStoredPolicy(storage, name)
		if err != nil {
			defer lm.UnlockPolicy(name, exclusive)
			return
		}
		if p == nil {
			defer lm.UnlockPolicy(name, exclusive)
			err = fmt.Errorf("error reloading policy for upgrade")
			return
		}

		if !p.needsUpgrade() {
			// Already happened, return the newly loaded policy
			return
		}

		err = p.upgrade(storage)
		if err != nil {
			defer lm.UnlockPolicy(name, exclusive)
		}
	}

	return
}

func (lm *lockManager) DeletePolicy(storage logical.Storage, name string) error {
	lm.LockAll(name)
	defer lm.UnlockAll(name)

	var p *Policy
	var err error

	if lm.CacheActive() {
		p = lm.cache[name]
		if p == nil {
			return fmt.Errorf("could not delete policy; not found")
		}
	} else {
		p, err = lm.getStoredPolicy(storage, name)
		if err != nil {
			return err
		}
		if p == nil {
			return fmt.Errorf("could not delete policy; not found")
		}
	}

	if !p.DeletionAllowed {
		return fmt.Errorf("deletion is not allowed for this policy")
	}

	err = storage.Delete("policy/" + name)
	if err != nil {
		return fmt.Errorf("error deleting policy %s: %s", name, err)
	}

	err = storage.Delete("archive/" + name)
	if err != nil {
		return fmt.Errorf("error deleting archive %s: %s", name, err)
	}

	if lm.CacheActive() {
		delete(lm.cache, name)
	}

	return nil
}

// When this function returns it's the responsibility of the caller to call UnlockAll if err is not nil
func (lm *lockManager) RefreshPolicy(storage logical.Storage, name string) (p *Policy, err error) {
	lm.LockPolicy(name, exclusive)

	if lm.CacheActive() {
		p = lm.cache[name]
		if p != nil {
			return
		}
		err = fmt.Errorf("could not refresh policy; not found")
		defer lm.UnlockPolicy(name, exclusive)
		return
	}

	p, err = lm.getStoredPolicy(storage, name)
	if err != nil {
		defer lm.UnlockPolicy(name, exclusive)
		return
	}

	if p == nil {
		err = fmt.Errorf("could not refresh policy; not found")
		defer lm.UnlockPolicy(name, exclusive)
	}

	if p.needsUpgrade() {
		err = p.upgrade(storage)
		if err != nil {
			defer lm.UnlockPolicy(name, exclusive)
		}
	}

	return
}

func (lm *lockManager) getStoredPolicy(storage logical.Storage, name string) (*Policy, error) {
	// Check if the policy already exists
	raw, err := storage.Get("policy/" + name)
	if err != nil {
		return nil, err
	}
	if raw == nil {
		return nil, nil
	}

	// Decode the policy
	policy := &Policy{
		Keys: KeyEntryMap{},
	}
	err = json.Unmarshal(raw.Value, policy)
	if err != nil {
		return nil, err
	}

	return policy, nil
}
<commit_msg>Address review feedback<commit_after>package transit

import (
	"encoding/json"
	"fmt"
	"sync"

	"github.com/hashicorp/vault/logical"
)

const (
	shared    = false
	exclusive = true
)

type lockManager struct {
	// A lock for each named key
	locks map[string]*sync.RWMutex

	// A mutex for the map itself
	locksMutex sync.RWMutex

	// If caching is enabled, the map of name to in-memory policy cache
	cache map[string]*Policy

	// Used for global locking, and as the cache map mutex
	globalMutex sync.RWMutex
}

func newLockManager(cacheDisabled bool) *lockManager {
	lm := &lockManager{
		locks: map[string]*sync.RWMutex{},
	}
	if !cacheDisabled {
		lm.cache = map[string]*Policy{}
	}
	return lm
}

func (lm *lockManager) CacheActive() bool {
	return lm.cache != nil
}

func (lm *lockManager) LockAll(name string) {
	lm.globalMutex.Lock()
	lm.LockPolicy(name, exclusive)
}

func (lm *lockManager) UnlockAll(name string) {
	lm.UnlockPolicy(name, exclusive)
	lm.globalMutex.Unlock()
}

func (lm *lockManager) LockPolicy(name string, writeLock bool) {
	lm.locksMutex.RLock()
	lock := lm.locks[name]
	if lock != nil {
		// We want to give this up before locking the lock, but it's safe --
		// the only time we ever write to a value in this map is the first time
		// we access the value, so it won't be changing out from under us
		lm.locksMutex.RUnlock()
		if writeLock {
			lock.Lock()
		} else {
			lock.RLock()
		}
		return
	}

	lm.locksMutex.RUnlock()
	lm.locksMutex.Lock()

	// Don't defer the unlock call because if we get a valid lock below we want
	// to release the lock mutex right away to avoid the possibility of
	// deadlock by trying to grab the second lock

	// Check to make sure it hasn't been created since
	lock = lm.locks[name]
	if lock != nil {
		lm.locksMutex.Unlock()
		if writeLock {
			lock.Lock()
		} else {
			lock.RLock()
		}
		return
	}

	lock = &sync.RWMutex{}
	lm.locks[name] = lock
	lm.locksMutex.Unlock()
	if writeLock {
		lock.Lock()
	} else {
		lock.RLock()
	}
}

func (lm *lockManager) UnlockPolicy(name string, writeLock bool) {
	lm.locksMutex.RLock()
	lock := lm.locks[name]
	lm.locksMutex.RUnlock()

	if writeLock {
		lock.Unlock()
	} else {
		lock.RUnlock()
	}
}

func (lm *lockManager) GetPolicy(storage logical.Storage, name string) (*Policy, bool, error) {
	p, lt, _, err := lm.getPolicyCommon(storage, name, false, false)
	return p, lt, err
}

func (lm *lockManager) GetPolicyUpsert(storage logical.Storage, name string, derived bool) (*Policy, bool, bool, error) {
	return lm.getPolicyCommon(storage, name, true, derived)
}

// When the function returns, a lock will be held on the policy if err == nil.
// The type of lock will be indicated by the return value. It is the caller's
// responsibility to unlock.
func (lm *lockManager) getPolicyCommon(storage logical.Storage, name string, upsert, derived bool) (p *Policy, lockType bool, upserted bool, err error) {
	// If we are using a cache, lock it now to avoid having to do really
	// complicated lock juggling as we call various functions. We'll also defer
	// the store into the cache.
	lockType = shared
	lm.LockPolicy(name, shared)

	if lm.CacheActive() {
		lm.globalMutex.RLock()
		p = lm.cache[name]
		if p != nil {
			lm.globalMutex.RUnlock()
			return
		}
		lm.globalMutex.RUnlock()

		// When we return, since we didn't have the policy in the cache, if
		// there was no error, write the value in.
		defer func() {
			lm.globalMutex.Lock()
			defer lm.globalMutex.Unlock()
			// Make sure a policy didn't appear. If so, it will only be set if
			// there was no error, so now just clear the error and return that
			// policy.
			exp := lm.cache[name]
			if exp != nil {
				upserted = false
				err = nil
				p = exp
				return
			}

			if err == nil {
				lm.cache[name] = p
			}
		}()
	}

	p, err = lm.getStoredPolicy(storage, name)
	if err != nil {
		lm.UnlockPolicy(name, shared)
		return
	}

	if p == nil {
		if !upsert {
			lm.UnlockPolicy(name, shared)
			return
		}

		// Get an exlusive lock; on success, check again to ensure that no
		// policy exists. Note that if we are using a cache we will already be
		// serializing this entire code path and it's currently the only one
		// that generates policies, so we don't need to check the cache here;
		// simply checking the disk again is sufficient.
		lm.UnlockPolicy(name, shared)
		lockType = exclusive
		lm.LockPolicy(name, exclusive)

		p, err = lm.getStoredPolicy(storage, name)
		if err != nil {
			defer lm.UnlockPolicy(name, exclusive)
			return
		}
		if p != nil {
			return
		}

		upserted = true

		p = &Policy{
			Name:       name,
			CipherMode: "aes-gcm",
			Derived:    derived,
		}
		if derived {
			p.KDFMode = kdfMode
		}

		err = p.rotate(storage)
		if err != nil {
			defer lm.UnlockPolicy(name, exclusive)
			p = nil
		}

		// We don't need to worry about upgrading since it will be a new policy
		return
	}

	if p.needsUpgrade() {
		lm.UnlockPolicy(name, shared)
		lockType = exclusive
		lm.LockPolicy(name, exclusive)

		// Reload the policy with the write lock to ensure we still need the upgrade
		p, err = lm.getStoredPolicy(storage, name)
		if err != nil {
			defer lm.UnlockPolicy(name, exclusive)
			return
		}
		if p == nil {
			defer lm.UnlockPolicy(name, exclusive)
			err = fmt.Errorf("error reloading policy for upgrade")
			return
		}

		if !p.needsUpgrade() {
			// Already happened, return the newly loaded policy
			return
		}

		err = p.upgrade(storage)
		if err != nil {
			defer lm.UnlockPolicy(name, exclusive)
		}
	}

	return
}

func (lm *lockManager) DeletePolicy(storage logical.Storage, name string) error {
	lm.LockAll(name)
	defer lm.UnlockAll(name)

	var p *Policy
	var err error

	if lm.CacheActive() {
		p = lm.cache[name]
		if p == nil {
			return fmt.Errorf("could not delete policy; not found")
		}
	} else {
		p, err = lm.getStoredPolicy(storage, name)
		if err != nil {
			return err
		}
		if p == nil {
			return fmt.Errorf("could not delete policy; not found")
		}
	}

	if !p.DeletionAllowed {
		return fmt.Errorf("deletion is not allowed for this policy")
	}

	err = storage.Delete("policy/" + name)
	if err != nil {
		return fmt.Errorf("error deleting policy %s: %s", name, err)
	}

	err = storage.Delete("archive/" + name)
	if err != nil {
		return fmt.Errorf("error deleting archive %s: %s", name, err)
	}

	if lm.CacheActive() {
		delete(lm.cache, name)
	}

	return nil
}

// When this function returns it's the responsibility of the caller to call
// UnlockPolicy if err is nil and policy is not nil
func (lm *lockManager) RefreshPolicy(storage logical.Storage, name string) (p *Policy, err error) {
	lm.LockPolicy(name, exclusive)

	if lm.CacheActive() {
		p = lm.cache[name]
		if p != nil {
			return
		}
		err = fmt.Errorf("could not refresh policy; not found")
		defer lm.UnlockPolicy(name, exclusive)
		return
	}

	p, err = lm.getStoredPolicy(storage, name)
	if err != nil {
		defer lm.UnlockPolicy(name, exclusive)
		return
	}

	if p == nil {
		err = fmt.Errorf("could not refresh policy; not found")
		defer lm.UnlockPolicy(name, exclusive)
	}

	if p.needsUpgrade() {
		err = p.upgrade(storage)
		if err != nil {
			defer lm.UnlockPolicy(name, exclusive)
		}
	}

	return
}

func (lm *lockManager) getStoredPolicy(storage logical.Storage, name string) (*Policy, error) {
	// Check if the policy already exists
	raw, err := storage.Get("policy/" + name)
	if err != nil {
		return nil, err
	}
	if raw == nil {
		return nil, nil
	}

	// Decode the policy
	policy := &Policy{
		Keys: KeyEntryMap{},
	}
	err = json.Unmarshal(raw.Value, policy)
	if err != nil {
		return nil, err
	}

	return policy, nil
}
<|endoftext|>


<commit_before>package progress

import (
	"io/ioutil"
	"log"
	"strings"
	"testing"
)

func TestProgressString(t *testing.T) {
	l := log.New(ioutil.Discard, "", 0)
	p := Start(l, WithTotal(100))
	defer p.Close()
	p.IncBy(10)

	s := p.String()

	for _, b := range []string{"010/100"} {
		if !strings.Contains(s, b) {
			t.Errorf("expected string %q to contain %q", s, b)
		}
	}

	p = Start(l, WithTotal(99))
	defer p.Close()
	p.IncBy(10)
	s = p.String()
	for _, b := range []string{"10/99"} {
		if !strings.Contains(s, b) {
			t.Errorf("expected string %q to contain %q", s, b)
		}
	}
}
<commit_msg>fix build<commit_after>package progress

import (
	"io/ioutil"
	"log"
	"strings"
	"testing"
)

func TestProgressString(t *testing.T) {
	l := log.New(ioutil.Discard, "", 0)
	p := Start(l, WithTotal(100))
	defer p.Close()
	p.IncBy(10)

	s := p.Status().String()

	for _, b := range []string{"010/100"} {
		if !strings.Contains(s, b) {
			t.Errorf("expected string %q to contain %q", s, b)
		}
	}

	p = Start(l, WithTotal(99))
	defer p.Close()
	p.IncBy(10)
	s = p.Status().String()
	for _, b := range []string{"10/99"} {
		if !strings.Contains(s, b) {
			t.Errorf("expected string %q to contain %q", s, b)
		}
	}
}
<|endoftext|>


<commit_before>package testutil

import (
	"io/ioutil"
	"testing"
	"net/http"
)

func AssertResponseStatus(t *testing.T, expectedStatus int, response *http.Response) {
	if response.StatusCode != expectedStatus {
		t.Fatalf("expected 200; got '%v'", response.StatusCode)
	}
}

func AssertResponseBody(t *testing.T, expectedBody string, response *http.Response) {
	if body := ReadResponseBody(t, response); body != expectedBody {
		t.Fatalf("expected '%v'; got '%v'", expectedBody, body)
	}
}

func AssertResponseHeaders(t *testing.T, expectedHeaders map[string]string, response *http.Response) {
	if len(expectedHeaders) != len(response.Header) {
		t.Fatalf("expected %v headers; got %v. Returned headers: %v", len(expectedHeaders), len(response.Header), response.Header)
	}
	for key, _ := range expectedHeaders {
		if val := response.Header.Get(key); val != expectedHeaders[key] {
			t.Fatalf("expected header %v to be '%v'; got '%v'", key, expectedHeaders[key], val)
		}
	}
}

func ReadResponseBody(t *testing.T, response *http.Response) string {
	bytes, err := ioutil.ReadAll(response.Body)
	if err != nil {
		t.Fatalf("Error reading body: %v", err)
	}
	return string(bytes)
}
<commit_msg>include some more debugging in the response status assertion<commit_after>package testutil

import (
	"io/ioutil"
	"testing"
	"net/http"
)

func AssertResponseStatus(t *testing.T, expectedStatus int, response *http.Response) {
	if response.StatusCode != expectedStatus {
		t.Fatalf("expected 200; got '%v' Body: '%v'", response.StatusCode, ReadResponseBody(t, response))
	}
}

func AssertResponseBody(t *testing.T, expectedBody string, response *http.Response) {
	if body := ReadResponseBody(t, response); body != expectedBody {
		t.Fatalf("expected '%v'; got '%v'", expectedBody, body)
	}
}

func AssertResponseHeaders(t *testing.T, expectedHeaders map[string]string, response *http.Response) {
	if len(expectedHeaders) != len(response.Header) {
		t.Fatalf("expected %v headers; got %v. Returned headers: %v", len(expectedHeaders), len(response.Header), response.Header)
	}
	for key, _ := range expectedHeaders {
		if val := response.Header.Get(key); val != expectedHeaders[key] {
			t.Fatalf("expected header %v to be '%v'; got '%v'", key, expectedHeaders[key], val)
		}
	}
}

func ReadResponseBody(t *testing.T, response *http.Response) string {
	bytes, err := ioutil.ReadAll(response.Body)
	if err != nil {
		t.Fatalf("Error reading body: %v", err)
	}
	return string(bytes)
}
<|endoftext|>


<commit_before>package gorpc

import (
	"errors"
	"sync"

	"github.com/gsdocker/gserrors"
)

// Errors
var (
	ErrRegistryNotFound = errors.New("search found nothing")
)

// Registry the service registry
type Registry interface {
	// Update update the registry
	Update(items map[string]uint16)
	// ServiceName get service name by service id
	ServiceName(id uint16) string
	// ServiceID get service id by service name
	ServiceID(name string) uint16
}

type _Registry struct {
	sync.RWMutex                   // mixin read/write mutex
	name         map[string]uint16 // the service registry name indexer
	id           map[uint16]string // the service registry id indexer
}

// NewRegistry create new registry table
func NewRegistry() Registry {
	return &_Registry{
		name: make(map[string]uint16),
		id:   make(map[uint16]string),
	}
}

func (registry *_Registry) Update(items map[string]uint16) {
	registry.Lock()
	defer registry.Unlock()

	registry.name = items

	registry.id = make(map[uint16]string)

	for k, v := range registry.name {
		registry.id[v] = k
	}
}

func (registry *_Registry) ServiceName(id uint16) string {
	registry.RLock()
	defer registry.RUnlock()

	if val, ok := registry.id[id]; ok {
		return val
	}

	gserrors.Panicf(ErrRegistryNotFound, "can't found service name for %s", id)

	return ""
}

func (registry *_Registry) ServiceID(name string) uint16 {
	registry.RLock()
	defer registry.RUnlock()

	if val, ok := registry.name[name]; ok {
		return val
	}

	gserrors.Panicf(ErrRegistryNotFound, "can't found service id for %s", name)

	return 0
}

var registry = NewRegistry()

// RegistryUpdate update default registry
func RegistryUpdate(items map[string]uint16) {
	registry.Update(items)
}

// ServiceName get service name by service id
func ServiceName(id uint16) string {
	return registry.ServiceName(id)
}

// ServiceID get service id by service name
func ServiceID(name string) uint16 {
	return registry.ServiceID(name)
}
<commit_msg>add Registry load API<commit_after>package gorpc

import (
	"bufio"
	"errors"
	"io"
	"math"
	"regexp"
	"strconv"
	"sync"

	"github.com/gsdocker/gserrors"
)

// Errors
var (
	ErrRegistryNotFound = errors.New("search found nothing")
)

var registryRegex = regexp.MustCompile(`(?P<name>[A-Za-z0-9_]+(\.[A-Za-z0-9_]+)*)=(?P<id>[0-9]+)`)

// Errors
var (
	ErrRegistry = errors.New("load registry file error")
)

// Registry the service registry
type Registry interface {
	// Update update the registry
	Update(items map[string]uint16)
	// ServiceName get service name by service id
	ServiceName(id uint16) string
	// ServiceID get service id by service name
	ServiceID(name string) uint16
	// Load load registry from io.Reader
	Load(r io.Reader, name string)
}

type _Registry struct {
	sync.RWMutex                   // mixin read/write mutex
	name         map[string]uint16 // the service registry name indexer
	id           map[uint16]string // the service registry id indexer
}

// NewRegistry create new registry table
func NewRegistry() Registry {
	return &_Registry{
		name: make(map[string]uint16),
		id:   make(map[uint16]string),
	}
}

func (registry *_Registry) Load(origin io.Reader, name string) {
	reader := bufio.NewReader(origin)

	lines := 0

	items := make(map[string]uint16)

	for {
		line, err := reader.ReadString('\n')

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

			gserrors.Panicf(err, "read registry file error :%s", name)
		}

		tokens := registryRegex.FindStringSubmatch(line)

		if tokens == nil {
			gserrors.Panicf(ErrRegistry, "load registry file error: invalid format\n\t%s(%d)", name, lines)
		}

		serviceName := ""

		serviceID := uint16(0)

		for i, name := range registryRegex.SubexpNames() {
			if name == "name" {
				serviceName = tokens[i]
			}

			if name == "id" {
				val, err := strconv.ParseInt(tokens[i], 0, 32)

				if err != nil {
					gserrors.Panicf(err, "load registry file error: invalid format\n\t%s(%d)", name, lines)
				}

				if val > math.MaxUint16 {
					gserrors.Panicf(ErrRegistry, "load registry file error: id out of range\n\t%s(%d)", name, lines)
				}

				serviceID = uint16(val)
			}
		}

		items[serviceName] = serviceID

		lines++

	}

	registry.Update(items)
}

func (registry *_Registry) Update(items map[string]uint16) {
	registry.Lock()
	defer registry.Unlock()

	registry.name = items

	registry.id = make(map[uint16]string)

	for k, v := range registry.name {
		registry.id[v] = k
	}
}

func (registry *_Registry) ServiceName(id uint16) string {
	registry.RLock()
	defer registry.RUnlock()

	if val, ok := registry.id[id]; ok {
		return val
	}

	gserrors.Panicf(ErrRegistryNotFound, "can't found service name for %s", id)

	return ""
}

func (registry *_Registry) ServiceID(name string) uint16 {
	registry.RLock()
	defer registry.RUnlock()

	if val, ok := registry.name[name]; ok {
		return val
	}

	gserrors.Panicf(ErrRegistryNotFound, "can't found service id for %s", name)

	return 0
}

var registry = NewRegistry()

// RegistryLoad load registry table from io.Reader
func RegistryLoad(r io.Reader, name string) {
	registry.Load(r, name)
}

// RegistryUpdate update default registry
func RegistryUpdate(items map[string]uint16) {
	registry.Update(items)
}

// ServiceName get service name by service id
func ServiceName(id uint16) string {
	return registry.ServiceName(id)
}

// ServiceID get service id by service name
func ServiceID(name string) uint16 {
	return registry.ServiceID(name)
}
<|endoftext|>


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

package rpc

import (
	"errors"

	"launchpad.net/juju-core/log"
)

var ErrShutdown = errors.New("connection is shut down")

// Call represents an active RPC.
type Call struct {
	Type     string
	Id       string
	Request  string
	Params   interface{}
	Response interface{}
	Error    error
	Done     chan *Call
}

// RequestError represents an error returned from an RPC request.
type RequestError struct {
	Message string
	Code    string
}

func (e *RequestError) Error() string {
	m := "request error: " + e.Message
	if e.Code != "" {
		m += " (" + e.Code + ")"
	}
	return m
}

func (e *RequestError) ErrorCode() string {
	return e.Code
}

func (conn *Conn) send(call *Call) {
	conn.sending.Lock()
	defer conn.sending.Unlock()

	// Register this call.
	conn.mutex.Lock()
	if conn.dead == nil {
		panic("rpc: call made when connection not started")
	}
	if conn.closing || conn.shutdown {
		call.Error = ErrShutdown
		conn.mutex.Unlock()
		call.done()
		return
	}
	conn.reqId++
	reqId := conn.reqId
	conn.clientPending[reqId] = call
	conn.mutex.Unlock()

	// Encode and send the request.
	hdr := &Header{
		RequestId: reqId,
		Type:      call.Type,
		Id:        call.Id,
		Request:   call.Request,
	}
	params := call.Params
	if params == nil {
		params = struct{}{}
	}
	if err := conn.codec.WriteMessage(hdr, params); err != nil {
		conn.mutex.Lock()
		call = conn.clientPending[reqId]
		delete(conn.clientPending, reqId)
		conn.mutex.Unlock()
		if call != nil {
			call.Error = err
			call.done()
		}
	}
}

func (conn *Conn) handleResponse(hdr *Header) error {
	reqId := hdr.RequestId
	conn.mutex.Lock()
	call := conn.clientPending[reqId]
	delete(conn.clientPending, reqId)
	conn.mutex.Unlock()

	var err error
	switch {
	case call == nil:
		// We've got no pending call. That usually means that
		// WriteHeader partially failed, and call was already
		// removed; response is a server telling us about an
		// error reading request body. We should still attempt
		// to read error body, but there's no one to give it to.
		err = conn.readBody(nil, false)
	case hdr.Error != "":
		// We've got an error response. Give this to the request;
		// any subsequent requests will get the ReadResponseBody
		// error if there is one.
		call.Error = &RequestError{
			Message: hdr.Error,
			Code:    hdr.ErrorCode,
		}
		err = conn.readBody(nil, false)
		call.done()
	default:
		err = conn.readBody(call.Response, false)
		call.done()
	}
	return err
}

func (call *Call) done() {
	select {
	case call.Done <- call:
		// ok
	default:
		// We don't want to block here.  It is the caller's responsibility to make
		// sure the channel has enough buffer space. See comment in Go().
		logger.Errorf("discarding Call reply due to insufficient Done chan capacity")
	}
}

// Call invokes the named action on the object of the given type with
// the given id.  The returned values will be stored in response, which
// should be a pointer.  If the action fails remotely, the returned
// error will be of type RequestError.  The params value may be nil if
// no parameters are provided; the response value may be nil to indicate
// that any result should be discarded.
func (conn *Conn) Call(objType, id, action string, params, response interface{}) error {
	call := <-conn.Go(objType, id, action, params, response, make(chan *Call, 1)).Done
	return call.Error
}

// Go invokes the request asynchronously.  It returns the Call structure representing
// the invocation.  The done channel will signal when the call is complete by returning
// the same Call object.  If done is nil, Go will allocate a new channel.
// If non-nil, done must be buffered or Go will deliberately panic.
func (conn *Conn) Go(objType, id, request string, args, response interface{}, done chan *Call) *Call {
	if done == nil {
		done = make(chan *Call, 1)
	} else {
		// If caller passes done != nil, it must arrange that
		// done has enough buffer for the number of simultaneous
		// RPCs that will be using that channel.  If the channel
		// is totally unbuffered, it's best not to run at all.
		if cap(done) == 0 {
			panic("launchpad.net/juju-core/rpc: done channel is unbuffered")
		}
	}
	call := &Call{
		Type:     objType,
		Id:       id,
		Request:  request,
		Params:   args,
		Response: response,
		Done:     done,
	}
	conn.send(call)
	return call
}
<commit_msg>Remove log import.<commit_after>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package rpc

import (
	"errors"
)

var ErrShutdown = errors.New("connection is shut down")

// Call represents an active RPC.
type Call struct {
	Type     string
	Id       string
	Request  string
	Params   interface{}
	Response interface{}
	Error    error
	Done     chan *Call
}

// RequestError represents an error returned from an RPC request.
type RequestError struct {
	Message string
	Code    string
}

func (e *RequestError) Error() string {
	m := "request error: " + e.Message
	if e.Code != "" {
		m += " (" + e.Code + ")"
	}
	return m
}

func (e *RequestError) ErrorCode() string {
	return e.Code
}

func (conn *Conn) send(call *Call) {
	conn.sending.Lock()
	defer conn.sending.Unlock()

	// Register this call.
	conn.mutex.Lock()
	if conn.dead == nil {
		panic("rpc: call made when connection not started")
	}
	if conn.closing || conn.shutdown {
		call.Error = ErrShutdown
		conn.mutex.Unlock()
		call.done()
		return
	}
	conn.reqId++
	reqId := conn.reqId
	conn.clientPending[reqId] = call
	conn.mutex.Unlock()

	// Encode and send the request.
	hdr := &Header{
		RequestId: reqId,
		Type:      call.Type,
		Id:        call.Id,
		Request:   call.Request,
	}
	params := call.Params
	if params == nil {
		params = struct{}{}
	}
	if err := conn.codec.WriteMessage(hdr, params); err != nil {
		conn.mutex.Lock()
		call = conn.clientPending[reqId]
		delete(conn.clientPending, reqId)
		conn.mutex.Unlock()
		if call != nil {
			call.Error = err
			call.done()
		}
	}
}

func (conn *Conn) handleResponse(hdr *Header) error {
	reqId := hdr.RequestId
	conn.mutex.Lock()
	call := conn.clientPending[reqId]
	delete(conn.clientPending, reqId)
	conn.mutex.Unlock()

	var err error
	switch {
	case call == nil:
		// We've got no pending call. That usually means that
		// WriteHeader partially failed, and call was already
		// removed; response is a server telling us about an
		// error reading request body. We should still attempt
		// to read error body, but there's no one to give it to.
		err = conn.readBody(nil, false)
	case hdr.Error != "":
		// We've got an error response. Give this to the request;
		// any subsequent requests will get the ReadResponseBody
		// error if there is one.
		call.Error = &RequestError{
			Message: hdr.Error,
			Code:    hdr.ErrorCode,
		}
		err = conn.readBody(nil, false)
		call.done()
	default:
		err = conn.readBody(call.Response, false)
		call.done()
	}
	return err
}

func (call *Call) done() {
	select {
	case call.Done <- call:
		// ok
	default:
		// We don't want to block here.  It is the caller's responsibility to make
		// sure the channel has enough buffer space. See comment in Go().
		logger.Errorf("discarding Call reply due to insufficient Done chan capacity")
	}
}

// Call invokes the named action on the object of the given type with
// the given id.  The returned values will be stored in response, which
// should be a pointer.  If the action fails remotely, the returned
// error will be of type RequestError.  The params value may be nil if
// no parameters are provided; the response value may be nil to indicate
// that any result should be discarded.
func (conn *Conn) Call(objType, id, action string, params, response interface{}) error {
	call := <-conn.Go(objType, id, action, params, response, make(chan *Call, 1)).Done
	return call.Error
}

// Go invokes the request asynchronously.  It returns the Call structure representing
// the invocation.  The done channel will signal when the call is complete by returning
// the same Call object.  If done is nil, Go will allocate a new channel.
// If non-nil, done must be buffered or Go will deliberately panic.
func (conn *Conn) Go(objType, id, request string, args, response interface{}, done chan *Call) *Call {
	if done == nil {
		done = make(chan *Call, 1)
	} else {
		// If caller passes done != nil, it must arrange that
		// done has enough buffer for the number of simultaneous
		// RPCs that will be using that channel.  If the channel
		// is totally unbuffered, it's best not to run at all.
		if cap(done) == 0 {
			panic("launchpad.net/juju-core/rpc: done channel is unbuffered")
		}
	}
	call := &Call{
		Type:     objType,
		Id:       id,
		Request:  request,
		Params:   args,
		Response: response,
		Done:     done,
	}
	conn.send(call)
	return call
}
<|endoftext|>