<commit_before>var BaseError = require('../error')
var Cache = require('./base')
var util = require('util')
var async = require('async')
var exec = require('child_process').exec

var CacheError = function (message) {
  BaseError.apply(this, arguments)
}
util.inherits(CacheError, BaseError)

var processIsRunning = function(pid) {
  try {
    // Attempt to ping the process.
    process.kill(pid, 0)
  } catch (ersch) {
    // If pinging the server throws an error (ESRCH), then the process isn't running.
    return false
  }

  return true
}


function Global() {
  Cache.apply(this, arguments)
}
util.inherits(Global, Cache)

Global.Error = CacheError

Global.prototype.client = function() {
  return this.impromptu.db
}

Global.prototype.run = function(fn) {
  if (this._needsRefresh) {
    this._setThenGet(fn)
  } else {
    this.get(fn)
  }
}

Global.prototype.unset = function(fn) {
  this.client().del(this.name, "lock:" + this.name, "lock-process:" + this.name, function(err, results) {
    if (fn) {
      return fn(err, !!results)
    }
  })
}

Global.prototype.get = function(fn) {
  var fallback = this.options.fallback
  return this.client().get(this.name, function(err, results) {
    if (results == null) {
      results = fallback
    }

    if (fn) {
      fn(err, results)
    }
  })
}

Global.prototype.set = function(fn) {
  var client = this.client()
  var name = this.name
  var options = this.options
  var update = this._update

  if (!this._claimSetLock(fn)) return

  // Try to update the cached value.
  async.waterfall([
    // Check if the cached value is locked (and therefore still valid).
    function(done) {
      client.exists("lock:" + name, done)
    },

    // Check if there's a process already running to update the cache.
    function(exists, done) {
      if (exists) {
        done(new CacheError('The cache is currently locked.'))
      } else {
        client.get("lock-process:" + name, done)
      }
    },

    function(pid, done) {
      if (pid && processIsRunning(pid)) {
        // There's already an update process running.
        done(new CacheError('A process is currently updating the cache.'))

      } else {
        // Time to update the cache.
        // Set the process lock.
        client.set("lock-process:" + name, process.pid, done)
      }
    },

    function(locked, done) {
      // Run the provided method to generate the new value to cache.
      update(function(err, value) {
        if (err) {
          done(err)
          return
        }

        // Update the cache with the new value and locks.
        async.parallel([
          function(fin) {
            // Update the cached value.
            client.set(name, value.toString(), fin)
          },<commit_msg>Don't cast null or undefined values to a string.<commit_after>var BaseError = require('../error')
var Cache = require('./base')
var util = require('util')
var async = require('async')
var exec = require('child_process').exec

var CacheError = function (message) {
  BaseError.apply(this, arguments)
}
util.inherits(CacheError, BaseError)

var processIsRunning = function(pid) {
  try {
    // Attempt to ping the process.
    process.kill(pid, 0)
  } catch (ersch) {
    // If pinging the server throws an error (ESRCH), then the process isn't running.
    return false
  }

  return true
}


function Global() {
  Cache.apply(this, arguments)
}
util.inherits(Global, Cache)

Global.Error = CacheError

Global.prototype.client = function() {
  return this.impromptu.db
}

Global.prototype.run = function(fn) {
  if (this._needsRefresh) {
    this._setThenGet(fn)
  } else {
    this.get(fn)
  }
}

Global.prototype.unset = function(fn) {
  this.client().del(this.name, "lock:" + this.name, "lock-process:" + this.name, function(err, results) {
    if (fn) {
      return fn(err, !!results)
    }
  })
}

Global.prototype.get = function(fn) {
  var fallback = this.options.fallback
  return this.client().get(this.name, function(err, results) {
    if (results == null) {
      results = fallback
    }

    if (fn) {
      fn(err, results)
    }
  })
}

Global.prototype.set = function(fn) {
  var client = this.client()
  var name = this.name
  var options = this.options
  var update = this._update

  if (!this._claimSetLock(fn)) return

  // Try to update the cached value.
  async.waterfall([
    // Check if the cached value is locked (and therefore still valid).
    function(done) {
      client.exists("lock:" + name, done)
    },

    // Check if there's a process already running to update the cache.
    function(exists, done) {
      if (exists) {
        done(new CacheError('The cache is currently locked.'))
      } else {
        client.get("lock-process:" + name, done)
      }
    },

    function(pid, done) {
      if (pid && processIsRunning(pid)) {
        // There's already an update process running.
        done(new CacheError('A process is currently updating the cache.'))

      } else {
        // Time to update the cache.
        // Set the process lock.
        client.set("lock-process:" + name, process.pid, done)
      }
    },

    function(locked, done) {
      // Run the provided method to generate the new value to cache.
      update(function(err, value) {
        if (err) {
          done(err)
          return
        }

        value = value == null ? '' : value.toString()

        // Update the cache with the new value and locks.
        async.parallel([
          function(fin) {
            // Update the cached value.
            client.set(name, value, fin)
          },
{'fraction_non_alphanumeric': 0.12951320280222742, 'fraction_numerical': 0.00035925992455541585, 'mean_word_length': 2.48, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '5131361', 'n_tokens_mistral': 1720, 'n_tokens_neox': 1683, 'n_words': 488}