<commit_before>var fs = require('fs');
var spawn = require('child_process').spawn;
var extend = require('util')._extend;

var Tail = require('tail').Tail;
var lib = require('./lib');
var adparser = require('./lib').adparser;

var temp = require('temp');
var Q = require('q');
var XML = require('xml-simple');

var path = require('path');

// Automatically track and cleanup files at exit
temp.track();

// Configuration for the module
exports.config = {
    condorLocation: null,
    condorConfig: null
}


function parse_attrvalue(attr) {
    if(attr.s) {
        return attr.s;
    }
    if(attr.i) {
        return parseInt(attr.i);
    }
    if(attr.b) {
        if(attr.v == "t") return true;
        return false;
    }
    if(attr.r) {
        return parseFloat(attr.r);
    }
    if(attr.e) {
        //TODO
        return "expression:"+attr.e;
    }
    console.log("don't know how to parse");
    console.dir(attr);
}

exports.Joblog = function(path) {
    var callbacks = this.callbacks = [];

    //console.log("tailing joblog "+path);
    this.tail = new Tail(path, "</c>\n");
    this.tail.on("line", function(xml) {
        xml +="</c>";
        parse_jobxml(xml, function(event) {
            if(callbacks.length == 0) {
                //I will never catch SubmitEvent, since the callback isn't registered until
                //after submission completes... But they get the job object which contains
                //pretty much the same info..
            }
            callbacks.forEach(function(callback) {
                callback(event);
            });
        });
    });

    function parse_jobxml(xml, callback) {
        XML.parse(xml, function(err, attrs) {
            if(err) {
                console.log("failed to parse job xml (skipping)");
                console.error(err);
                console.log(xml);
            } else {
                var event = {};
                attrs.a.forEach(function(attr) {
                    var name = attr['@'].n;
                    event[name] = parse_attrvalue(attr);
                });
                callback(event);
            }<commit_msg>wrapped callback with nexttick to reset call stack for better error message something goes wrong inside user callback handler<commit_after>var fs = require('fs');
var spawn = require('child_process').spawn;
var extend = require('util')._extend;

var Tail = require('tail').Tail;
var lib = require('./lib');
var adparser = require('./lib').adparser;

var temp = require('temp');
var Q = require('q');
var XML = require('xml-simple');

var path = require('path');

// Automatically track and cleanup files at exit
temp.track();

// Configuration for the module
exports.config = {
    condorLocation: null,
    condorConfig: null
}


function parse_attrvalue(attr) {
    if(attr.s) {
        return attr.s;
    }
    if(attr.i) {
        return parseInt(attr.i);
    }
    if(attr.b) {
        if(attr.v == "t") return true;
        return false;
    }
    if(attr.r) {
        return parseFloat(attr.r);
    }
    if(attr.e) {
        //TODO
        return "expression:"+attr.e;
    }
    console.log("don't know how to parse");
    console.dir(attr);
}

exports.Joblog = function(path) {
    var callbacks = this.callbacks = [];

    //console.log("tailing joblog "+path);
    this.tail = new Tail(path, "</c>\n");
    this.tail.on("line", function(xml) {
        xml +="</c>";
        parse_jobxml(xml, function(event) {
            if(callbacks.length == 0) {
                //I will never catch SubmitEvent, since the callback isn't registered until
                //after submission completes... But they get the job object which contains
                //pretty much the same info..
            }
            callbacks.forEach(function(callback) {
                //see http://howtonode.org/understanding-process-next-tick
                process.nextTick(function() {
                    callback(event);
                });
            });
        });
    });

    function parse_jobxml(xml, callback) {
        XML.parse(xml, function(err, attrs) {
            if(err) {
                console.log("failed to parse job xml (skipping)");
                console.error(err);
                console.log(xml);
            } else {
                var event = {};
                attrs.a.forEach(function(attr) {
                    var name = attr['@'].n;
                    event[name] = parse_attrvalue(attr);
                });
                callback(event);
            }
{'fraction_non_alphanumeric': 0.14035864511844146, 'fraction_numerical': 0.00044277175116227583, 'mean_word_length': 1.8813775510204083, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 20}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6548991', 'n_tokens_mistral': 1323, 'n_tokens_neox': 1282, 'n_words': 319}