OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-sensory / examples / file-tail.scm

97 lines · scm ref:
;
; file-tail.scm -- Tailing a changing file
;
; Demo that follows (tails) a file, placing the updates into a stream,
; and attached that stream to a processing pipeline.
;
; Please review file-read.scm first; this demo expands on some of the
; techniques there.
;
(use-modules (opencog) (opencog exec) (opencog sensory))

; --------------------------------------------------------
; Open a file, and follw the changes being made to it.

(define file-node (TextFile "file:///tmp/tail.txt"))

(cog-execute!
	(SetValue file-node (Predicate "*-open-*") (Type 'StringValue)))

(cog-set-value!  file-node (Predicate "*-follow-*") (BoolValue #t))

; Read one line of text from the file. Do this by sending the *-read-*
; message to the file object.
(cog-execute! (ValueOf file-node (Predicate "*-read-*")))

; Do it again and again. Keep doing it untile one of these blocks.
; When it blocks, it will wait until more text is appended to the file.
; Thus: `echo "gaba gaba hey" >> /tmp/tail.txt` will unstick it.
(cog-execute! (ValueOf file-node (Predicate "*-read-*")))
(cog-execute! (ValueOf file-node (Predicate "*-read-*")))
(cog-execute! (ValueOf file-node (Predicate "*-read-*")))
(cog-execute! (ValueOf file-node (Predicate "*-read-*")))

; --------------------------------------------------------
; The *-stream-* message will return a handle to a StreamValue
; that will return appended lines, one by one. Referencing the
; stream will dequeue them one at a time, again blocking when
; there's nothing there.

(define txt-stream
	(cog-execute! (ValueOf file-node (Predicate "*-stream-*"))))

; Repeated references to the stream will return single lines from
; the file. Remember to `echo First rule is ... >> /tmp/tail.txt`
txt-stream
txt-stream
txt-stream

; --------------------------------------------------------
; Demo: Perform processing on the stream. For each line of the
; input file, apply a rule to rewrite it into a different form.
;
; To make the stream processor "realistic", the text-dtream source
; needs to placed somewhere, where it can be found.  Notice a trick
; used here: the `DontExec` link shelters the `ValueOf`, and prevents
; it from being executed while the SetValue is running.
(cog-execute!
	(SetValue (Concept "foo") (Predicate "some place")
		(DontExec (ValueOf file-node (Predicate "*-stream-*")))))

; Access to the stream.
(define txt-stream-gen
	(ValueOf (Concept "foo") (Predicate "some place")))

; This rule just makes two copies of each input line, interleaving
; it with other text. The `txt-stream-gen` is the source of input.
(define rule-applier
	(Filter
		(Rule
			(TypedVariable (Variable "$x") (Type 'StringValue))
			(Variable "$x")
			(LinkSignature       ; Or use List here and skip next line.
				(Type 'LinkValue)
				(Variable "$x")
				(Item "yo the first\n")
				(Variable "$x")
				(Item "yo the second\n")
				(Item "====\n")))
		txt-stream-gen))

; Run the rule, once.
(cog-execute! rule-applier)

; Repeat it again, over and over. This will block, unless the
; file is appended to. This will continue, until the text stream
; is sent the `*-close-*` message. If blocked, then the `*-close-*`
; has to be sent from another thread.
(cog-execute! rule-applier)
(cog-execute! rule-applier)
(cog-execute! rule-applier)
(cog-execute! rule-applier)
(cog-execute! rule-applier)
(cog-execute! rule-applier)

; --------------------------------------------------------
; The End! That's All, Folks!