Skip to content
Snippets Groups Projects
Select Git revision
  • 352b21c4849c51b82c10fd7d4cd03ed03e160f67
  • master default protected
2 results

200114_simulation.PNG

Blame
  • oldLink.js 5.34 KiB
    /*
    
    line input
    
    */
    
    // HEADER
    import {
      Hunkify,
      Input,
      Output,
      State
    } from './hunks.js'
    // END HEADER
    
    function Link() {
      Hunkify(this, 'Link')
    
      // data in/out
      // assumed that whatever is on the other end of bytes
      // does byte / packet level flowcontrol
    
      // links can be assumed to have data ports, these ferry byteArrays always ...
      this.inputs.data = new Input('byteArray', 'data')
      this.outputs.data = new Output('byteArray', 'data')
    
      // default, 0th ip and op are messages for managers
      this.state.inputList = new State('string', 'inputList', "msgs (byteArray)")
      this.state.outputList = new State('string', 'outputList', "msgs (byteArray)")
    
      // ip and op,
      let inports = [this.inputs.zero, this.inputs.one, this.inputs.two]
      let outports = [this.outputs.zero, this.outputs.one]
      
      // ok, on init look at state list
    
      // these are *special link inputs* keeping track of downstream status
      this.inputs.zero = new Input('any', 'zero')
      this.inputs.zero.dss = 'open'
    
      this.inputs.one = new Input('any', 'one')
      this.inputs.zero.dss = 'open'
    
      this.inputs.two = new Input('any', 'two')
      this.inputs.two.dss = 'open'
    
    
      // special outputs having upstream buffers
      this.outputs.zero = new Output('any', 'zero')
      this.outputs.zero.hold = {}
      this.outputs.zero.hold.status = 'open'
      this.outputs.zero.hold.msg = {}
    
      this.outputs.one = new Output('any', 'one')
      this.outputs.one.hold = {}
      this.outputs.one.hold.status = 'open'
      this.outputs.one.hold.msg = {}
    
      this.init = () => {
        // manager calls this once
        // it is loaded and state is updated (from program)
        this.log('hello Link')
        // HERE write those inputs via that list
      }
    
      // so far we won't ack at the link layer,
      // i.e. we will assume that we can send all ports across,
      // without getting an ack back from the link
      // but we will need to do this for the dmarippers
      // perhaps that should live in the layer that 'websocket' is at now
    
    
      let outbuffer = new Array()
    
      // I think we just need to buffer
      // the outputs that we pull but can't send
    
      /*
      let msg = {
          msg: content,
          port: portnum,
          isAck: false
      }
      // or
      let msg = {
          port: portnum,
          isAck: true
      }
      */
    
      // the link level will flow control across bytes,
      // so we just flow control across ports
    
      this.loop = () => {
        // for everything we're holding, check our outputs
        for (let i in outports) {
          if (outports[i].hold.status === 'occupied' && outports[i].ie) {
            // gr8 news, we can ship it
            outports[i].put(outports.hold.msg)
            outports[i].hold.status = 'clear'
            let ack = {
              isAck: true,
              port: i
            }
            outbuffer.push(ack)
          } else {
            // we can't do anything, waiting for outside world
          }
        }
    
        // then check for messages from the data link
        if (this.inputs.data.io()) {
          // we pull every time
          let msg = this.inputs.data.get()
          // if it's an ack, we can clear an input
          if (msg.isAck) {
            if (inports[msg.port].dss !== 'await ack') {
              console.log("LINK ERROR: ACK FROM NON WAIT")
              throw new Error('link panic', msg)
            } else {
              inports[msg.port].dss = 'open'
            }
          } else {
            // otherwise we have a message for one of our outputs
            let dsport = outports[msg.port]
            // if we have one
            if (dsport !== null && dsport !== undefined) {
              if (dsport.hold.status === 'occupied') {
                // bad news, we are already waiting to send
                // but we have this new thing, so
                console.log('LINK ERROR: 2ND MSG TO NON ACKED PORT')
                throw new Error('link panic', msg)
              } else if (dsport.ie) {
                // this is easy, we can just ship it
                dsport.put(msg.msg)
                let ack = {
                  isAck: true,
                  port: msg.port
                }
                outbuffer.push(ack)
              } else {
                // well, we already pulled it off stream, so
                dsport.hold.status = 'occupied'
                dsport.hold.msg = msg.msg
                // store it locally, but don't ack
                // so we should not get another message on this port until we ack ...
                // if we do, the 1st if statement in this block will be triggered
              }
            } else {
              console.log('LINK ERROR: RECEIVES MESSAGE FOR PORT IT DOTH NOT HAVE')
              console.log(msg.port, typeof msg.port)
              // TODO: make one, and report to manager that we have done so
            }
          } // end message-not-ack
        } // end if input has bytes
    
        // now let's run over our inputs,
        for (let i in inports) {
          // if there's a message on the input, and the downstream is clear,
          if (inports[i].io() && inports[i].dss === 'open') {
            // we can send it, and reset to await an ack
            this.log('i', typeof i)
            let dsmsg = {
              msg: inports[i].get(),
              port: parseInt(i),
              isAck: false,
            }
            this.log('LNK MSG OUT', dsmsg)
            inports[i].dss = 'await ack'
            outbuffer.push(dsmsg)
          } else {
            // otherwise, there's nothing we can do but let it sit there
          }
        }
    
        // flow control outgoing messages
        // one per loop !
        if (this.outputs.data.ie && outbuffer.length > 0) {
          this.outputs.data.put(outbuffer.shift())
        }
      } // end loop
    }
    
    // FOOTER
    export default Link
    // END FOOTER