<commit_before>// MODULE_NAME will be defined here.
var child_process = require('child_process');
var fs = require('fs');
var OS = require('os');
var Path = require('path');

var RS_RUNTIME_URL =
    'http://registrationcenter-download.intel.com/akdlm/irc_nas/8516/' +
    'intel_rs_sdk_runtime_websetup_8.0.24.6528.exe';
var FeatureNameMap = {
  'RS_R200_DEP': 'epv',
  'RS_R200_SP': 'scene_perception',
  'RS_R200_Face': 'face3d'
};

function RsRuntimePackagingHooks(app, configId, extraArgs, sharedState) {
  this._app = app;
  this._sharedState = sharedState;
  this._output = app.output;
  this._util = app.util;
  this._hooksTempPath = app.rootPath + Path.sep + 'hooksTemp';
  this._util.ShellJS.mkdir(this._hooksTempPath);

  this._moduleNamesFile = this._hooksTempPath + Path.sep + 'RS_MODULE_NAMES';
  this._postTaskLockFile = this._hooksTempPath + Path.sep + 'POST_TASK_LOCK';
}

RsRuntimePackagingHooks.prototype.prePackage = function(platform, callback) {
  this._app.output.info('Hooks: prePackage ' + MODULE_NAME + ' ' + platform);
  if (process.env.NO_RS_RUNTIME_HOOKS == 1 || process.env.NO_RS_RUNTIME_HOOKS == true) {
    this._app.output.warning(
        'Skip RealSense runtime packaging hooks, because NO_RS_RUNTIME_HOOKS was set.');
    callback(0);
    return;
  }
  fs.appendFileSync(this._moduleNamesFile, MODULE_NAME + ';');
  if (callback instanceof Function)
    callback(0);
};

RsRuntimePackagingHooks.prototype.postPackage = function(platform, callback) {
  this._app.output.info('Hooks: postPackage ' + MODULE_NAME + ' ' + platform);
  if (process.env.NO_RS_RUNTIME_HOOKS == 1 || process.env.NO_RS_RUNTIME_HOOKS == true) {
    this._app.output.warning(
        'Skip RealSense runtime packaging hooks, because NO_RS_RUNTIME_HOOKS was set.');
    callback(0);
    return;
  }
  // Get the lock to do post work.
  if (this._util.ShellJS.test('-f', this._postTaskLockFile)) {
    callback(0);
    return;
  }
  fs.closeSync(fs.openSync(this._postTaskLockFile, 'w'));

  // Get the generated msi file.
  var msiFile = this._app.generatedPackage;
  if (!this._util.ShellJS.test('-f', msiFile)) {
    this._output.error('Error: not msi found.');
    callback(1);
    return;
  }

  // Get the needed modules, registerred by prePackage phase.
  var modules = fs.readFileSync(this._moduleNamesFile, 'utf8');
  var length = modules.length;
  if (modules[length - 1] == ';') {
    modules = modules.substr(0, length - 1);
  }
  modules = modules.split(';');

  // Try to get the runtime installer.
  var runtimeFile = null;
  if (process.env.RS_RUNTIME_WEB_INSTALLER) {
    if (this._util.ShellJS.test('-f', process.env.RS_RUNTIME_WEB_INSTALLER)) {
      runtimeFile = process.env.RS_RUNTIME_WEB_INSTALLER;
    }
  }
  if (process.env.RS_RUNTIME_OFFLINE_INSTALLER) {
    // TODO(Donna):
    // Create right pre-bundle command line according to the modules
    // Pre-bundle the installer, so that we can just include the needed modules.
    // Bundle the customized runtime with Application MSI with correct
    // command line options.
  }
  // If no environment variables we can use to can runtime installer, we need to
  // downdown the web installer from website and then bundle it with App MSI.
  function bundleCbk(success) {
    if (callback instanceof Function) callback(success ? 0 : 1);
  }
  if (this._util.ShellJS.test('-f', runtimeFile)) {
    this.bundleThemAll(msiFile, runtimeFile, modules, bundleCbk);
    return;
  }
  this.downloadFromUrl(RS_RUNTIME_URL, '.', 10, function(runtimeFile, errorMsg) {
    if (this._util.ShellJS.test('-f', runtimeFile)) {
      this.bundleThemAll(msiFile, runtimeFile, modules, bundleCbk);
    } else {
      this._output.error('Failed to download runtime installer, ' + errorMsg);
      callback(1);
    }
  }.bind(this));
};

// Return name like:
// 'intel_rs_sdk_runtime_websetup_7.0.23.6161.exe'
function buildFileName(url) {
  return Path.basename(url);
  /*
     var name = 'intel_rs_sdk_runtime_';
     if (!offline)
     name = name + 'websetup_';
     return name + version + '.exe';
     */
}

function getWindowsVersion(appVersion) {
  // WiX wants 4 component version numbers, so append as many '.0' as needed.
  // Manifest versions are restricted to 4 parts max.
  if (!appVersion || appVersion.length < 1)
    return '0.0.0.0';
  var nComponents = appVersion.split('.').length;
  var versionPadding = new Array(4 - nComponents + 1).join('.0');
  return appVersion + versionPadding;
}

// To be used for cmd line arguments.
function InQuotes(arg) {
  return '\"' + arg + '\"';
}
RsRuntimePackagingHooks.prototype.runWix = function(basename, options, callback) {
  var candle = 'candle ' + options + ' ' + basename + '.wxs';
  this._output.info('Running "' + candle + '"');
  var child = child_process.exec(candle);

  child.stdout.on('data', function(data) {
    this.onData(data);
  }.bind(this));

  child.stderr.on('data', function(data) {
    this._output.warning(data);
  }.bind(this));

  child.on('exit', function(code, signal) {
    if (code) {
      this._output.error('Unhandled error ' + code);
      callback(false);
    } else {
      this.runWixLight(basename, options, callback);
    }
    return;
  }.bind(this));
};

RsRuntimePackagingHooks.prototype.runWixLight = function(basename, options, callback) {

  var light = 'light ' + options + ' ' + basename + '.wixobj';
  this._output.info('Running "' + light + '"');
  var child = child_process.exec(light);

  child.stdout.on('data', function(data) {
    this.onData(data);
  }.bind(this));

  child.stderr.on('data', function(data) {
    this._output.warning(data);
  }.bind(this));

  child.on('exit', function(code, signal) {
    if (code) {
      this._output.error('Unhandled error ' + code);
    }
    callback(code === 0);
    return;
  }.bind(this));
};

RsRuntimePackagingHooks.prototype.onData = function(data) {
};

RsRuntimePackagingHooks.prototype.selectIcon = function() {
  var output = this._output;
  var appPath = this._app.appPath;

  var icons = this._app.manifest.icons;
  var winIcon = null;
  if (icons && icons.length > 0) {
    for (var i = 0; i < icons.length; i++) {
      var icon = icons[i];
      var ext = Path.extname(icon.src).toLowerCase();
      if (ext === '.ico') {
        winIcon = icon.src;
        break;
      }
    }
  }

  if (winIcon) {
    winIcon = Path.join(appPath, winIcon);
  } else {
    output.warning('No icon in ".ico" format found in the manifest');
    output.warning('Using default crosswalk.ico');
    winIcon = Path.join(appPath, 'crosswalk.ico');
    this._util.ShellJS.cp(
        Path.join(__dirname, '..', '..', 'app-template', 'crosswalk.ico'), winIcon);
  }

  return winIcon;
};
// This callback of this function:
// function ([Boolean] success) {}
RsRuntimePackagingHooks.prototype.bundleThemAll =
    function(msiFile, runtimeFile, modules, callback) {
  this._output.info('Create a bundle with following files:');
  this._output.info('msiFile:' + msiFile);
  this._output.info('modules:' + modules);
  this._output.info('runtimeFile:' + runtimeFile);
  var root = this._util.XmlBuilder.create('Wix')
             .att('xmlns', 'http://schemas.microsoft.com/wix/2006/wi');
  var version = getWindowsVersion(this._app.manifest.appVersion);
  var bundle = root.ele('Bundle', {
    'Version': version,
    'IconSourceFile': this.selectIcon(),
    'UpgradeCode': this._util.NodeUuid.v1()
  });
  var bootStrapper = bundle.ele('BootstrapperApplicationRef', {
    'Id': 'WixStandardBootstrapperApplication.HyperlinkLicense'
  });
  bootStrapper.ele('bal:WixStandardBootstrapperApplication', {
    'xmlns:bal': 'http://schemas.microsoft.com/wix/BalExtension',
    'LicenseUrl': ''
  });
  var chain = bundle.ele('Chain');
  var rtCmdLine = getRuntimeCmdOptions(modules);
  this._output.info('RealSense runtime intall command:' + rtCmdLine);
  chain.ele('ExePackage', {
    'SourceFile': runtimeFile,
    'InstallCommand': rtCmdLine,
    'Vital': 'no'
  });
  chain.ele('RollbackBoundary');
  chain.ele('MsiPackage', {
    'SourceFile': msiFile,
    'ForcePerMachine': 'yes',
    'Vital': 'yes'
  });
  var xml_str = root.end({ pretty: true });
  var basename = this._app.manifest.packageId + '_with_rssdk_runtime_' + version;
  fs.writeFileSync(basename + '.wxs', xml_str);
  var wixOptions = '-v -ext WixBalExtension';
  this.runWix(InQuotes(basename), wixOptions, function(success) {
    if (success) {
      //TODO(Donna): Should we exposePackagedFile like the original
      //             process of msi file?
      var bundleExe = Path.resolve(basename + '.exe');
      if (!this._util.ShellJS.test('-f', bundleExe)) {
        this._output.error('Bundle installer could not be found ' + bundleExe);
        success = false;
      } else {
        this._output.highlight('Installer including RealSense runtime: ' + bundleExe);
      }

      // Only delete on success, for debugging reasons.
      //Move the files to hooksTempDir in case the '-k' option was used.
      this._util.ShellJS.mv('-f', basename + '.wxs', this._hooksTempPath);
      this._util.ShellJS.mv('-f', basename + '.wixobj', this._hooksTempPath);
      this._util.ShellJS.mv('-f', basename + '.wixpdb', this._hooksTempPath);
    }
    if (callback instanceof Function)
      callback(success);
  }.bind(this));
};

function getRuntimeCmdOptions(modules) {
  var features = ' --fnone=all --finstall=';
  modules.forEach(function(m, i) {
    if (FeatureNameMap.hasOwnProperty(m)) {
      features += FeatureNameMap[m];
      features += ',';
    }
  });
  features += 'core,vs_rt_2012';
  return features;
}

/**
 * Download file from a URL, checks for already existing file,
 * and returns it in case.
 * @param {String} url runtime URL string
 * @param {String} defaultPath Directory to download to if not already exists
 * @param {Number} tryTimes Max try times if download failed.
 * @param {downloadFinishedCb} callback callback function
 * @throws {FileCreationFailed} If download file could not be written.
 */
RsRuntimePackagingHooks.prototype.downloadFromUrl = function(url, defaultPath, tryTimes, callback) {
  // Namespaces

  var fileName = buildFileName(url);

  // Check for existing download in defaultPath, parent dir, and cache dir if set
  var handler = new this._util.DownloadHandler(defaultPath, fileName);
  var localDirs = [defaultPath, ''];
  if (process.env.RS_RUNTIME_CACHE_DIR)
    localDirs.push(process.env.RS_RUNTIME_CACHE_DIR);
  var localPath = handler.findLocally(localDirs);
  if (localPath) {
    this._output.info('Using cached', localPath);
    callback(localPath);
    return;
  }

  // Download
  var label = 'Downloading ' + url;
  var indicator = this._output.createFiniteProgress(label);

  var stream = handler.createStream();
  var downloader = new this._util.Downloader(url, stream);
  downloader.progress = function(progress) {
    indicator.update(progress);
  };
  downloader.get(function(errormsg) {
    indicator.done('');

    if (errormsg) {
      if (--tryTimes > 0) {
        this.downloadFromUrl(url, defaultPath, tryTimes, callback);
        return;
      }
      callback(null, errormsg);
    } else {
      var finishedPath = handler.finish(process.env.RS_RUNTIME_CACHE_DIR);
      callback(finishedPath);
    }
  }.bind(this));
};
module.exports = RsRuntimePackagingHooks;
<commit_msg>[Hooks] make the msi visible in the control panel<commit_after>// MODULE_NAME will be defined here.
var child_process = require('child_process');
var fs = require('fs');
var OS = require('os');
var Path = require('path');

var RS_RUNTIME_URL =
    'http://registrationcenter-download.intel.com/akdlm/irc_nas/8516/' +
    'intel_rs_sdk_runtime_websetup_8.0.24.6528.exe';
var FeatureNameMap = {
  'RS_R200_DEP': 'epv',
  'RS_R200_SP': 'scene_perception',
  'RS_R200_Face': 'face3d'
};

function RsRuntimePackagingHooks(app, configId, extraArgs, sharedState) {
  this._app = app;
  this._sharedState = sharedState;
  this._output = app.output;
  this._util = app.util;
  this._hooksTempPath = app.rootPath + Path.sep + 'hooksTemp';
  this._util.ShellJS.mkdir(this._hooksTempPath);

  this._moduleNamesFile = this._hooksTempPath + Path.sep + 'RS_MODULE_NAMES';
  this._postTaskLockFile = this._hooksTempPath + Path.sep + 'POST_TASK_LOCK';
}

RsRuntimePackagingHooks.prototype.prePackage = function(platform, callback) {
  this._app.output.info('Hooks: prePackage ' + MODULE_NAME + ' ' + platform);
  if (process.env.NO_RS_RUNTIME_HOOKS == 1 || process.env.NO_RS_RUNTIME_HOOKS == true) {
    this._app.output.warning(
        'Skip RealSense runtime packaging hooks, because NO_RS_RUNTIME_HOOKS was set.');
    callback(0);
    return;
  }
  fs.appendFileSync(this._moduleNamesFile, MODULE_NAME + ';');
  if (callback instanceof Function)
    callback(0);
};

RsRuntimePackagingHooks.prototype.postPackage = function(platform, callback) {
  this._app.output.info('Hooks: postPackage ' + MODULE_NAME + ' ' + platform);
  if (process.env.NO_RS_RUNTIME_HOOKS == 1 || process.env.NO_RS_RUNTIME_HOOKS == true) {
    this._app.output.warning(
        'Skip RealSense runtime packaging hooks, because NO_RS_RUNTIME_HOOKS was set.');
    callback(0);
    return;
  }
  // Get the lock to do post work.
  if (this._util.ShellJS.test('-f', this._postTaskLockFile)) {
    callback(0);
    return;
  }
  fs.closeSync(fs.openSync(this._postTaskLockFile, 'w'));

  // Get the generated msi file.
  var msiFile = this._app.generatedPackage;
  if (!this._util.ShellJS.test('-f', msiFile)) {
    this._output.error('Error: not msi found.');
    callback(1);
    return;
  }

  // Get the needed modules, registerred by prePackage phase.
  var modules = fs.readFileSync(this._moduleNamesFile, 'utf8');
  var length = modules.length;
  if (modules[length - 1] == ';') {
    modules = modules.substr(0, length - 1);
  }
  modules = modules.split(';');

  // Try to get the runtime installer.
  var runtimeFile = null;
  if (process.env.RS_RUNTIME_WEB_INSTALLER) {
    if (this._util.ShellJS.test('-f', process.env.RS_RUNTIME_WEB_INSTALLER)) {
      runtimeFile = process.env.RS_RUNTIME_WEB_INSTALLER;
    }
  }
  if (process.env.RS_RUNTIME_OFFLINE_INSTALLER) {
    // TODO(Donna):
    // Create right pre-bundle command line according to the modules
    // Pre-bundle the installer, so that we can just include the needed modules.
    // Bundle the customized runtime with Application MSI with correct
    // command line options.
  }
  // If no environment variables we can use to can runtime installer, we need to
  // downdown the web installer from website and then bundle it with App MSI.
  function bundleCbk(success) {
    if (callback instanceof Function) callback(success ? 0 : 1);
  }
  if (this._util.ShellJS.test('-f', runtimeFile)) {
    this.bundleThemAll(msiFile, runtimeFile, modules, bundleCbk);
    return;
  }
  this.downloadFromUrl(RS_RUNTIME_URL, '.', 10, function(runtimeFile, errorMsg) {
    if (this._util.ShellJS.test('-f', runtimeFile)) {
      this.bundleThemAll(msiFile, runtimeFile, modules, bundleCbk);
    } else {
      this._output.error('Failed to download runtime installer, ' + errorMsg);
      callback(1);
    }
  }.bind(this));
};

// Return name like:
// 'intel_rs_sdk_runtime_websetup_7.0.23.6161.exe'
function buildFileName(url) {
  return Path.basename(url);
  /*
     var name = 'intel_rs_sdk_runtime_';
     if (!offline)
     name = name + 'websetup_';
     return name + version + '.exe';
     */
}

function getWindowsVersion(appVersion) {
  // WiX wants 4 component version numbers, so append as many '.0' as needed.
  // Manifest versions are restricted to 4 parts max.
  if (!appVersion || appVersion.length < 1)
    return '0.0.0.0';
  var nComponents = appVersion.split('.').length;
  var versionPadding = new Array(4 - nComponents + 1).join('.0');
  return appVersion + versionPadding;
}

// To be used for cmd line arguments.
function InQuotes(arg) {
  return '\"' + arg + '\"';
}
RsRuntimePackagingHooks.prototype.runWix = function(basename, options, callback) {
  var candle = 'candle ' + options + ' ' + basename + '.wxs';
  this._output.info('Running "' + candle + '"');
  var child = child_process.exec(candle);

  child.stdout.on('data', function(data) {
    this.onData(data);
  }.bind(this));

  child.stderr.on('data', function(data) {
    this._output.warning(data);
  }.bind(this));

  child.on('exit', function(code, signal) {
    if (code) {
      this._output.error('Unhandled error ' + code);
      callback(false);
    } else {
      this.runWixLight(basename, options, callback);
    }
    return;
  }.bind(this));
};

RsRuntimePackagingHooks.prototype.runWixLight = function(basename, options, callback) {

  var light = 'light ' + options + ' ' + basename + '.wixobj';
  this._output.info('Running "' + light + '"');
  var child = child_process.exec(light);

  child.stdout.on('data', function(data) {
    this.onData(data);
  }.bind(this));

  child.stderr.on('data', function(data) {
    this._output.warning(data);
  }.bind(this));

  child.on('exit', function(code, signal) {
    if (code) {
      this._output.error('Unhandled error ' + code);
    }
    callback(code === 0);
    return;
  }.bind(this));
};

RsRuntimePackagingHooks.prototype.onData = function(data) {
};

RsRuntimePackagingHooks.prototype.selectIcon = function() {
  var output = this._output;
  var appPath = this._app.appPath;

  var icons = this._app.manifest.icons;
  var winIcon = null;
  if (icons && icons.length > 0) {
    for (var i = 0; i < icons.length; i++) {
      var icon = icons[i];
      var ext = Path.extname(icon.src).toLowerCase();
      if (ext === '.ico') {
        winIcon = icon.src;
        break;
      }
    }
  }

  if (winIcon) {
    winIcon = Path.join(appPath, winIcon);
  } else {
    output.warning('No icon in ".ico" format found in the manifest');
    output.warning('Using default crosswalk.ico');
    winIcon = Path.join(appPath, 'crosswalk.ico');
    this._util.ShellJS.cp(
        Path.join(__dirname, '..', '..', 'app-template', 'crosswalk.ico'), winIcon);
  }

  return winIcon;
};
// This callback of this function:
// function ([Boolean] success) {}
RsRuntimePackagingHooks.prototype.bundleThemAll =
    function(msiFile, runtimeFile, modules, callback) {
  this._output.info('Create a bundle with following files:');
  this._output.info('msiFile:' + msiFile);
  this._output.info('modules:' + modules);
  this._output.info('runtimeFile:' + runtimeFile);
  var root = this._util.XmlBuilder.create('Wix')
             .att('xmlns', 'http://schemas.microsoft.com/wix/2006/wi');
  var version = getWindowsVersion(this._app.manifest.appVersion);
  var bundle = root.ele('Bundle', {
    'Version': version,
    'IconSourceFile': this.selectIcon(),
    'UpgradeCode': this._util.NodeUuid.v1()
  });
  var bootStrapper = bundle.ele('BootstrapperApplicationRef', {
    'Id': 'WixStandardBootstrapperApplication.HyperlinkLicense'
  });
  bootStrapper.ele('bal:WixStandardBootstrapperApplication', {
    'xmlns:bal': 'http://schemas.microsoft.com/wix/BalExtension',
    'LicenseUrl': ''
  });
  var chain = bundle.ele('Chain');
  var rtCmdLine = getRuntimeCmdOptions(modules);
  this._output.info('RealSense runtime intall command:' + rtCmdLine);
  chain.ele('ExePackage', {
    'SourceFile': runtimeFile,
    'InstallCommand': rtCmdLine,
    'Vital': 'no'
  });
  chain.ele('RollbackBoundary');
  chain.ele('MsiPackage', {
    'SourceFile': msiFile,
    'ForcePerMachine': 'yes',
    'Visible': 'yes',
    'Vital': 'yes'
  });
  var xml_str = root.end({ pretty: true });
  var basename = this._app.manifest.packageId + '_with_rssdk_runtime_' + version;
  fs.writeFileSync(basename + '.wxs', xml_str);
  var wixOptions = '-v -ext WixBalExtension';
  this.runWix(InQuotes(basename), wixOptions, function(success) {
    if (success) {
      //TODO(Donna): Should we exposePackagedFile like the original
      //             process of msi file?
      var bundleExe = Path.resolve(basename + '.exe');
      if (!this._util.ShellJS.test('-f', bundleExe)) {
        this._output.error('Bundle installer could not be found ' + bundleExe);
        success = false;
      } else {
        this._output.highlight('Installer including RealSense runtime: ' + bundleExe);
      }

      // Only delete on success, for debugging reasons.
      //Move the files to hooksTempDir in case the '-k' option was used.
      this._util.ShellJS.mv('-f', basename + '.wxs', this._hooksTempPath);
      this._util.ShellJS.mv('-f', basename + '.wixobj', this._hooksTempPath);
      this._util.ShellJS.mv('-f', basename + '.wixpdb', this._hooksTempPath);
    }
    if (callback instanceof Function)
      callback(success);
  }.bind(this));
};

function getRuntimeCmdOptions(modules) {
  var features = ' --fnone=all --finstall=';
  modules.forEach(function(m, i) {
    if (FeatureNameMap.hasOwnProperty(m)) {
      features += FeatureNameMap[m];
      features += ',';
    }
  });
  features += 'core,vs_rt_2012';
  return features;
}

/**
 * Download file from a URL, checks for already existing file,
 * and returns it in case.
 * @param {String} url runtime URL string
 * @param {String} defaultPath Directory to download to if not already exists
 * @param {Number} tryTimes Max try times if download failed.
 * @param {downloadFinishedCb} callback callback function
 * @throws {FileCreationFailed} If download file could not be written.
 */
RsRuntimePackagingHooks.prototype.downloadFromUrl = function(url, defaultPath, tryTimes, callback) {
  // Namespaces

  var fileName = buildFileName(url);

  // Check for existing download in defaultPath, parent dir, and cache dir if set
  var handler = new this._util.DownloadHandler(defaultPath, fileName);
  var localDirs = [defaultPath, ''];
  if (process.env.RS_RUNTIME_CACHE_DIR)
    localDirs.push(process.env.RS_RUNTIME_CACHE_DIR);
  var localPath = handler.findLocally(localDirs);
  if (localPath) {
    this._output.info('Using cached', localPath);
    callback(localPath);
    return;
  }

  // Download
  var label = 'Downloading ' + url;
  var indicator = this._output.createFiniteProgress(label);

  var stream = handler.createStream();
  var downloader = new this._util.Downloader(url, stream);
  downloader.progress = function(progress) {
    indicator.update(progress);
  };
  downloader.get(function(errormsg) {
    indicator.done('');

    if (errormsg) {
      if (--tryTimes > 0) {
        this.downloadFromUrl(url, defaultPath, tryTimes, callback);
        return;
      }
      callback(null, errormsg);
    } else {
      var finishedPath = handler.finish(process.env.RS_RUNTIME_CACHE_DIR);
      callback(finishedPath);
    }
  }.bind(this));
};
module.exports = RsRuntimePackagingHooks;
<|endoftext|>


<commit_before>tabris.load(function() {

  var IMAGE_PATH = "images/";
  var IMAGE_SIZE = 128;
  var THUMB_SIZE = 64;
  var MARGIN_SMALL = 4;
  var MARGIN = 12;
  var MARGIN_LARGE = 24;
  var ANIMATION_START_DELAY = 500;

  var people = [
    ["Holger", "Staudacher", "holger.jpg"],
    ["Ian", "Bull", "ian.jpg"],
    ["Jochen", "Krause", "jochen.jpg"],
    ["Jordi ", "Böhme López", "jordi.jpg"],
    ["Markus ", "Knauer", "markus.jpg"],
    ["Moritz", "Post", "moritz.jpg"],
    ["Tim", "Buschtöns", "tim.jpg"]
  ].map(function(element) {
    return {firstName: element[0], lastName: element[1], image: IMAGE_PATH + element[2]};
  });

  function animateInFromBottom(widget, i) {
    widget.set({
      opacity: 0.0,
      transform: {
        translationY: THUMB_SIZE / 2
      }
    });
    tabris.create("_Animation", {
      target: widget,
      delay: i * 100 + 800 + ANIMATION_START_DELAY,
      duration: 200,
      easing: "ease-in-out",
      properties: {
        opacity: 1.0,
        transform: {
          translationY: 0
        }
      }
    }).on("Completion", function() {
      this.dispose();
    }).call("start");
  }

  function animateInFromRight(widget, delay) {
    widget.set({
      opacity: 0.0,
      transform: {
        translationX: 32
      }
    });
    tabris.create("_Animation", {
      target: widget,
      duration: 500,
      delay: delay,
      easing: "ease-out",
      properties: {
        opacity: 1.0,
        transform: {
          translationX: 0
        }
      }
    }).on("Completion", function() {
      this.dispose();
    }).call("start");
  }

  function animateInScaleUp(widget, delay) {
    widget.set("opacity", 0.0);
    tabris.create("_Animation", {
      target: widget,
      delay: delay,
      duration: 400,
      easing: "ease-out",
      properties: {
        opacity: 1.0,
        transform: {
          scaleX: 1.0,
          scaleY: 1.0
        }
      }
    }).on("Completion", function() {
      this.dispose();
    }).call("start");
  }

  function animateOutLeftCreateCurrentPerson(person) {
    tabris.create("_Animation", {
      target: curPersonDetailComposite,
      duration: 500,
      easing: "ease-out",
      properties: {
        opacity: 0.0,
        transform: {
          translationX: -64
        }
      }
    }).on("Completion", function() {
      this.dispose();
      curPersonDetailComposite.dispose();
      curPersonDetailComposite = createPersonDetail(personDetailsCompositeParent, person, 0);
    }).call("start");
  }

  function createPersonDetail(parent, person, delay) {
    var composite = tabris.create("Composite", {
      layoutData: {left: 0, right: 0, top: 0, height: IMAGE_SIZE + MARGIN_LARGE}
    });
    var imageLabel = tabris.create("Label", {
      image: {src: person.image, width: IMAGE_SIZE, height: IMAGE_SIZE},
      transform: {
        scaleX: 0.75,
        scaleY: 0.75
      },
      opacity: 0.0
    });
    var nameLabel = tabris.create("Label", {
      layoutData: {left: [imageLabel, MARGIN], top: 0},
      text: person.firstName + " " + person.lastName,
      font: "bold 18px"
    });
    var professionLabel = tabris.create("Label", {
      layoutData: {left: [imageLabel, MARGIN], top: [nameLabel, MARGIN]},
      text: "Software developer"
    });
    var companyLabel = tabris.create("Label", {
      layoutData: {left: [imageLabel, MARGIN], top: [professionLabel, MARGIN_SMALL]},
      text: "EclipseSource"
    });
    var mailLabel = tabris.create("Label", {
      layoutData: {left: [imageLabel, MARGIN], top: [companyLabel, MARGIN]},
      text: "mail@eclipsesource.com",
      font: "italic 14px"
    });
    parent.append(composite);
    composite.append(imageLabel, nameLabel, professionLabel, companyLabel, mailLabel);
    animateInScaleUp(imageLabel, delay);
    animateInFromRight(nameLabel, delay);
    animateInFromRight(professionLabel, 100 + delay);
    animateInFromRight(companyLabel, 200 + delay);
    animateInFromRight(mailLabel, 300 + delay);
    return composite;
  }

  function createPersonThumbComposite(parent, neighborComposite, person) {
    var layoutData;
    if (neighborComposite === undefined) {
      layoutData = {left: 0, top: 0};
    } else {
      layoutData = {top: 0, left: [neighborComposite, MARGIN]};
    }
    var composite = tabris.create("Composite", {
      layoutData: layoutData
    });
    var imageLabel = tabris.create("Label", {
      layoutData: {left: 0, top: 0, width: THUMB_SIZE, height: THUMB_SIZE},
      image: {src: person.image, width: THUMB_SIZE, height: THUMB_SIZE},
      data: {showTouch: true}
    });
    imageLabel.on("touchend", function() {
      animateOutLeftCreateCurrentPerson(person);
    });
    var firstNameLabel = tabris.create("Label", {
      alignment: "center",
      layoutData: {left: 0, top: [imageLabel, 0], width: THUMB_SIZE},
      text: person.firstName
    });
    parent.append(composite);
    composite.append(imageLabel, firstNameLabel);
    return composite;
  }

  function createPersonThumbComposites(parent) {
    var composite;
    for (var i = 0; i < people.length; i++) {
      composite = createPersonThumbComposite(parent, composite, people[i]);
      animateInFromBottom(composite, i);
    }
  }

  var page = tabris.create("Page", {
    title: "People",
    topLevel: true
  });

  var personDetailsCompositeParent = tabris.create("Composite", {
    layoutData: {left: MARGIN, top: MARGIN_LARGE, right: MARGIN}
  });

  var curPersonDetailComposite = createPersonDetail(personDetailsCompositeParent, people[2], ANIMATION_START_DELAY);

  var peopleComposite = tabris.create("Composite", {
    layoutData: {left: MARGIN, top: [personDetailsCompositeParent, MARGIN]}
  });

  page.append(personDetailsCompositeParent, peopleComposite);
  createPersonThumbComposites(peopleComposite);

  page.open();

});
<commit_msg>Update people animation example to use new API<commit_after>tabris.load(function() {

  var IMAGE_PATH = "images/";
  var IMAGE_SIZE = 128;
  var THUMB_SIZE = 64;
  var MARGIN_SMALL = 4;
  var MARGIN = 12;
  var MARGIN_LARGE = 24;
  var ANIMATION_START_DELAY = 500;

  var people = [
    ["Holger", "Staudacher", "holger.jpg"],
    ["Ian", "Bull", "ian.jpg"],
    ["Jochen", "Krause", "jochen.jpg"],
    ["Jordi ", "Böhme López", "jordi.jpg"],
    ["Markus ", "Knauer", "markus.jpg"],
    ["Moritz", "Post", "moritz.jpg"],
    ["Tim", "Buschtöns", "tim.jpg"]
  ].map(function(element) {
    return {firstName: element[0], lastName: element[1], image: IMAGE_PATH + element[2]};
  });

  var page = tabris.create("Page", {
    title: "People",
    topLevel: true
  });

  var personDetailsParent = tabris.create("Composite", {
    layoutData: {left: MARGIN, top: MARGIN_LARGE, right: MARGIN}
  }).appendTo(page);

  var personDetailView = createPersonDetail(personDetailsParent, people[2], ANIMATION_START_DELAY);

  var peopleComposite = tabris.create("Composite", {
    layoutData: {left: MARGIN, top: [personDetailsParent, MARGIN], right: 1000}
  }).appendTo(page);

  people.forEach(function(person, index) {
    var composite = createPersonThumbView(peopleComposite, person);
    animateInFromBottom(composite, index);
  });

  page.open();

  function animateInFromBottom(widget, index) {
    widget.set({
      opacity: 0.0,
      transform: {translationY: THUMB_SIZE / 2}
    });
    widget.animate({
      opacity: 1.0,
      transform: {translationY: 0}
    }, {
      delay: index * 100 + 800 + ANIMATION_START_DELAY,
      duration: 200,
      easing: "ease-in-out"
    });
  }

  function animateInFromRight(widget, delay) {
    widget.set({
      opacity: 0.0,
      transform: {translationX: 32}
    });
    widget.animate({
        opacity: 1.0,
        transform: {translationX: 0}
      }, {
        duration: 500,
        delay: delay,
        easing: "ease-out"
      }
    );
  }

  function animateInScaleUp(widget, delay) {
    widget.set("opacity", 0.0);
    widget.animate({
      opacity: 1.0,
      transform: {scaleX: 1.0, scaleY: 1.0}
    }, {
      delay: delay,
      duration: 400,
      easing: "ease-out"
    });
  }

  function animateOutLeftCreateCurrentPerson(person) {
    // this animation uses internal api to get notified when the animation ended
    // the callback will be exposed via official api soon
    tabris.create("_Animation", {
      target: personDetailView,
      duration: 500,
      easing: "ease-out",
      properties: {
        opacity: 0.0,
        transform: {
          translationX: -64
        }
      }
    }).on("Completion", function() {
      this.dispose();
      personDetailView.dispose();
      personDetailView = createPersonDetail(personDetailsParent, person, 0);
    }).call("start");
  }

  function createPersonDetail(parent, person, delay) {
    var composite = tabris.create("Composite", {
      layoutData: {left: 0, right: 0, top: 0, height: IMAGE_SIZE + MARGIN_LARGE}
    });
    var personImage = tabris.create("ImageView", {
      layoutData: {left: 0, top: 0, width: IMAGE_SIZE, height: IMAGE_SIZE},
      image: {src: person.image, width: IMAGE_SIZE, height: IMAGE_SIZE},
      transform: {
        scaleX: 0.75,
        scaleY: 0.75
      },
      opacity: 0.0
    });
    var nameLabel = tabris.create("Label", {
      layoutData: {left: [personImage, MARGIN], top: 0},
      text: person.firstName + " " + person.lastName,
      font: "bold 18px"
    });
    var professionLabel = tabris.create("Label", {
      layoutData: {left: [personImage, MARGIN], top: [nameLabel, MARGIN]},
      text: "Software developer"
    });
    var companyLabel = tabris.create("Label", {
      layoutData: {left: [personImage, MARGIN], top: [professionLabel, MARGIN_SMALL]},
      text: "EclipseSource"
    });
    var mailLabel = tabris.create("Label", {
      layoutData: {left: [personImage, MARGIN], top: [companyLabel, MARGIN]},
      text: "mail@eclipsesource.com",
      font: "italic 14px"
    });
    parent.append(composite);
    composite.append(personImage, nameLabel, professionLabel, companyLabel, mailLabel);
    animateInScaleUp(personImage, delay);
    animateInFromRight(nameLabel, delay);
    animateInFromRight(professionLabel, 100 + delay);
    animateInFromRight(companyLabel, 200 + delay);
    animateInFromRight(mailLabel, 300 + delay);
    return composite;
  }

  function createPersonThumbView(parent, person) {
    var neighbor = parent.children().pop();
    var composite = tabris.create("Composite", {
      layoutData: {left: neighbor ? [neighbor, MARGIN] : 0, top: 0}
    }).appendTo(parent);
    var personView = tabris.create("ImageView", {
      layoutData: {left: 0, top: 0, width: THUMB_SIZE, height: THUMB_SIZE},
      image: {src: person.image, width: THUMB_SIZE, height: THUMB_SIZE},
      data: {showTouch: true} // internal API
    }).on("touchend", function() {
      animateOutLeftCreateCurrentPerson(person);
    }).appendTo(composite);
    tabris.create("Label", {
      alignment: "center",
      layoutData: {left: 0, top: [personView, 0], width: THUMB_SIZE},
      text: person.firstName
    }).appendTo(composite);
    return composite;
  }

});
<|endoftext|>


<commit_before>define(
    [
        'jquery',
        'CheckoutCom_Magento2/js/view/payment/config-loader',
        'Magento_Checkout/js/model/quote',
        'Magento_Checkout/js/checkout-data',
        'mage/url',
        'Magento_Checkout/js/action/redirect-on-success',
        'Magento_Checkout/js/model/full-screen-loader',
        'mage/translate',
        'mage/cookies'
    ],
    function ($, Config, Quote, CheckoutData, Url, RedirectOnSuccessAction, FullScreenLoader, __) {
        'use strict';

        const KEY_CONFIG = 'checkoutcom_configuration';
        const KEY_DATA = 'checkoutcom_data';

        return {
            /**
             * Gets a field value.
             *
             * @param  {string}  methodId The method id
             * @param  {string}  field    The field
             * @return {mixed}            The value
             */
            getValue: function (methodId, field) {
                var val = null;
                if (methodId && Config.hasOwnProperty(methodId) && Config[methodId].hasOwnProperty(field)) {
                    val = Config[methodId][field]
                } else if (Config.hasOwnProperty(KEY_CONFIG) && Config[KEY_CONFIG].hasOwnProperty(field)) {
                    val = Config[KEY_CONFIG][field];
                }

                return val;
            },

            getStoreName: function () {
                return Config[KEY_DATA].store.name;
            },

            getQuoteValue: function () {
                return Config[KEY_DATA].quote.value;
            },

            getQuoteCurrency: function () {
                return Config[KEY_DATA].quote.currency;
            },

            userHasCards: function () {
                return Config[KEY_DATA].user.hasCards;
            },

            /**
             * Builds the controller URL.
             *
             * @param  {string}  path  The path
             * @return {string}
             */
            getUrl: function (path) {
                return Url.build('checkout_com/' + path);
            },

            /**
             * Customer name.
             *
             * @param  {bool} return in object format.
             * @return {mixed}  The billing address.
             */
            getCustomerName: function (obj = false) {
                var billingAddress = Quote.billingAddress();
                if (billingAddress) {
                    name = {
                        first_name: billingAddress.firstname,
                        last_name: billingAddress.lastname
                    };

                    if (!obj) {
                        name = name.first_name + ' ' + name.last_name
                    }

                    return name;
                }

                return null;
            },

            /**
             * Billing address.
             *
             * @return {object}  The billing address.
             */
            getBillingAddress: function () {
                return Quote.billingAddress();
            },

            /**
             * @returns {string}
             */
            getEmail: function () {
                return window.checkoutConfig.customerData.email || Quote.guestEmail || CheckoutData.getValidatedEmailValue();
            },

            /**
             * @returns {void}
             */
            setEmail: function () {
                $.cookie(
                    this.getValue(null, 'email_cookie_name'),
                    this.getEmail()
                );
            },

            /**
             * @returns {object}
             */
            getPhone: function () {
                var billingAddress = Quote.billingAddress();

                return {
                    number: billingAddress.telephone
                };
            },

            /**
             * Handle error logging.
             */
            log: function (val) {
                if (this.getValue(null, 'debug')
                    && this.getValue(null, 'console_logging')
                ) {
                    console.log(val);
                }
            },

            /**
             * Show a message.
             */
            showMessage: function (type, message, methodId) {
                this.clearMessages(methodId);
                var messageContainer = this.getMethodContainer(methodId).find('.message');
                messageContainer.addClass('message-' + type + ' ' + type);
                messageContainer.append('
' + __(message) + '
');
                messageContainer.show();
            },

            /**
             * Clear all messages.
             */
            clearMessages: function (methodId) {
                var messageContainer = this.getMethodContainer(methodId).find('.message');
                messageContainer.hide();
                messageContainer.empty();
            },

            /**
             * Get a payment method container instance.
             */
            getMethodContainer: function (methodId) {
                return $('#' + methodId + '_container');
            },

            /**
             * Check if an URL is valid.
             */
            isUrl: function (str) {
                var pattern = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/;
                return pattern.test(str);
            },

            /**
             * Handle the place order button state.
             */
            allowPlaceOrder: function (buttonId, yesNo) {
                $('#' + buttonId).prop('disabled', !yesNo);
            },

            /**
             * Place a new order.
             *
             * @returns {void}
             */
            placeOrder: function (payload, methodId) {
                var self = this;

                // Start the loader
                FullScreenLoader.startLoader();

                // Send the request
                $.ajax({
                    type: 'POST',
                    url: self.getUrl('payment/placeorder'),
                    data: payload,
                    success: function (data) {
                        if (!data.success) {
                            FullScreenLoader.stopLoader();
                            self.showMessage('error', data.message, methodId);
                        } else if (data.success && data.url) {
                            // Handle 3DS redirection
                            window.location.href = data.url
                        } else {
                            // Normal redirection
                            RedirectOnSuccessAction.execute();
                        }
                    },
                    error: function (request, status, error) {
                        self.showMessage('error', error, methodId);
                        FullScreenLoader.stopLoader();
                    }
                });
            }
        };
    }
);
<commit_msg>Updated the customer name handling in Frames payments<commit_after>define(
    [
        'jquery',
        'CheckoutCom_Magento2/js/view/payment/config-loader',
        'Magento_Checkout/js/model/quote',
        'Magento_Checkout/js/checkout-data',
        'mage/url',
        'Magento_Checkout/js/action/redirect-on-success',
        'Magento_Checkout/js/model/full-screen-loader',
        'mage/translate',
        'mage/cookies'
    ],
    function ($, Config, Quote, CheckoutData, Url, RedirectOnSuccessAction, FullScreenLoader, __) {
        'use strict';

        const KEY_CONFIG = 'checkoutcom_configuration';
        const KEY_DATA = 'checkoutcom_data';

        return {
            /**
             * Gets a field value.
             *
             * @param  {string}  methodId The method id
             * @param  {string}  field    The field
             * @return {mixed}            The value
             */
            getValue: function (methodId, field) {
                var val = null;
                if (methodId && Config.hasOwnProperty(methodId) && Config[methodId].hasOwnProperty(field)) {
                    val = Config[methodId][field]
                } else if (Config.hasOwnProperty(KEY_CONFIG) && Config[KEY_CONFIG].hasOwnProperty(field)) {
                    val = Config[KEY_CONFIG][field];
                }

                return val;
            },

            getStoreName: function () {
                return Config[KEY_DATA].store.name;
            },

            getQuoteValue: function () {
                return Config[KEY_DATA].quote.value;
            },

            getQuoteCurrency: function () {
                return Config[KEY_DATA].quote.currency;
            },

            userHasCards: function () {
                return Config[KEY_DATA].user.hasCards;
            },

            /**
             * Builds the controller URL.
             *
             * @param  {string}  path  The path
             * @return {string}
             */
            getUrl: function (path) {
                return Url.build('checkout_com/' + path);
            },

            /**
             * Customer name.
             *
             * @param  {bool} return in object format.
             * @return {mixed}  The billing address.
             */
            getCustomerName: function () {
                var billingAddress = Quote.billingAddress();
                var customerName = '';
                if (billingAddress) {
                    customerName += billingAddress.firstname;
                    customerName += ' ' + billingAddress.lastname;
                }

                return customerName;
            },

            /**
             * Billing address.
             *
             * @return {object}  The billing address.
             */
            getBillingAddress: function () {
                return Quote.billingAddress();
            },

            /**
             * @returns {string}
             */
            getEmail: function () {
                return window.checkoutConfig.customerData.email || Quote.guestEmail || CheckoutData.getValidatedEmailValue();
            },

            /**
             * @returns {void}
             */
            setEmail: function () {
                $.cookie(
                    this.getValue(null, 'email_cookie_name'),
                    this.getEmail()
                );
            },

            /**
             * @returns {object}
             */
            getPhone: function () {
                var billingAddress = Quote.billingAddress();

                return {
                    number: billingAddress.telephone
                };
            },

            /**
             * Handle error logging.
             */
            log: function (val) {
                if (this.getValue(null, 'debug')
                    && this.getValue(null, 'console_logging')
                ) {
                    console.log(val);
                }
            },

            /**
             * Show a message.
             */
            showMessage: function (type, message, methodId) {
                this.clearMessages(methodId);
                var messageContainer = this.getMethodContainer(methodId).find('.message');
                messageContainer.addClass('message-' + type + ' ' + type);
                messageContainer.append('
' + __(message) + '
');
                messageContainer.show();
            },

            /**
             * Clear all messages.
             */
            clearMessages: function (methodId) {
                var messageContainer = this.getMethodContainer(methodId).find('.message');
                messageContainer.hide();
                messageContainer.empty();
            },

            /**
             * Get a payment method container instance.
             */
            getMethodContainer: function (methodId) {
                return $('#' + methodId + '_container');
            },

            /**
             * Check if an URL is valid.
             */
            isUrl: function (str) {
                var pattern = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/;
                return pattern.test(str);
            },

            /**
             * Handle the place order button state.
             */
            allowPlaceOrder: function (buttonId, yesNo) {
                $('#' + buttonId).prop('disabled', !yesNo);
            },

            /**
             * Place a new order.
             *
             * @returns {void}
             */
            placeOrder: function (payload, methodId) {
                var self = this;

                // Start the loader
                FullScreenLoader.startLoader();

                // Send the request
                $.ajax({
                    type: 'POST',
                    url: self.getUrl('payment/placeorder'),
                    data: payload,
                    success: function (data) {
                        if (!data.success) {
                            FullScreenLoader.stopLoader();
                            self.showMessage('error', data.message, methodId);
                        } else if (data.success && data.url) {
                            // Handle 3DS redirection
                            window.location.href = data.url
                        } else {
                            // Normal redirection
                            RedirectOnSuccessAction.execute();
                        }
                    },
                    error: function (request, status, error) {
                        self.showMessage('error', error, methodId);
                        FullScreenLoader.stopLoader();
                    }
                });
            }
        };
    }
);
<|endoftext|>


<commit_before>/*    Copyright 2019-2020 Firewalla Inc.
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

'use strict';

const log = require("../../net2/logger.js")(__filename, "info");

const util = require('util');

const f = require('../../net2/Firewalla.js');
const logFolder = f.getLogFolder();

const config = require("../../net2/config.js").getConfig();

const df = util.promisify(require('node-df'))

const os = require('../../vendor_lib/osutils.js');

const exec = require('child-process-promise').exec;
const { execSync } = require('child_process')

const rclient = require('../../util/redis_manager.js').getRedisClient()

const platformLoader = require('../../platform/PlatformLoader.js');
const platform = platformLoader.getPlatform();

const rateLimit = require('../../extension/ratelimit/RateLimit.js');

const fs = require('fs');

let cpuUsage = 0;
let realMemUsage = 0;
let usedMem = 0;
let allMem = 0;
let curTemp = 0;
let peakTemp = 0;

let conn = 0;
let peakConn = 0;

let rateLimitInfo = null;

let redisMemory = 0;

let updateFlag = 0;

let updateInterval = 600 * 1000; // every 10 minutes

let threadInfo = {};

let diskInfo = null;

let intelQueueSize = 0;

let multiProfileSupport = false;

let no_auto_upgrade = false;

let uptimeInfo = {};
let updateTime = null;

let maxPid = 0;
let activeContainers = 0;

getMultiProfileSupportFlag();

async function update() {
  await Promise.all([
    // this takes 10s
    os.cpuUsage().then((v) => cpuUsage = v),

    // Redis
    getRedisMemoryUsage()
      .then(getConns)
      .then(getIntelQueueSize)
      .then(getRateLimitInfo),

    // bash
    getRealMemoryUsage()
      .then(getTemp)
      .then(getThreadInfo)
      .then(getDiskInfo)
      .then(getMultiProfileSupportFlag)
      .then(getAutoUpgrade)
      .then(getUptimeInfo)
      .then(getMaxPid)
      .then(getActiveContainers)
  ])

  if(updateFlag) {
    setTimeout(() => { update(); }, updateInterval);
  }
}

function startUpdating() {
  updateFlag = 1;
  update();
}

function stopUpdating() {
  updateFlag = 0;
}

async function getThreadInfo() {
  try {
    const count = await exec("ps -Haux | wc -l", {encoding: 'utf8'});
    const mainCount = await exec("ps -Haux | grep Fi[r]eMain | wc -l", {encoding: 'utf8'});
    const apiCount = await exec("ps -Haux | grep Fi[r]eApi | wc -l", {encoding: 'utf8'});
    const monitorCount = await exec("ps -Haux | grep Fi[r]eMon | wc -l", {encoding: 'utf8'});
    threadInfo.count = count.stdout.replace("\n", "");
    threadInfo.mainCount = mainCount.stdout.replace("\n", "");
    threadInfo.apiCount = apiCount.stdout.replace("\n", "");
    threadInfo.monitorCount = monitorCount.stdout.replace("\n", "");
  } catch(err) {
    log.error("Failed to get thread info", err);
  }
}

async function getUptimeInfo() {
  try {
    uptimeInfo.fireMain = 0;
    uptimeInfo.FireApi = 0;
    uptimeInfo.FireMon = 0;
    uptimeInfo.bitbridge6 = 0;
    uptimeInfo.bitbridge7 = 0;
    uptimeInfo.dnscrypt = 0;
    uptimeInfo.dnsmasq = 0;
    uptimeInfo.openvpn = 0;

    const cmdResult = await exec("ps -eo etimes,cmd | awk '{print $1, $2}'", {encoding: 'utf8'});
    let lines = cmdResult.stdout.split("\n");
    lines.shift();
    lines.pop();
    updateTime = Date.now() / 1000;
    for (const line of lines) {
      let contents = line.split(' ');
      if (contents[1] == "FireMain") {
        uptimeInfo.fireMain = Number(contents[0])
      } else if (contents[1] == "FireApi") {
        uptimeInfo.FireApi = Number(contents[0])
      } else if (contents[1] == "FireMon") {
        uptimeInfo.FireMon = Number(contents[0])
      } else if (contents[1].indexOf("bitbridge6") > -1) {
        uptimeInfo.bitbridge6 = Number(contents[0])
      } else if (contents[1].indexOf("bitbridge7") > -1) {
        uptimeInfo.bitbridge7 = Number(contents[0])
      } else if (contents[1].indexOf("dnscrypt") > -1) {
        uptimeInfo.dnscrypt = Number(contents[0])
      } else if (contents[1].indexOf("dnsmasq") > -1) {
        uptimeInfo.dnsmasq = Number(contents[0])
      } else if (contents[1].indexOf("openvpn") > -1) {
        uptimeInfo.openvpn = Number(contents[0])
      }
    }
  } catch(err) {
    log.error("Failed to get uptime info", err);
  }
}

async function getRateLimitInfo() {
  rateLimitInfo = await rateLimit.getLastTS();
}

async function getDiskInfo() {
  try {
    const response = await df()
    const disks = response.filter(entry => ["/dev/mmc", "overlay"].some(x => entry.filesystem.startsWith(x)));
    diskInfo = disks;
  } catch(err) {
    log.error("Failed to get disk info", err);
  }
}

function getAutoUpgrade() {
  return new Promise((resolve, reject) => {
    fs.exists("/home/pi/.firewalla/config/.no_auto_upgrade", function(exists) {
      no_auto_upgrade = exists;
      resolve(no_auto_upgrade);
    });
  })
}

async function getMultiProfileSupportFlag() {
  const cmd = "sudo bash -c 'test -e /etc/openvpn/easy-rsa/keys2/ta.key'"
  try {
    await exec(cmd);
    multiProfileSupport = false;
  } catch(err) {
    multiProfileSupport = true;
  }
}

async function getIntelQueueSize() {
  intelQueueSize = await rclient.zcountAsync("ip_set_to_be_processed", "-inf", "+inf");
}

async function getRealMemoryUsage() {
  try {
    const res = await exec('free');
    var lines = res.stdout.split(/\n/g);
    for(var i = 0; i < lines.length; i++) {
      lines[i] = lines[i].split(/\s+/);
    }

    usedMem = parseInt(lines[1][2]);
    allMem = parseInt(lines[1][1]);
    realMemUsage = 1.0 * usedMem / allMem;
    log.debug("Memory Usage: ", usedMem, " ", allMem, " ", realMemUsage);
  } catch (err) {
    log.error("Failed to get memory usuage:", err);
  }
}

async function getTemp() {
  try {
    curTemp = await platform.getCpuTemperature();
    if (Array.isArray(curTemp)) curTemp = curTemp[0]
    log.debug("Current Temp: ", curTemp);
    peakTemp = peakTemp > curTemp ? peakTemp : curTemp;
  } catch(err) {
    log.debug("Failed getting CPU temperature", err);
    curTemp = -1;
  }
}

function getUptime() {
  return process.uptime();
}

function getOSUptime() {
  return require('os').uptime();
}

function getTimestamp() {
  return new Date();
}

async function getConns() {
  // get conns in last 24 hours
  try {
    const keys = await rclient.keysAsync('flow:conn:*');

    let results = await Promise.all(
      keys.map(key => rclient.zcountAsync(key, '-inf', '+inf'))
    );

    if(results.length > 0) {
      conn = results.reduce((a,b) => (a + b));
      peakConn = peakConn > conn ? peakConn : conn;
    }
  } catch(err) {
    log.error("Failed getting connections in 24 hrs", err);
    conn = -1;
    return;
  }
}

async function getRedisMemoryUsage() {
  const cmd = "redis-cli info | grep used_memory: | awk -F: '{print $2}'";
  try {
    const res = await exec(cmd);
    redisMemory = res.stdout.replace(/\r?\n$/,'');
  } catch(err) {
    log.error("Error getting Redis memory usage", err);
  }
}

function getCategoryStats() {
  try {
    const output = execSync(`${f.getFirewallaHome()}/scripts/category_blocking_stats.sh`, {encoding: 'utf8'})
    const lines = output.split("\n");

    let stats = {};
    lines.forEach((line) => {
      const entries = line.split(" ");
      const category = entries[0];
      const num = entries[1];
      stats[category] = num;
    })

    return stats;

  } catch(err) {
    return {};
  }
}

async function getMaxPid() {
  try {
    const cmd = await exec('echo $$')
    const pid = Number(cmd.stdout)
    if (pid < maxPid) {
      log.warn(`maxPid decresed. max: ${maxPid}, now: ${pid}`)
    } else {
      maxPid = pid
    }
  } catch(err) {
    log.error("Error getting max pid", err)
  }
}

async function getActiveContainers() {
  try {
    if (! platform.isDockerSupported()) { return; }
    const cmd = await exec('sudo docker container ls -q | wc -l')
    activeContainers = Number(cmd.stdout)
    log.info(`active docker containers count = ${activeContainers}`);
  } catch(err) {
    log.error("failed to get number of active docker containers", err)
  }
}

function getSysInfo() {
  let sysinfo = {
    cpu: cpuUsage,
    mem: 1 - os.freememPercentage(),
    realMem: realMemUsage,
    totalMem: os.totalmem(),
    load1: os.loadavg(1),
    load5: os.loadavg(5),
    load15: os.loadavg(15),
    curTemp: curTemp + "",
    peakTemp: peakTemp + "",
    timestamp: getTimestamp(),
    uptime: getUptime(),
    osUptime: getOSUptime(),
    conn: conn + "",
    peakConn: peakConn + "",
    redisMem: redisMemory,
    releaseType: f.getReleaseType(),
    threadInfo: threadInfo,
    intelQueueSize: intelQueueSize,
    nodeVersion: process.version,
    diskInfo: diskInfo,
    //categoryStats: getCategoryStats(),
    multiProfileSupport: multiProfileSupport,
    no_auto_upgrade: no_auto_upgrade,
    maxPid: maxPid
  }

  let newUptimeInfo = {};
  Object.keys(uptimeInfo).forEach((uptimeName) => {
    if (uptimeInfo[uptimeName] > 0 ) {
      newUptimeInfo[uptimeName] = uptimeInfo[uptimeName] + Date.now() / 1000 - updateTime; // add time difference between update and getSysInfo()
    } else {
      newUptimeInfo[uptimeName] = 0;
    }
  });
  sysinfo.uptimeInfo = newUptimeInfo;

  if(rateLimitInfo) {
    sysinfo.rateLimitInfo = rateLimitInfo;
  }

  if (platform.isDockerSupported()) {
    sysinfo.activeContainers = activeContainers;
  }

  return sysinfo;
}

async function getRecentLogs() {
  const logFiles = ["api.log", "kickui.log", "main.log", "monitor.log", "dns.log"].map((name) => logFolder + "/" + name);

  const tailNum = config.sysInfo.tailNum || 100; // default 100

  let results = await Promise.all(logFiles.map(async file => {
    // ignore all errors
    try {
      let res = await exec(util.format('tail -n %d %s', tailNum, file))
      return { file: file, content: res.stdout }
    } catch(err) {
      return { file: file, content: "" }
    }
  }));

  return results
}

function getTopStats() {
  return execSync("top -b -n 1 -o %MEM | head -n 20").toString('utf-8').split("\n");
}

async function getTop5Flows() {
  let flows = await rclient.keysAsync("flow:conn:*");

  let stats = await Promise.all(flows.map(async (flow) => {
    let count = await rclient.zcountAsync(flow, "-inf", "+inf")
    return {name: flow, count: count};
  }))

  return stats.sort((a, b) => b.count - a.count).slice(0, 5);
}

async function getPerfStats() {
  return {
    top: getTopStats(),
    sys: getSysInfo(),
    perf: await getTop5Flows()
  }
}

function getHeapDump(file, callback) {
  callback(null);
  // let heapdump = require('heapdump');
  // heapdump.writeSnapshot(file, callback);
}

module.exports = {
  getSysInfo: getSysInfo,
  startUpdating: startUpdating,
  stopUpdating: stopUpdating,
  getRealMemoryUsage:getRealMemoryUsage,
  getRecentLogs: getRecentLogs,
  getPerfStats: getPerfStats,
  getHeapDump: getHeapDump
};
<commit_msg>remove maxPid log<commit_after>/*    Copyright 2019-2020 Firewalla Inc.
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

'use strict';

const log = require("../../net2/logger.js")(__filename, "info");

const util = require('util');

const f = require('../../net2/Firewalla.js');
const logFolder = f.getLogFolder();

const config = require("../../net2/config.js").getConfig();

const df = util.promisify(require('node-df'))

const os = require('../../vendor_lib/osutils.js');

const exec = require('child-process-promise').exec;
const { execSync } = require('child_process')

const rclient = require('../../util/redis_manager.js').getRedisClient()

const platformLoader = require('../../platform/PlatformLoader.js');
const platform = platformLoader.getPlatform();

const rateLimit = require('../../extension/ratelimit/RateLimit.js');

const fs = require('fs');

let cpuUsage = 0;
let realMemUsage = 0;
let usedMem = 0;
let allMem = 0;
let curTemp = 0;
let peakTemp = 0;

let conn = 0;
let peakConn = 0;

let rateLimitInfo = null;

let redisMemory = 0;

let updateFlag = 0;

let updateInterval = 600 * 1000; // every 10 minutes

let threadInfo = {};

let diskInfo = null;

let intelQueueSize = 0;

let multiProfileSupport = false;

let no_auto_upgrade = false;

let uptimeInfo = {};
let updateTime = null;

let maxPid = 0;
let activeContainers = 0;

getMultiProfileSupportFlag();

async function update() {
  await Promise.all([
    // this takes 10s
    os.cpuUsage().then((v) => cpuUsage = v),

    // Redis
    getRedisMemoryUsage()
      .then(getConns)
      .then(getIntelQueueSize)
      .then(getRateLimitInfo),

    // bash
    getRealMemoryUsage()
      .then(getTemp)
      .then(getThreadInfo)
      .then(getDiskInfo)
      .then(getMultiProfileSupportFlag)
      .then(getAutoUpgrade)
      .then(getUptimeInfo)
      .then(getMaxPid)
      .then(getActiveContainers)
  ])

  if(updateFlag) {
    setTimeout(() => { update(); }, updateInterval);
  }
}

function startUpdating() {
  updateFlag = 1;
  update();
}

function stopUpdating() {
  updateFlag = 0;
}

async function getThreadInfo() {
  try {
    const count = await exec("ps -Haux | wc -l", {encoding: 'utf8'});
    const mainCount = await exec("ps -Haux | grep Fi[r]eMain | wc -l", {encoding: 'utf8'});
    const apiCount = await exec("ps -Haux | grep Fi[r]eApi | wc -l", {encoding: 'utf8'});
    const monitorCount = await exec("ps -Haux | grep Fi[r]eMon | wc -l", {encoding: 'utf8'});
    threadInfo.count = count.stdout.replace("\n", "");
    threadInfo.mainCount = mainCount.stdout.replace("\n", "");
    threadInfo.apiCount = apiCount.stdout.replace("\n", "");
    threadInfo.monitorCount = monitorCount.stdout.replace("\n", "");
  } catch(err) {
    log.error("Failed to get thread info", err);
  }
}

async function getUptimeInfo() {
  try {
    uptimeInfo.fireMain = 0;
    uptimeInfo.FireApi = 0;
    uptimeInfo.FireMon = 0;
    uptimeInfo.bitbridge6 = 0;
    uptimeInfo.bitbridge7 = 0;
    uptimeInfo.dnscrypt = 0;
    uptimeInfo.dnsmasq = 0;
    uptimeInfo.openvpn = 0;

    const cmdResult = await exec("ps -eo etimes,cmd | awk '{print $1, $2}'", {encoding: 'utf8'});
    let lines = cmdResult.stdout.split("\n");
    lines.shift();
    lines.pop();
    updateTime = Date.now() / 1000;
    for (const line of lines) {
      let contents = line.split(' ');
      if (contents[1] == "FireMain") {
        uptimeInfo.fireMain = Number(contents[0])
      } else if (contents[1] == "FireApi") {
        uptimeInfo.FireApi = Number(contents[0])
      } else if (contents[1] == "FireMon") {
        uptimeInfo.FireMon = Number(contents[0])
      } else if (contents[1].indexOf("bitbridge6") > -1) {
        uptimeInfo.bitbridge6 = Number(contents[0])
      } else if (contents[1].indexOf("bitbridge7") > -1) {
        uptimeInfo.bitbridge7 = Number(contents[0])
      } else if (contents[1].indexOf("dnscrypt") > -1) {
        uptimeInfo.dnscrypt = Number(contents[0])
      } else if (contents[1].indexOf("dnsmasq") > -1) {
        uptimeInfo.dnsmasq = Number(contents[0])
      } else if (contents[1].indexOf("openvpn") > -1) {
        uptimeInfo.openvpn = Number(contents[0])
      }
    }
  } catch(err) {
    log.error("Failed to get uptime info", err);
  }
}

async function getRateLimitInfo() {
  rateLimitInfo = await rateLimit.getLastTS();
}

async function getDiskInfo() {
  try {
    const response = await df()
    const disks = response.filter(entry => ["/dev/mmc", "overlay"].some(x => entry.filesystem.startsWith(x)));
    diskInfo = disks;
  } catch(err) {
    log.error("Failed to get disk info", err);
  }
}

function getAutoUpgrade() {
  return new Promise((resolve, reject) => {
    fs.exists("/home/pi/.firewalla/config/.no_auto_upgrade", function(exists) {
      no_auto_upgrade = exists;
      resolve(no_auto_upgrade);
    });
  })
}

async function getMultiProfileSupportFlag() {
  const cmd = "sudo bash -c 'test -e /etc/openvpn/easy-rsa/keys2/ta.key'"
  try {
    await exec(cmd);
    multiProfileSupport = false;
  } catch(err) {
    multiProfileSupport = true;
  }
}

async function getIntelQueueSize() {
  intelQueueSize = await rclient.zcountAsync("ip_set_to_be_processed", "-inf", "+inf");
}

async function getRealMemoryUsage() {
  try {
    const res = await exec('free');
    var lines = res.stdout.split(/\n/g);
    for(var i = 0; i < lines.length; i++) {
      lines[i] = lines[i].split(/\s+/);
    }

    usedMem = parseInt(lines[1][2]);
    allMem = parseInt(lines[1][1]);
    realMemUsage = 1.0 * usedMem / allMem;
    log.debug("Memory Usage: ", usedMem, " ", allMem, " ", realMemUsage);
  } catch (err) {
    log.error("Failed to get memory usuage:", err);
  }
}

async function getTemp() {
  try {
    curTemp = await platform.getCpuTemperature();
    if (Array.isArray(curTemp)) curTemp = curTemp[0]
    log.debug("Current Temp: ", curTemp);
    peakTemp = peakTemp > curTemp ? peakTemp : curTemp;
  } catch(err) {
    log.debug("Failed getting CPU temperature", err);
    curTemp = -1;
  }
}

function getUptime() {
  return process.uptime();
}

function getOSUptime() {
  return require('os').uptime();
}

function getTimestamp() {
  return new Date();
}

async function getConns() {
  // get conns in last 24 hours
  try {
    const keys = await rclient.keysAsync('flow:conn:*');

    let results = await Promise.all(
      keys.map(key => rclient.zcountAsync(key, '-inf', '+inf'))
    );

    if(results.length > 0) {
      conn = results.reduce((a,b) => (a + b));
      peakConn = peakConn > conn ? peakConn : conn;
    }
  } catch(err) {
    log.error("Failed getting connections in 24 hrs", err);
    conn = -1;
    return;
  }
}

async function getRedisMemoryUsage() {
  const cmd = "redis-cli info | grep used_memory: | awk -F: '{print $2}'";
  try {
    const res = await exec(cmd);
    redisMemory = res.stdout.replace(/\r?\n$/,'');
  } catch(err) {
    log.error("Error getting Redis memory usage", err);
  }
}

function getCategoryStats() {
  try {
    const output = execSync(`${f.getFirewallaHome()}/scripts/category_blocking_stats.sh`, {encoding: 'utf8'})
    const lines = output.split("\n");

    let stats = {};
    lines.forEach((line) => {
      const entries = line.split(" ");
      const category = entries[0];
      const num = entries[1];
      stats[category] = num;
    })

    return stats;

  } catch(err) {
    return {};
  }
}

async function getMaxPid() {
  try {
    const cmd = await exec('echo $$')
    const pid = Number(cmd.stdout)
    if (pid < maxPid) {
      log.debug(`maxPid decresed. max: ${maxPid}, now: ${pid}`)
    } else {
      maxPid = pid
    }
  } catch(err) {
    log.error("Error getting max pid", err)
  }
}

async function getActiveContainers() {
  try {
    if (! platform.isDockerSupported()) { return; }
    const cmd = await exec('sudo docker container ls -q | wc -l')
    activeContainers = Number(cmd.stdout)
    log.info(`active docker containers count = ${activeContainers}`);
  } catch(err) {
    log.error("failed to get number of active docker containers", err)
  }
}

function getSysInfo() {
  let sysinfo = {
    cpu: cpuUsage,
    mem: 1 - os.freememPercentage(),
    realMem: realMemUsage,
    totalMem: os.totalmem(),
    load1: os.loadavg(1),
    load5: os.loadavg(5),
    load15: os.loadavg(15),
    curTemp: curTemp + "",
    peakTemp: peakTemp + "",
    timestamp: getTimestamp(),
    uptime: getUptime(),
    osUptime: getOSUptime(),
    conn: conn + "",
    peakConn: peakConn + "",
    redisMem: redisMemory,
    releaseType: f.getReleaseType(),
    threadInfo: threadInfo,
    intelQueueSize: intelQueueSize,
    nodeVersion: process.version,
    diskInfo: diskInfo,
    //categoryStats: getCategoryStats(),
    multiProfileSupport: multiProfileSupport,
    no_auto_upgrade: no_auto_upgrade,
    maxPid: maxPid
  }

  let newUptimeInfo = {};
  Object.keys(uptimeInfo).forEach((uptimeName) => {
    if (uptimeInfo[uptimeName] > 0 ) {
      newUptimeInfo[uptimeName] = uptimeInfo[uptimeName] + Date.now() / 1000 - updateTime; // add time difference between update and getSysInfo()
    } else {
      newUptimeInfo[uptimeName] = 0;
    }
  });
  sysinfo.uptimeInfo = newUptimeInfo;

  if(rateLimitInfo) {
    sysinfo.rateLimitInfo = rateLimitInfo;
  }

  if (platform.isDockerSupported()) {
    sysinfo.activeContainers = activeContainers;
  }

  return sysinfo;
}

async function getRecentLogs() {
  const logFiles = ["api.log", "kickui.log", "main.log", "monitor.log", "dns.log"].map((name) => logFolder + "/" + name);

  const tailNum = config.sysInfo.tailNum || 100; // default 100

  let results = await Promise.all(logFiles.map(async file => {
    // ignore all errors
    try {
      let res = await exec(util.format('tail -n %d %s', tailNum, file))
      return { file: file, content: res.stdout }
    } catch(err) {
      return { file: file, content: "" }
    }
  }));

  return results
}

function getTopStats() {
  return execSync("top -b -n 1 -o %MEM | head -n 20").toString('utf-8').split("\n");
}

async function getTop5Flows() {
  let flows = await rclient.keysAsync("flow:conn:*");

  let stats = await Promise.all(flows.map(async (flow) => {
    let count = await rclient.zcountAsync(flow, "-inf", "+inf")
    return {name: flow, count: count};
  }))

  return stats.sort((a, b) => b.count - a.count).slice(0, 5);
}

async function getPerfStats() {
  return {
    top: getTopStats(),
    sys: getSysInfo(),
    perf: await getTop5Flows()
  }
}

function getHeapDump(file, callback) {
  callback(null);
  // let heapdump = require('heapdump');
  // heapdump.writeSnapshot(file, callback);
}

module.exports = {
  getSysInfo: getSysInfo,
  startUpdating: startUpdating,
  stopUpdating: stopUpdating,
  getRealMemoryUsage:getRealMemoryUsage,
  getRecentLogs: getRecentLogs,
  getPerfStats: getPerfStats,
  getHeapDump: getHeapDump
};
<|endoftext|>


<commit_before>//自动加载进行识别的路径
var autoloadPaths = {}
/**
 * [exports description]
 * @type {Object}
 */
var Think = module.exports = {
    //setInterval timer
    timer: 0,
    /**
     * [start description]
     * @return {[type]} [description]
     */
    start: function(){
        //debug模式下不捕获异常
        if (!APP_DEBUG) {
            this.register_exception();
        };
        //加载文件
        this.loadFiles();
        //合并自动加载的路径
        this.mergeAutoloadPath();
        //thinkRequire的autoload
        registerAutoload(this.autoload);
        //debug模式
        if (APP_DEBUG) {
            this.debug();
        };
        //记录进程的id
        this.log_process_pid();

        thinkRequire('App').run();
    },
    /**
     * 注册异常处理
     * @return {[type]} [description]
     */
    register_exception: function(){
        process.on('uncaughtException', function(err) {
            console.log(err);
        });
    },
    /**
     * 加载项目下对应的文件
     * @return {[type]} [description]
     */
    loadFiles: function(){
        //加载系统默认配置
        C(require(THINK_PATH + '/Conf/config.js'));
        //加载用户配置
        var file = CONF_PATH + '/config.js';
        if (isFile(file)) {
            C(require(file));
        };
        //加载模式的配置文件
        if (APP_MODE) {
            var modeFile = CONF_PATH + "/" + APP_MODE + "_config.js";
            if (isFile(modeFile)) {
                C(require(modeFile));
            };
        };
        //自定义路由
        if (C('url_route_on') && isFile(CONF_PATH + "/route.js")) {
            C("url_route_rules", require(CONF_PATH + "/route.js"));
        };
        //加载行为配置
        if (C('app_tag_on')) {
            //加载系统行为配置
            C('sys_tag', require(THINK_PATH + "/Conf/tag.js"));
            //加载用户的行为配置
            var tagFile = CONF_PATH + "/tag.js";
            if (isFile(tagFile)) {
                C('tag', require(tagFile));
            };
        };
        //common文件
        if (isFile(COMMON_PATH + "/common.js")) {
            require(COMMON_PATH + "/common.js");
        };
        //别名文件
        if (isFile(COMMON_PATH + "/alias.js")) {
            aliasImport(require(COMMON_PATH + "/alias.js"));
        };
        this.loadExtConfig();
        this.loadExtFiles();
    },
    //加载自定义外部文件
    loadExtFiles: function(){
        var files = C('load_ext_file');
        if (files) {
            if (isString(files)) {
                files = files.split(',');
            };
            files.forEach(function(file){
                file = COMMON_PATH + "/" + file + ".js";
                if (isFile(file)) {
                    require(file);
                };
            })
        };
    },
    //加载额外的配置
    loadExtConfig: function(){
        var files = C('load_ext_config');
        if (files) {
            if (isString(files)) {
                files = files.split(",");
            };
            files.forEach(function(file){
                file = CONF_PATH + "/" + file + ".js";
                if (isFile(file)) {
                    C(require(file));
                };
            })
        };
    },
    //加载debug模式配置文件
    loadDebugFiles: function(){
        //加载debug模式下的配置
        C(require(THINK_PATH + "/Conf/debug.js"));
        if (APP_MODE) {
            var modeDebugFile = THINK_PATH + "/Conf/" + APP_MODE + "_debug.js";
            if (isFile(modeDebugFile)) {
                C(require(modeDebugFile));
            };
        };
        //debug下自定义状态的配置
        var status = C('app_status');
        if (status) {
            if (isFile(CONF_PATH + "/" + status + '.js')) {
                C(require(CONF_PATH + "/" + status + ".js"));
            };
        }else{
            if (isFile(CONF_PATH + '/debug.js')) {
                C(require(CONF_PATH + '/debug.js'));
            };
        }
    },
    /**
     * debug模式下一些特殊处理
     * @return {[type]} [description]
     */
    debug: function(){
        this.loadDebugFiles();
        //清除require的缓存
        if (C('clear_require_cache')) {
            //这些文件不清除缓存
            var retainFiles = C('debug_retain_files');
            var self = this;
            this.timer = setInterval(function(){
                //清除已经绑定的自定义事件
                E(null);
                for(var file in require.cache){
                    var flag = retainFiles.some(function(item){
                        if (file.indexOf(item) > -1) {
                            return true;
                        };
                    });
                    if (!flag) {
                        delete require.cache[file];
                    };
                }
                self.loadFiles();
                self.loadDebugFiles();
            }, 100);
        };
    },
    /**
     * 记录当前进程的id
     * 记录在Runtime/Data/app.pid文件里
     * @return {[type]} [description]
     */
    log_process_pid: function(){
        var isMaster = require('cluster').isMaster;
        if (C('log_process_pid') && isMaster) {
            mkdir(DATA_PATH);
            var pidFile = DATA_PATH + "/app.pid";
            var fs = require("fs");
            fs.writeFileSync(pidFile, process.pid);
            //进程退出时删除该文件
            process.on('SIGTERM', function () {
                if (fs.existsSync(pidFile)) {
                    fs.unlinkSync(pidFile);
                }
                process.exit(0);
            });
        };
    },
    /**
     * 合并autoload的path
     * @return {[type]} [description]
     */
    mergeAutoloadPath: function(){
        var cls = "__CLASS__";
        var sysfile = cls + ".class.js";
        var file = cls + C("class_file_suffix");
        var sysAutoloadPath = {
            "Behavior": [
                LIB_PATH + "/Behavior/" + file,
                THINK_LIB_PATH + "/Behavior/" + sysfile,
                THINK_EXTEND_PATH + "/Behavior/" + sysfile
            ],
            "Model": [
                LIB_PATH + "/Model/" + file,
                THINK_EXTEND_PATH + "/Model/" + sysfile
            ],
            "Controller": [
                LIB_PATH + "/Controller/" + file
            ],
            "Cache": [
                LIB_PATH + "/Driver/Cache/" + file,
                THINK_LIB_PATH + "/Driver/Cache/" + sysfile,
                THINK_EXTEND_PATH + "/Driver/Cache/" + sysfile
            ],
            "Db": [
                LIB_PATH + "/Driver/Db/" + file,
                THINK_LIB_PATH + "/Driver/Db/" + sysfile,
                THINK_EXTEND_PATH + "/Driver/Db/" + sysfile
            ],
            "Template": [
                LIB_PATH + "/Driver/Template/" + file,
                THINK_LIB_PATH + "/Driver/Template/" + sysfile
            ],
            "Socket": [
                LIB_PATH + "/Driver/Socket/" + file,
                THINK_LIB_PATH + "/Driver/Socket/" + sysfile
            ],
            "Session": [
                LIB_PATH + "/Driver/Session/" + file,
                THINK_LIB_PATH + "/Driver/Session/" + sysfile
            ]
        };
        var autoloadPath = C('autoload_path');
        for(var type in autoloadPath){
            var paths = autoloadPath[type];
            if (!isArray(paths)) {
                paths = [paths];
            };
            var override = false;
            if (isBoolean(paths[0])) {
                override = paths[0];
                paths.shift();
            };
            if (override) {
                sysAutoloadPath[type] = paths;
            }else{
                paths.push.apply(paths, sysAutoloadPath[type]);
                sysAutoloadPath[type] = paths;
            }
        }
        autoloadPaths = sysAutoloadPath;
    },
    //thinkRequire的自动加载
    autoload: function(cls){
        for(var name in autoloadPaths){
            var length = name.length;
            if (cls.substr(0 - length) === name) {
                var list = autoloadPaths[name];
                var filepath = '';
                list.some(function(item){
                    item = item.replace(/__CLASS__/g, cls);
                    if (isFile(item)) {
                        filepath = item;
                        return true;
                    };
                });
                if (filepath) {
                    return filepath;
                };
            };
        }
    }
}
<commit_msg>update<commit_after>//自动加载进行识别的路径
var autoloadPaths = {}
/**
 * [exports description]
 * @type {Object}
 */
var Think = module.exports = {
    //setInterval timer
    timer: 0,
    /**
     * [start description]
     * @return {[type]} [description]
     */
    start: function(){
        //debug模式下不捕获异常
        if (!APP_DEBUG) {
            this.register_exception();
        };
        //加载文件
        this.loadFiles();
        //合并自动加载的路径
        this.mergeAutoloadPath();
        //thinkRequire的autoload
        registerAutoload(this.autoload);
        //debug模式
        if (APP_DEBUG) {
            this.debug();
        };
        //记录进程的id
        this.log_process_pid();

        thinkRequire('App').run();
    },
    /**
     * 注册异常处理
     * @return {[type]} [description]
     */
    register_exception: function(){
        process.on('uncaughtException', function(err) {
            console.log(err);
        });
    },
    /**
     * 加载项目下对应的文件
     * @return {[type]} [description]
     */
    loadFiles: function(){
        //加载系统默认配置
        C(require(THINK_PATH + '/Conf/config.js'));
        //加载用户配置
        var file = CONF_PATH + '/config.js';
        if (isFile(file)) {
            C(require(file));
        };
        //加载模式的配置文件
        if (APP_MODE) {
            var modeFile = CONF_PATH + "/" + APP_MODE + "_config.js";
            if (isFile(modeFile)) {
                C(require(modeFile));
            };
        };
        //自定义路由
        if (C('url_route_on') && isFile(CONF_PATH + "/route.js")) {
            C("url_route_rules", require(CONF_PATH + "/route.js"));
        };
        //加载行为配置
        if (C('app_tag_on')) {
            //加载系统行为配置
            C('sys_tag', require(THINK_PATH + "/Conf/tag.js"));
            //加载用户的行为配置
            var tagFile = CONF_PATH + "/tag.js";
            if (isFile(tagFile)) {
                C('tag', require(tagFile));
            };
        };
        //common文件
        if (isFile(COMMON_PATH + "/common.js")) {
            require(COMMON_PATH + "/common.js");
        };
        //别名文件
        if (isFile(COMMON_PATH + "/alias.js")) {
            aliasImport(require(COMMON_PATH + "/alias.js"));
        };
        this.loadExtConfig();
        this.loadExtFiles();
    },
    //加载自定义外部文件
    loadExtFiles: function(){
        var files = C('load_ext_file');
        if (files) {
            if (isString(files)) {
                files = files.split(',');
            };
            files.forEach(function(file){
                file = COMMON_PATH + "/" + file + ".js";
                if (isFile(file)) {
                    require(file);
                };
            })
        };
    },
    //加载额外的配置
    loadExtConfig: function(){
        var files = C('load_ext_config');
        if (files) {
            if (isString(files)) {
                files = files.split(",");
            };
            files.forEach(function(file){
                file = CONF_PATH + "/" + file + ".js";
                if (isFile(file)) {
                    C(require(file));
                };
            })
        };
    },
    //加载debug模式配置文件
    loadDebugFiles: function(){
        //加载debug模式下的配置
        C(require(THINK_PATH + "/Conf/debug.js"));
        if (APP_MODE) {
            var modeDebugFile = THINK_PATH + "/Conf/" + APP_MODE + "_debug.js";
            if (isFile(modeDebugFile)) {
                C(require(modeDebugFile));
            };
        };
        //debug下自定义状态的配置
        var status = C('app_status');
        if (status) {
            if (isFile(CONF_PATH + "/" + status + '.js')) {
                C(require(CONF_PATH + "/" + status + ".js"));
            };
        }else{
            if (isFile(CONF_PATH + '/debug.js')) {
                C(require(CONF_PATH + '/debug.js'));
            };
        }
    },
    /**
     * debug模式下一些特殊处理
     * @return {[type]} [description]
     */
    debug: function(){
        this.loadDebugFiles();
        //清除require的缓存
        if (C('clear_require_cache')) {
            //这些文件不清除缓存
            var retainFiles = C('debug_retain_files');
            var self = this;
            this.timer = setInterval(function(){
                //清除已经绑定的自定义事件
                E(null);
                for(var file in require.cache){
                    var flag = retainFiles.some(function(item){
                        if (file.indexOf(item) > -1) {
                            return true;
                        };
                    });
                    if (!flag) {
                        delete require.cache[file];
                    };
                }
                self.loadFiles();
                self.loadDebugFiles();
            }, 100);
        };
    },
    /**
     * 记录当前进程的id
     * 记录在Runtime/Data/app.pid文件里
     * @return {[type]} [description]
     */
    log_process_pid: function(){
        var isMaster = require('cluster').isMaster;
        if (C('log_process_pid') && isMaster) {
            mkdir(DATA_PATH);
            var pidFile = DATA_PATH + "/app.pid";
            var fs = require("fs");
            fs.writeFileSync(pidFile, process.pid);
            chmod(pidFile);
            //进程退出时删除该文件
            process.on('SIGTERM', function () {
                if (fs.existsSync(pidFile)) {
                    fs.unlinkSync(pidFile);
                }
                process.exit(0);
            });
        };
    },
    /**
     * 合并autoload的path
     * @return {[type]} [description]
     */
    mergeAutoloadPath: function(){
        var cls = "__CLASS__";
        var sysfile = cls + ".class.js";
        var file = cls + C("class_file_suffix");
        var sysAutoloadPath = {
            "Behavior": [
                LIB_PATH + "/Behavior/" + file,
                THINK_LIB_PATH + "/Behavior/" + sysfile,
                THINK_EXTEND_PATH + "/Behavior/" + sysfile
            ],
            "Model": [
                LIB_PATH + "/Model/" + file,
                THINK_EXTEND_PATH + "/Model/" + sysfile
            ],
            "Controller": [
                LIB_PATH + "/Controller/" + file
            ],
            "Cache": [
                LIB_PATH + "/Driver/Cache/" + file,
                THINK_LIB_PATH + "/Driver/Cache/" + sysfile,
                THINK_EXTEND_PATH + "/Driver/Cache/" + sysfile
            ],
            "Db": [
                LIB_PATH + "/Driver/Db/" + file,
                THINK_LIB_PATH + "/Driver/Db/" + sysfile,
                THINK_EXTEND_PATH + "/Driver/Db/" + sysfile
            ],
            "Template": [
                LIB_PATH + "/Driver/Template/" + file,
                THINK_LIB_PATH + "/Driver/Template/" + sysfile
            ],
            "Socket": [
                LIB_PATH + "/Driver/Socket/" + file,
                THINK_LIB_PATH + "/Driver/Socket/" + sysfile
            ],
            "Session": [
                LIB_PATH + "/Driver/Session/" + file,
                THINK_LIB_PATH + "/Driver/Session/" + sysfile
            ]
        };
        var autoloadPath = C('autoload_path');
        for(var type in autoloadPath){
            var paths = autoloadPath[type];
            if (!isArray(paths)) {
                paths = [paths];
            };
            var override = false;
            if (isBoolean(paths[0])) {
                override = paths[0];
                paths.shift();
            };
            if (override) {
                sysAutoloadPath[type] = paths;
            }else{
                paths.push.apply(paths, sysAutoloadPath[type]);
                sysAutoloadPath[type] = paths;
            }
        }
        autoloadPaths = sysAutoloadPath;
    },
    //thinkRequire的自动加载
    autoload: function(cls){
        for(var name in autoloadPaths){
            var length = name.length;
            if (cls.substr(0 - length) === name) {
                var list = autoloadPaths[name];
                var filepath = '';
                list.some(function(item){
                    item = item.replace(/__CLASS__/g, cls);
                    if (isFile(item)) {
                        filepath = item;
                        return true;
                    };
                });
                if (filepath) {
                    return filepath;
                };
            };
        }
    }
}
<|endoftext|>


<commit_before>const path = require("path"),
	http = require("http"),
	ip = "127.0.0.1",
	port = 8001,
	url = `http://${ip}:${port}/index.html`,
	router = require("woodland")({
		defaultHeaders: {
			"cache-control": "no-cache",
			"content-type": "text/plain; charset=utf-8"
		},
		logging: {
			enabled: false
		},
		time: false
	});

router.get("/.*?", (req, res) => router.serve(req, res, req.parsed.pathname.substring(1), path.join(__dirname, "www")));
http.createServer(router.route).listen(port, ip);

describe("Tabbed UI Tests", function () {
	before(browser => browser.navigateTo(url));

	it("Default starting state - returns #main", function (browser) {
		browser
			.waitForElementVisible("body")
			.assert.visible("#main")
			.assert.not.visible("#settings")
			.expect.url().to.endWith("#main");
	});

	it("Click tabbed navigation - returns #settings/billing", function (browser) {
		browser
			.waitForElementVisible("body")
			.click("a[href='#settings/billing']")
			.assert.visible("#settings")
			.assert.visible("#billing")
			.assert.not.visible("#password")
			.assert.not.visible("#main")
			.expect.url().to.endWith("#settings/billing");
	});

	after(browser => {
		browser.end();
		process.exit();
	});
});
<commit_msg>Adding functional test for sticky routing<commit_after>const path = require("path"),
	http = require("http"),
	ip = "127.0.0.1",
	port = 8001,
	url = `http://${ip}:${port}/index.html`,
	webroot = path.join(__dirname, "www"),
	router = require("woodland")({
		defaultHeaders: {
			"cache-control": "no-cache",
			"content-type": "text/plain; charset=utf-8"
		},
		logging: {
			enabled: false
		},
		time: false
	});

router.get("/.*?", (req, res) => router.serve(req, res, req.parsed.pathname.substring(1), webroot));
http.createServer(router.route).listen(port, ip);

describe("Tabbed UI Tests", function () {
	before(browser => browser.navigateTo(url));

	it("Default starting state - returns #main", function (browser) {
		browser
			.waitForElementVisible("body")
			.assert.visible("#main")
			.assert.not.visible("#settings")
			.expect.url().to.endWith("#main");
	});

	it("Click tabbed navigation - returns #settings/billing", function (browser) {
		browser
			.waitForElementVisible("body")
			.click("a[href='#settings/billing']")
			.assert.visible("#settings")
			.assert.visible("#billing")
			.assert.not.visible("#password")
			.assert.not.visible("#main")
			.expect.url().to.endWith("#settings/billing");
	});

	it("Sticky routing - returns #settings/billing", function (browser) {
		browser
			.waitForElementVisible("body")
			.assert.visible("#settings")
			.assert.visible("#billing")
			.assert.not.visible("#password")
			.assert.not.visible("#main")
			.expect.url().to.endWith("#settings/billing");
	});

	after(browser => {
		browser.end();
		process.exit();
	});
});
<|endoftext|>


<commit_before>export default function(state, ctx, model, helpers) {

	const ConcretizeIfNative = helpers.ConcretizeIfNative;

	//TODO: Test IsNative for apply, bind & call
	model.add(Function.prototype.apply, ConcretizeIfNative(Function.prototype.apply));
	model.add(Function.prototype.call, ConcretizeIfNative(Function.prototype.call));
	model.add(Function.prototype.bind, ConcretizeIfNative(Function.prototype.bind));

  model.add(Object.prototype.hasOwnProperty, function(base, args) {

    for (let i = 0; i < args.length; i++) {
      args[i] = state.getConcrete(args[i]);
    }

    Function.prototype.hasOwnProperty.apply(state.getConcrete(base), args);
  });

  model.add(Object.prototype.keys, function(base, args) {

    for (let i = 0; i < args.length; i++) {
      args[i] = state.getConcrete(args[i]);
    }

    return Object.prototype.keys.apply(this.getConcrete(base), args);
  });

  model.add(Object.assign, (base, args) => {
    return Object.assign.call(base, this.getConcrete(args[0]), this.getConcrete(args[1]));
  });

  model.add(console.log, function(base, args) {

    for (let i = 0; i < args.length; i++) {
      args[i] = state.getConcrete(args[i]);
    }

		console.log.apply(base, args);
	});
}
<commit_msg>Add an isArray model<commit_after>export default function(state, ctx, model, helpers) {

	const ConcretizeIfNative = helpers.ConcretizeIfNative;

	//TODO: Test IsNative for apply, bind & call
	model.add(Function.prototype.apply, ConcretizeIfNative(Function.prototype.apply));
	model.add(Function.prototype.call, ConcretizeIfNative(Function.prototype.call));
	model.add(Function.prototype.bind, ConcretizeIfNative(Function.prototype.bind));

  model.add(Object.prototype.hasOwnProperty, function(base, args) {

    for (let i = 0; i < args.length; i++) {
      args[i] = state.getConcrete(args[i]);
    }

    Function.prototype.hasOwnProperty.apply(state.getConcrete(base), args);
  });

  model.add(Object.prototype.keys, function(base, args) {

    for (let i = 0; i < args.length; i++) {
      args[i] = state.getConcrete(args[i]);
    }

    return Object.prototype.keys.apply(this.getConcrete(base), args);
  });

  model.add(Object.assign, (base, args) => {
    return Object.assign.call(base, this.getConcrete(args[0]), this.getConcrete(args[1]));
  });

  model.add(Array.isArray, (base, args) => {
    return Array.isArray.call(base, this.getConcrete(args[0]));
  });

  model.add(console.log, function(base, args) {

    for (let i = 0; i < args.length; i++) {
      args[i] = state.getConcrete(args[i]);
    }

		console.log.apply(base, args);
	});
}
<|endoftext|>