<commit_before>'use strict';

const commander = require('commander');
const cp = require('child_process');
const _ = require('underscore');
const util = require('util');
const jwt = require('jsonwebtoken');

const request = require('abacus-request');
const router = require('abacus-router');
const express = require('abacus-express');

const clone = _.clone;

// Setup the debug log
const debug = require('abacus-debug')('abacus-cf-bridge-itest');

// Module directory
const moduleDir = (module) => {
  const path = require.resolve(module);
  return path.substr(0, path.indexOf(module + '/') + module.length);
};

const timeWindows = {
  'second' : 0,
  'minute' : 1,
  'hour'   : 2,
  'day'    : 3,
  'month'  : 4
};

// Checks if the difference between start and end time fall within a window
const isWithinWindow = (start, end, timeWindow) => {
  // [Second, Minute, Hour, Day, Month]
  const timescale = [1, 100, 10000, 1000000, 100000000];
  // Converts a millisecond number to a format a number that is YYYYMMDDHHmmSS
  const dateUTCNumbify = (t) => {
    const d = new Date(t);
    return d.getUTCFullYear() * 10000000000 + d.getUTCMonth() * timescale[4]
      + d.getUTCDate() * timescale[3] + d.getUTCHours() * timescale[2]
      + d.getUTCMinutes() * timescale[1] + d.getUTCSeconds();
  };

  return Math.floor(dateUTCNumbify(end) / timescale[timeWindow]) -
    Math.floor(dateUTCNumbify(start) / timescale[timeWindow]) === 0;
};

// Parse command line options
const argv = clone(process.argv);
argv.splice(1, 1, 'usage-collector-itest');
commander
  .option('-t, --start-timeout <n>',
    'external processes start timeout in milliseconds', parseInt)
  .option('-x, --total-timeout <n>',
    'test timeout in milliseconds', parseInt)
  .allowUnknownOption(true)
  .parse(argv);

// External Abacus processes start timeout
const startTimeout = commander.startTimeout || 10000;

// This test timeout
const totalTimeout = commander.totalTimeout || 60000;

// Token setup
process.env.API = 'http://localhost:4321';

process.env.CF_CLIENT_ID = 'abacus-cf-bridge';
process.env.CF_CLIENT_SECRET = 'secret';

process.env.CLIENT_ID = 'abacus-linux-container';
process.env.CLIENT_SECRET = 'secret';
const tokenSecret = 'secret';
const tokenAlgorithm = 'HS256';
process.env.JWTKEY = tokenSecret;
process.env.JWTALGO = tokenAlgorithm;

const decodedToken = {
  header: {
    alg: tokenAlgorithm
  },
  payload: {
    jti: '254abca5-1c25-40c5-99d7-2cc641791517',
    sub: 'abacus-cf-bridge',
    authorities: [
      'abacus.usage.linux-container.write',
      'abacus.usage.linux-container.read'
    ],
    scope: [
      'abacus.usage.linux-container.read',
      'abacus.usage.linux-container.write'
    ],
    client_id: 'abacus-cf-bridge',
    cid: 'abacus-cf-bridge',
    azp: 'abacus-cf-bridge',
    grant_type: 'client_credentials',
    rev_sig: '2cf89595',
    iat: 1456147679,
    exp: 1456190879,
    iss: 'https://localhost:1234/oauth/token',
    zid: 'uaa',
    aud: [
      'abacus-cf-bridge',
      'abacus.usage.linux-container'
    ]
  },
  signature: 'irxoV230hkDJenXoTSHQFfqzoUl353lS2URo1fJm21Y'
};

// Sign a known token using default algorithm (HS256)
const signedToken = jwt.sign(decodedToken.payload, tokenSecret, {
  expiresIn: 43200
});

const test = (secured) => {
  let server;
  let submittime = new Date();

  beforeEach(() => {
    process.env.SECURED = secured ? 'true' : 'false';

    const start = (module) => {
      debug('Starting %s in directory %s', module, moduleDir(module));
      const c = cp.spawn('npm', ['run', 'start'], {
        cwd: moduleDir(module),
        env: clone(process.env)
      });

      // Add listeners to stdout, stderr and exit messsage and forward the
      // messages to debug logs
      c.stdout.on('data', (d) => process.stdout.write(d));
      c.stderr.on('data', (d) => process.stderr.write(d));
      c.on('exit', (c) => debug('Application exited with code %d', c));
    };

    const app = express();
    const routes = router();
    routes.get('/v2/app_usage_events', (request, response) => {
      response.status(200).send({
        total_results: 1,
        total_pages: 1,
        prev_url: null,
        next_url: null,
        resources: [
          {
            metadata: {
              guid: '904419c4',
              url: '/v2/app_usage_events/904419c4',
              created_at: submittime.toISOString()
            },
            entity: {
              state: 'STARTED',
              memory_in_mb_per_instance: 512,
              instance_count: 1,
              app_guid: '35c4ff2f',
              app_name: 'app',
              space_guid: 'a7e44fcd-25bf-4023-8a87-03fba4882995',
              space_name: 'diego',
              org_guid: 'e8139b76-e829-4af3-b332-87316b1c0a6c',
              buildpack_guid: null,
              buildpack_name: null,
              package_state: 'PENDING',
              parent_app_guid: null,
              parent_app_name: null,
              process_type: 'web'
            }
          }
        ]
      });
    });
    routes.get('/v2/apps', (request, response) => {
      response.status(200).send({});
    });
    routes.get('/v2/info',
      (request, response) => {
        response.status(200).send({
          token_endpoint: 'http://localhost:4321'
        });
      });
    routes.get('/oauth/token',
      (request, response) => {
        response.status(200).send({
          token_type: 'bearer',
          access_token: signedToken,
          expires_in: 100000,
          scope: 'abacus.usage.linux-container.read ' +
            'abacus.usage.linux-container.write',
          jti: '254abca5-1c25-40c5-99d7-2cc641791517'
        });
      });
    app.use(routes);
    app.use(router.batch(routes));
    server = app.listen(4321);

    if (!process.env.DB)
      start('abacus-pouchserver');
    start('abacus-eureka-plugin');
    start('abacus-authserver-plugin');
    start('abacus-provisioning-plugin');
    start('abacus-account-plugin');
    start('abacus-usage-collector');
    start('abacus-usage-meter');
    start('abacus-usage-accumulator');
    start('abacus-usage-aggregator');
    start('abacus-usage-reporting');
    start('abacus-cf-bridge');
  });

  afterEach(() => {
    const stop = (module) => {
      cp.spawn('npm', ['run', 'stop'],
        { cwd: moduleDir(module), env: clone(process.env) });
    };

    stop('abacus-cf-bridge');
    stop('abacus-usage-reporting');
    stop('abacus-usage-aggregator');
    stop('abacus-usage-accumulator');
    stop('abacus-usage-meter');
    stop('abacus-usage-collector');
    stop('abacus-account-plugin');
    stop('abacus-provisioning-plugin');
    stop('abacus-authserver-plugin');
    stop('abacus-eureka-plugin');
    if (!process.env.DB)
      stop('abacus-pouchserver');

    server.close();
  });

  const checkAllTimeWindows = (usage, reporttime) => {
    for (const windowType in timeWindows) {
      if(isWithinWindow(submittime, reporttime, timeWindows[windowType])) {
        const windowUsage = usage.windows[timeWindows[windowType]];
        expect(windowUsage[0].quantity.consuming).to.equal(0.5);
        expect(windowUsage[0].charge).to.be.above(0);
      }
    }
  };

  const checkReport = (cb) => {
    request.get('http://localhost:9088/v1/metering/organizations' +
      '/:organization_id/aggregated/usage', {
        organization_id: 'e8139b76-e829-4af3-b332-87316b1c0a6c',
        headers: {
          authorization: 'bearer ' + signedToken
        }
      },
      (error, response) => {
        try {
          expect(error).to.equal(undefined);

          expect(response.body).to.contain.all.keys('resources', 'spaces');
          const resources = response.body.resources;
          expect(resources.length).to.equal(1);
          expect(response.body.spaces.length).to.equal(1);
          const reporttime = new Date();

          expect(resources[0]).to.contain.all.keys(
            'plans', 'aggregated_usage');

          const planUsage = resources[0].plans[0].aggregated_usage[0];
          checkAllTimeWindows(planUsage, reporttime);

          const aggregatedUsage = resources[0].aggregated_usage[0];
          checkAllTimeWindows(aggregatedUsage, reporttime);

          cb();
        }
        catch (e) {
          const errorMsg = util.format('Check failed with %s.\n' +
            'Usage report:\n', e.stack,
            response ? JSON.stringify(response.body, null, 2) : 'unknown');
          cb(new Error(errorMsg, e));
        }
      });
  };

  const poll = (fn, done, timeout = 1000, interval = 100) => {
    let lastError;

    const doneInterceptor = (err) => {
      if (!err) {
        debug('Expectation in %s met', fn.name);
        clearInterval(intervalTimer);
        clearTimeout(timeoutTimer);
        setImmediate(done);
      }
      lastError = err;
    };

    const intervalTimer = setInterval(() => {
      debug('Calling %s ...', fn.name);
      fn(doneInterceptor);
    }, interval);

    const timeoutTimer = setTimeout(() => {
      debug('Clearing expectation timer ...');
      clearInterval(intervalTimer);

      const msg = util.format('Expectation not met for %d ms. Last error: %s',
        timeout, lastError ? lastError.stack : 'unknown');
      debug(msg);
      setImmediate(() => done(lastError));
    }, timeout);
  };

  it('submit runtime usage to usage collector', function(done) {
    this.timeout(totalTimeout + 2000);

    // Wait for bridge to start
    request.waitFor('http://localhost::p/v1/cf/bridge',
      { p: 9500 }, startTimeout, (err, uri, opts) => {
        // Failed to ping bridge before timing out
        if (err) throw err;

        // Check report
        request.get(uri, opts, (err, response) => {
          expect(err).to.equal(undefined);
          expect(response.statusCode).to.equal(200);

          poll(checkReport, done, totalTimeout, 2000);
        });
      }
    );
  });
};

describe('abacus-cf-bridge-itest with oAuth', () => test(true));

describe('abacus-cf-bridge-itest without oAuth', () => test(false));
<commit_msg>Increase cf-bridge timeout twice (2 executions)<commit_after>'use strict';

const commander = require('commander');
const cp = require('child_process');
const _ = require('underscore');
const util = require('util');
const jwt = require('jsonwebtoken');

const request = require('abacus-request');
const router = require('abacus-router');
const express = require('abacus-express');

const clone = _.clone;

// Setup the debug log
const debug = require('abacus-debug')('abacus-cf-bridge-itest');

// Module directory
const moduleDir = (module) => {
  const path = require.resolve(module);
  return path.substr(0, path.indexOf(module + '/') + module.length);
};

const timeWindows = {
  'second' : 0,
  'minute' : 1,
  'hour'   : 2,
  'day'    : 3,
  'month'  : 4
};

// Checks if the difference between start and end time fall within a window
const isWithinWindow = (start, end, timeWindow) => {
  // [Second, Minute, Hour, Day, Month]
  const timescale = [1, 100, 10000, 1000000, 100000000];
  // Converts a millisecond number to a format a number that is YYYYMMDDHHmmSS
  const dateUTCNumbify = (t) => {
    const d = new Date(t);
    return d.getUTCFullYear() * 10000000000 + d.getUTCMonth() * timescale[4]
      + d.getUTCDate() * timescale[3] + d.getUTCHours() * timescale[2]
      + d.getUTCMinutes() * timescale[1] + d.getUTCSeconds();
  };

  return Math.floor(dateUTCNumbify(end) / timescale[timeWindow]) -
    Math.floor(dateUTCNumbify(start) / timescale[timeWindow]) === 0;
};

// Parse command line options
const argv = clone(process.argv);
argv.splice(1, 1, 'usage-collector-itest');
commander
  .option('-t, --start-timeout <n>',
    'external processes start timeout in milliseconds', parseInt)
  .option('-x, --total-timeout <n>',
    'test timeout in milliseconds', parseInt)
  .allowUnknownOption(true)
  .parse(argv);

// External Abacus processes start timeout
const startTimeout = commander.startTimeout || 10000;

// This test timeout
const totalTimeout = commander.totalTimeout || 120000;

// Token setup
process.env.API = 'http://localhost:4321';

process.env.CF_CLIENT_ID = 'abacus-cf-bridge';
process.env.CF_CLIENT_SECRET = 'secret';

process.env.CLIENT_ID = 'abacus-linux-container';
process.env.CLIENT_SECRET = 'secret';
const tokenSecret = 'secret';
const tokenAlgorithm = 'HS256';
process.env.JWTKEY = tokenSecret;
process.env.JWTALGO = tokenAlgorithm;

const decodedToken = {
  header: {
    alg: tokenAlgorithm
  },
  payload: {
    jti: '254abca5-1c25-40c5-99d7-2cc641791517',
    sub: 'abacus-cf-bridge',
    authorities: [
      'abacus.usage.linux-container.write',
      'abacus.usage.linux-container.read'
    ],
    scope: [
      'abacus.usage.linux-container.read',
      'abacus.usage.linux-container.write'
    ],
    client_id: 'abacus-cf-bridge',
    cid: 'abacus-cf-bridge',
    azp: 'abacus-cf-bridge',
    grant_type: 'client_credentials',
    rev_sig: '2cf89595',
    iat: 1456147679,
    exp: 1456190879,
    iss: 'https://localhost:1234/oauth/token',
    zid: 'uaa',
    aud: [
      'abacus-cf-bridge',
      'abacus.usage.linux-container'
    ]
  },
  signature: 'irxoV230hkDJenXoTSHQFfqzoUl353lS2URo1fJm21Y'
};

// Sign a known token using default algorithm (HS256)
const signedToken = jwt.sign(decodedToken.payload, tokenSecret, {
  expiresIn: 43200
});

const test = (secured) => {
  let server;
  let submittime = new Date();

  beforeEach(() => {
    process.env.SECURED = secured ? 'true' : 'false';

    const start = (module) => {
      debug('Starting %s in directory %s', module, moduleDir(module));
      const c = cp.spawn('npm', ['run', 'start'], {
        cwd: moduleDir(module),
        env: clone(process.env)
      });

      // Add listeners to stdout, stderr and exit messsage and forward the
      // messages to debug logs
      c.stdout.on('data', (d) => process.stdout.write(d));
      c.stderr.on('data', (d) => process.stderr.write(d));
      c.on('exit', (c) => debug('Application exited with code %d', c));
    };

    const app = express();
    const routes = router();
    routes.get('/v2/app_usage_events', (request, response) => {
      response.status(200).send({
        total_results: 1,
        total_pages: 1,
        prev_url: null,
        next_url: null,
        resources: [
          {
            metadata: {
              guid: '904419c4',
              url: '/v2/app_usage_events/904419c4',
              created_at: submittime.toISOString()
            },
            entity: {
              state: 'STARTED',
              memory_in_mb_per_instance: 512,
              instance_count: 1,
              app_guid: '35c4ff2f',
              app_name: 'app',
              space_guid: 'a7e44fcd-25bf-4023-8a87-03fba4882995',
              space_name: 'diego',
              org_guid: 'e8139b76-e829-4af3-b332-87316b1c0a6c',
              buildpack_guid: null,
              buildpack_name: null,
              package_state: 'PENDING',
              parent_app_guid: null,
              parent_app_name: null,
              process_type: 'web'
            }
          }
        ]
      });
    });
    routes.get('/v2/apps', (request, response) => {
      response.status(200).send({});
    });
    routes.get('/v2/info',
      (request, response) => {
        response.status(200).send({
          token_endpoint: 'http://localhost:4321'
        });
      });
    routes.get('/oauth/token',
      (request, response) => {
        response.status(200).send({
          token_type: 'bearer',
          access_token: signedToken,
          expires_in: 100000,
          scope: 'abacus.usage.linux-container.read ' +
            'abacus.usage.linux-container.write',
          jti: '254abca5-1c25-40c5-99d7-2cc641791517'
        });
      });
    app.use(routes);
    app.use(router.batch(routes));
    server = app.listen(4321);

    if (!process.env.DB)
      start('abacus-pouchserver');
    start('abacus-eureka-plugin');
    start('abacus-authserver-plugin');
    start('abacus-provisioning-plugin');
    start('abacus-account-plugin');
    start('abacus-usage-collector');
    start('abacus-usage-meter');
    start('abacus-usage-accumulator');
    start('abacus-usage-aggregator');
    start('abacus-usage-reporting');
    start('abacus-cf-bridge');
  });

  afterEach(() => {
    const stop = (module) => {
      cp.spawn('npm', ['run', 'stop'],
        { cwd: moduleDir(module), env: clone(process.env) });
    };

    stop('abacus-cf-bridge');
    stop('abacus-usage-reporting');
    stop('abacus-usage-aggregator');
    stop('abacus-usage-accumulator');
    stop('abacus-usage-meter');
    stop('abacus-usage-collector');
    stop('abacus-account-plugin');
    stop('abacus-provisioning-plugin');
    stop('abacus-authserver-plugin');
    stop('abacus-eureka-plugin');
    if (!process.env.DB)
      stop('abacus-pouchserver');

    server.close();
  });

  const checkAllTimeWindows = (usage, reporttime) => {
    for (const windowType in timeWindows) {
      if(isWithinWindow(submittime, reporttime, timeWindows[windowType])) {
        const windowUsage = usage.windows[timeWindows[windowType]];
        expect(windowUsage[0].quantity.consuming).to.equal(0.5);
        expect(windowUsage[0].charge).to.be.above(0);
      }
    }
  };

  const checkReport = (cb) => {
    request.get('http://localhost:9088/v1/metering/organizations' +
      '/:organization_id/aggregated/usage', {
        organization_id: 'e8139b76-e829-4af3-b332-87316b1c0a6c',
        headers: {
          authorization: 'bearer ' + signedToken
        }
      },
      (error, response) => {
        try {
          expect(error).to.equal(undefined);

          expect(response.body).to.contain.all.keys('resources', 'spaces');
          const resources = response.body.resources;
          expect(resources.length).to.equal(1);
          expect(response.body.spaces.length).to.equal(1);
          const reporttime = new Date();

          expect(resources[0]).to.contain.all.keys(
            'plans', 'aggregated_usage');

          const planUsage = resources[0].plans[0].aggregated_usage[0];
          checkAllTimeWindows(planUsage, reporttime);

          const aggregatedUsage = resources[0].aggregated_usage[0];
          checkAllTimeWindows(aggregatedUsage, reporttime);

          cb();
        }
        catch (e) {
          const errorMsg = util.format('Check failed with %s.\n' +
            'Usage report:\n', e.stack,
            response ? JSON.stringify(response.body, null, 2) : 'unknown');
          cb(new Error(errorMsg, e));
        }
      });
  };

  const poll = (fn, done, timeout = 1000, interval = 100) => {
    let lastError;

    const doneInterceptor = (err) => {
      if (!err) {
        debug('Expectation in %s met', fn.name);
        clearInterval(intervalTimer);
        clearTimeout(timeoutTimer);
        setImmediate(done);
      }
      lastError = err;
    };

    const intervalTimer = setInterval(() => {
      debug('Calling %s ...', fn.name);
      fn(doneInterceptor);
    }, interval);

    const timeoutTimer = setTimeout(() => {
      debug('Clearing expectation timer ...');
      clearInterval(intervalTimer);

      const msg = util.format('Expectation not met for %d ms. Last error: %s',
        timeout, lastError ? lastError.stack : 'unknown');
      debug(msg);
      setImmediate(() => done(lastError));
    }, timeout);
  };

  it('submit runtime usage to usage collector', function(done) {
    this.timeout(totalTimeout + 2000);

    // Wait for bridge to start
    request.waitFor('http://localhost::p/v1/cf/bridge',
      { p: 9500 }, startTimeout, (err, uri, opts) => {
        // Failed to ping bridge before timing out
        if (err) throw err;

        // Check report
        request.get(uri, opts, (err, response) => {
          expect(err).to.equal(undefined);
          expect(response.statusCode).to.equal(200);

          poll(checkReport, done, totalTimeout, 2000);
        });
      }
    );
  });
};

describe('abacus-cf-bridge-itest with oAuth', () => test(true));

describe('abacus-cf-bridge-itest without oAuth', () => test(false));
<|endoftext|>


<commit_before>angular.module('orkaApp')

.controller('appCtrl', ['$scope', '$timeout', 'MapService', 'ConfigService', function ($scope, $timeout, MapService, ConfigService) {
    $scope.selectedTab = false;
    $scope.fullscreen = true;
    $scope.printAvailable = ConfigService.config.print !== undefined;
    $scope.themesAvailable = (ConfigService.config.poi !== undefined && ConfigService.config.track !== undefined);
    $scope.locationsAvailable = ConfigService.config.locations !== undefined;
    $scope.showHeader = ConfigService.config.header;
    $scope.layerswitcherStatus = ConfigService.config.map.layerswitcher;
    $scope.legendStatus = ConfigService.config.map.legend;

    $scope.selectTab = function(tab) {
        $scope.selectedTab = tab === $scope.selectedTab ? false : tab;
        $scope.fullscreen = $scope.selectedTab === false;
    };

    $scope.searchInput = '';
    $scope.searchType = 'address';
    $scope.searchCurrentBboxOnly = false;

    $scope.search = function(query) {
        var ajaxData = "";
        if ($scope.searchCurrentBboxOnly) {
            var map = MapService.getMap();
            var x1 = map.getView().calculateExtent(map.getSize())[0];
            var y1 = map.getView().calculateExtent(map.getSize())[1];
            var x2 = map.getView().calculateExtent(map.getSize())[2];
            var y2 = map.getView().calculateExtent(map.getSize())[3];
            ajaxData = {
                key: $scope.searchType === 'address' ? ConfigService.config.addressSearch.key : ConfigService.config.poiSearch.key,
                type: $scope.searchType === 'address' ? ConfigService.config.addressSearch.type : ConfigService.config.poiSearch.type,
                class: $scope.searchType === 'address' ? ConfigService.config.addressSearch.class : ConfigService.config.poiSearch.class,
                shape: $scope.searchType === 'address' ? ConfigService.config.addressSearch.shape : ConfigService.config.poiSearch.shape,
                limit: $scope.searchType === 'address' ? ConfigService.config.addressSearch.limit : ConfigService.config.poiSearch.limit,
                bbox: x1 + ',' + y1 + ',' + x2 + ',' + y2,
                bbox_epsg: '25833',
                query: query
            };
        } else {
            ajaxData = {
                key: $scope.searchType === 'address' ? ConfigService.config.addressSearch.key : ConfigService.config.poiSearch.key,
                type: $scope.searchType === 'address' ? ConfigService.config.addressSearch.type : ConfigService.config.poiSearch.type,
                class: $scope.searchType === 'address' ? ConfigService.config.addressSearch.class : ConfigService.config.poiSearch.class,
                shape: $scope.searchType === 'address' ? ConfigService.config.addressSearch.shape : ConfigService.config.poiSearch.shape,
                limit: $scope.searchType === 'address' ? ConfigService.config.addressSearch.limit : ConfigService.config.poiSearch.limit,
                query: query
            };
        }
        $.ajax({
            url: $scope.searchType === 'address' ? ConfigService.config.addressSearch.url : ConfigService.config.poiSearch.url,
            data: ajaxData,
            dataType: 'json',
            success: function(data) {
                $scope.showSearchResults = true;
                $scope.populateSearchResults(data.features);
            }
        });
    }

    $scope.searchInputKeyup = function() {
        if ($scope.searchInput.length > 2) {
            var value = $scope.searchInput.toLowerCase().trim();
            if (value != '') {
                $scope.search(value);
            }
            else {
                $scope.showSearchResults = false;
            }
        }
        else {
            $scope.showSearchResults = false;
        }
    };

    $scope.searchChange = function() {
        $scope.searchInputKeyup();
    };

    $scope.populateSearchResults = function(resultsData) {
        var results = '';
        jQuery.each(resultsData, function(index, item) {
          var geometry = item.geometry;
          if (geometry.type === 'Point') {
              var x1 = geometry.coordinates[0];
              var y1 = geometry.coordinates[1];
              var x2 = geometry.coordinates[0];
              var y2 = geometry.coordinates[1];
          } else {
              var x1 = geometry.coordinates[0][0][0];
              var y1 = geometry.coordinates[0][0][1];
              var x2 = geometry.coordinates[0][2][0];
              var y2 = geometry.coordinates[0][2][1];
          }
          if ($scope.searchType === 'poi') {
              results += '
';
          } else {
              results += '
';
          }
          if ($scope.searchType === 'address') {
              results += item.properties.gemeinde_name.indexOf(',') !== -1 ? item.properties.gemeinde_name.substring(0, item.properties._title_.indexOf(',')) : item.properties.gemeinde_name;
              if (item.properties.objektgruppe === 'Gemeindeteil') {
                  results += ', ';
                  results += item.properties.gemeindeteil_name;
              } else if (item.properties.objektgruppe !== 'Gemeinde') {
                  results += ', ';
                  if (item.properties.gemeindeteil_name) {
                      results += item.properties.gemeindeteil_name;
                      results += ', ';
                  }
                  results += item.properties._title_.substring(item.properties._title_.lastIndexOf(',') + 2);
              }
          } else {
              results += item.properties._title_;
          }
          results += '
';
        });
        $('#orka-search-results').html(results);
    };

    $scope.clearSearchInput = function() {
        $scope.searchInput = '';
        $scope.showSearchResults = false;
    };

    $scope.$watch('fullscreen', function() {
        $timeout(function() {
            MapService.getMap().updateSize();
        }, 0, false);
    });

    $('body').on('click', '.orka-search-result', function(e) {
        var map = MapService.getMap();
        var x1 = parseInt($(e.target).data('x1'));
        var y1 = parseInt($(e.target).data('y1'));
        var x2 = parseInt($(e.target).data('x2'));
        var y2 = parseInt($(e.target).data('y2'));
        map.getView().fitExtent([x1, y2, x2, y2], map.getSize());
        if ($scope.searchType === 'poi') {
            var theme = $('label:contains(' + $(e.target).data('theme') + ') > :input');
            if (!theme.is(':checked'))
                $('label:contains(' + $(e.target).data('theme') + ') > :input').click();
        }
    });

    $scope.appReady = true;
}]);
<commit_msg>Verbesserung der Suche: POI nur in M-V suchen<commit_after>angular.module('orkaApp')

.controller('appCtrl', ['$scope', '$timeout', 'MapService', 'ConfigService', function ($scope, $timeout, MapService, ConfigService) {
    $scope.selectedTab = false;
    $scope.fullscreen = true;
    $scope.printAvailable = ConfigService.config.print !== undefined;
    $scope.themesAvailable = (ConfigService.config.poi !== undefined && ConfigService.config.track !== undefined);
    $scope.locationsAvailable = ConfigService.config.locations !== undefined;
    $scope.showHeader = ConfigService.config.header;
    $scope.layerswitcherStatus = ConfigService.config.map.layerswitcher;
    $scope.legendStatus = ConfigService.config.map.legend;

    $scope.selectTab = function(tab) {
        $scope.selectedTab = tab === $scope.selectedTab ? false : tab;
        $scope.fullscreen = $scope.selectedTab === false;
    };

    $scope.searchInput = '';
    $scope.searchType = 'address';
    $scope.searchCurrentBboxOnly = false;

    $scope.search = function(query) {
        var ajaxData = {
            key: $scope.searchType === 'address' ? ConfigService.config.addressSearch.key : ConfigService.config.poiSearch.key,
            type: $scope.searchType === 'address' ? ConfigService.config.addressSearch.type : ConfigService.config.poiSearch.type,
            class: $scope.searchType === 'address' ? ConfigService.config.addressSearch.class : ConfigService.config.poiSearch.class,
            shape: $scope.searchType === 'address' ? ConfigService.config.addressSearch.shape : ConfigService.config.poiSearch.shape,
            limit: $scope.searchType === 'address' ? ConfigService.config.addressSearch.limit : ConfigService.config.poiSearch.limit,
            query: query
        };
        if ($scope.searchCurrentBboxOnly) {
            var map = MapService.getMap();
            var x1 = map.getView().calculateExtent(map.getSize())[0];
            var y1 = map.getView().calculateExtent(map.getSize())[1];
            var x2 = map.getView().calculateExtent(map.getSize())[2];
            var y2 = map.getView().calculateExtent(map.getSize())[3];
            ajaxData.bbox = x1 + ',' + y1 + ',' + x2 + ',' + y2;
            ajaxData.bbox_epsg = '25833';
        } else if ($scope.searchType === 'poi') {
            ajaxData.bbox = '206885,5890624,460857,6060841';
            ajaxData.bbox_epsg = '25833';
        }
        $.ajax({
            url: $scope.searchType === 'address' ? ConfigService.config.addressSearch.url : ConfigService.config.poiSearch.url,
            data: ajaxData,
            dataType: 'json',
            success: function(data) {
                $scope.showSearchResults = true;
                $scope.populateSearchResults(data.features);
            }
        });
    }

    $scope.searchInputKeyup = function() {
        if ($scope.searchInput.length > 2) {
            var value = $scope.searchInput.toLowerCase().trim();
            if (value != '') {
                $scope.search(value);
            }
            else {
                $scope.showSearchResults = false;
            }
        }
        else {
            $scope.showSearchResults = false;
        }
    };

    $scope.searchChange = function() {
        $scope.searchInputKeyup();
    };

    $scope.populateSearchResults = function(resultsData) {
        var results = '';
        jQuery.each(resultsData, function(index, item) {
            var geometry = item.geometry;
            if (geometry.type === 'Point') {
                var x1 = geometry.coordinates[0];
                var y1 = geometry.coordinates[1];
                var x2 = geometry.coordinates[0];
                var y2 = geometry.coordinates[1];
            } else {
                var x1 = geometry.coordinates[0][0][0];
                var y1 = geometry.coordinates[0][0][1];
                var x2 = geometry.coordinates[0][2][0];
                var y2 = geometry.coordinates[0][2][1];
            }
            if ($scope.searchType === 'poi') {
                results += '
';
            } else {
                results += '
';
            }
            if ($scope.searchType === 'address') {
                results += item.properties.gemeinde_name.indexOf(',') !== -1 ? item.properties.gemeinde_name.substring(0, item.properties._title_.indexOf(',')) : item.properties.gemeinde_name;
                if (item.properties.objektgruppe === 'Gemeindeteil') {
                    results += ', ';
                    results += item.properties.gemeindeteil_name;
                } else if (item.properties.objektgruppe !== 'Gemeinde') {
                    results += ', ';
                    if (item.properties.gemeindeteil_name) {
                        results += item.properties.gemeindeteil_name;
                        results += ', ';
                    }
                    results += item.properties._title_.substring(item.properties._title_.lastIndexOf(',') + 2);
                }
            } else {
                results += item.properties._title_;
            }
            results += '
';
        });
        $('#orka-search-results').html(results);
    };

    $scope.clearSearchInput = function() {
        $scope.searchInput = '';
        $scope.showSearchResults = false;
    };

    $scope.$watch('fullscreen', function() {
        $timeout(function() {
            MapService.getMap().updateSize();
        }, 0, false);
    });

    $('body').on('click', '.orka-search-result', function(e) {
        var map = MapService.getMap();
        var x1 = parseInt($(e.target).data('x1'));
        var y1 = parseInt($(e.target).data('y1'));
        var x2 = parseInt($(e.target).data('x2'));
        var y2 = parseInt($(e.target).data('y2'));
        map.getView().fitExtent([x1, y2, x2, y2], map.getSize());
        if ($scope.searchType === 'poi') {
            var theme = $('label:contains(' + $(e.target).data('theme') + ') > :input');
            if (!theme.is(':checked'))
                $('label:contains(' + $(e.target).data('theme') + ') > :input').click();
        }
    });

    $scope.appReady = true;
}]);
<|endoftext|>


<commit_before>/* Core rebalance algorithms, no UI. */

function rebalance(ctx, req) {
  return run(ctx, req,
             validatePartitionSettings,
             allocNextMap,
             planNextRebalanceMap,
             actualizeNextMap);
}
function failOver(ctx, req) {
  return run(ctx, req,
             validatePartitionSettings,
             allocNextMap,
             planNextFailOverMap,
             actualizeNextMap);
}
function restoreBack(ctx, req) {
  return run(ctx, req,
             validatePartitionSettings,
             allocNextMap,
             planNextRestoreBackMap,
             actualizeNextMap);
}
function cancelRebalance(ctx, req) {
  return run(ctx, req,
             cancelTakeOverSteps,
             takeCurrentMapAsNextMap,
             actualizeNextMap);
}
function actualizeNextMap(ctx, req) {
  return run(ctx, req,
             validateNextMap,
             scheduleSteps,
             executeSteps,
             checkHealth);
}

// --------------------------------------------------------

function validatePartitionSettings(ctx, req) {
  req.nextBucketEvents = _.clone(req.prevBucketEvents);
  req.nextBucketEvents.events = sortDesc(req.nextBucketEvents.events || [],
                                         "when");

  req.lastPartitionMap = _.findWhere(req.nextBucketEvents.events,
                                     { class: "partitionMap" });
  if (req.lastPartitionMap) {
    req.lastPartitions = partitionsWithNodeNames(req.lastPartitionMap.partitions,
                                                 req.lastPartitionMap.nodes);
  }

  req.arrNodes = { want: req.wantPartitionParams.nodes };
  req.mapNodes = {};

  req.lastPartitionParams = _.findWhere(req.nextBucketEvents.events,
                                        { class: "partitionParams" });
  if (req.lastPartitionParams) {
    req.err =
      _.reduce(["keyFunc", "assignment", "numPartitions"], function(r, k) {
          if (req.lastPartitionParams[k] != req.wantPartitionParams[k]) {
            return "partitionParams." + k + " not equal: " +
              req.lastPartitionParams[k] + " vs " + req.wantPartitionParams[k];
          }
          return r;
        }, null);
    if (req.err) {
      return;
    }

    req.arrNodes.added =
      _.difference(req.wantPartitionParams.nodes, req.lastPartitionParams.nodes);
    req.arrNodes.removed =
      _.difference(req.lastPartitionParams.nodes, req.wantPartitionParams.nodes);
    req.arrNodes.same =
      _.intersection(req.lastPartitionParams.nodes, req.wantPartitionParams.nodes);
  } else {
    req.arrNodes.added   = req.wantPartitionParams.nodes;
    req.arrNodes.removed = [];
    req.arrNodes.same    = [];
  }
  _.each(req.arrNodes, function(a, k) { req.mapNodes[k] = arrToMap(a); });
  function arrToMap(a) {
    return _.reduce(a, function(m, k) { m[k] = {}; return m; }, {});
  }

  req.partitionModel =
    ctx.getObj("partitionModel-" + req.wantPartitionParams.assignment).result;
  if (!req.partitionModel) {
    req.err = "error: missing partitionModel-" + req.wantPartitionParams.assignment;
    return;
  }
  req.partitionModelStates =
    sortDesc(_.reduce(req.partitionModel.states,
                      function(a, v, k) {
                        a.push(_.defaults(_.clone(v), { name: k }));
                        return a;
                      }, []),
             "priority");
  req.mapStatePriority = // Key is state name (e.g., "master"), val is priority int.
    _.reduce(req.partitionModel.states,
             function(m, partitionModel, name) {
               m[name] = partitionModel.priority;
               return m;
             }, {});
}

function allocNextMap(ctx, req) {
  req.nextPartitionMap =
    ctx.newObj("partitionMap", _.omit(req.wantPartitionParams, "class")).result;
  req.nextPartitionMap.partitions =
    keyFunc[req.wantPartitionParams.keyFunc].allocPartitions(req);
  req.nextPartitionMapNumPartitions =
    _.size(req.nextPartitionMap.partitions);
}

function planNextRebalanceMap(ctx, req) {
  return planNextMap(ctx, req);
}

function planNextFailOverMap(ctx, req) {
  return planNextMap(ctx, req);
}

function planNextRestoreBackMap(ctx, req) {
  return planNextMap(ctx, req);
}

function planNextMap(ctx, req) {
  // TODO: maintenance mode & swap rebalance detected as part of rebalance.

  // Remove nodes that user wants to be removed.
  var lastPartitions = req.lastPartitions || {};
  var nextPartitions =
    _.object(_.map(req.nextPartitionMap.partitions,
                   function(partition, partitionId) {
                     var lastPartition = lastPartitions[partitionId] || {};
                     var nextPartition = removeNodesFromPartition(lastPartition,
                                                                  req.arrNodes.removed);
                     return [partitionId, nextPartition];
                   }));

  req.stateNodeCountsBeg = countStateNodes(nextPartitions);
  req.stateNodeCountsCur = countStateNodes(nextPartitions);

  // Run through the sorted partition states (master, slave, etc) that
  // have constraints and invoke assignStateToPartitions().
  _.each(req.partitionModelStates,
         function(s) {
           var constraints =
             parseInt((req.wantPartitionParams.constraints || {})[s.name]) ||
             parseInt(s.constraints);
           if (constraints >= 0) {
             assignStateToPartitions(s.name, constraints);
           }
         });

  // Given a state and its constraints, for every partition, find and
  // assign the best nodes to that state.
  function assignStateToPartitions(state, constraints) {
    nextPartitions =
      _.object(_.map(nextPartitions,
                     function(partition, partitionId) {
                       var nodesToAssign =
                         findBestNodes(partitionId, partition, state, constraints);
                       partition = removeNodesFromPartition(partition,
                                                            nodesToAssign,
                                                            decStateNodeCountsCur);
                       partition[state] = nodesToAssign;
                       incStateNodeCountsCur(state, nodesToAssign);
                       return [partitionId, partition];
                     }));
  }

  function findBestNodes(partitionId, partition, state, constraints) {
    var stateNodeCounts = req.stateNodeCountsCur[state] || {}
    var statePriority = req.mapStatePriority[state];
    var candidateNodes = req.nextPartitionMap.nodes;
    _.each(partition,
           function(sNodes, s) {
             // Filter out or don't touch nodes at a higher priority state.
             if (req.mapStatePriority[s] > statePriority) {
               candidateNodes = _.difference(candidateNodes, sNodes);
             }
           });
    candidateNodes = _.sortBy(candidateNodes, function(n) {
        return stateNodeCounts[n] || 0;
      });
    return candidateNodes.slice(0, constraints);
  }

  function incStateNodeCountsCur(state, nodes) {
    adjustStateNodeCounts(req.stateNodeCountsCur, state, nodes, 1);
  }
  function decStateNodeCountsCur(state, nodes) {
    adjustStateNodeCounts(req.stateNodeCountsCur, state, nodes, -1);
  }

  function adjustStateNodeCounts(stateNodeCounts, state, nodes, amt) {
    _.each(nodes, function(n) {
        var s = stateNodeCounts[state] = stateNodeCounts[state] || {};
        s[n] = (s[n] || 0) + amt;
        if (s[n] < 0) {
          console.log("ERROR: adjustStateNodeCounts < 0" +
                      ", state: " + state + " node: " + n + " s[n]: " + s[n]);
        }
        if (s[n] > req.nextPartitionMapNumPartitions) {
          console.log("ERROR: adjustStateNodeCounts < numPartitions" +
                      ", state: " + state + " node: " + n + " s[n]: " + s[n]);
        }
      });
  }

  req.stateNodeCountsCur = countStateNodes(nextPartitions);

  req.nextPartitionMap.partitions = nextPartitions;
  req.nextPartitionMap.partitions =
    partitionsWithNodeIndexes(req.nextPartitionMap.partitions,
                              req.nextPartitionMap.nodes);

  // TODO: mark partitions on removed node as dead.
}

function validateNextMap(ctx, req) {
  // TODO: do real validation here.
  req.nextBucketEvents.events.unshift(req.wantPartitionParams);
  req.nextBucketEvents.events.unshift(req.nextPartitionMap);
}

function scheduleSteps(ctx, req) {
}

function executeSteps(ctx, req) {
}

function cancelTakeOverSteps(ctx, req) {
}

function takeCurrentMapAsNextMap(ctx, req) {
}

function checkHealth(ctx, req) {
}

// --------------------------------------------------------

// Returns partition with nodes removed.  Example, when removeNodes == ["a"],
//   before - partition: {"0": { "master": ["a"], "slave": ["b"] } }
//   after  - partition: {"0": { "master": [], "slave": ["b"] } }
function removeNodesFromPartition(partition, removeNodes, cb) {
  return _.object(_.map(partition,
                        function(partitionNodes, state) {
                          if (cb) {
                            cb(state, _.intersection(partitionNodes, removeNodes));
                          }
                          return [state, _.difference(partitionNodes, removeNodes)];
                        }));
}

// Converts node indexes to node names.  Example, with "nodes": ["a", "b"]:
//   before - "partitions": { "0": { "master": [0], "slave": [1] }, ... }
//   after  - "partitions": { "0": { "master": ["a"], "slave": ["b"] }, ... }
// Reverse of partitionsWithNodeIndexes().
function partitionsWithNodeNames(partitions, nodes) {
  return partitionsMap(partitions,
                       function(nodeIdx) { return nodes[nodeIdx]; });
}

// Converts node names to indexes.  Example, with node" == ["a", "b"]:
//   before - partitions: { "0": { "master": ["a"], "slave": ["b"] }, ... }
//   after  - partitions: { "0": { "master": [0], "slave": [1] }, ... }
// Reverse of partitionsWithNodeNames().
function partitionsWithNodeIndexes(partitions, nodes) {
  return partitionsMap(partitions,
                       function(nodeName) { return _.indexOf(nodes, nodeName); });
}

// Like map(), but runs f() on every nodes array in the partition.
// Example, with partitions == { "0": { "master": ["a"], "slave": ["b", "c"] } }
// then you'll see f(["a"]) and f(["b", "c"]).
function partitionsMap(partitions, f) {
  return _.object(_.map(partitions,
                        function(partition, partitionId) {
                          return [partitionId,
                                  _.object(_.map(partition,
                                                 function(arr, state) {
                                                   return [state, _.map(arr, f)];
                                                 }))];
                        }));
}

// Example, with partitions of...
//   { "0": { "master": ["a"], "slave": ["b", "c"] } },
//   { "1": { "master": ["b"], "slave": ["c"] } }
// then return value will be...
//   { "master": { "a": 1, "b": 1 } },
//   { "slave": { "b": 1, "c": 2 } }
function countStateNodes(partitions) {
  return _.reduce(partitions, function(r, partition, partitionId) {
      return _.reduce(partition, function(r, nodes, state) {
          _.each(nodes, function(node) {
              var s = r[state] = r[state] || {};
              s[node] = (s[node] || 0) + 1;
            });
          return r;
        }, r);
    }, {});
}

// --------------------------------------------------------

function run(ctx, req) { // Varargs are steps to apply to req as long as no req.err.
  return _.reduce(_.rest(arguments, 2),
                  function(req, step) {
                    return req.err ? req : step(ctx, req) || req;
                  }, req);
}

function sortDesc(a, field) { return _.sortBy(a, field).reverse(); }
<commit_msg>Add a factor for when node already is current.<commit_after>/* Core rebalance algorithms, no UI. */

function rebalance(ctx, req) {
  return run(ctx, req,
             validatePartitionSettings,
             allocNextMap,
             planNextRebalanceMap,
             actualizeNextMap);
}
function failOver(ctx, req) {
  return run(ctx, req,
             validatePartitionSettings,
             allocNextMap,
             planNextFailOverMap,
             actualizeNextMap);
}
function restoreBack(ctx, req) {
  return run(ctx, req,
             validatePartitionSettings,
             allocNextMap,
             planNextRestoreBackMap,
             actualizeNextMap);
}
function cancelRebalance(ctx, req) {
  return run(ctx, req,
             cancelTakeOverSteps,
             takeCurrentMapAsNextMap,
             actualizeNextMap);
}
function actualizeNextMap(ctx, req) {
  return run(ctx, req,
             validateNextMap,
             scheduleSteps,
             executeSteps,
             checkHealth);
}

// --------------------------------------------------------

function validatePartitionSettings(ctx, req) {
  req.nextBucketEvents = _.clone(req.prevBucketEvents);
  req.nextBucketEvents.events = sortDesc(req.nextBucketEvents.events || [],
                                         "when");

  req.lastPartitionMap = _.findWhere(req.nextBucketEvents.events,
                                     { class: "partitionMap" });
  if (req.lastPartitionMap) {
    req.lastPartitions = partitionsWithNodeNames(req.lastPartitionMap.partitions,
                                                 req.lastPartitionMap.nodes);
  }

  req.arrNodes = { want: req.wantPartitionParams.nodes };
  req.mapNodes = {};

  req.lastPartitionParams = _.findWhere(req.nextBucketEvents.events,
                                        { class: "partitionParams" });
  if (req.lastPartitionParams) {
    req.err =
      _.reduce(["keyFunc", "assignment", "numPartitions"], function(r, k) {
          if (req.lastPartitionParams[k] != req.wantPartitionParams[k]) {
            return "partitionParams." + k + " not equal: " +
              req.lastPartitionParams[k] + " vs " + req.wantPartitionParams[k];
          }
          return r;
        }, null);
    if (req.err) {
      return;
    }

    req.arrNodes.added =
      _.difference(req.wantPartitionParams.nodes, req.lastPartitionParams.nodes);
    req.arrNodes.removed =
      _.difference(req.lastPartitionParams.nodes, req.wantPartitionParams.nodes);
    req.arrNodes.same =
      _.intersection(req.lastPartitionParams.nodes, req.wantPartitionParams.nodes);
  } else {
    req.arrNodes.added   = req.wantPartitionParams.nodes;
    req.arrNodes.removed = [];
    req.arrNodes.same    = [];
  }
  _.each(req.arrNodes, function(a, k) { req.mapNodes[k] = arrToMap(a); });
  function arrToMap(a) {
    return _.reduce(a, function(m, k) { m[k] = {}; return m; }, {});
  }

  req.partitionModel =
    ctx.getObj("partitionModel-" + req.wantPartitionParams.assignment).result;
  if (!req.partitionModel) {
    req.err = "error: missing partitionModel-" + req.wantPartitionParams.assignment;
    return;
  }
  req.partitionModelStates =
    sortDesc(_.reduce(req.partitionModel.states,
                      function(a, v, k) {
                        a.push(_.defaults(_.clone(v), { name: k }));
                        return a;
                      }, []),
             "priority");
  req.mapStatePriority = // Key is state name (e.g., "master"), val is priority int.
    _.reduce(req.partitionModel.states,
             function(m, partitionModel, name) {
               m[name] = partitionModel.priority;
               return m;
             }, {});
}

function allocNextMap(ctx, req) {
  req.nextPartitionMap =
    ctx.newObj("partitionMap", _.omit(req.wantPartitionParams, "class")).result;
  req.nextPartitionMap.partitions =
    keyFunc[req.wantPartitionParams.keyFunc].allocPartitions(req);
  req.nextPartitionMapNumPartitions =
    _.size(req.nextPartitionMap.partitions);
}

function planNextRebalanceMap(ctx, req) {
  return planNextMap(ctx, req);
}

function planNextFailOverMap(ctx, req) {
  return planNextMap(ctx, req);
}

function planNextRestoreBackMap(ctx, req) {
  return planNextMap(ctx, req);
}

function planNextMap(ctx, req) {
  // TODO: maintenance mode & swap rebalance detected as part of rebalance.

  // Remove nodes that user wants to be removed.
  var lastPartitions = req.lastPartitions || {};
  var nextPartitions =
    _.object(_.map(req.nextPartitionMap.partitions,
                   function(partition, partitionId) {
                     var lastPartition = lastPartitions[partitionId] || {};
                     var nextPartition = removeNodesFromPartition(lastPartition,
                                                                  req.arrNodes.removed);
                     return [partitionId, nextPartition];
                   }));

  req.stateNodeCountsBeg = countStateNodes(nextPartitions);
  req.stateNodeCountsCur = countStateNodes(nextPartitions);

  // Run through the sorted partition states (master, slave, etc) that
  // have constraints and invoke assignStateToPartitions().
  _.each(req.partitionModelStates,
         function(s) {
           var constraints =
             parseInt((req.wantPartitionParams.constraints || {})[s.name]) ||
             parseInt(s.constraints);
           if (constraints >= 0) {
             assignStateToPartitions(s.name, constraints);
           }
         });

  // Given a state and its constraints, for every partition, find and
  // assign the best nodes to that state.
  function assignStateToPartitions(state, constraints) {
    nextPartitions =
      _.object(_.map(nextPartitions,
                     function(partition, partitionId) {
                       var nodesToAssign =
                         findBestNodes(partitionId, partition, state, constraints);
                       partition = removeNodesFromPartition(partition,
                                                            nodesToAssign,
                                                            decStateNodeCountsCur);
                       partition[state] = nodesToAssign;
                       incStateNodeCountsCur(state, nodesToAssign);
                       return [partitionId, partition];
                     }));
  }

  function findBestNodes(partitionId, partition, state, constraints) {
    var stateNodeCounts = req.stateNodeCountsCur[state] || {}
    var statePriority = req.mapStatePriority[state];
    var candidateNodes = req.nextPartitionMap.nodes;
    _.each(partition,
           function(sNodes, s) {
             // Filter out or don't touch nodes at a higher priority state.
             if (req.mapStatePriority[s] > statePriority) {
               candidateNodes = _.difference(candidateNodes, sNodes);
             }
           });
    candidateNodes = _.sortBy(candidateNodes, function(node) {
        var isCurrent = _.contains(partition[state] || [], node);
        var currentFactor = isCurrent ? 0 : 1;
        var r = stateNodeCounts[node] || 0;
        return (r * 100) + currentFactor;
      });
    return candidateNodes.slice(0, constraints);
  }

  function incStateNodeCountsCur(state, nodes) {
    adjustStateNodeCounts(req.stateNodeCountsCur, state, nodes, 1);
  }
  function decStateNodeCountsCur(state, nodes) {
    adjustStateNodeCounts(req.stateNodeCountsCur, state, nodes, -1);
  }

  function adjustStateNodeCounts(stateNodeCounts, state, nodes, amt) {
    _.each(nodes, function(n) {
        var s = stateNodeCounts[state] = stateNodeCounts[state] || {};
        s[n] = (s[n] || 0) + amt;
        if (s[n] < 0) {
          console.log("ERROR: adjustStateNodeCounts < 0" +
                      ", state: " + state + " node: " + n + " s[n]: " + s[n]);
        }
        if (s[n] > req.nextPartitionMapNumPartitions) {
          console.log("ERROR: adjustStateNodeCounts < numPartitions" +
                      ", state: " + state + " node: " + n + " s[n]: " + s[n]);
        }
      });
  }

  req.stateNodeCountsCur = countStateNodes(nextPartitions);

  req.nextPartitionMap.partitions = nextPartitions;
  req.nextPartitionMap.partitions =
    partitionsWithNodeIndexes(req.nextPartitionMap.partitions,
                              req.nextPartitionMap.nodes);

  // TODO: mark partitions on removed node as dead.
}

function validateNextMap(ctx, req) {
  // TODO: do real validation here.
  req.nextBucketEvents.events.unshift(req.wantPartitionParams);
  req.nextBucketEvents.events.unshift(req.nextPartitionMap);
}

function scheduleSteps(ctx, req) {
}

function executeSteps(ctx, req) {
}

function cancelTakeOverSteps(ctx, req) {
}

function takeCurrentMapAsNextMap(ctx, req) {
}

function checkHealth(ctx, req) {
}

// --------------------------------------------------------

// Returns partition with nodes removed.  Example, when removeNodes == ["a"],
//   before - partition: {"0": { "master": ["a"], "slave": ["b"] } }
//   after  - partition: {"0": { "master": [], "slave": ["b"] } }
function removeNodesFromPartition(partition, removeNodes, cb) {
  return _.object(_.map(partition,
                        function(partitionNodes, state) {
                          if (cb) {
                            cb(state, _.intersection(partitionNodes, removeNodes));
                          }
                          return [state, _.difference(partitionNodes, removeNodes)];
                        }));
}

// Converts node indexes to node names.  Example, with "nodes": ["a", "b"]:
//   before - "partitions": { "0": { "master": [0], "slave": [1] }, ... }
//   after  - "partitions": { "0": { "master": ["a"], "slave": ["b"] }, ... }
// Reverse of partitionsWithNodeIndexes().
function partitionsWithNodeNames(partitions, nodes) {
  return partitionsMap(partitions,
                       function(nodeIdx) { return nodes[nodeIdx]; });
}

// Converts node names to indexes.  Example, with node" == ["a", "b"]:
//   before - partitions: { "0": { "master": ["a"], "slave": ["b"] }, ... }
//   after  - partitions: { "0": { "master": [0], "slave": [1] }, ... }
// Reverse of partitionsWithNodeNames().
function partitionsWithNodeIndexes(partitions, nodes) {
  return partitionsMap(partitions,
                       function(nodeName) { return _.indexOf(nodes, nodeName); });
}

// Like map(), but runs f() on every nodes array in the partition.
// Example, with partitions == { "0": { "master": ["a"], "slave": ["b", "c"] } }
// then you'll see f(["a"]) and f(["b", "c"]).
function partitionsMap(partitions, f) {
  return _.object(_.map(partitions,
                        function(partition, partitionId) {
                          return [partitionId,
                                  _.object(_.map(partition,
                                                 function(arr, state) {
                                                   return [state, _.map(arr, f)];
                                                 }))];
                        }));
}

// Example, with partitions of...
//   { "0": { "master": ["a"], "slave": ["b", "c"] } },
//   { "1": { "master": ["b"], "slave": ["c"] } }
// then return value will be...
//   { "master": { "a": 1, "b": 1 } },
//   { "slave": { "b": 1, "c": 2 } }
function countStateNodes(partitions) {
  return _.reduce(partitions, function(r, partition, partitionId) {
      return _.reduce(partition, function(r, nodes, state) {
          _.each(nodes, function(node) {
              var s = r[state] = r[state] || {};
              s[node] = (s[node] || 0) + 1;
            });
          return r;
        }, r);
    }, {});
}

// --------------------------------------------------------

function run(ctx, req) { // Varargs are steps to apply to req as long as no req.err.
  return _.reduce(_.rest(arguments, 2),
                  function(req, step) {
                    return req.err ? req : step(ctx, req) || req;
                  }, req);
}

function sortDesc(a, field) { return _.sortBy(a, field).reverse(); }
<|endoftext|>


<commit_before>// LICENSE : MIT
"use strict";
import assert from "power-assert"
import {wrapAssert,toAST} from "../src/ast-utils"
import {parse} from "esprima"
import {astEqual} from "./lib/ast-equal"
import {ast} from "esutils"
describe("ast-utils", function () {
    describe("#wrapNode", function () {
        it("should return ast", function () {
            var expressionNode = parse("1");
            var results = wrapAssert(expressionNode);
            var expected = "assert(1)";
            astEqual(results, expected);
        });
    });
    describe("#toAST", function () {
        it("should return AST Node", function () {
            var nodeForInline = parse(1);
            var astNode = toAST`var a = ${nodeForInline}`;
            assert(typeof astNode === "object");
            assert(astNode.type === "Program");
        });
        it("should return ast that inlined parameter node", function () {
            var nodeForInline = parse('"string"');
            var astNode = toAST`var a = ${nodeForInline}`;
            var expected = `var a = "string"`;
            astEqual(astNode, expected);
        });
        it("support `${var} code`", function () {
            var nodeForInline = parse('"string"');
            var astNode = toAST`${nodeForInline}; var a;`;
            var expected = `"string";var a;`;
            astEqual(astNode, expected);
        });
    });
});<commit_msg>test(util): add test<commit_after>// LICENSE : MIT
"use strict";
import assert from "power-assert"
import {wrapAssert,toAST} from "../src/ast-utils"
import {parse} from "esprima"
import {astEqual} from "./lib/ast-equal"
import {ast} from "esutils"
describe("ast-utils", function () {
    describe("#wrapNode", function () {
        it("should return ast", function () {
            var expressionNode = parse("1");
            var results = wrapAssert(expressionNode);
            var expected = "assert(1)";
            astEqual(results, expected);
        });
    });
    describe("#toAST", function () {
        it("should return AST Node", function () {
            var nodeForInline = parse(1);
            var astNode = toAST`var a = ${nodeForInline}`;
            assert(typeof astNode === "object");
            assert(astNode.type === "Program");
        });
        it("should return ast that inlined parameter node", function () {
            var nodeForInline = parse('"string"');
            var astNode = toAST`var a = ${nodeForInline}`;
            var expected = `var a = "string"`;
            astEqual(astNode, expected);
        });
        it("support `${var} code`", function () {
            var nodeForInline = parse('"string"');
            var astNode = toAST`${nodeForInline}; var a;`;
            var expected = `"string";var a;`;
            astEqual(astNode, expected);
        });
        it("support function expression", function () {
            var nodeForInline = {
                "type": "FunctionExpression",
                "id": null,
                "params": [],
                "defaults": [],
                "body": {
                    "type": "BlockStatement",
                    "body": []
                },
                "generator": false,
                "expression": false
            };
            var astNode = toAST`var a = ${nodeForInline};`;
            var expected = `var a = function (){};`;
            astEqual(astNode, expected);
        });
    });
});<|endoftext|>


<commit_before>/**
 * Guzzle node.js test server to return queued responses to HTTP requests and
 * expose a RESTful API for enqueueing responses and retrieving the requests
 * that have been received.
 *
 * - Delete all requests that have been received:
 *      DELETE /guzzle-server/requests
 *      Host: 127.0.0.1:8124
 *
 *  - Enqueue responses
 *      PUT /guzzle-server/responses
 *      Host: 127.0.0.1:8124
 *
 *      [{ "statusCode": 200, "reasonPhrase": "OK", "headers": {}, "body": "" }]
 *
 *  - Get the received requests
 *      GET /guzzle-server/requests
 *      Host: 127.0.0.1:8124
 *
 *  - Shutdown the server
 *      DELETE /guzzle-server
 *      Host: 127.0.0.1:8124
 *
 * @package Guzzle PHP <http://www.guzzlephp.org>
 * @license See the LICENSE file that was distributed with this source code.
 */

var http = require("http");

/**
 * Guzzle node.js server
 * @class
 */
var GuzzleServer = function(port) {

    this.port = port;
    this.log = log;
    this.responses = [];
    this.requests = [];
    var that = this;

    /**
     * Handle a Guzzle Server control request
     * @param (String) request HTTP request as a string
     * @param (ServerRequest) req Received server request
     * @param (ServerResponse) res Outgoing server response
     */
    var controlRequest = function(request, req, res) {
        if (req.method == "DELETE") {
            if (req.url == "/guzzle-server/requests") {
                // Clear the received requests
                that.requests = [];
                res.writeHead(200, "OK", { "Content-Length": 0 });
                res.end();
                if (this.log) {
                    console.log("Flushing requests");
                }
            } else if (req.url == "/guzzle-server") {
                // Shutdown the server
                res.writeHead(200, "OK", { "Content-Length": 0, "Connection": "close" });
                res.end();
                if (this.log) {
                    console.log("Shutting down");
                }
                that.server.close();
            }
        } else if (req.method == "GET") {
            if (req.url === "/guzzle-server/requests") {
                // Get received requests
                var data = that.requests.join("\n----[request]\n");
                res.writeHead(200, "OK", { "Content-Length": data.length });
                res.end(data);
                if (that.log) {
                    console.log("Sending receiving requests");
                }
            }
        } else if (req.method == "PUT") {
            if (req.url == "/guzzle-server/responses") {
                if (that.log) {
                    console.log("Adding responses...");
                }
                // Received response to queue
                var data = request.split("\r\n\r\n")[1];
                if (!data) {
                    if (that.log) {
                        console.log("No response data was provided");
                    }
                    res.writeHead(500, "NO RESPONSES IN REQUEST", { "Content-Length": 0 });
                } else {
                    that.responses = eval("(" + data + ")");
                    if (that.log) {
                        console.log(that.responses);
                    }
                    res.writeHead(200, "OK", { "Content-Length": 0 });
                }
                res.end();
            }
        }
    };

    /**
     * Received a complete request
     * @param (String) request HTTP request as a string
     * @param (ServerRequest) req Received server request
     * @param (ServerResponse) res Outgoing server response
     */
    var receivedRequest = function(request, req, res) {
        if (req.url.indexOf("/guzzle-server") === 0) {
            controlRequest(request, req, res);
        } else {
            var response = that.responses.shift();
            res.writeHead(response.statusCode, response.reasonPhrase, response.headers);
            res.end(response.body);
            that.requests.push(request);
        }
    };

    /**
     * Start the node.js Guzzle server
     */
    this.start = function() {

        that.server = http.createServer(function(req, res) {

            // If this is not a control request and no responses are in queue, return 500 response
            if (req.url.indexOf("/guzzle-server") == -1 && !that.responses.length) {
                res.writeHead(500);
                res.end("No responses in queue");
                return;
            }

            // Begin building the request message as a string
            var request = req.method + " " + req.url + " HTTP/" + req.httpVersion + "\r\n";
            // Add the request headers
            for (var i in req.headers) {
                request += i + ": " + req.headers[i] + "\r\n";
            }
            request += "\r\n";

            // Receive each chunk of the request body
            req.addListener("data", function(chunk) {
                request += chunk;
            });

            // Called when the request completes
            req.addListener("end", function() {
                receivedRequest(request, req, res);
            });
        });
        that.server.listen(port, "127.0.0.1");

        if (this.log) {
            console.log("Server running at http://127.0.0.1:8124/");
        }
    };
};

// Get the port from the arguments
port = process.argv.length >= 3 ? process.argv[2] : 8124;
log = process.argv.length >= 4 ? process.argv[3] : false;

// Start the server
server = new GuzzleServer(port, log);
server.start();
<commit_msg>Adding a guzzle-perf endpoint to the test server<commit_after>/**
 * Guzzle node.js test server to return queued responses to HTTP requests and
 * expose a RESTful API for enqueueing responses and retrieving the requests
 * that have been received.
 *
 * - Delete all requests that have been received:
 *      DELETE /guzzle-server/requests
 *      Host: 127.0.0.1:8124
 *
 *  - Enqueue responses
 *      PUT /guzzle-server/responses
 *      Host: 127.0.0.1:8124
 *
 *      [{ "statusCode": 200, "reasonPhrase": "OK", "headers": {}, "body": "" }]
 *
 *  - Get the received requests
 *      GET /guzzle-server/requests
 *      Host: 127.0.0.1:8124
 *
 *  - Shutdown the server
 *      DELETE /guzzle-server
 *      Host: 127.0.0.1:8124
 *
 * @package Guzzle PHP <http://www.guzzlephp.org>
 * @license See the LICENSE file that was distributed with this source code.
 */

var http = require("http");

/**
 * Guzzle node.js server
 * @class
 */
var GuzzleServer = function(port) {

    this.port = port;
    this.log = log;
    this.responses = [];
    this.requests = [];
    var that = this;

    /**
     * Handle a Guzzle Server control request
     * @param (String) request HTTP request as a string
     * @param (ServerRequest) req Received server request
     * @param (ServerResponse) res Outgoing server response
     */
    var controlRequest = function(request, req, res) {
        if (req.method == "DELETE") {
            if (req.url == "/guzzle-server/requests") {
                // Clear the received requests
                that.requests = [];
                res.writeHead(200, "OK", { "Content-Length": 0 });
                res.end();
                if (this.log) {
                    console.log("Flushing requests");
                }
            } else if (req.url == "/guzzle-server") {
                // Shutdown the server
                res.writeHead(200, "OK", { "Content-Length": 0, "Connection": "close" });
                res.end();
                if (this.log) {
                    console.log("Shutting down");
                }
                that.server.close();
            }
        } else if (req.method == "GET") {
            if (req.url === "/guzzle-server/requests") {
                // Get received requests
                var data = that.requests.join("\n----[request]\n");
                res.writeHead(200, "OK", { "Content-Length": data.length });
                res.end(data);
                if (that.log) {
                    console.log("Sending receiving requests");
                }
            }
        } else if (req.method == "PUT") {
            if (req.url == "/guzzle-server/responses") {
                if (that.log) {
                    console.log("Adding responses...");
                }
                // Received response to queue
                var data = request.split("\r\n\r\n")[1];
                if (!data) {
                    if (that.log) {
                        console.log("No response data was provided");
                    }
                    res.writeHead(500, "NO RESPONSES IN REQUEST", { "Content-Length": 0 });
                } else {
                    that.responses = eval("(" + data + ")");
                    if (that.log) {
                        console.log(that.responses);
                    }
                    res.writeHead(200, "OK", { "Content-Length": 0 });
                }
                res.end();
            }
        }
    };

    /**
     * Received a complete request
     * @param (String) request HTTP request as a string
     * @param (ServerRequest) req Received server request
     * @param (ServerResponse) res Outgoing server response
     */
    var receivedRequest = function(request, req, res) {
        if (req.url.indexOf("/guzzle-server") === 0) {
            controlRequest(request, req, res);
        } else {
            var response = that.responses.shift();
            res.writeHead(response.statusCode, response.reasonPhrase, response.headers);
            res.end(response.body);
            that.requests.push(request);
        }
    };

    /**
     * Start the node.js Guzzle server
     */
    this.start = function() {

        that.server = http.createServer(function(req, res) {

            // If this is not a control request and no responses are in queue, return 500 response
            if (req.url.indexOf("/guzzle-server") == -1 && !that.responses.length) {
                if (req.url == '/guzzle-perf') {
                    res.writeHead(200);
                    res.end("Body of response");
                    return;
                } else {
                    res.writeHead(500);
                    res.end("No responses in queue");
                    return;
                }
            }

            // Begin building the request message as a string
            var request = req.method + " " + req.url + " HTTP/" + req.httpVersion + "\r\n";
            // Add the request headers
            for (var i in req.headers) {
                request += i + ": " + req.headers[i] + "\r\n";
            }
            request += "\r\n";

            // Receive each chunk of the request body
            req.addListener("data", function(chunk) {
                request += chunk;
            });

            // Called when the request completes
            req.addListener("end", function() {
                receivedRequest(request, req, res);
            });
        });
        that.server.listen(port, "127.0.0.1");

        if (this.log) {
            console.log("Server running at http://127.0.0.1:8124/");
        }
    };
};

// Get the port from the arguments
port = process.argv.length >= 3 ? process.argv[2] : 8124;
log = process.argv.length >= 4 ? process.argv[3] : false;

// Start the server
server = new GuzzleServer(port, log);
server.start();
<|endoftext|>