blob: 3a71623eeaff9f99c07efa25cc5dffc1f81eee92 [file] [log] [blame]
khenaidoo1ce37ad2019-03-24 22:07:24 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package utils
17
khenaidoo2c6a0992019-04-29 13:46:56 -040018import (
19 "google.golang.org/grpc/codes"
20 "google.golang.org/grpc/status"
khenaidoo631fe542019-05-31 15:44:43 -040021 "os"
khenaidoo2c6a0992019-04-29 13:46:56 -040022 "time"
23)
24
khenaidoo1ce37ad2019-03-24 22:07:24 -040025type DeviceID struct {
26 Id string
27}
28
29type LogicalDeviceID struct {
30 Id string
31}
khenaidoo2c6a0992019-04-29 13:46:56 -040032
khenaidoo631fe542019-05-31 15:44:43 -040033func GetHostName() string {
34 return os.Getenv("HOSTNAME")
35}
36
Kent Hagerman8da2f1e2019-11-25 17:28:09 -050037type Response struct {
38 *response
39}
40type response struct {
41 err error
42 ch chan struct{}
43 done bool
44}
45
46func NewResponse() Response {
47 return Response{
48 &response{
49 ch: make(chan struct{}),
50 },
51 }
52}
53
54// Error sends a response with the given error. It may only be called once.
55func (r Response) Error(err error) {
56 // if this is called twice, it will panic; this is intentional
57 r.err = err
58 r.done = true
59 close(r.ch)
60}
61
62// Done sends a non-error response unless Error has already been called, in which case this is a no-op.
63func (r Response) Done() {
64 if !r.done {
65 close(r.ch)
66 }
67}
68
khenaidoo2c6a0992019-04-29 13:46:56 -040069//WaitForNilOrErrorResponses waits on a variadic number of channels for either a nil response or an error
70//response. If an error is received from a given channel then the returned error array will contain that error.
71//The error will be at the index corresponding to the order in which the channel appear in the parameter list.
72//If no errors is found then nil is returned. This method also takes in a timeout in milliseconds. If a
73//timeout is obtained then this function will stop waiting for the remaining responses and abort.
Kent Hagerman8da2f1e2019-11-25 17:28:09 -050074func WaitForNilOrErrorResponses(timeout int64, responses ...Response) []error {
75 timedOut := make(chan struct{})
76 timer := time.AfterFunc(time.Duration(timeout)*time.Millisecond, func() { close(timedOut) })
77 defer timer.Stop()
khenaidoo2c6a0992019-04-29 13:46:56 -040078
Kent Hagerman8da2f1e2019-11-25 17:28:09 -050079 gotError := false
80 errors := make([]error, 0, len(responses))
81 for _, response := range responses {
82 var err error
83 select {
84 case <-response.ch:
85 // if a response is already available, use it
86 err = response.err
87 default:
88 // otherwise, wait for either a response or a timeout
89 select {
90 case <-response.ch:
91 err = response.err
92 case <-timedOut:
93 err = status.Error(codes.Aborted, "timeout")
khenaidoo2c6a0992019-04-29 13:46:56 -040094 }
khenaidoo2c6a0992019-04-29 13:46:56 -040095 }
Kent Hagerman8da2f1e2019-11-25 17:28:09 -050096 gotError = gotError || err != nil
97 errors = append(errors, err)
khenaidoo2c6a0992019-04-29 13:46:56 -040098 }
99
Kent Hagerman8da2f1e2019-11-25 17:28:09 -0500100 if gotError {
khenaidoo2c6a0992019-04-29 13:46:56 -0400101 return errors
102 }
103 return nil
104}