// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab /* * Ceph - scalable distributed file system * * Copyright (C) 2011 New Dream Network * * This 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. See file COPYING. * */ #ifndef CEPH_CEPHCONTEXT_H #define CEPH_CEPHCONTEXT_H #include #include #include #include "common/cmdparse.h" #include "common/code_environment.h" #include "crush/CrushLocation.h" #include "include/Spinlock.h" class AdminSocket; class CephContextServiceThread; class PerfCountersCollection; class PerfCounters; class md_config_obs_t; struct md_config_t; class CephContextHook; class CephContextObs; class CryptoHandler; namespace ceph { class PluginRegistry; class HeartbeatMap; namespace logging { class Log; } } /* A CephContext represents the context held by a single library user. * There can be multiple CephContexts in the same process. * * For daemons and utility programs, there will be only one CephContext. The * CephContext contains the configuration, the dout object, and anything else * that you might want to pass to libcommon with every function call. */ class CephContext { public: CephContext(uint32_t module_type_, enum code_environment_t code_env=CODE_ENVIRONMENT_UTILITY, int init_flags_ = 0); // ref count! private: ~CephContext(); std::atomic nref; public: CephContext *get() { ++nref; return this; } void put(); md_config_t *_conf; ceph::logging::Log *_log; /* init ceph::crypto */ void init_crypto(); /* Start the Ceph Context's service thread */ void start_service_thread(); /* Reopen the log files */ void reopen_logs(); /* Get the module type (client, mon, osd, mds, etc.) */ uint32_t get_module_type() const; void set_init_flags(int flags); int get_init_flags() const; /* Get the PerfCountersCollection of this CephContext */ PerfCountersCollection *get_perfcounters_collection(); ceph::HeartbeatMap *get_heartbeat_map() { return _heartbeat_map; } /** * Enable the performance counter, currently we only have counter for the * number of total/unhealthy workers. */ void enable_perf_counter(); /** * Disable the performance counter. */ void disable_perf_counter(); /** * Refresh perf counter values. */ void refresh_perf_values(); /** * Get the admin socket associated with this CephContext. * * Currently there is always an admin socket object, * so this will never return NULL. * * @return the admin socket */ AdminSocket *get_admin_socket(); /** * process an admin socket command */ void do_command(std::string command, cmdmap_t& cmdmap, std::string format, ceph::bufferlist *out); template void lookup_or_create_singleton_object(T*& p, const std::string &name) { ceph_spin_lock(&_associated_objs_lock); if (!_associated_objs.count(name)) { p = new T(this); _associated_objs[name] = new TypedSingletonWrapper(p); } else { TypedSingletonWrapper *wrapper = dynamic_cast *>(_associated_objs[name]); assert(wrapper != NULL); p = wrapper->singleton; } ceph_spin_unlock(&_associated_objs_lock); } /** * get a crypto handler */ CryptoHandler *get_crypto_handler(int type); /// check if experimental feature is enable, and emit appropriate warnings bool check_experimental_feature_enabled(const std::string& feature); bool check_experimental_feature_enabled(const std::string& feature, std::ostream *message); PluginRegistry *get_plugin_registry() { return _plugin_registry; } void set_uid_gid(uid_t u, gid_t g) { _set_uid = u; _set_gid = g; } uid_t get_set_uid() const { return _set_uid; } gid_t get_set_gid() const { return _set_gid; } void set_uid_gid_strings(std::string u, std::string g) { _set_uid_string = u; _set_gid_string = g; } std::string get_set_uid_string() const { return _set_uid_string; } std::string get_set_gid_string() const { return _set_gid_string; } class ForkWatcher { public: virtual ~ForkWatcher() {} virtual void handle_pre_fork() = 0; virtual void handle_post_fork() = 0; }; void register_fork_watcher(ForkWatcher *w) { ceph_spin_lock(&_fork_watchers_lock); _fork_watchers.push_back(w); ceph_spin_unlock(&_fork_watchers_lock); } void notify_pre_fork() { ceph_spin_lock(&_fork_watchers_lock); for (auto &&t : _fork_watchers) t->handle_pre_fork(); ceph_spin_unlock(&_fork_watchers_lock); } void notify_post_fork() { ceph_spin_lock(&_fork_watchers_lock); for (auto &&t : _fork_watchers) t->handle_post_fork(); ceph_spin_unlock(&_fork_watchers_lock); } private: struct SingletonWrapper : boost::noncopyable { virtual ~SingletonWrapper() {} }; template struct TypedSingletonWrapper : public SingletonWrapper { TypedSingletonWrapper(T *p) : singleton(p) { } ~TypedSingletonWrapper() override { delete singleton; } T *singleton; }; CephContext(const CephContext &rhs); CephContext &operator=(const CephContext &rhs); /* Stop and join the Ceph Context's service thread */ void join_service_thread(); uint32_t _module_type; int _init_flags; uid_t _set_uid; ///< uid to drop privs to gid_t _set_gid; ///< gid to drop privs to std::string _set_uid_string; std::string _set_gid_string; bool _crypto_inited; /* libcommon service thread. * SIGHUP wakes this thread, which then reopens logfiles */ friend class CephContextServiceThread; CephContextServiceThread *_service_thread; md_config_obs_t *_log_obs; /* The admin socket associated with this context */ AdminSocket *_admin_socket; /* lock which protects service thread creation, destruction, etc. */ ceph_spinlock_t _service_thread_lock; /* The collection of profiling loggers associated with this context */ PerfCountersCollection *_perf_counters_collection; md_config_obs_t *_perf_counters_conf_obs; CephContextHook *_admin_hook; ceph::HeartbeatMap *_heartbeat_map; ceph_spinlock_t _associated_objs_lock; std::map _associated_objs; ceph_spinlock_t _fork_watchers_lock; std::vector _fork_watchers; // crypto CryptoHandler *_crypto_none; CryptoHandler *_crypto_aes; // experimental CephContextObs *_cct_obs; ceph_spinlock_t _feature_lock; std::set _experimental_features; PluginRegistry *_plugin_registry; md_config_obs_t *_lockdep_obs; public: CrushLocation crush_location; private: enum { l_cct_first, l_cct_total_workers, l_cct_unhealthy_workers, l_cct_last }; PerfCounters *_cct_perf; ceph_spinlock_t _cct_perf_lock; friend class CephContextObs; }; #endif