summaryrefslogtreecommitdiff
path: root/vendor/github.com/digitalocean/go-libvirt/internal/event
diff options
context:
space:
mode:
authorbaude <bbaude@redhat.com>2021-03-15 14:52:43 -0500
committerbaude <bbaude@redhat.com>2021-03-25 08:43:51 -0500
commitb5f54a9b23e8d9418700494da9aa78d8db354c43 (patch)
tree59dfb9edf3faf6d184f6af40522f71968948133a /vendor/github.com/digitalocean/go-libvirt/internal/event
parenta861f6fd3ebe4fe0b63a1b550e6b99d7525228c0 (diff)
downloadpodman-b5f54a9b23e8d9418700494da9aa78d8db354c43.tar.gz
podman-b5f54a9b23e8d9418700494da9aa78d8db354c43.tar.bz2
podman-b5f54a9b23e8d9418700494da9aa78d8db354c43.zip
introduce podman machine
podman machine allows podman to create, manage, and interact with a vm running some form of linux (default is fcos). podman is then configured to be able to interact with the vm automatically. while this is usable on linux, the real push is to get this working on both current apple architectures in macos. Ashley Cui contributed to this PR and was a great help. [NO TESTS NEEDED] Signed-off-by: baude <bbaude@redhat.com>
Diffstat (limited to 'vendor/github.com/digitalocean/go-libvirt/internal/event')
-rw-r--r--vendor/github.com/digitalocean/go-libvirt/internal/event/event.go20
-rw-r--r--vendor/github.com/digitalocean/go-libvirt/internal/event/stream.go145
2 files changed, 165 insertions, 0 deletions
diff --git a/vendor/github.com/digitalocean/go-libvirt/internal/event/event.go b/vendor/github.com/digitalocean/go-libvirt/internal/event/event.go
new file mode 100644
index 000000000..67a1885b9
--- /dev/null
+++ b/vendor/github.com/digitalocean/go-libvirt/internal/event/event.go
@@ -0,0 +1,20 @@
+// Copyright 2020 The go-libvirt Authors.
+//
+// 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 event
+
+// Event represents an internal Event.
+type Event interface {
+ GetCallbackID() int32
+}
diff --git a/vendor/github.com/digitalocean/go-libvirt/internal/event/stream.go b/vendor/github.com/digitalocean/go-libvirt/internal/event/stream.go
new file mode 100644
index 000000000..b14e41b64
--- /dev/null
+++ b/vendor/github.com/digitalocean/go-libvirt/internal/event/stream.go
@@ -0,0 +1,145 @@
+// Copyright 2020 The go-libvirt Authors.
+//
+// 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 event
+
+import "context"
+
+// Stream is an unbounded buffered event channel. The implementation
+// consists of a pair of unbuffered channels and a goroutine to manage them.
+// Client behavior will not cause incoming events to block.
+type Stream struct {
+ // Program specifies the source of the events - libvirt or QEMU.
+ Program uint32
+
+ // CallbackID is returned by the event registration call.
+ CallbackID int32
+
+ // manage unbounded channel behavior.
+ queue []Event
+ in, out chan Event
+
+ // terminates processing
+ shutdown context.CancelFunc
+}
+
+// Recv returns the next available event from the Stream's queue.
+func (s *Stream) Recv() chan Event {
+ return s.out
+}
+
+// Push appends a new event to the queue.
+func (s *Stream) Push(e Event) {
+ s.in <- e
+}
+
+// Shutdown gracefully terminates Stream processing, releasing all
+// internal resources. Events which have not yet been received by the client
+// will be dropped. Subsequent calls to Shutdown() are idempotent.
+func (s *Stream) Shutdown() {
+ if s.shutdown != nil {
+ s.shutdown()
+ }
+}
+
+// start starts the event processing loop, which will continue to run until
+// terminated by the returned context.CancelFunc. Starting a previously started
+// Stream is an idempotent operation.
+func (s *Stream) start() context.CancelFunc {
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go s.process(ctx)
+
+ return cancel
+}
+
+// process manages an Stream's lifecycle until canceled by the provided
+// context. Incoming events are appended to a queue which is then relayed to
+// the a listening client. New events pushed onto the queue will not block due
+// to client behavior.
+func (s *Stream) process(ctx context.Context) {
+ defer func() {
+ close(s.in)
+ close(s.out)
+ }()
+
+ for {
+ // informs send() to stop trying
+ nctx, next := context.WithCancel(ctx)
+ defer next()
+
+ select {
+ // new event received, append to queue
+ case e := <-s.in:
+ s.queue = append(s.queue, e)
+
+ // client recieved an event, pop from queue
+ case <-s.send(nctx):
+ if len(s.queue) > 1 {
+ s.queue = s.queue[1:]
+ } else {
+ s.queue = []Event{}
+ }
+
+ // shutdown requested
+ case <-ctx.Done():
+ return
+
+ }
+
+ next()
+ }
+}
+
+// send returns a channel which blocks until either the first item on the queue
+// (if existing) is sent to the client, or the provided context is canceled.
+// The stream's queue is never modified.
+func (s *Stream) send(ctx context.Context) <-chan struct{} {
+ ch := make(chan struct{})
+
+ go func() {
+ defer close(ch)
+
+ // do nothing and block if the queue is empty
+ if len(s.queue) == 0 {
+ <-ctx.Done()
+ return
+ }
+
+ // otherwise, attempt to send the event
+ select {
+ case s.out <- s.queue[0]:
+ case <-ctx.Done():
+ }
+ }()
+
+ return ch
+}
+
+// NewStream configures a new Event Stream. Incoming events are appended to a
+// queue, which is then relayed to the listening client. Client behavior will
+// not cause incoming events to block. It is the responsibility of the caller
+// to terminate the Stream via Shutdown() when no longer in use.
+func NewStream(program uint32, cbID int32) *Stream {
+ ic := &Stream{
+ Program: program,
+ CallbackID: cbID,
+ in: make(chan Event),
+ out: make(chan Event),
+ }
+
+ ic.shutdown = ic.start()
+
+ return ic
+}