Class ::nsmcp::BoundedLogScanner

::nsmcp::BoundedLogScanner[i] create ... \
           [ -blockBytes:integer (default "4194304") ] \
           [ -buffer (default "") ] \
           [ -bufferEnd (default "0") ] \
           [ -bufferFrom (default "0") ] \
           [ -cacheDirectory:required cacheDirectory:required ] \
           [ -channel (default "") ] \
           [ -keys (default "") ] \
           [ -limit (default "") ] \
           [ -literals:required literals:required ] \
           [ -native:boolean (default "true") ] \
           [ -nativePrepared (default "false") ] \
           [ -nativeThreshold:integer (default "32") ] \
           [ -overlap (default "0") ] \
           [ -readBytes (default "65536") ] \
           [ -temporaryChannel (default "") ] \
           [ -temporaryPath (default "") ] \
           [ -windowCeiling (default "-1") ] \
           [ -windowHits (default "0") ]

Defined in /usr/local/ns/tcl/nsmcp/log-01-scanner.tcl

Class Relations

  • class: ::nx::Class[i]
  • superclass: ::nx::Object[i]
::nx::Class create ::nsmcp::BoundedLogScanner \
     -superclass ::nx::Object

Methods (to be applied on instances)

  • destroy (scripted, public)

     <instance of nsmcp::BoundedLogScanner[i]> destroy

    Testcases:
    No testcase defined.
    if {[info exists :temporaryChannel] && ${:temporaryChannel} ne ""} {catch {close ${:temporaryChannel}}}
    if {[info exists :temporaryPath] && ${:temporaryPath} ne ""} {catch {file delete -- ${:temporaryPath}}}
    next
  • find (scripted, public)

     <instance of nsmcp::BoundedLogScanner[i]> find from [ ceiling ]
    Parameters:
    from (required)
    ceiling (optional)

    Testcases:
    No testcase defined.
    if {$ceiling eq ""} {set ceiling ${:limit}}
    if {![string is entier -strict $from] || ![string is entier -strict $ceiling]
        || $from<0 || $ceiling<$from || $ceiling>${:limit}} {error "invalid scanner byte interval"}
    set position $from
    while {$position<$ceiling} {
        if {${:channel} eq ""} {
            set found [:first $position $ceiling]
            if {$found>=0} {incr :windowHits}
            return $found
        }
        if {$position<${:bufferFrom} || $position>=${:bufferEnd} || ${:windowCeiling}!=$ceiling} {
            seek ${:channel} $position
            set expected [expr {min(${:readBytes},$ceiling-$position)}]
            set bytes [read ${:channel} $expected]
            if {[string length $bytes]<$expected} {error "source ended before its fixed scanner bound"}
            :setBuffer $bytes $position $ceiling
        }
        set found [:first $position [expr {min($ceiling,${:bufferEnd})}]]
        # A short batch key near the end cannot win before a longer key
        # beginning earlier but crossing this boundary has been checked.
        if {$found>=0 && (${:bufferEnd}>=$ceiling || $found<${:bufferEnd}-${:overlap})} {incr :windowHits; return $found}
        if {${:bufferEnd}>=$ceiling} {return -1}
        if {${:windowHits}==0} {
            set :readBytes [expr {min(${:blockBytes},2*${:readBytes})}]
        } else {
            set :readBytes [expr {min(${:blockBytes},65536)}]
        }
        set position [expr {max($from,${:bufferEnd}-${:overlap})}]
        # Refill even though the overlap is inside the previous buffer.
        set :windowCeiling -1
    }
    return -1
  • load (scripted, public)

     <instance of nsmcp::BoundedLogScanner[i]> load bytes
    Parameters:
    bytes (required)

    Testcases:
    No testcase defined.
    if {${:channel} ne ""} {error "load requires an in-memory scanner"}
    if {[string length $bytes]>${:blockBytes}} {error "scanner chunk exceeds its byte bound"}
    :setBuffer $bytes 0 [string length $bytes]
    set :limit ${:bufferEnd}
  • nextLine (scripted, public)

     <instance of nsmcp::BoundedLogScanner[i]> nextLine position \
        [ filter ]
    Parameters:
    position (required)
    filter (optional, defaults to "true")

    Testcases:
    No testcase defined.
    if {${:channel} ne ""} {error "nextLine requires an in-memory scanner"}
    if {$position<0 || $position>${:limit}} {error "invalid line cursor"}
    if {$position==${:limit}} {return {}}
    if {$filter} {
        set found [:find $position]
        if {$found<0} {return {}}
        set start [expr {[string last \n ${:buffer} [expr {$found-1}]]+1}]
    } else {set start $position}
    set end [string first \n ${:buffer} $start]
    set terminated [expr {$end>=0}]
    if {!$terminated} {set end ${:limit}}
    return [dict create start $start end [expr {$end+($terminated ? 1 : 0)}]  raw [string range ${:buffer} $start [expr {$end-1}]] terminated $terminated]