std::shared_ptr<raii_deleter> 
register_shared_memory_name(std::string m_name) {
  garbage_collect();

  // tag file is located as [system temp directory]/glshm_[userid]/[shmname]
  // tag file contains a PID in it.
  auto tagfile = (shared_memory_tagfile_path() / m_name).generic_string();
  std::ofstream fout(tagfile);
  fout << get_my_pid();
  fout.close();
  return std::make_shared<raii_deleter>(m_name, tagfile);
}
//-----------------------------------------------------------------------------
// Send NVQR_QUERY_CONNECT to the server and verify that it ACKs with
// NVQR_QUERY_CONNECT. Returns TRUE on success; FALSE on failure.
static bool connect_to_server(NVQRConnection *conn)
{
    NVQRQueryDataBuffer data;
    bool ret = write_server_command(*conn, NVQR_QUERY_CONNECT, 0, get_my_pid());

    if (ret) {
        ret = open_client_connection(conn);

        if (ret) {
            if (!read_server_response(*conn, &data) ||
                data.op != NVQR_QUERY_CONNECT) {
                close_client_connection(*conn);
            }
        }
    }

    return ret;
}
static bool create_client(NVQRConnection *c)
{
#if defined(_WIN32)
    char *name = nvqr_ipc_client_pipe_name(get_my_pid());
    c->client_handle = CreateNamedPipe(
          (LPCSTR)(LPCTSTR)name,    // pipe name
          PIPE_ACCESS_INBOUND,      // read access
          PIPE_TYPE_MESSAGE |       // message type pipe
          PIPE_READMODE_MESSAGE |   // message-read mode
          PIPE_WAIT,                // blocking mode
          PIPE_UNLIMITED_INSTANCES, // max. instances
          512,                      // output buffer size
          512,                      // input buffer size
          0,                        // client time-out
          NULL);                    // default security attribute
    free(name);
    return c->client_handle != INVALID_HANDLE_VALUE;
#else
    return true;
#endif
}
示例#4
0
/** The main function to be called from the python ctypes library to
 *  create a pylambda worker process.
 *
 *  Different error routes produce different error codes of 101 and
 *  above.
 */
int EXPORT pylambda_worker_main(const std::string& root_path,
                                const std::string& server_address, int loglevel) {

  /** Set up the debug configuration.
   *
   *  By default, all LOG_ERROR and LOG_FATAL messages are sent to
   *  stderr, and all messages above loglevel are sent to stdout.
   *
   *  If GRAPHLAB_LAMBDA_WORKER_LOG_FILE is set and is non-empty, then
   *  all log messages are sent to the file instead of the stdout and
   *  stderr.  In this case, the only errors logged to stderr/stdout
   *  concern opening the log file.
   *
   *  If GRAPHLAB_LAMBDA_WORKER_DEBUG_MODE is set, then the default
   *  log level is set to LOG_DEBUG.  If a log file is set, then all
   *  log messages are sent there, otherwise they are sent to stderr.
   */
  boost::optional<std::string> debug_mode_str = graphlab::getenv_str("GRAPHLAB_LAMBDA_WORKER_DEBUG_MODE");
  boost::optional<std::string> debug_mode_file_str = graphlab::getenv_str("GRAPHLAB_LAMBDA_WORKER_LOG_FILE");

  std::string log_file_string = debug_mode_file_str ? *debug_mode_file_str :  "";
  bool log_to_file = (!log_file_string.empty());

  bool debug_mode = (bool)(debug_mode_str);

  global_logger().set_log_level(loglevel);
  global_logger().set_log_to_console(true);

  // Logging using the LOG_DEBUG_WITH_PID macro requires this_pid to be set.
  size_t this_pid = get_my_pid();
  global_logger().set_pid(this_pid);

  // Set up the logging to file if needed.
  if(log_to_file) {
    // Set up the logging to the file, with any errors being fully logged.
    global_logger().set_log_to_console(true, true);
    global_logger().set_log_file(log_file_string);
    LOG_DEBUG_WITH_PID("Logging lambda worker logs to " << log_file_string);
    global_logger().set_log_to_console(false);
  }

  // Now, set the log mode for debug
  if(debug_mode) {
    global_logger().set_log_level(LOG_DEBUG);
    if(!log_to_file) {
      // Set logging to console, with everything logged to stderr.
      global_logger().set_log_to_console(true, true);
    }
  }

  // Log the basic information about parameters.
  size_t parent_pid = get_parent_pid();

  LOG_DEBUG_WITH_PID("root_path = '" << root_path << "'");
  LOG_DEBUG_WITH_PID("server_address = '" << server_address << "'");
  LOG_DEBUG_WITH_PID("parend pid = " << parent_pid);

  size_t _last_line = __LINE__;
#define __TRACK do { _last_line = __LINE__; } while(0)  
  try {

    LOG_DEBUG_WITH_PID("Library function entered successfully.");

    if(server_address == "debug") {
      logstream(LOG_INFO) << "Exiting dry run." << std::endl;
      return 1;
    }

    __TRACK; boost::optional<std::string> disable_shm = graphlab::getenv_str("GRAPHLAB_DISABLE_LAMBDA_SHM");
    bool use_shm = true;
    if(disable_shm && *disable_shm == "1") {
      use_shm = false;
      __TRACK; LOG_DEBUG_WITH_PID("shm disabled.");
    }

    __TRACK; graphlab::shmipc::server shm_comm_server;
    bool has_shm = false;
    
    try { 
      __TRACK; has_shm = use_shm ? shm_comm_server.bind() : false;
    } catch (const std::string& error) {
      logstream(LOG_ERROR) << "Internal PyLambda Error binding SHM server: "
                           << error << "; disabling SHM." << std::endl;
      has_shm = false;      
    } catch (const std::exception& error) {
      logstream(LOG_ERROR) << "Internal PyLambda Error binding SHM server: "
                           << error.what() << "; disabling SHM." << std::endl;
      has_shm = false;      
    } catch (...) {
      logstream(LOG_ERROR) << "Unknown internal PyLambda Error binding SHM server; disabling SHM."
                           << std::endl;
      has_shm = false;      
    }
    
    __TRACK; LOG_DEBUG_WITH_PID("shm_comm_server bind: has_shm=" << has_shm);

    // construct the server
    __TRACK; cppipc::comm_server server(std::vector<std::string>(), "", server_address);

    __TRACK; server.register_type<graphlab::lambda::lambda_evaluator_interface>([&](){
        if (has_shm) {
          __TRACK; auto n = new graphlab::lambda::pylambda_evaluator(&shm_comm_server);
          __TRACK; LOG_DEBUG_WITH_PID("creation of pylambda_evaluator with SHM complete.");
          __TRACK; return n;
        } else {
          __TRACK; auto n = new graphlab::lambda::pylambda_evaluator();
          __TRACK; LOG_DEBUG_WITH_PID("creation of pylambda_evaluator without SHM complete.");
          __TRACK; return n;
        }
      });
    
    __TRACK; server.register_type<graphlab::lambda::graph_lambda_evaluator_interface>([&](){
        __TRACK; auto n = new graphlab::lambda::graph_pylambda_evaluator();
        __TRACK; LOG_DEBUG_WITH_PID("creation of graph_pylambda_evaluator complete.");
        __TRACK; return n;
      });
    
    __TRACK; LOG_DEBUG_WITH_PID("Starting server.");
    __TRACK; server.start();

    __TRACK; wait_for_parent_exit(parent_pid);

    return 0;

    /** Any exceptions happening?  If so, propegate back what's going
     *  on through the error codes.
     */
  } catch (const std::string& error) {
    logstream(LOG_ERROR) << "Internal PyLambda Error: " << error
                         << "; last successful line =" << _last_line  << std::endl;
    return _last_line;
  } catch (const std::exception& error) {
    logstream(LOG_ERROR) << "PyLambda C++ Error: " << error.what()
                         << "; last successful line =" << _last_line << std::endl;
    return _last_line;
  } catch (...) {
    logstream(LOG_ERROR) << "Unknown PyLambda Error"
                         << "; last successful line =" << _last_line << std::endl;
    return _last_line;
  }
}