go-hep.org/x/hep@v0.38.1/fwk/inputstream.go (about)

     1  // Copyright ©2017 The go-hep Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package fwk
     6  
     7  import (
     8  	"reflect"
     9  )
    10  
    11  // InputStream implements a task reading data from an InputStreamer.
    12  //
    13  // InputStream is concurrent-safe.
    14  //
    15  // InputStream declares a property 'Ports', a []fwk.Port, which will
    16  // be used to declare the output ports the streamer will publish,
    17  // loading in data from the underlying InputStreamer.
    18  //
    19  // InputStream declares a property 'Streamer', a fwk.InputStreamer,
    20  // which will be used to actually read data from.
    21  type InputStream struct {
    22  	TaskBase
    23  
    24  	streamer InputStreamer
    25  	ctrl     StreamControl
    26  }
    27  
    28  // Configure declares the output ports defined by the 'Ports' property.
    29  func (tsk *InputStream) Configure(ctx Context) error {
    30  	for _, port := range tsk.ctrl.Ports {
    31  		err := tsk.DeclOutPort(port.Name, port.Type)
    32  		if err != nil {
    33  			return err
    34  		}
    35  	}
    36  	return nil
    37  }
    38  
    39  // StartTask starts the InputStreamer task
    40  func (tsk *InputStream) StartTask(ctx Context) error {
    41  	return nil
    42  }
    43  
    44  // StopTask stops the InputStreamer task
    45  func (tsk *InputStream) StopTask(ctx Context) error {
    46  	return tsk.disconnect()
    47  }
    48  
    49  func (tsk *InputStream) connect(ctrl StreamControl) error {
    50  	ctrl.Ports = make([]Port, len(tsk.ctrl.Ports))
    51  	copy(ctrl.Ports, tsk.ctrl.Ports)
    52  
    53  	tsk.ctrl = ctrl
    54  	err := tsk.streamer.Connect(ctrl.Ports)
    55  	if err != nil {
    56  		return err
    57  	}
    58  
    59  	go tsk.read()
    60  
    61  	return err
    62  }
    63  
    64  func (tsk *InputStream) disconnect() error {
    65  	return tsk.streamer.Disconnect()
    66  }
    67  
    68  func (tsk *InputStream) read() {
    69  	for {
    70  		select {
    71  
    72  		case ctx := <-tsk.ctrl.Ctx:
    73  			tsk.ctrl.Err <- tsk.streamer.Read(ctx)
    74  
    75  		case <-tsk.ctrl.Quit:
    76  			return
    77  		}
    78  	}
    79  }
    80  
    81  // Process loads data from the underlying InputStreamer
    82  // and puts it in the event store.
    83  func (tsk *InputStream) Process(ctx Context) error {
    84  	var err error
    85  
    86  	tsk.ctrl.Ctx <- ctx
    87  	err = <-tsk.ctrl.Err
    88  
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	return err
    94  }
    95  
    96  func newInputStream(typ, name string, mgr App) (Component, error) {
    97  	var err error
    98  
    99  	tsk := &InputStream{
   100  		TaskBase: NewTask(typ, name, mgr),
   101  		streamer: nil,
   102  		ctrl: StreamControl{
   103  			Ports: make([]Port, 0),
   104  		},
   105  	}
   106  
   107  	err = tsk.DeclProp("Ports", &tsk.ctrl.Ports)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  
   112  	err = tsk.DeclProp("Streamer", &tsk.streamer)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  
   117  	return tsk, err
   118  }
   119  
   120  // inputStream provides fake input events when no input file is present
   121  type inputStream struct {
   122  	TaskBase
   123  }
   124  
   125  func (tsk *inputStream) StartTask(ctx Context) error {
   126  	return nil
   127  }
   128  
   129  func (tsk *inputStream) StopTask(ctx Context) error {
   130  	return nil
   131  }
   132  
   133  func (tsk *inputStream) Process(ctx Context) error {
   134  	return nil
   135  }
   136  
   137  func init() {
   138  	Register(reflect.TypeOf(InputStream{}), newInputStream)
   139  }