<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stdint.h>

#include <vector>
#include <utility>

#include <mesos/authorizer/authorizer.hpp>

#include <mesos/master/detector.hpp>

#include <mesos/mesos.hpp>

#include <mesos/module/anonymous.hpp>

#include <mesos/slave/resource_estimator.hpp>

#include <process/owned.hpp>

#ifdef __WINDOWS__
#include <process/windows/winsock.hpp>
#endif // __WINDOWS__

#include <stout/check.hpp>
#include <stout/flags.hpp>
#include <stout/hashset.hpp>
#include <stout/nothing.hpp>
#include <stout/os.hpp>
#include <stout/stringify.hpp>
#include <stout/try.hpp>

#include "common/build.hpp"
#include "common/http.hpp"

#include "hook/manager.hpp"

#ifdef __linux__
#include "linux/systemd.hpp"
#endif // __linux__

#include "logging/logging.hpp"

#include "messages/flags.hpp"
#include "messages/messages.hpp"

#include "module/manager.hpp"

#include "slave/gc.hpp"
#include "slave/slave.hpp"
#include "slave/status_update_manager.hpp"

#include "version/version.hpp"

using namespace mesos::internal;
using namespace mesos::internal::slave;

using mesos::master::detector::MasterDetector;

using mesos::modules::Anonymous;
using mesos::modules::ModuleManager;

using mesos::master::detector::MasterDetector;

using mesos::slave::QoSController;
using mesos::slave::ResourceEstimator;

using mesos::Authorizer;
using mesos::SlaveInfo;

using process::Owned;

using process::firewall::DisabledEndpointsFirewallRule;
using process::firewall::FirewallRule;

using std::cerr;
using std::cout;
using std::endl;
using std::move;
using std::string;
using std::vector;

int main(int argc, char** argv)
{
  // The order of initialization is as follows:
  // * Windows socket stack.
  // * Validate flags.
  // * Log build information.
  // * Libprocess
  // * Logging
  // * Version process
  // * Firewall rules: should be initialized before initializing HTTP endpoints.
  // * Modules: Load module libraries and manifests before they
  //   can be instantiated.
  // * Anonymous modules: Later components such as Allocators, and master
  //   contender/detector might depend upon anonymous modules.
  // * Hooks.
  // * Systemd support (if it exists).
  // * Fetcher and Containerizer.
  // * Master detector.
  // * Authorizer.
  // * Garbage collector.
  // * Status update manager.
  // * Resource estimator.
  // * QoS controller.
  // * `Agent` process.
  //
  // TODO(avinash): Add more comments discussing the rationale behind for this
  // particular component ordering.

#ifdef __WINDOWS__
  // Initialize the Windows socket stack.
  process::Winsock winsock;
#endif

  GOOGLE_PROTOBUF_VERIFY_VERSION;

  slave::Flags flags;

  // The following flags are executable specific (e.g., since we only
  // have one instance of libprocess per execution, we only want to
  // advertise the IP and port option once, here).
  Option<string> ip;
  flags.add(&ip,
            "ip",
            "IP address to listen on. This cannot be used in conjunction\n"
            "with `--ip_discovery_command`.");

  uint16_t port;
  flags.add(&port,
            "port",
            "Port to listen on.",
            SlaveInfo().port());

  Option<string> advertise_ip;
  flags.add(&advertise_ip,
            "advertise_ip",
            "IP address advertised to reach this Mesos agent.\n"
            "The agent does not bind to this IP address.\n"
            "However, this IP address may be used to access this agent.");

  Option<string> advertise_port;
  flags.add(&advertise_port,
            "advertise_port",
            "Port advertised to reach this Mesos agent (along with\n"
            "`advertise_ip`). The agent does not bind to this port.\n"
            "However, this port (along with `advertise_ip`) may be used to\n"
            "access this agent.");

  Option<string> master;
  flags.add(&master,
            "master",
            "May be one of:\n"
            "  `host:port`\n"
            "  `zk://host1:port1,host2:port2,.../path`\n"
            "  `zk://username:password@host1:port1,host2:port2,.../path`\n"
            "  `file:///path/to/file` (where file contains one of the above)");

  // Optional IP discover script that will set the slave's IP.
  // If set, its output is expected to be a valid parseable IP string.
  Option<string> ip_discovery_command;
  flags.add(&ip_discovery_command,
            "ip_discovery_command",
            "Optional IP discovery binary: if set, it is expected to emit\n"
            "the IP address which the agent will try to bind to.\n"
            "Cannot be used in conjunction with `--ip`.");

  Try<flags::Warnings> load = flags.load("MESOS_", argc, argv);

  // TODO(marco): this pattern too should be abstracted away
  // in FlagsBase; I have seen it at least 15 times.
  if (load.isError()) {
    cerr << flags.usage(load.error()) << endl;
    return EXIT_FAILURE;
  }

  if (flags.help) {
    cout << flags.usage() << endl;
    return EXIT_SUCCESS;
  }

  if (flags.version) {
    cout << "mesos" << " " << MESOS_VERSION << endl;
    return EXIT_SUCCESS;
  }

  if (master.isNone() && flags.master_detector.isNone()) {
    cerr << flags.usage("Missing required option `--master` or "
                        "`--master_detector`.") << endl;
    return EXIT_FAILURE;
  }

  if (master.isSome() && flags.master_detector.isSome()) {
    cerr << flags.usage("Only one of --master or --master_detector options "
                        "should be specified.");
    return EXIT_FAILURE;
  }

  // Initialize libprocess.
  if (ip_discovery_command.isSome() && ip.isSome()) {
    EXIT(EXIT_FAILURE) << flags.usage(
        "Only one of `--ip` or `--ip_discovery_command` should be specified");
  }

  if (ip_discovery_command.isSome()) {
    Try<string> ipAddress = os::shell(ip_discovery_command.get());

    if (ipAddress.isError()) {
      EXIT(EXIT_FAILURE) << ipAddress.error();
    }

    os::setenv("LIBPROCESS_IP", strings::trim(ipAddress.get()));
  } else if (ip.isSome()) {
    os::setenv("LIBPROCESS_IP", ip.get());
  }

  os::setenv("LIBPROCESS_PORT", stringify(port));

  if (advertise_ip.isSome()) {
    os::setenv("LIBPROCESS_ADVERTISE_IP", advertise_ip.get());
  }

  if (advertise_port.isSome()) {
    os::setenv("LIBPROCESS_ADVERTISE_PORT", advertise_port.get());
  }

  // Log build information.
  LOG(INFO) << "Build: " << build::DATE << " by " << build::USER;
  LOG(INFO) << "Version: " << MESOS_VERSION;

  if (build::GIT_TAG.isSome()) {
    LOG(INFO) << "Git tag: " << build::GIT_TAG.get();
  }

  if (build::GIT_SHA.isSome()) {
    LOG(INFO) << "Git SHA: " << build::GIT_SHA.get();
  }

  const string id = process::ID::generate("slave"); // Process ID.

  // If `process::initialize()` returns `false`, then it was called before this
  // invocation, meaning the authentication realm for libprocess-level HTTP
  // endpoints was set incorrectly. This should be the first invocation.
  if (!process::initialize(
          id,
          READWRITE_HTTP_AUTHENTICATION_REALM,
          READONLY_HTTP_AUTHENTICATION_REALM)) {
    EXIT(EXIT_FAILURE) << "The call to `process::initialize()` in the agent's "
                       << "`main()` was not the function's first invocation";
  }

  logging::initialize(argv[0], flags, true); // Catch signals.

  // Log any flag warnings (after logging is initialized).
  foreach (const flags::Warning& warning, load->warnings) {
    LOG(WARNING) << warning.message;
  }

  spawn(new VersionProcess(), true);

  if (flags.firewall_rules.isSome()) {
    vector<Owned<FirewallRule>> rules;

    const Firewall firewall = flags.firewall_rules.get();

    if (firewall.has_disabled_endpoints()) {
      hashset<string> paths;

      foreach (const string& path, firewall.disabled_endpoints().paths()) {
        paths.insert(path);
      }

      rules.emplace_back(new DisabledEndpointsFirewallRule(paths));
    }

    process::firewall::install(move(rules));
  }

  // Initialize modules.
  if (flags.modules.isSome() && flags.modulesDir.isSome()) {
    EXIT(EXIT_FAILURE) <<
      flags.usage("Only one of --modules or --modules_dir should be specified");
  }

  if (flags.modulesDir.isSome()) {
    Try<Nothing> result = ModuleManager::load(flags.modulesDir.get());
    if (result.isError()) {
      EXIT(EXIT_FAILURE) << "Error loading modules: " << result.error();
    }
  }

  if (flags.modules.isSome()) {
    Try<Nothing> result = ModuleManager::load(flags.modules.get());
    if (result.isError()) {
      EXIT(EXIT_FAILURE) << "Error loading modules: " << result.error();
    }
  }

  // Create anonymous modules.
  foreach (const string& name, ModuleManager::find<Anonymous>()) {
    Try<Anonymous*> create = ModuleManager::create<Anonymous>(name);
    if (create.isError()) {
      EXIT(EXIT_FAILURE)
        << "Failed to create anonymous module named '" << name << "'";
    }

    // We don't bother keeping around the pointer to this anonymous
    // module, when we exit that will effectively free it's memory.
    //
    // TODO(benh): We might want to add explicit finalization (and
    // maybe explicit initialization too) in order to let the module
    // do any housekeeping necessary when the slave is cleanly
    // terminating.
  }

  // Initialize hooks.
  if (flags.hooks.isSome()) {
    Try<Nothing> result = HookManager::initialize(flags.hooks.get());
    if (result.isError()) {
      EXIT(EXIT_FAILURE) << "Error installing hooks: " << result.error();
    }
  }

#ifdef __linux__
  // Initialize systemd if it exists.
  if (systemd::exists() && flags.systemd_enable_support) {
    LOG(INFO) << "Inializing systemd state";

    systemd::Flags systemdFlags;
    systemdFlags.enabled = flags.systemd_enable_support;
    systemdFlags.runtime_directory = flags.systemd_runtime_directory;
    systemdFlags.cgroups_hierarchy = flags.cgroups_hierarchy;

    Try<Nothing> initialize = systemd::initialize(systemdFlags);
    if (initialize.isError()) {
      EXIT(EXIT_FAILURE)
        << "Failed to initialize systemd: " + initialize.error();
    }
  }
#endif // __linux__

  Fetcher fetcher;

  Try<Containerizer*> containerizer =
    Containerizer::create(flags, false, &fetcher);

  if (containerizer.isError()) {
    EXIT(EXIT_FAILURE)
      << "Failed to create a containerizer: " << containerizer.error();
  }

  Try<MasterDetector*> detector_ = MasterDetector::create(
      master, flags.master_detector);

  if (detector_.isError()) {
    EXIT(EXIT_FAILURE)
      << "Failed to create a master detector: " << detector_.error();
  }

  MasterDetector* detector = detector_.get();

  Option<Authorizer*> authorizer_ = None();

  string authorizerName = flags.authorizer;

  Result<Authorizer*> authorizer((None()));
  if (authorizerName != slave::DEFAULT_AUTHORIZER) {
    LOG(INFO) << "Creating '" << authorizerName << "' authorizer";

    // NOTE: The contents of --acls will be ignored.
    authorizer = Authorizer::create(authorizerName);
  } else {
    // `authorizerName` is `DEFAULT_AUTHORIZER` at this point.
    if (flags.acls.isSome()) {
      LOG(INFO) << "Creating default '" << authorizerName << "' authorizer";

      authorizer = Authorizer::create(flags.acls.get());
    }
  }

  if (authorizer.isError()) {
    EXIT(EXIT_FAILURE) << "Could not create '" << authorizerName
                       << "' authorizer: " << authorizer.error();
  } else if (authorizer.isSome()) {
    authorizer_ = authorizer.get();

    // Set the authorization callbacks for libprocess HTTP endpoints.
    // Note that these callbacks capture `authorizer_.get()`, but the agent
    // creates a copy of the authorizer during construction. Thus, if in the
    // future it becomes possible to dynamically set the authorizer, this would
    // break.
    process::http::authorization::setCallbacks(
        createAuthorizationCallbacks(authorizer_.get()));
  }

  Files files(READONLY_HTTP_AUTHENTICATION_REALM, authorizer_);
  GarbageCollector gc;
  StatusUpdateManager statusUpdateManager(flags);

  Try<ResourceEstimator*> resourceEstimator =
    ResourceEstimator::create(flags.resource_estimator);

  if (resourceEstimator.isError()) {
    cerr << "Failed to create resource estimator: "
         << resourceEstimator.error() << endl;
    return EXIT_FAILURE;
  }

  Try<QoSController*> qosController =
    QoSController::create(flags.qos_controller);

  if (qosController.isError()) {
    cerr << "Failed to create QoS Controller: "
         << qosController.error() << endl;
    return EXIT_FAILURE;
  }

  Slave* slave = new Slave(
      id,
      flags,
      detector,
      containerizer.get(),
      &files,
      &gc,
      &statusUpdateManager,
      resourceEstimator.get(),
      qosController.get(),
      authorizer_);

  process::spawn(slave);
  process::wait(slave->self());

  delete slave;

  delete resourceEstimator.get();

  delete qosController.get();

  delete detector;

  delete containerizer.get();

  if (authorizer_.isSome()) {
    delete authorizer_.get();
  }

  return EXIT_SUCCESS;
}
<commit_msg>Mesos-slave --help should not return as failed.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stdint.h>

#include <vector>
#include <utility>

#include <mesos/authorizer/authorizer.hpp>

#include <mesos/master/detector.hpp>

#include <mesos/mesos.hpp>

#include <mesos/module/anonymous.hpp>

#include <mesos/slave/resource_estimator.hpp>

#include <process/owned.hpp>

#ifdef __WINDOWS__
#include <process/windows/winsock.hpp>
#endif // __WINDOWS__

#include <stout/check.hpp>
#include <stout/flags.hpp>
#include <stout/hashset.hpp>
#include <stout/nothing.hpp>
#include <stout/os.hpp>
#include <stout/stringify.hpp>
#include <stout/try.hpp>

#include "common/build.hpp"
#include "common/http.hpp"

#include "hook/manager.hpp"

#ifdef __linux__
#include "linux/systemd.hpp"
#endif // __linux__

#include "logging/logging.hpp"

#include "messages/flags.hpp"
#include "messages/messages.hpp"

#include "module/manager.hpp"

#include "slave/gc.hpp"
#include "slave/slave.hpp"
#include "slave/status_update_manager.hpp"

#include "version/version.hpp"

using namespace mesos::internal;
using namespace mesos::internal::slave;

using mesos::master::detector::MasterDetector;

using mesos::modules::Anonymous;
using mesos::modules::ModuleManager;

using mesos::master::detector::MasterDetector;

using mesos::slave::QoSController;
using mesos::slave::ResourceEstimator;

using mesos::Authorizer;
using mesos::SlaveInfo;

using process::Owned;

using process::firewall::DisabledEndpointsFirewallRule;
using process::firewall::FirewallRule;

using std::cerr;
using std::cout;
using std::endl;
using std::move;
using std::string;
using std::vector;

int main(int argc, char** argv)
{
  // The order of initialization is as follows:
  // * Windows socket stack.
  // * Validate flags.
  // * Log build information.
  // * Libprocess
  // * Logging
  // * Version process
  // * Firewall rules: should be initialized before initializing HTTP endpoints.
  // * Modules: Load module libraries and manifests before they
  //   can be instantiated.
  // * Anonymous modules: Later components such as Allocators, and master
  //   contender/detector might depend upon anonymous modules.
  // * Hooks.
  // * Systemd support (if it exists).
  // * Fetcher and Containerizer.
  // * Master detector.
  // * Authorizer.
  // * Garbage collector.
  // * Status update manager.
  // * Resource estimator.
  // * QoS controller.
  // * `Agent` process.
  //
  // TODO(avinash): Add more comments discussing the rationale behind for this
  // particular component ordering.

#ifdef __WINDOWS__
  // Initialize the Windows socket stack.
  process::Winsock winsock;
#endif

  GOOGLE_PROTOBUF_VERIFY_VERSION;

  slave::Flags flags;

  // The following flags are executable specific (e.g., since we only
  // have one instance of libprocess per execution, we only want to
  // advertise the IP and port option once, here).
  Option<string> ip;
  flags.add(&ip,
            "ip",
            "IP address to listen on. This cannot be used in conjunction\n"
            "with `--ip_discovery_command`.");

  uint16_t port;
  flags.add(&port,
            "port",
            "Port to listen on.",
            SlaveInfo().port());

  Option<string> advertise_ip;
  flags.add(&advertise_ip,
            "advertise_ip",
            "IP address advertised to reach this Mesos agent.\n"
            "The agent does not bind to this IP address.\n"
            "However, this IP address may be used to access this agent.");

  Option<string> advertise_port;
  flags.add(&advertise_port,
            "advertise_port",
            "Port advertised to reach this Mesos agent (along with\n"
            "`advertise_ip`). The agent does not bind to this port.\n"
            "However, this port (along with `advertise_ip`) may be used to\n"
            "access this agent.");

  Option<string> master;
  flags.add(&master,
            "master",
            "May be one of:\n"
            "  `host:port`\n"
            "  `zk://host1:port1,host2:port2,.../path`\n"
            "  `zk://username:password@host1:port1,host2:port2,.../path`\n"
            "  `file:///path/to/file` (where file contains one of the above)");

  // Optional IP discover script that will set the slave's IP.
  // If set, its output is expected to be a valid parseable IP string.
  Option<string> ip_discovery_command;
  flags.add(&ip_discovery_command,
            "ip_discovery_command",
            "Optional IP discovery binary: if set, it is expected to emit\n"
            "the IP address which the agent will try to bind to.\n"
            "Cannot be used in conjunction with `--ip`.");

  Try<flags::Warnings> load = flags.load("MESOS_", argc, argv);

  if (flags.help) {
    cout << flags.usage() << endl;
    return EXIT_SUCCESS;
  }

  // TODO(marco): this pattern too should be abstracted away
  // in FlagsBase; I have seen it at least 15 times.
  if (load.isError()) {
    cerr << flags.usage(load.error()) << endl;
    return EXIT_FAILURE;
  }

  if (flags.version) {
    cout << "mesos" << " " << MESOS_VERSION << endl;
    return EXIT_SUCCESS;
  }

  if (master.isNone() && flags.master_detector.isNone()) {
    cerr << flags.usage("Missing required option `--master` or "
                        "`--master_detector`.") << endl;
    return EXIT_FAILURE;
  }

  if (master.isSome() && flags.master_detector.isSome()) {
    cerr << flags.usage("Only one of --master or --master_detector options "
                        "should be specified.");
    return EXIT_FAILURE;
  }

  // Initialize libprocess.
  if (ip_discovery_command.isSome() && ip.isSome()) {
    EXIT(EXIT_FAILURE) << flags.usage(
        "Only one of `--ip` or `--ip_discovery_command` should be specified");
  }

  if (ip_discovery_command.isSome()) {
    Try<string> ipAddress = os::shell(ip_discovery_command.get());

    if (ipAddress.isError()) {
      EXIT(EXIT_FAILURE) << ipAddress.error();
    }

    os::setenv("LIBPROCESS_IP", strings::trim(ipAddress.get()));
  } else if (ip.isSome()) {
    os::setenv("LIBPROCESS_IP", ip.get());
  }

  os::setenv("LIBPROCESS_PORT", stringify(port));

  if (advertise_ip.isSome()) {
    os::setenv("LIBPROCESS_ADVERTISE_IP", advertise_ip.get());
  }

  if (advertise_port.isSome()) {
    os::setenv("LIBPROCESS_ADVERTISE_PORT", advertise_port.get());
  }

  // Log build information.
  LOG(INFO) << "Build: " << build::DATE << " by " << build::USER;
  LOG(INFO) << "Version: " << MESOS_VERSION;

  if (build::GIT_TAG.isSome()) {
    LOG(INFO) << "Git tag: " << build::GIT_TAG.get();
  }

  if (build::GIT_SHA.isSome()) {
    LOG(INFO) << "Git SHA: " << build::GIT_SHA.get();
  }

  const string id = process::ID::generate("slave"); // Process ID.

  // If `process::initialize()` returns `false`, then it was called before this
  // invocation, meaning the authentication realm for libprocess-level HTTP
  // endpoints was set incorrectly. This should be the first invocation.
  if (!process::initialize(
          id,
          READWRITE_HTTP_AUTHENTICATION_REALM,
          READONLY_HTTP_AUTHENTICATION_REALM)) {
    EXIT(EXIT_FAILURE) << "The call to `process::initialize()` in the agent's "
                       << "`main()` was not the function's first invocation";
  }

  logging::initialize(argv[0], flags, true); // Catch signals.

  // Log any flag warnings (after logging is initialized).
  foreach (const flags::Warning& warning, load->warnings) {
    LOG(WARNING) << warning.message;
  }

  spawn(new VersionProcess(), true);

  if (flags.firewall_rules.isSome()) {
    vector<Owned<FirewallRule>> rules;

    const Firewall firewall = flags.firewall_rules.get();

    if (firewall.has_disabled_endpoints()) {
      hashset<string> paths;

      foreach (const string& path, firewall.disabled_endpoints().paths()) {
        paths.insert(path);
      }

      rules.emplace_back(new DisabledEndpointsFirewallRule(paths));
    }

    process::firewall::install(move(rules));
  }

  // Initialize modules.
  if (flags.modules.isSome() && flags.modulesDir.isSome()) {
    EXIT(EXIT_FAILURE) <<
      flags.usage("Only one of --modules or --modules_dir should be specified");
  }

  if (flags.modulesDir.isSome()) {
    Try<Nothing> result = ModuleManager::load(flags.modulesDir.get());
    if (result.isError()) {
      EXIT(EXIT_FAILURE) << "Error loading modules: " << result.error();
    }
  }

  if (flags.modules.isSome()) {
    Try<Nothing> result = ModuleManager::load(flags.modules.get());
    if (result.isError()) {
      EXIT(EXIT_FAILURE) << "Error loading modules: " << result.error();
    }
  }

  // Create anonymous modules.
  foreach (const string& name, ModuleManager::find<Anonymous>()) {
    Try<Anonymous*> create = ModuleManager::create<Anonymous>(name);
    if (create.isError()) {
      EXIT(EXIT_FAILURE)
        << "Failed to create anonymous module named '" << name << "'";
    }

    // We don't bother keeping around the pointer to this anonymous
    // module, when we exit that will effectively free it's memory.
    //
    // TODO(benh): We might want to add explicit finalization (and
    // maybe explicit initialization too) in order to let the module
    // do any housekeeping necessary when the slave is cleanly
    // terminating.
  }

  // Initialize hooks.
  if (flags.hooks.isSome()) {
    Try<Nothing> result = HookManager::initialize(flags.hooks.get());
    if (result.isError()) {
      EXIT(EXIT_FAILURE) << "Error installing hooks: " << result.error();
    }
  }

#ifdef __linux__
  // Initialize systemd if it exists.
  if (systemd::exists() && flags.systemd_enable_support) {
    LOG(INFO) << "Inializing systemd state";

    systemd::Flags systemdFlags;
    systemdFlags.enabled = flags.systemd_enable_support;
    systemdFlags.runtime_directory = flags.systemd_runtime_directory;
    systemdFlags.cgroups_hierarchy = flags.cgroups_hierarchy;

    Try<Nothing> initialize = systemd::initialize(systemdFlags);
    if (initialize.isError()) {
      EXIT(EXIT_FAILURE)
        << "Failed to initialize systemd: " + initialize.error();
    }
  }
#endif // __linux__

  Fetcher fetcher;

  Try<Containerizer*> containerizer =
    Containerizer::create(flags, false, &fetcher);

  if (containerizer.isError()) {
    EXIT(EXIT_FAILURE)
      << "Failed to create a containerizer: " << containerizer.error();
  }

  Try<MasterDetector*> detector_ = MasterDetector::create(
      master, flags.master_detector);

  if (detector_.isError()) {
    EXIT(EXIT_FAILURE)
      << "Failed to create a master detector: " << detector_.error();
  }

  MasterDetector* detector = detector_.get();

  Option<Authorizer*> authorizer_ = None();

  string authorizerName = flags.authorizer;

  Result<Authorizer*> authorizer((None()));
  if (authorizerName != slave::DEFAULT_AUTHORIZER) {
    LOG(INFO) << "Creating '" << authorizerName << "' authorizer";

    // NOTE: The contents of --acls will be ignored.
    authorizer = Authorizer::create(authorizerName);
  } else {
    // `authorizerName` is `DEFAULT_AUTHORIZER` at this point.
    if (flags.acls.isSome()) {
      LOG(INFO) << "Creating default '" << authorizerName << "' authorizer";

      authorizer = Authorizer::create(flags.acls.get());
    }
  }

  if (authorizer.isError()) {
    EXIT(EXIT_FAILURE) << "Could not create '" << authorizerName
                       << "' authorizer: " << authorizer.error();
  } else if (authorizer.isSome()) {
    authorizer_ = authorizer.get();

    // Set the authorization callbacks for libprocess HTTP endpoints.
    // Note that these callbacks capture `authorizer_.get()`, but the agent
    // creates a copy of the authorizer during construction. Thus, if in the
    // future it becomes possible to dynamically set the authorizer, this would
    // break.
    process::http::authorization::setCallbacks(
        createAuthorizationCallbacks(authorizer_.get()));
  }

  Files files(READONLY_HTTP_AUTHENTICATION_REALM, authorizer_);
  GarbageCollector gc;
  StatusUpdateManager statusUpdateManager(flags);

  Try<ResourceEstimator*> resourceEstimator =
    ResourceEstimator::create(flags.resource_estimator);

  if (resourceEstimator.isError()) {
    cerr << "Failed to create resource estimator: "
         << resourceEstimator.error() << endl;
    return EXIT_FAILURE;
  }

  Try<QoSController*> qosController =
    QoSController::create(flags.qos_controller);

  if (qosController.isError()) {
    cerr << "Failed to create QoS Controller: "
         << qosController.error() << endl;
    return EXIT_FAILURE;
  }

  Slave* slave = new Slave(
      id,
      flags,
      detector,
      containerizer.get(),
      &files,
      &gc,
      &statusUpdateManager,
      resourceEstimator.get(),
      qosController.get(),
      authorizer_);

  process::spawn(slave);
  process::wait(slave->self());

  delete slave;

  delete resourceEstimator.get();

  delete qosController.get();

  delete detector;

  delete containerizer.get();

  if (authorizer_.isSome()) {
    delete authorizer_.get();
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: popupmenudispatcher.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-13 15:05:51 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
//#include "precompiled_framework.hxx"

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_DISPATCH_POPUPMENUDISPATCHER_HXX_
#include <dispatch/popupmenudispatcher.hxx>
#endif
#ifndef __FRAMEWORK_GENERAL_H_
#include <general.h>
#endif
#ifndef __FRAMEWORK_CLASSES_MENUCONFIGURATION_HXX_
#include <classes/menuconfiguration.hxx>
#endif
#ifndef __FRAMEWORK_CLASSES_ADDONMENU_HXX_
#include <classes/addonmenu.hxx>
#endif
#include <services.h>
#include <properties.h>

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_FRAME_FRAMESEARCHFLAG_HPP_
#include <com/sun/star/frame/FrameSearchFlag.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_XTOOLKIT_HPP_
#include <com/sun/star/awt/XToolkit.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_WINDOWATTRIBUTE_HPP_
#include <com/sun/star/awt/WindowAttribute.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_WINDOWDESCRIPTOR_HPP_
#include <com/sun/star/awt/WindowDescriptor.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_POSSIZE_HPP_
#include <com/sun/star/awt/PosSize.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_XWINDOWPEER_HPP_
#include <com/sun/star/awt/XWindowPeer.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_UNKNOWNPROPERTYEXCEPTION_HPP_
#include <com/sun/star/beans/UnknownPropertyException.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_WRAPPEDTARGETEXCEPTION_HPP_
#include <com/sun/star/lang/WrappedTargetException.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATION_HPP_
#include <com/sun/star/container/XEnumeration.hpp>
#endif

//_________________________________________________________________________________________________________________
//  includes of other projects
//_________________________________________________________________________________________________________________

#include <ucbhelper/content.hxx>
#include <vos/mutex.hxx>
#include <rtl/ustrbuf.hxx>
#include <vcl/svapp.hxx>

//_________________________________________________________________________________________________________________
//  namespace
//_________________________________________________________________________________________________________________

namespace framework{

using namespace ::com::sun::star                ;
using namespace ::com::sun::star::awt           ;
using namespace ::com::sun::star::beans         ;
using namespace ::com::sun::star::container     ;
using namespace ::com::sun::star::frame         ;
using namespace ::com::sun::star::lang          ;
using namespace ::com::sun::star::uno           ;
using namespace ::com::sun::star::util          ;
using namespace ::cppu                          ;
using namespace ::osl                           ;
using namespace ::rtl                           ;
using namespace ::vos                           ;

//_________________________________________________________________________________________________________________
//  non exported const
//_________________________________________________________________________________________________________________
const char*     PROTOCOL_VALUE      = "vnd.sun.star.popup:";
const sal_Int32 PROTOCOL_LENGTH     = 19;

//_________________________________________________________________________________________________________________
//  non exported definitions
//_________________________________________________________________________________________________________________

//_________________________________________________________________________________________________________________
//  declarations
//_________________________________________________________________________________________________________________

//*****************************************************************************************************************
//  constructor
//*****************************************************************************************************************
PopupMenuDispatcher::PopupMenuDispatcher(
    const Reference< XMultiServiceFactory >& xFactory )
        //  Init baseclasses first
        :   ThreadHelpBase          ( &Application::GetSolarMutex()  )
        ,   OWeakObject             (                                )
        // Init member
        ,   m_xFactory              ( xFactory                       )
        ,   m_aListenerContainer    ( m_aLock.getShareableOslMutex() )
        ,   m_bAlreadyDisposed      ( sal_False                      )
        ,   m_bActivateListener     ( sal_False                      )
{
}

//*****************************************************************************************************************
//  destructor
//*****************************************************************************************************************
PopupMenuDispatcher::~PopupMenuDispatcher()
{
    // Warn programmer if he forgot to dispose this instance.
    // We must release all our references ...
    // and a dtor isn't the best place to do that!
}

//*****************************************************************************************************************
//  XInterface, XTypeProvider
//*****************************************************************************************************************
DEFINE_XINTERFACE_7     ( PopupMenuDispatcher                                     ,
                          ::cppu::OWeakObject                                     ,
                          DIRECT_INTERFACE( XTypeProvider                         ),
                          DIRECT_INTERFACE( XServiceInfo                          ),
                          DIRECT_INTERFACE( XDispatchProvider                     ),
                          DIRECT_INTERFACE( XDispatch                             ),
                          DIRECT_INTERFACE( XEventListener                        ),
                          DIRECT_INTERFACE( XInitialization                       ),
                          DERIVED_INTERFACE( XFrameActionListener, XEventListener )
                        )

DEFINE_XTYPEPROVIDER_7  (   PopupMenuDispatcher ,
                            XTypeProvider       ,
                            XServiceInfo        ,
                            XDispatchProvider   ,
                            XDispatch           ,
                            XEventListener      ,
                            XInitialization     ,
                            XFrameActionListener
                        )

DEFINE_XSERVICEINFO_MULTISERVICE( PopupMenuDispatcher                    ,
                                  ::cppu::OWeakObject                    ,
                                  SERVICENAME_PROTOCOLHANDLER            ,
                                  IMPLEMENTATIONNAME_POPUPMENUDISPATCHER )

DEFINE_INIT_SERVICE(PopupMenuDispatcher,
{
    /*Attention
    I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
    to create a new instance of this class by our own supported service factory.
    see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
    */
}
)

//*****************************************************************************************************************
//  XInitialization
//*****************************************************************************************************************
void SAL_CALL PopupMenuDispatcher::initialize(
    const css::uno::Sequence< css::uno::Any >& lArguments )
throw( css::uno::Exception, css::uno::RuntimeException)
{
    css::uno::Reference< css::frame::XFrame > xFrame;

    /* SAFE { */
    WriteGuard aWriteLock(m_aLock);

    for (int a=0; a<lArguments.getLength(); ++a)
    {
        if (a==0)
        {
            lArguments[a] >>= xFrame;
            m_xWeakFrame = xFrame;

            m_bActivateListener = sal_True;
            Reference< css::frame::XFrameActionListener > xFrameActionListener(
                (OWeakObject *)this, css::uno::UNO_QUERY );
            xFrame->addFrameActionListener( xFrameActionListener );
        }
    }

    aWriteLock.unlock();
    /* } SAFE */
}

//*****************************************************************************************************************
//  XDispatchProvider
//*****************************************************************************************************************
css::uno::Reference< css::frame::XDispatch >
SAL_CALL PopupMenuDispatcher::queryDispatch(
    const css::util::URL&  rURL    ,
    const ::rtl::OUString& sTarget ,
    sal_Int32              nFlags  )
throw( css::uno::RuntimeException )
{
    css::uno::Reference< css::frame::XDispatch > xDispatch;

    if ( rURL.Complete.compareToAscii( PROTOCOL_VALUE, PROTOCOL_LENGTH ) == 0 )
    {
        // --- SAFE ---
        ResetableGuard aGuard( m_aLock );
        impl_RetrievePopupControllerQuery();
        impl_CreateUriRefFactory();

        css::uno::Reference< css::container::XNameAccess > xPopupCtrlQuery( m_xPopupCtrlQuery );
        css::uno::Reference< css::uri::XUriReferenceFactory > xUriRefFactory( m_xUriRefFactory );
        aGuard.unlock();
        // --- SAFE ---

        if ( xPopupCtrlQuery.is() )
        {
            try
            {
                // Just use the main part of the URL for popup menu controllers
                sal_Int32     nQueryPart( 0 );
                sal_Int32     nSchemePart( 0 );
                rtl::OUString aBaseURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" ));
                rtl::OUString aURL( rURL.Complete );

                nSchemePart = aURL.indexOf( ':' );
                if (( nSchemePart > 0 ) &&
                    ( aURL.getLength() > ( nSchemePart+1 )))
                {
                    nQueryPart  = aURL.indexOf( '?', nSchemePart );
                    if ( nQueryPart > 0 )
                        aBaseURL += aURL.copy( nSchemePart+1, nQueryPart-(nSchemePart+1) );
                    else if ( nQueryPart == -1 )
                        aBaseURL += aURL.copy( nSchemePart+1 );
                }

                css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider;

                // Find popup menu controller using the base URL
                Any a = xPopupCtrlQuery->getByName( aBaseURL );
                a >>= xDispatchProvider;
                aGuard.unlock();

                // Ask popup menu dispatch provider for dispatch object
                if ( xDispatchProvider.is() )
                    xDispatch = xDispatchProvider->queryDispatch( rURL, sTarget, nFlags );
            }
            catch ( RuntimeException& )
            {
                throw;
            }
            catch ( Exception& )
            {
            }
        }
    }
    return xDispatch;
}

css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL
PopupMenuDispatcher::queryDispatches(
    const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor )
throw( css::uno::RuntimeException )
{
    sal_Int32 nCount = lDescriptor.getLength();
    css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
    for( sal_Int32 i=0; i<nCount; ++i )
    {
        lDispatcher[i] = this->queryDispatch(
                            lDescriptor[i].FeatureURL,
                            lDescriptor[i].FrameName,
                            lDescriptor[i].SearchFlags);
    }
    return lDispatcher;
}

//*****************************************************************************************************************
//  XDispatch
//*****************************************************************************************************************
void
SAL_CALL PopupMenuDispatcher::dispatch(
    const URL&                        /*aURL*/            ,
    const Sequence< PropertyValue >&  /*seqProperties*/ )
throw( RuntimeException )
{
}

//*****************************************************************************************************************
//  XDispatch
//*****************************************************************************************************************
void
SAL_CALL PopupMenuDispatcher::addStatusListener(
    const Reference< XStatusListener >& xControl,
    const URL&                          aURL    )
throw( RuntimeException )
{
    // Ready for multithreading
    ResetableGuard aGuard( m_aLock );
    // Safe impossible cases
    // Add listener to container.
    m_aListenerContainer.addInterface( aURL.Complete, xControl );
}

//*****************************************************************************************************************
//  XDispatch
//*****************************************************************************************************************
void
SAL_CALL PopupMenuDispatcher::removeStatusListener(
    const Reference< XStatusListener >& xControl,
    const URL&                          aURL    )
throw( RuntimeException )
{
    // Ready for multithreading
    ResetableGuard aGuard( m_aLock );
    // Safe impossible cases
    // Add listener to container.
    m_aListenerContainer.removeInterface( aURL.Complete, xControl );
}

//*****************************************************************************************************************
//   XFrameActionListener
//*****************************************************************************************************************

void
SAL_CALL PopupMenuDispatcher::frameAction(
    const FrameActionEvent& aEvent )
throw ( RuntimeException )
{
    ResetableGuard aGuard( m_aLock );

    if (( aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING ) ||
        ( aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED  ))
    {
        // Reset query reference to requery it again next time
        m_xPopupCtrlQuery.clear();
    }
}

//*****************************************************************************************************************
//   XEventListener
//*****************************************************************************************************************
void
SAL_CALL PopupMenuDispatcher::disposing( const EventObject& ) throw( RuntimeException )
{
    // Ready for multithreading
    ResetableGuard aGuard( m_aLock );
    // Safe impossible cases
    LOG_ASSERT( !(m_bAlreadyDisposed==sal_True), "MenuDispatcher::disposing()\nObject already disposed .. don't call it again!\n" )

    if( m_bAlreadyDisposed == sal_False )
    {
        m_bAlreadyDisposed = sal_True;

        if ( m_bActivateListener )
        {
            Reference< XFrame > xFrame( m_xWeakFrame.get(), UNO_QUERY );
            if ( xFrame.is() )
            {
                xFrame->removeFrameActionListener( Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY ));
                m_bActivateListener = sal_False;
            }
        }

        // Forget our factory.
        m_xFactory = Reference< XMultiServiceFactory >();
    }
}

void PopupMenuDispatcher::impl_RetrievePopupControllerQuery()
{
    if ( !m_xPopupCtrlQuery.is() )
    {
        css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
        css::uno::Reference< css::frame::XFrame > xFrame( m_xWeakFrame );

        if ( xFrame.is() )
        {
            css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, css::uno::UNO_QUERY );
            if ( xPropSet.is() )
            {
                try
                {
                    Any a = xPropSet->getPropertyValue( FRAME_PROPNAME_LAYOUTMANAGER );
                    a >>= xLayoutManager;

                    if ( xLayoutManager.is() )
                    {
                        css::uno::Reference< css::ui::XUIElement > xMenuBar;
                        rtl::OUString aMenuBar( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" ));
                        xMenuBar = xLayoutManager->getElement( aMenuBar );

                        m_xPopupCtrlQuery = css::uno::Reference< css::container::XNameAccess >(
                                                xMenuBar, css::uno::UNO_QUERY );
                    }
                }
                catch ( css::uno::RuntimeException& )
                {
                    throw;
                }
                catch ( css::uno::Exception& )
                {
                }
            }
        }
    }
}

void PopupMenuDispatcher::impl_CreateUriRefFactory()
{
    if ( !m_xUriRefFactory.is() )
    {
        rtl::OUString aUriRefFactoryService(
            RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uri.UriReferenceFactory" ));

        m_xUriRefFactory = css::uno::Reference< css::uri::XUriReferenceFactory >(
                                m_xFactory->createInstance( aUriRefFactoryService ),
                                css::uno::UNO_QUERY);

    }
}

}       //  namespace framework
<commit_msg>INTEGRATION: CWS bgdlremove (1.2.72); FILE MERGED 2007/05/11 08:57:55 kso 1.2.72.1: #i76911# - ucbhelper lib no longer uses VOS. (vos::ORef => rtl::Reference, vos::OMutex => osl::Mutex, ...)<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: popupmenudispatcher.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: ihi $ $Date: 2007-06-05 14:45:33 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
//#include "precompiled_framework.hxx"

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_DISPATCH_POPUPMENUDISPATCHER_HXX_
#include <dispatch/popupmenudispatcher.hxx>
#endif
#ifndef __FRAMEWORK_GENERAL_H_
#include <general.h>
#endif
#ifndef __FRAMEWORK_CLASSES_MENUCONFIGURATION_HXX_
#include <classes/menuconfiguration.hxx>
#endif
#ifndef __FRAMEWORK_CLASSES_ADDONMENU_HXX_
#include <classes/addonmenu.hxx>
#endif
#include <services.h>
#include <properties.h>

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_FRAME_FRAMESEARCHFLAG_HPP_
#include <com/sun/star/frame/FrameSearchFlag.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_XTOOLKIT_HPP_
#include <com/sun/star/awt/XToolkit.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_WINDOWATTRIBUTE_HPP_
#include <com/sun/star/awt/WindowAttribute.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_WINDOWDESCRIPTOR_HPP_
#include <com/sun/star/awt/WindowDescriptor.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_POSSIZE_HPP_
#include <com/sun/star/awt/PosSize.hpp>
#endif
#ifndef _COM_SUN_STAR_AWT_XWINDOWPEER_HPP_
#include <com/sun/star/awt/XWindowPeer.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_UNKNOWNPROPERTYEXCEPTION_HPP_
#include <com/sun/star/beans/UnknownPropertyException.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_WRAPPEDTARGETEXCEPTION_HPP_
#include <com/sun/star/lang/WrappedTargetException.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATION_HPP_
#include <com/sun/star/container/XEnumeration.hpp>
#endif

//_________________________________________________________________________________________________________________
//  includes of other projects
//_________________________________________________________________________________________________________________

#include <ucbhelper/content.hxx>
#include <vos/mutex.hxx>
#include <rtl/ustrbuf.hxx>
#include <vcl/svapp.hxx>

//_________________________________________________________________________________________________________________
//  namespace
//_________________________________________________________________________________________________________________

namespace framework{

using namespace ::com::sun::star                ;
using namespace ::com::sun::star::awt           ;
using namespace ::com::sun::star::beans         ;
using namespace ::com::sun::star::container     ;
using namespace ::com::sun::star::frame         ;
using namespace ::com::sun::star::lang          ;
using namespace ::com::sun::star::uno           ;
using namespace ::com::sun::star::util          ;
using namespace ::cppu                          ;
using namespace ::osl                           ;
using namespace ::rtl                           ;
using namespace ::vos                           ;

//_________________________________________________________________________________________________________________
//  non exported const
//_________________________________________________________________________________________________________________
const char*     PROTOCOL_VALUE      = "vnd.sun.star.popup:";
const sal_Int32 PROTOCOL_LENGTH     = 19;

//_________________________________________________________________________________________________________________
//  non exported definitions
//_________________________________________________________________________________________________________________

//_________________________________________________________________________________________________________________
//  declarations
//_________________________________________________________________________________________________________________

//*****************************************************************************************************************
//  constructor
//*****************************************************************************************************************
PopupMenuDispatcher::PopupMenuDispatcher(
    const uno::Reference< XMultiServiceFactory >& xFactory )
        //  Init baseclasses first
        :   ThreadHelpBase          ( &Application::GetSolarMutex()  )
        ,   OWeakObject             (                                )
        // Init member
        ,   m_xFactory              ( xFactory                       )
        ,   m_aListenerContainer    ( m_aLock.getShareableOslMutex() )
        ,   m_bAlreadyDisposed      ( sal_False                      )
        ,   m_bActivateListener     ( sal_False                      )
{
}

//*****************************************************************************************************************
//  destructor
//*****************************************************************************************************************
PopupMenuDispatcher::~PopupMenuDispatcher()
{
    // Warn programmer if he forgot to dispose this instance.
    // We must release all our references ...
    // and a dtor isn't the best place to do that!
}

//*****************************************************************************************************************
//  XInterface, XTypeProvider
//*****************************************************************************************************************
DEFINE_XINTERFACE_7     ( PopupMenuDispatcher                                     ,
                          ::cppu::OWeakObject                                     ,
                          DIRECT_INTERFACE( XTypeProvider                         ),
                          DIRECT_INTERFACE( XServiceInfo                          ),
                          DIRECT_INTERFACE( XDispatchProvider                     ),
                          DIRECT_INTERFACE( XDispatch                             ),
                          DIRECT_INTERFACE( XEventListener                        ),
                          DIRECT_INTERFACE( XInitialization                       ),
                          DERIVED_INTERFACE( XFrameActionListener, XEventListener )
                        )

DEFINE_XTYPEPROVIDER_7  (   PopupMenuDispatcher ,
                            XTypeProvider       ,
                            XServiceInfo        ,
                            XDispatchProvider   ,
                            XDispatch           ,
                            XEventListener      ,
                            XInitialization     ,
                            XFrameActionListener
                        )

DEFINE_XSERVICEINFO_MULTISERVICE( PopupMenuDispatcher                    ,
                                  ::cppu::OWeakObject                    ,
                                  SERVICENAME_PROTOCOLHANDLER            ,
                                  IMPLEMENTATIONNAME_POPUPMENUDISPATCHER )

DEFINE_INIT_SERVICE(PopupMenuDispatcher,
{
    /*Attention
    I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
    to create a new instance of this class by our own supported service factory.
    see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
    */
}
)

//*****************************************************************************************************************
//  XInitialization
//*****************************************************************************************************************
void SAL_CALL PopupMenuDispatcher::initialize(
    const css::uno::Sequence< css::uno::Any >& lArguments )
throw( css::uno::Exception, css::uno::RuntimeException)
{
    css::uno::Reference< css::frame::XFrame > xFrame;

    /* SAFE { */
    WriteGuard aWriteLock(m_aLock);

    for (int a=0; a<lArguments.getLength(); ++a)
    {
        if (a==0)
        {
            lArguments[a] >>= xFrame;
            m_xWeakFrame = xFrame;

            m_bActivateListener = sal_True;
            uno::Reference< css::frame::XFrameActionListener > xFrameActionListener(
                (OWeakObject *)this, css::uno::UNO_QUERY );
            xFrame->addFrameActionListener( xFrameActionListener );
        }
    }

    aWriteLock.unlock();
    /* } SAFE */
}

//*****************************************************************************************************************
//  XDispatchProvider
//*****************************************************************************************************************
css::uno::Reference< css::frame::XDispatch >
SAL_CALL PopupMenuDispatcher::queryDispatch(
    const css::util::URL&  rURL    ,
    const ::rtl::OUString& sTarget ,
    sal_Int32              nFlags  )
throw( css::uno::RuntimeException )
{
    css::uno::Reference< css::frame::XDispatch > xDispatch;

    if ( rURL.Complete.compareToAscii( PROTOCOL_VALUE, PROTOCOL_LENGTH ) == 0 )
    {
        // --- SAFE ---
        ResetableGuard aGuard( m_aLock );
        impl_RetrievePopupControllerQuery();
        impl_CreateUriRefFactory();

        css::uno::Reference< css::container::XNameAccess > xPopupCtrlQuery( m_xPopupCtrlQuery );
        css::uno::Reference< css::uri::XUriReferenceFactory > xUriRefFactory( m_xUriRefFactory );
        aGuard.unlock();
        // --- SAFE ---

        if ( xPopupCtrlQuery.is() )
        {
            try
            {
                // Just use the main part of the URL for popup menu controllers
                sal_Int32     nQueryPart( 0 );
                sal_Int32     nSchemePart( 0 );
                rtl::OUString aBaseURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" ));
                rtl::OUString aURL( rURL.Complete );

                nSchemePart = aURL.indexOf( ':' );
                if (( nSchemePart > 0 ) &&
                    ( aURL.getLength() > ( nSchemePart+1 )))
                {
                    nQueryPart  = aURL.indexOf( '?', nSchemePart );
                    if ( nQueryPart > 0 )
                        aBaseURL += aURL.copy( nSchemePart+1, nQueryPart-(nSchemePart+1) );
                    else if ( nQueryPart == -1 )
                        aBaseURL += aURL.copy( nSchemePart+1 );
                }

                css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider;

                // Find popup menu controller using the base URL
                Any a = xPopupCtrlQuery->getByName( aBaseURL );
                a >>= xDispatchProvider;
                aGuard.unlock();

                // Ask popup menu dispatch provider for dispatch object
                if ( xDispatchProvider.is() )
                    xDispatch = xDispatchProvider->queryDispatch( rURL, sTarget, nFlags );
            }
            catch ( RuntimeException& )
            {
                throw;
            }
            catch ( Exception& )
            {
            }
        }
    }
    return xDispatch;
}

css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL
PopupMenuDispatcher::queryDispatches(
    const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor )
throw( css::uno::RuntimeException )
{
    sal_Int32 nCount = lDescriptor.getLength();
    css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
    for( sal_Int32 i=0; i<nCount; ++i )
    {
        lDispatcher[i] = this->queryDispatch(
                            lDescriptor[i].FeatureURL,
                            lDescriptor[i].FrameName,
                            lDescriptor[i].SearchFlags);
    }
    return lDispatcher;
}

//*****************************************************************************************************************
//  XDispatch
//*****************************************************************************************************************
void
SAL_CALL PopupMenuDispatcher::dispatch(
    const URL&                        /*aURL*/            ,
    const Sequence< PropertyValue >&  /*seqProperties*/ )
throw( RuntimeException )
{
}

//*****************************************************************************************************************
//  XDispatch
//*****************************************************************************************************************
void
SAL_CALL PopupMenuDispatcher::addStatusListener(
    const uno::Reference< XStatusListener >& xControl,
    const URL&                          aURL    )
throw( RuntimeException )
{
    // Ready for multithreading
    ResetableGuard aGuard( m_aLock );
    // Safe impossible cases
    // Add listener to container.
    m_aListenerContainer.addInterface( aURL.Complete, xControl );
}

//*****************************************************************************************************************
//  XDispatch
//*****************************************************************************************************************
void
SAL_CALL PopupMenuDispatcher::removeStatusListener(
    const uno::Reference< XStatusListener >& xControl,
    const URL&                          aURL    )
throw( RuntimeException )
{
    // Ready for multithreading
    ResetableGuard aGuard( m_aLock );
    // Safe impossible cases
    // Add listener to container.
    m_aListenerContainer.removeInterface( aURL.Complete, xControl );
}

//*****************************************************************************************************************
//   XFrameActionListener
//*****************************************************************************************************************

void
SAL_CALL PopupMenuDispatcher::frameAction(
    const FrameActionEvent& aEvent )
throw ( RuntimeException )
{
    ResetableGuard aGuard( m_aLock );

    if (( aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING ) ||
        ( aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED  ))
    {
        // Reset query reference to requery it again next time
        m_xPopupCtrlQuery.clear();
    }
}

//*****************************************************************************************************************
//   XEventListener
//*****************************************************************************************************************
void
SAL_CALL PopupMenuDispatcher::disposing( const EventObject& ) throw( RuntimeException )
{
    // Ready for multithreading
    ResetableGuard aGuard( m_aLock );
    // Safe impossible cases
    LOG_ASSERT( !(m_bAlreadyDisposed==sal_True), "MenuDispatcher::disposing()\nObject already disposed .. don't call it again!\n" )

    if( m_bAlreadyDisposed == sal_False )
    {
        m_bAlreadyDisposed = sal_True;

        if ( m_bActivateListener )
        {
            uno::Reference< XFrame > xFrame( m_xWeakFrame.get(), UNO_QUERY );
            if ( xFrame.is() )
            {
                xFrame->removeFrameActionListener( uno::Reference< XFrameActionListener >( (OWeakObject *)this, UNO_QUERY ));
                m_bActivateListener = sal_False;
            }
        }

        // Forget our factory.
        m_xFactory = uno::Reference< XMultiServiceFactory >();
    }
}

void PopupMenuDispatcher::impl_RetrievePopupControllerQuery()
{
    if ( !m_xPopupCtrlQuery.is() )
    {
        css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
        css::uno::Reference< css::frame::XFrame > xFrame( m_xWeakFrame );

        if ( xFrame.is() )
        {
            css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, css::uno::UNO_QUERY );
            if ( xPropSet.is() )
            {
                try
                {
                    Any a = xPropSet->getPropertyValue( FRAME_PROPNAME_LAYOUTMANAGER );
                    a >>= xLayoutManager;

                    if ( xLayoutManager.is() )
                    {
                        css::uno::Reference< css::ui::XUIElement > xMenuBar;
                        rtl::OUString aMenuBar( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" ));
                        xMenuBar = xLayoutManager->getElement( aMenuBar );

                        m_xPopupCtrlQuery = css::uno::Reference< css::container::XNameAccess >(
                                                xMenuBar, css::uno::UNO_QUERY );
                    }
                }
                catch ( css::uno::RuntimeException& )
                {
                    throw;
                }
                catch ( css::uno::Exception& )
                {
                }
            }
        }
    }
}

void PopupMenuDispatcher::impl_CreateUriRefFactory()
{
    if ( !m_xUriRefFactory.is() )
    {
        rtl::OUString aUriRefFactoryService(
            RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.uri.UriReferenceFactory" ));

        m_xUriRefFactory = css::uno::Reference< css::uri::XUriReferenceFactory >(
                                m_xFactory->createInstance( aUriRefFactoryService ),
                                css::uno::UNO_QUERY);

    }
}

}       //  namespace framework
<|endoftext|>


<commit_before>/*
 * DIPlib 3.0
 * This file contains basic binary morphology functions: dilation, erosion, opening, closing.
 *
 * (c)2017, Erik Schuitema.
 * Based on original DIPlib code: (c)1995-2014, Delft University of Technology.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "diplib.h"
#include "diplib/binary.h"
#include "diplib/neighborlist.h"
#include "diplib/iterators.h"
#include "binary_support.h"

namespace dip {

namespace {

/// The BinaryPropagationFunc type is used to define what to do with pixels added
/// to the processing queue during dilation and erosion.
using BinaryPropagationFunc = std::function< void( uint8& pixel, uint8 dataMask ) >;

/// Worker function for both dilation and erosion, since they are very alike
void BinaryDilationErosion(
      Image const& in,
      Image& out,
      dip::sint connectivity,
      dip::uint iterations,
      String const& s_edgeCondition,
      bool findObjectPixels,
      BinaryPropagationFunc const& propagationOperation
) {
   // Verify that the image is forged, scalar and binary
   DIP_THROW_IF( !in.IsForged(), E::IMAGE_NOT_FORGED );
   DIP_THROW_IF( !in.DataType().IsBinary(), E::IMAGE_NOT_BINARY );
   DIP_THROW_IF( !in.IsScalar(), E::IMAGE_NOT_SCALAR );
   dip::uint nDims = in.Dimensionality();
   DIP_THROW_IF( connectivity > static_cast< dip::sint >( nDims ), E::PARAMETER_OUT_OF_RANGE );

   // Edge condition: true means object, false means background
   bool outsideImageIsObject = BooleanFromString( s_edgeCondition, S::OBJECT, S::BACKGROUND );

   // Copy input plane to output plane. Operation takes place directly in the output plane.
   Image c_in = in; // temporary copy of image header, so we can strip out
   out.ReForge( in.Sizes(), 1, DT_BIN ); // reforging first in case `out` is the right size but a different data type
   out.Copy( c_in );

   // Negative connectivity means: alternate between two different connectivities

   // Create arrays with offsets to neighbours for even iterations
   dip::uint iterConnectivity0 = GetAbsBinaryConnectivity( nDims, connectivity, 0 );
   NeighborList neighborList0( { Metric::TypeCode::CONNECTED, iterConnectivity0 }, nDims );
   IntegerArray neighborOffsetsOut0 = neighborList0.ComputeOffsets( out.Strides() );

   // Create arrays with offsets to neighbours for odd iterations
   dip::uint iterConnectivity1 = GetAbsBinaryConnectivity( nDims, connectivity, 1 );
   NeighborList neighborList1( { Metric::TypeCode::CONNECTED, iterConnectivity1 }, nDims );
   IntegerArray neighborOffsetsOut1 = neighborList1.ComputeOffsets( out.Strides() );

   // Data mask: the pixel data is in the first 'plane'
   uint8 dataMask = 1;

   // Use border mask to mark pixels of the image border
   uint8 borderMask = uint8( 1 << 2 );
   ApplyBinaryBorderMask( out, borderMask );

   // The edge pixel queue
   dip::queue< dip::bin* > edgePixels;

   // Initialize the queue by finding all edge pixels of the type according to findObjectPixels
   FindBinaryEdgePixels( out, findObjectPixels, neighborList0, neighborOffsetsOut0, dataMask, borderMask, outsideImageIsObject, &edgePixels );

   // First iteration: simply process the queue
   if( iterations > 0 ) {
      for( dip::queue< dip::bin* >::const_iterator itEP = edgePixels.begin(); itEP != edgePixels.end(); ++itEP ) {
         propagationOperation( static_cast< uint8& >( **itEP ), dataMask );
      }
   }

   // Create a coordinates computer for bounds checking of border pixels
   const CoordinatesComputer coordsComputer = out.OffsetToCoordinatesComputer();

   // Second and further iterations
   for( dip::uint iDilIter = 1; iDilIter < iterations; ++iDilIter ) {
      // Obtain neighbor list and offsets for this iteration
      NeighborList const& neighborList = iDilIter & 1 ? neighborList1 : neighborList0;
      IntegerArray const& neighborOffsetsOut = iDilIter & 1 ? neighborOffsetsOut1 : neighborOffsetsOut0;

      // Process all elements currently in the queue
      dip::sint count = static_cast< dip::sint >( edgePixels.size() );

      while( --count >= 0 ) {
         // Get front pixel from the queue
         dip::bin* pPixel = edgePixels.front();
         uint8& pixelByte = static_cast< uint8& >( *pPixel );
         bool isBorderPixel = pixelByte & borderMask;

         // Propagate to all neighbours which are not yet processed
         dip::IntegerArray::const_iterator itNeighborOffset = neighborOffsetsOut.begin();
         for( NeighborList::Iterator itNeighbor = neighborList.begin(); itNeighbor != neighborList.end(); ++itNeighbor, ++itNeighborOffset ) {
            if( !isBorderPixel || itNeighbor.IsInImage( coordsComputer( pPixel - static_cast< dip::bin* >( out.Origin() )), out.Sizes() )) { // IsInImage() is not evaluated for non-border pixels
               dip::bin* pNeighbor = pPixel + *itNeighborOffset;
               uint8& neighborByte = static_cast< uint8& >( *pNeighbor );
               bool neighborIsObject = neighborByte & dataMask;
               if( neighborIsObject == findObjectPixels ) {
                  // Propagate to the neighbor pixel
                  propagationOperation( neighborByte, dataMask );
                  // Add neighbor to the queue
                  edgePixels.push_back( pNeighbor );
               }
            }
         }

         // Remove the front pixel from the queue
         edgePixels.pop_front();
      }
   }

   // Clear the edge mask of the image border
   ClearBinaryBorderMask( out, borderMask );
}

} // namespace

void BinaryDilation(
      Image const& in,
      Image& out,
      dip::sint connectivity,
      dip::uint iterations,
      String const& s_edgeCondition
) {
   bool findObjectPixels = false; // Dilation propagates to background pixels
   auto propagationFunc = []( uint8& pixel, uint8 dataMask ) { pixel |= dataMask; };   // Propagate by adding the data mask
   BinaryDilationErosion( in, out, connectivity, iterations, s_edgeCondition, findObjectPixels, propagationFunc );
}

void BinaryErosion(
      Image const& in,
      Image& out,
      dip::sint connectivity,
      dip::uint iterations,
      String const& s_edgeCondition
) {
   bool findObjectPixels = true; // Erosion propagates to object pixels
   auto propagationFunc = []( uint8& pixel, uint8 dataMask ) { pixel &= static_cast< uint8 >( ~dataMask ); };  // Propagate by removing the data mask
   BinaryDilationErosion( in, out, connectivity, iterations, s_edgeCondition, findObjectPixels, propagationFunc );
}

void BinaryOpening(
      Image const& in,
      Image& out,
      dip::sint connectivity,
      dip::uint iterations,
      String const& edgeCondition
) {
   if( edgeCondition == S::BACKGROUND || edgeCondition == S::OBJECT ) {
      BinaryErosion( in, out, connectivity, iterations, edgeCondition );
      BinaryDilation( out, out, connectivity, iterations, edgeCondition );
   } else {
      // "Special handling"
      DIP_THROW_IF( edgeCondition != S::SPECIAL, E::INVALID_FLAG );
      BinaryErosion( in, out, connectivity, iterations, S::OBJECT );
      BinaryDilation( out, out, connectivity, iterations, S::BACKGROUND );
   }
}

void BinaryClosing(
      Image const& in,
      Image& out,
      dip::sint connectivity,
      dip::uint iterations,
      String const& edgeCondition
) {
   if( edgeCondition == S::BACKGROUND || edgeCondition == S::OBJECT ) {
      BinaryDilation( in, out, connectivity, iterations, edgeCondition );
      BinaryErosion( out, out, connectivity, iterations, edgeCondition );
   } else {
      // "Special handling"
      DIP_THROW_IF( edgeCondition != S::SPECIAL, E::INVALID_FLAG );
      BinaryDilation( in, out, connectivity, iterations, S::BACKGROUND );
      BinaryErosion( out, out, connectivity, iterations, S::OBJECT );
   }
}

} // namespace dip

#ifdef DIP__ENABLE_DOCTEST
#include "doctest.h"
#include "diplib/statistics.h"

DOCTEST_TEST_CASE("[DIPlib] testing the binary morphological filters") {
   dip::Image in( { 64, 41 }, 1, dip::DT_BIN );
   in = 0;
   in.At( 32, 20 ) = 1;
   dip::Image out;

   // connectivity = 2
   dip::BinaryDilation( in, out, 2, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 15 * 15 );
   dip::BinaryErosion( out, out, 2, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 1 );
   DOCTEST_CHECK( out.At( 32, 20 ) == 1 );

   // connectivity = 1
   dip::BinaryDilation( in, out, 1, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 7*8*2 + 1 );
   dip::BinaryErosion( out, out, 1, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 1 );
   DOCTEST_CHECK( out.At( 32, 20 ) == 1 );

   // connectivity = -1
   dip::BinaryDilation( in, out, -1, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 185 );
   dip::BinaryErosion( out, out, -1, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 1 );
   DOCTEST_CHECK( out.At( 32, 20 ) == 1 );

   // connectivity = -2
   dip::BinaryDilation( in, out, -2, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 201 );
   dip::BinaryErosion( out, out, -2, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 1 );
   DOCTEST_CHECK( out.At( 32, 20 ) == 1 );
}

#endif // DIP__ENABLE_DOCTEST
<commit_msg>Small speed increase using template with lambda over `std::function`.<commit_after>/*
 * DIPlib 3.0
 * This file contains basic binary morphology functions: dilation, erosion, opening, closing.
 *
 * (c)2017, Erik Schuitema.
 * Based on original DIPlib code: (c)1995-2014, Delft University of Technology.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "diplib.h"
#include "diplib/binary.h"
#include "diplib/neighborlist.h"
#include "diplib/iterators.h"
#include "binary_support.h"

namespace dip {

namespace {

// Worker function for both dilation and erosion, since they are very alike
template< typename F >
void BinaryDilationErosion(
      Image const& in,
      Image& out,
      dip::sint connectivity,
      dip::uint iterations,
      String const& s_edgeCondition,
      bool findObjectPixels,
      F const& propagationOperation
) {
   // Verify that the image is forged, scalar and binary
   DIP_THROW_IF( !in.IsForged(), E::IMAGE_NOT_FORGED );
   DIP_THROW_IF( !in.DataType().IsBinary(), E::IMAGE_NOT_BINARY );
   DIP_THROW_IF( !in.IsScalar(), E::IMAGE_NOT_SCALAR );
   dip::uint nDims = in.Dimensionality();
   DIP_THROW_IF( connectivity > static_cast< dip::sint >( nDims ), E::PARAMETER_OUT_OF_RANGE );

   // Edge condition: true means object, false means background
   bool outsideImageIsObject = BooleanFromString( s_edgeCondition, S::OBJECT, S::BACKGROUND );

   // Copy input plane to output plane. Operation takes place directly in the output plane.
   Image c_in = in; // temporary copy of image header, so we can strip out
   out.ReForge( in.Sizes(), 1, DT_BIN ); // reforging first in case `out` is the right size but a different data type
   out.Copy( c_in );

   // Negative connectivity means: alternate between two different connectivities

   // Create arrays with offsets to neighbours for even iterations
   dip::uint iterConnectivity0 = GetAbsBinaryConnectivity( nDims, connectivity, 0 );
   NeighborList neighborList0( { Metric::TypeCode::CONNECTED, iterConnectivity0 }, nDims );
   IntegerArray neighborOffsetsOut0 = neighborList0.ComputeOffsets( out.Strides() );

   // Create arrays with offsets to neighbours for odd iterations
   dip::uint iterConnectivity1 = GetAbsBinaryConnectivity( nDims, connectivity, 1 );
   NeighborList neighborList1( { Metric::TypeCode::CONNECTED, iterConnectivity1 }, nDims );
   IntegerArray neighborOffsetsOut1 = neighborList1.ComputeOffsets( out.Strides() );

   // Data mask: the pixel data is in the first 'plane'
   uint8 dataMask = 1;

   // Use border mask to mark pixels of the image border
   uint8 borderMask = uint8( 1 << 2 );
   ApplyBinaryBorderMask( out, borderMask );

   // The edge pixel queue
   dip::queue< dip::bin* > edgePixels;

   // Initialize the queue by finding all edge pixels of the type according to findObjectPixels
   FindBinaryEdgePixels( out, findObjectPixels, neighborList0, neighborOffsetsOut0, dataMask, borderMask, outsideImageIsObject, &edgePixels );

   // First iteration: simply process the queue
   if( iterations > 0 ) {
      for( dip::queue< dip::bin* >::const_iterator itEP = edgePixels.begin(); itEP != edgePixels.end(); ++itEP ) {
         propagationOperation( static_cast< uint8& >( **itEP ), dataMask );
      }
   }

   // Create a coordinates computer for bounds checking of border pixels
   const CoordinatesComputer coordsComputer = out.OffsetToCoordinatesComputer();

   // Second and further iterations
   for( dip::uint iDilIter = 1; iDilIter < iterations; ++iDilIter ) {
      // Obtain neighbor list and offsets for this iteration
      NeighborList const& neighborList = iDilIter & 1 ? neighborList1 : neighborList0;
      IntegerArray const& neighborOffsetsOut = iDilIter & 1 ? neighborOffsetsOut1 : neighborOffsetsOut0;

      // Process all elements currently in the queue
      dip::sint count = static_cast< dip::sint >( edgePixels.size() );

      while( --count >= 0 ) {
         // Get front pixel from the queue
         dip::bin* pPixel = edgePixels.front();
         uint8& pixelByte = static_cast< uint8& >( *pPixel );
         bool isBorderPixel = pixelByte & borderMask;

         // Propagate to all neighbours which are not yet processed
         dip::IntegerArray::const_iterator itNeighborOffset = neighborOffsetsOut.begin();
         for( NeighborList::Iterator itNeighbor = neighborList.begin(); itNeighbor != neighborList.end(); ++itNeighbor, ++itNeighborOffset ) {
            if( !isBorderPixel || itNeighbor.IsInImage( coordsComputer( pPixel - static_cast< dip::bin* >( out.Origin() )), out.Sizes() )) { // IsInImage() is not evaluated for non-border pixels
               dip::bin* pNeighbor = pPixel + *itNeighborOffset;
               uint8& neighborByte = static_cast< uint8& >( *pNeighbor );
               bool neighborIsObject = neighborByte & dataMask;
               if( neighborIsObject == findObjectPixels ) {
                  // Propagate to the neighbor pixel
                  propagationOperation( neighborByte, dataMask );
                  // Add neighbor to the queue
                  edgePixels.push_back( pNeighbor );
               }
            }
         }

         // Remove the front pixel from the queue
         edgePixels.pop_front();
      }
   }

   // Clear the edge mask of the image border
   ClearBinaryBorderMask( out, borderMask );
}

} // namespace

void BinaryDilation(
      Image const& in,
      Image& out,
      dip::sint connectivity,
      dip::uint iterations,
      String const& s_edgeCondition
) {
   bool findObjectPixels = false; // Dilation propagates to background pixels
   auto propagationFunc = []( uint8& pixel, uint8 dataMask ) { pixel |= dataMask; };   // Propagate by adding the data mask
   BinaryDilationErosion( in, out, connectivity, iterations, s_edgeCondition, findObjectPixels, propagationFunc );
}

void BinaryErosion(
      Image const& in,
      Image& out,
      dip::sint connectivity,
      dip::uint iterations,
      String const& s_edgeCondition
) {
   bool findObjectPixels = true; // Erosion propagates to object pixels
   auto propagationFunc = []( uint8& pixel, uint8 dataMask ) { pixel &= static_cast< uint8 >( ~dataMask ); };  // Propagate by removing the data mask
   BinaryDilationErosion( in, out, connectivity, iterations, s_edgeCondition, findObjectPixels, propagationFunc );
}

void BinaryOpening(
      Image const& in,
      Image& out,
      dip::sint connectivity,
      dip::uint iterations,
      String const& edgeCondition
) {
   if( edgeCondition == S::BACKGROUND || edgeCondition == S::OBJECT ) {
      BinaryErosion( in, out, connectivity, iterations, edgeCondition );
      BinaryDilation( out, out, connectivity, iterations, edgeCondition );
   } else {
      // "Special handling"
      DIP_THROW_IF( edgeCondition != S::SPECIAL, E::INVALID_FLAG );
      BinaryErosion( in, out, connectivity, iterations, S::OBJECT );
      BinaryDilation( out, out, connectivity, iterations, S::BACKGROUND );
   }
}

void BinaryClosing(
      Image const& in,
      Image& out,
      dip::sint connectivity,
      dip::uint iterations,
      String const& edgeCondition
) {
   if( edgeCondition == S::BACKGROUND || edgeCondition == S::OBJECT ) {
      BinaryDilation( in, out, connectivity, iterations, edgeCondition );
      BinaryErosion( out, out, connectivity, iterations, edgeCondition );
   } else {
      // "Special handling"
      DIP_THROW_IF( edgeCondition != S::SPECIAL, E::INVALID_FLAG );
      BinaryDilation( in, out, connectivity, iterations, S::BACKGROUND );
      BinaryErosion( out, out, connectivity, iterations, S::OBJECT );
   }
}

} // namespace dip

#ifdef DIP__ENABLE_DOCTEST
#include "doctest.h"
#include "diplib/statistics.h"

DOCTEST_TEST_CASE("[DIPlib] testing the binary morphological filters") {
   dip::Image in( { 64, 41 }, 1, dip::DT_BIN );
   in = 0;
   in.At( 32, 20 ) = 1;
   dip::Image out;

   // connectivity = 2
   dip::BinaryDilation( in, out, 2, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 15 * 15 );
   dip::BinaryErosion( out, out, 2, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 1 );
   DOCTEST_CHECK( out.At( 32, 20 ) == 1 );

   // connectivity = 1
   dip::BinaryDilation( in, out, 1, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 7*8*2 + 1 );
   dip::BinaryErosion( out, out, 1, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 1 );
   DOCTEST_CHECK( out.At( 32, 20 ) == 1 );

   // connectivity = -1
   dip::BinaryDilation( in, out, -1, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 185 );
   dip::BinaryErosion( out, out, -1, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 1 );
   DOCTEST_CHECK( out.At( 32, 20 ) == 1 );

   // connectivity = -2
   dip::BinaryDilation( in, out, -2, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 201 );
   dip::BinaryErosion( out, out, -2, 7 );
   DOCTEST_CHECK( dip::Count( out ) == 1 );
   DOCTEST_CHECK( out.At( 32, 20 ) == 1 );
}

#endif // DIP__ENABLE_DOCTEST
<|endoftext|>


<commit_before>/*
Proxy for the crypto project. Simply creates a new thread for each incoming connection and forwards its data
Derived from code at http://www.cs.rpi.edu/~goldsd/docs/spring2015-csci4210/server.c.txt
*/

#include <sys/socket.h>
#include <iostream>
#include <thread>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <netinet/in.h>
#include <signal.h>

#include "constants.h"

using namespace std;

//Evil global variables because it's simplest to do it this way
int send_port;
int listener_socket;

//Load tested via for i in $(seq 1 10000); do (nc localhost 8080 &) ; done
void handle_control_c(int s){
    close(listener_socket);
    exit(0);
}

void handleConnection(int sd){
    cout << "Connection handled on sd " << sd << endl;
    close(sd);
}

int main(int argc, char* argv[]){
    if(argc != 3){
        cout << "Proxy takes arguments <listen port> <send port>" << endl;
        return EXIT_FAILURE;
    }

    //Get ports
    int listen_port = (unsigned short) atoi(argv[1]);
    send_port = (unsigned short) atoi(argv[2]);
    if( listen_port > 65535 || send_port > 65535 ){
        cout << "Port larger than supported value" << endl;
        return EXIT_FAILURE;
    }

    //Create listener socket
    listener_socket = socket( PF_INET, SOCK_STREAM, 0 );
    if ( listener_socket < 0 ){
        cerr << "Socket creation failed" << endl;
        return EXIT_FAILURE;
    }
    signal(SIGINT, &handle_control_c);

    //Bind socket
    struct sockaddr_in server;
    server.sin_family = PF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(listen_port);
    int len = sizeof(server);
    if ( bind( listener_socket, (struct sockaddr *)&server, len ) < 0 ){
        cerr << "Bind failed" << endl;
        return EXIT_FAILURE;
    }

    //Start listening
    listen(listener_socket, MAX_CLIENTS);

    struct sockaddr_in client;
    int fromlen = sizeof(client);

    while(true){
        int client_sock = accept(listener_socket, (struct sockaddr *) &client, (socklen_t*) &fromlen);
        if(client_sock < 0){
            cerr << "Failed to accept connection" << endl;
            continue;
        }

        thread client_thread(handleConnection, client_sock);
        client_thread.detach();
    }
}<commit_msg>Finished proxy except for the fact that it doesn't work<commit_after>/*
Proxy for the crypto project. Simply creates a new thread for each incoming connection and forwards its data
Derived from code at http://www.cs.rpi.edu/~goldsd/docs/spring2015-csci4210/server.c.txt
*/

#include <sys/socket.h>
#include <iostream>
#include <thread>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/epoll.h>

#include "constants.h"

#define MAX_EVENTS 2
#define NUM_BYTES_FORWARD 1024

using namespace std;

//Evil global variables because it's simplest to do it this way
unsigned short send_port;
int listener_socket;

//Close socket on ^C
void handle_control_c(int s){
    close(listener_socket);
    exit(EXIT_SUCCESS);
}

//Forwards data from one socket to the other
int forwardData(int in_sd, int out_sd){
    ssize_t num_bytes_read, num_bytes_sent;
    char buffer[NUM_BYTES_FORWARD];

    num_bytes_read = recv(in_sd, buffer, (size_t)NUM_BYTES_FORWARD, 0);
    if(num_bytes_read == 0){
        return 0;
    }
    else if(num_bytes_read < 0){
        return -1;
    }

    num_bytes_sent = send(out_sd, buffer, (size_t) num_bytes_read, 0);
    if(num_bytes_sent != num_bytes_read){
        return -1;
    }

    return num_bytes_sent;
}

//Handle an incoming connection from an ATM
//Load tested via "for i in $(seq 1 10000); do (nc localhost 8080 &) ; done"
void handleConnection(int client_sd){
    cout  << "Start" << endl;
    //Create a socket for the connection to the bank
    int server_sd = socket(AF_INET, SOCK_STREAM, 0);
    if(server_sd < 0){
        cerr << "Failed to create socket for connection to bank" << endl;
        close(client_sd);
        return;
    }

    cout << "Server socket created" << endl;

    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_LOOPBACK;
    server.sin_port = htons(send_port);

    //Connect to the bank
    if( connect(server_sd, (struct sockaddr*) &server, sizeof(server)) < 0 ){
        cerr << "Failed to connect to bank" << endl;
        close(client_sd);
        close(server_sd);
        return;
    }

    cout << "Connected to bank" << endl;

    //Create epoll
    int epoll_fd = epoll_create1(0);
    if(epoll_fd < 0){
        cerr << "epoll creation failed" << endl;
        close(client_sd);
        close(server_sd);
        return;
    }

    cout << "Epoll created" << endl;

    //Setup epoll
    struct epoll_event ev, events[MAX_EVENTS];
    ev.events = EPOLLIN;
    ev.data.fd = client_sd;
    if( epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_sd, &ev) < 0 ){
        cerr << "Failed to setup epoll for atm" << endl;
        close(client_sd);
        close(server_sd);
        close(epoll_fd);
        return;
    }
    ev.data.fd = server_sd;
    if( epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_sd, &ev) < 0 ){
        cerr << "Failed to setup epoll for bank" << endl;
        close(client_sd);
        close(server_sd);
        close(epoll_fd);
        return;
    }

    //Listen for any data and forward it
    int num_fds, rc;
    while(true){
        num_fds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
        for(int i = 0; i < num_fds; i++){
            if(events[i].data.fd == client_sd){
                cout << "Received data from client" << endl;
                rc = forwardData(client_sd, server_sd);
            }
            else{
                cout << "Received data from server" << endl;
                rc = forwardData(server_sd, client_sd);
            }
            if(rc == -1){
                cerr << "Error forwarding data" << endl;
                close(client_sd);
                close(server_sd);
                close(epoll_fd);
                return;
            }
            else if(rc == 0){
                cerr << "Connection closed" << endl;
                close(client_sd);
                close(server_sd);
                close(epoll_fd);
                return;
            }
        }
    }

    close(client_sd);
    close(server_sd);
    close(epoll_fd);
}

//Listens for connections on the specified port and creates a thread to handle each one
int main(int argc, char* argv[]){
    if(argc != 3){
        cout << "Proxy takes arguments <listen port> <send port>" << endl;
        return EXIT_FAILURE;
    }

    //Get ports
    unsigned short listen_port = (unsigned short) atoi(argv[1]);
    send_port = (unsigned short) atoi(argv[2]);
    if( listen_port > 65535 || send_port > 65535 ){
        cout << "Port larger than supported value" << endl;
        return EXIT_FAILURE;
    }

    //Create listener socket
    listener_socket = socket( AF_INET, SOCK_STREAM, 0 );
    if ( listener_socket < 0 ){
        cerr << "Socket creation failed" << endl;
        return EXIT_FAILURE;
    }
    signal(SIGINT, &handle_control_c);

    //Bind socket
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(listen_port);
    int len = sizeof(server);
    if ( bind( listener_socket, (struct sockaddr *) &server, len ) < 0 ){
        cerr << "Bind failed" << endl;
        return EXIT_FAILURE;
    }

    //Start listening
    listen(listener_socket, MAX_CLIENTS);

    struct sockaddr_in client;
    int fromlen = sizeof(client);

    while(true){
        int client_sd = accept(listener_socket, (struct sockaddr *) &client, (socklen_t*) &fromlen);
        if(client_sd < 0){
            cerr << "Failed to accept connection" << endl;
            continue;
        }

        thread client_thread(handleConnection, client_sd);
        client_thread.detach();
    }
}<|endoftext|>