;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- (in-package :bgp-logger) (defun xml-top-elem-from-octets (xml-octets) (dom:document-element (cxml:parse xml-octets (cxml-dom:make-dom-builder)))) (defun new-entries (top-elem) "Return BGP-MESSAGE's, one per prefix mentioned in TOP-ELEM. TOP-ELEM is an XML document element." ;; We assume that top-elem is "BGP_MESSAGE". ;(print (describe top-elem)) (let ((updates (dom:get-elements-by-tag-name top-elem "UPDATE")) (new-elements nil)) (when (> (length updates) 0) (let ((update (aref updates 0))) (when (string= (dom:tag-name (dom:parent-node update)) "ASCII_MSG") (let ((templ (make-instance 'bgp-message)) (new-prefs nil) (octet-msgs (dom:get-elements-by-tag-name top-elem "OCTET_MSG")) (prefixes (dom:get-elements-by-tag-name top-elem "PREFIX")) (time (aref (dom:get-elements-by-tag-name top-elem "TIME") 0))) ;; Populate new-prefs. (when (> (length prefixes) 0) (setf new-prefs (concatenate 'list new-elements (map 'list (lambda (p) (list (dom:data (aref (dom:child-nodes p) 0)) (dom:get-attribute p "label"))) prefixes)))) ;; TIMESTAMP and PRECISION_TIME --> template. (let ((ts (aref (dom:get-elements-by-tag-name time "TIMESTAMP") 0)) (pt (aref (dom:get-elements-by-tag-name time "PRECISION_TIME") 0))) (setf (timestamp templ) (dom:data (aref (dom:child-nodes ts) 0))) (setf (precision-time templ) (dom:data (aref (dom:child-nodes pt) 0)))) ;; AS-PATH --> template. Note that we want AS_PATH->AS ;; only, to avoid getting COMMUNITY->AS. (setf (path templ) (let ((as-paths (dom:get-elements-by-tag-name update "AS_PATH"))) (if (= 0 (length as-paths)) "{}" (let ((str "{")) (map nil (lambda (node) (let ((as (dom:data (aref (dom:child-nodes node) 0)))) (setf str (concatenate 'string str (format nil "~A," as))))) (dom:child-nodes (aref as-paths 0))) (concatenate 'string (subseq str 0 (- (length str) 1)) "}"))))) ;; NEXT_HOP --> template. (setf (nexthop templ) (let ((nexthops (dom:get-elements-by-tag-name update "NEXT_HOP"))) (if (= 0 (length nexthops)) "0.0.0.0" (dom:data (aref (dom:child-nodes (aref nexthops 0)) 0))))) ;; OCTETS --> template. (when (> (length octet-msgs) 0) (let* ((oct (aref (dom:get-elements-by-tag-name (aref octet-msgs 0) "OCTETS") 0)) (txt (aref (dom:child-nodes oct) 0))) (setf (bgp-octets templ) (dom:data txt)))) ;; Create new elements from new-prefs and the template. ;(format t "templ: ~A~%" (describe templ)) ;(format t "new-prefs: ~A~%" new-prefs) (dolist (p new-prefs) (push (new-bgp-message templ p) new-elements)))))) new-elements)) (defun new-entry-klacks (xml-doc) "Return a fresh BGP-MESSAGE built from XML-DOC (array of unsigned bytes)." (let ((s (cxml:make-source xml-doc)) (e (make-instance 'bgp-message)) (cur-name nil)) (do ((key (klacks:peek s) (klacks:peek s))) ((null key) e) (case key (:start-element (setf cur-name (klacks:current-qname s))) (:end-element (setf cur-name nil)) (:characters (let ((txt (klacks:current-characters s))) (unless (or (string= cur-name "OCTET_MSG")) (setf (slot-value e (intern cur-name)) txt))))) (klacks:consume s)))) (defun marker (mark) (format t mark) (force-output)) (defun start-bgpstore (host port) (with-connection *db-spec* (let ((reader (new-reader host port)) (count 0)) (marker (format nil "~A: bgpstore started " (iso-date (get-universal-time) t))) (do ((e (next-xml-blurb reader "BGP_MESSAGE") (next-xml-blurb reader "BGP_MESSAGE"))) ((null e)) (dolist (obj (new-entries (xml-top-elem-from-octets e))) (insert-dao obj) (incf count) (if (= 0 (mod count 10000)) (marker (format nil "~%~A: ~A " (iso-date (get-universal-time) t) count)) (if (= 0 (mod count 1000)) (marker "*") (if (= 0 (mod count 100)) (marker ".")))))) (close-reader)))) (defun stop-bgpstore ()) ;;;;