nsmcp::AccessRecordStoreSQLite method prepare (public)
<instance of nsmcp::AccessRecordStoreSQLite> prepare file
Defined in /usr/local/ns/tcl/nsmcp/log-traffic-record-store.tcl
Resolve or initialize the stored generation for a discovered log file. Validate the source prefix and committed-range anchors before reusing a generation. Writers retire or replace changed generations; readers only accept an existing active generation.
- Parameters:
- file (required)
- Discovered source descriptor, including path, identity, size and modification time.
- Returns:
- The stored file identifier, or -1 when a reader cannot use the generation.
- Testcases:
- No testcase defined.
Source code: file stat [dict get $file path] actual set identity [dict get $file identity] set policy [:dict getdef ${:settings} policy {}] set key [ns_crypto::md string -digest sha256 -- [list schema1 $identity $policy]] set fid {} set old [${:db} execute {SELECT * FROM main.files WHERE k=:key}] set f [open [dict get $file path] rb] try { set reset false if {$old ne {}} { set old [lindex $old 0] set fid [dict get $old fid] set prefix [ns_crypto::md string -digest sha256 -binary -- [read $f [dict get $old plen]]] if {[dict get $old high]>$actual(size) || $prefix ne [dict get $old prefix] || ([dict get $old high]==$actual(size) && [dict get $old stamp]!=$actual(mtime))} { set reset true } if {!$reset} { # A small boundary anchor per contiguous imported range # detects rewrites near committed cursors before reuse. foreach span [${:db} execute {SELECT hi,anchor FROM main.ranges WHERE fid=:fid LIMIT 4097}] { set hi [dict get $span hi] seek $f [expr {max(0,$hi-64)}] if {[ns_crypto::md string -digest sha256 -binary -- [read $f [expr {min(64,$hi)}]]] ne [dict get $span anchor]} { set reset true break } } } } if {${:mode} eq "reader"} { return [expr {$old eq {} || $reset || ![dict get $old active] ? -1 : $fid}] } if {$old eq {} || $reset} { set plen [expr {min(64,[dict get $file size])}] seek $f 0 set prefix [ns_crypto::md string -digest sha256 -binary -- [read $f $plen]] set high 0 set stamp [dict get $file mtime] set now [clock seconds] ${:db} transaction { if {[:dict getdef ${:settings} unified false] && $fid ne {}} { set retired "${key}:retired:$fid" set oldIdentity "${identity}:retired:$fid" ${:db} execute { UPDATE main.files SET k=:retired,identity=:oldIdentity WHERE fid=:fid } } else { if {$fid ne {}} { ${:db} execute {DELETE FROM main.rows WHERE fid=:fid} } ${:db} execute { DELETE FROM main.ranges WHERE fid=:fid; DELETE FROM main.files WHERE k=:key } } ${:db} execute { INSERT INTO main.files(k, identity, prefix, plen, high, stamp, touched) VALUES(:key, :identity, :prefix, :plen, :high, :stamp, :now) } } } } finally { close $f } set fid [${:db} scalar {SELECT fid FROM main.files WHERE k=:key}] set now [clock seconds] set touchBefore [expr {$now-max(1,min(3600,int([dict get ${:settings} retention]/4)))}] ${:db} execute {UPDATE main.files SET touched=:now WHERE fid=:fid AND touched<:touchBefore} ${:db} execute { UPDATE main.files SET active=0 WHERE identity=:identity AND fid<>:fid AND active=1; UPDATE main.files SET active=1 WHERE fid=:fid } return $fidXQL Not present: Generic, PostgreSQL, Oracle
![[i]](/resources/acs-subsite/ZoomIn16.gif)