storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/event/targetlist.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2018 MinIO, Inc.
     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   */
    16  
    17  package event
    18  
    19  import (
    20  	"fmt"
    21  	"sync"
    22  )
    23  
    24  // Target - event target interface
    25  type Target interface {
    26  	ID() TargetID
    27  	IsActive() (bool, error)
    28  	Save(Event) error
    29  	Send(string) error
    30  	Close() error
    31  	HasQueueStore() bool
    32  }
    33  
    34  // TargetList - holds list of targets indexed by target ID.
    35  type TargetList struct {
    36  	sync.RWMutex
    37  	targets map[TargetID]Target
    38  }
    39  
    40  // Add - adds unique target to target list.
    41  func (list *TargetList) Add(targets ...Target) error {
    42  	list.Lock()
    43  	defer list.Unlock()
    44  
    45  	for _, target := range targets {
    46  		if _, ok := list.targets[target.ID()]; ok {
    47  			return fmt.Errorf("target %v already exists", target.ID())
    48  		}
    49  		list.targets[target.ID()] = target
    50  	}
    51  
    52  	return nil
    53  }
    54  
    55  // Exists - checks whether target by target ID exists or not.
    56  func (list *TargetList) Exists(id TargetID) bool {
    57  	list.RLock()
    58  	defer list.RUnlock()
    59  
    60  	_, found := list.targets[id]
    61  	return found
    62  }
    63  
    64  // TargetIDResult returns result of Remove/Send operation, sets err if
    65  // any for the associated TargetID
    66  type TargetIDResult struct {
    67  	// ID where the remove or send were initiated.
    68  	ID TargetID
    69  	// Stores any error while removing a target or while sending an event.
    70  	Err error
    71  }
    72  
    73  // Remove - closes and removes targets by given target IDs.
    74  func (list *TargetList) Remove(targetIDSet TargetIDSet) {
    75  	list.Lock()
    76  	defer list.Unlock()
    77  
    78  	for id := range targetIDSet {
    79  		target, ok := list.targets[id]
    80  		if ok {
    81  			target.Close()
    82  			delete(list.targets, id)
    83  		}
    84  	}
    85  }
    86  
    87  // Targets - list all targets
    88  func (list *TargetList) Targets() []Target {
    89  	if list == nil {
    90  		return []Target{}
    91  	}
    92  
    93  	list.RLock()
    94  	defer list.RUnlock()
    95  
    96  	targets := []Target{}
    97  	for _, tgt := range list.targets {
    98  		targets = append(targets, tgt)
    99  	}
   100  
   101  	return targets
   102  }
   103  
   104  // List - returns available target IDs.
   105  func (list *TargetList) List() []TargetID {
   106  	list.RLock()
   107  	defer list.RUnlock()
   108  
   109  	keys := []TargetID{}
   110  	for k := range list.targets {
   111  		keys = append(keys, k)
   112  	}
   113  
   114  	return keys
   115  }
   116  
   117  // TargetMap - returns available targets.
   118  func (list *TargetList) TargetMap() map[TargetID]Target {
   119  	list.RLock()
   120  	defer list.RUnlock()
   121  	return list.targets
   122  }
   123  
   124  // Send - sends events to targets identified by target IDs.
   125  func (list *TargetList) Send(event Event, targetIDset TargetIDSet, resCh chan<- TargetIDResult) {
   126  	go func() {
   127  		var wg sync.WaitGroup
   128  		for id := range targetIDset {
   129  			list.RLock()
   130  			target, ok := list.targets[id]
   131  			list.RUnlock()
   132  			if ok {
   133  				wg.Add(1)
   134  				go func(id TargetID, target Target) {
   135  					defer wg.Done()
   136  					tgtRes := TargetIDResult{ID: id}
   137  					if err := target.Save(event); err != nil {
   138  						tgtRes.Err = err
   139  					}
   140  					resCh <- tgtRes
   141  				}(id, target)
   142  			} else {
   143  				resCh <- TargetIDResult{ID: id}
   144  			}
   145  		}
   146  		wg.Wait()
   147  	}()
   148  }
   149  
   150  // NewTargetList - creates TargetList.
   151  func NewTargetList() *TargetList {
   152  	return &TargetList{targets: make(map[TargetID]Target)}
   153  }