diff options
| author | Andrew Stitcher <astitcher@apache.org> | 2009-12-15 18:24:02 +0000 |
|---|---|---|
| committer | Andrew Stitcher <astitcher@apache.org> | 2009-12-15 18:24:02 +0000 |
| commit | faf8a3a3a9f2355ec7044144d63ef869788eebb3 (patch) | |
| tree | f8f1d22ceb1a04d44f2353fcc352fdeafeafbbad /cpp/src/windows | |
| parent | a66973a94f41bc034d98d39028e13cbbff805b93 (diff) | |
| download | qpid-python-faf8a3a3a9f2355ec7044144d63ef869788eebb3.tar.gz | |
QPID-1951: Removed need for Windows versions of ssize_t and pid_t
- Trivially removed Windows uses of ssize_t
- Rearchitected how the Windows port finds an existing qpidd to stop it
- Split Posix Lockfile functionality using pids into a new PidFile class
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@890929 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/windows')
| -rw-r--r-- | cpp/src/windows/QpiddBroker.cpp | 191 |
1 files changed, 119 insertions, 72 deletions
diff --git a/cpp/src/windows/QpiddBroker.cpp b/cpp/src/windows/QpiddBroker.cpp index fc4f9f8a92..15380dda0b 100644 --- a/cpp/src/windows/QpiddBroker.cpp +++ b/cpp/src/windows/QpiddBroker.cpp @@ -34,7 +34,6 @@ const char *QPIDD_MODULE_DIR = "."; #include "qpid/Options.h" #include "qpid/Plugin.h" #include "qpid/sys/IntegerTypes.h" -#include "qpid/sys/LockFile.h" #include "qpid/sys/windows/check.h" #include "qpid/broker/Broker.h" @@ -59,74 +58,68 @@ namespace { const std::string TCP = "tcp"; -std::string brokerPidFile(std::string piddir, uint16_t port) -{ - std::ostringstream path; - path << piddir << "\\broker_" << port << ".pid"; - return path.str(); -} - // ShutdownEvent maintains an event that can be used to ask the broker // to stop. Analogous to sending SIGTERM/SIGINT to the posix broker. // The signal() method signals the event. class ShutdownEvent { public: - ShutdownEvent(pid_t other = 0); + ShutdownEvent(int port); ~ShutdownEvent(); + void create(); + void open(); void signal(); + private: + std::string eventName; + protected: - std::string eventName(pid_t pid); HANDLE event; }; class ShutdownHandler : public ShutdownEvent, public qpid::sys::Runnable { public: - ShutdownHandler(const boost::intrusive_ptr<Broker>& b) - : ShutdownEvent() { broker = b; } + ShutdownHandler(int port, const boost::intrusive_ptr<Broker>& b) + : ShutdownEvent(port) { broker = b; } private: virtual void run(); // Inherited from Runnable boost::intrusive_ptr<Broker> broker; }; -ShutdownEvent::ShutdownEvent(pid_t other) : event(NULL) { - // If given a pid, open an event assumedly created by that pid. If there's - // no pid, create a new event using the current process id. - if (other == 0) { - std::string name = eventName(GetCurrentProcessId()); - // Auto-reset event in case multiple processes try to signal a - // broker that doesn't respond for some reason. Initially not signaled. - event = CreateEvent(NULL, false, false, name.c_str()); - } - else { - std::string name = eventName(other); - event = OpenEvent(EVENT_MODIFY_STATE, false, name.c_str()); - } +ShutdownEvent::ShutdownEvent(int port) : event(NULL) { + std::ostringstream name; + name << "qpidd_" << port << std::ends; + eventName = name.str(); +} + +void ShutdownEvent::create() { + // Auto-reset event in case multiple processes try to signal a + // broker that doesn't respond for some reason. Initially not signaled. + event = ::CreateEvent(NULL, false, false, eventName.c_str()); + QPID_WINDOWS_CHECK_NULL(event); +} + +void ShutdownEvent::open() { + // TODO: Might need to search Global\\ name if unadorned name fails + event = ::OpenEvent(EVENT_MODIFY_STATE, false, eventName.c_str()); QPID_WINDOWS_CHECK_NULL(event); } ShutdownEvent::~ShutdownEvent() { - CloseHandle(event); + ::CloseHandle(event); event = NULL; } void ShutdownEvent::signal() { - QPID_WINDOWS_CHECK_NOT(SetEvent(event), 0); -} - -std::string ShutdownEvent::eventName(pid_t pid) { - std::ostringstream name; - name << "qpidd_" << pid << std::ends; - return name.str(); + QPID_WINDOWS_CHECK_NOT(::SetEvent(event), 0); } void ShutdownHandler::run() { if (event == NULL) return; - WaitForSingleObject(event, INFINITE); + ::WaitForSingleObject(event, INFINITE); if (broker.get()) { broker->shutdown(); broker = 0; // Release the broker reference @@ -134,19 +127,89 @@ void ShutdownHandler::run() { } // Console control handler to properly handle ctl-c. +int ourPort; BOOL CtrlHandler(DWORD ctl) { - ShutdownEvent shutter; // no pid specified == shut me down + ShutdownEvent shutter(ourPort); // We have to have set up the port before interrupting + shutter.open(); shutter.signal(); return ((ctl == CTRL_C_EVENT || ctl == CTRL_CLOSE_EVENT) ? TRUE : FALSE); } +template <typename T> +class NamedSharedMemory { + std::string name; + HANDLE memory; + T* data; + +public: + NamedSharedMemory(const std::string&); + ~NamedSharedMemory(); + + T& create(); + T& get(); +}; + +template <typename T> +NamedSharedMemory<T>::NamedSharedMemory(const std::string& n) : + name(n), + memory(NULL), + data(0) +{}; + +template <typename T> +NamedSharedMemory<T>::~NamedSharedMemory() { + if (data) + ::UnmapViewOfFile(data); + if (memory != NULL) + ::CloseHandle(memory); +}; + +template <typename T> +T& NamedSharedMemory<T>::create() { + assert(memory == NULL); + + // Create named shared memory file + memory = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(T), name.c_str()); + QPID_WINDOWS_CHECK_NULL(memory); + + // Map file into memory + data = static_cast<T*>(::MapViewOfFile(memory, FILE_MAP_WRITE, 0, 0, 0)); + QPID_WINDOWS_CHECK_NULL(data); + + return *data; +} + +template <typename T> +T& NamedSharedMemory<T>::get() { + if (memory == NULL) { + // TODO: Might need to search Global\\ name if unadorned name fails + memory = ::OpenFileMapping(FILE_MAP_WRITE, FALSE, name.c_str()); + QPID_WINDOWS_CHECK_NULL(memory); + + data = static_cast<T*>(::MapViewOfFile(memory, FILE_MAP_WRITE, 0, 0, 0)); + QPID_WINDOWS_CHECK_NULL(data); + } + + return *data; +} + +std::string brokerInfoName(uint16_t port) +{ + std::ostringstream path; + path << "qpidd_info_" << port; + return path.str(); +} + +struct BrokerInfo { + DWORD pid; +}; + } struct ProcessControlOptions : public qpid::Options { bool quit; bool check; - std::string piddir; //std::string transport; No transport options yet - TCP is it. ProcessControlOptions() @@ -154,18 +217,9 @@ struct ProcessControlOptions : public qpid::Options { quit(false), check(false) //, transport(TCP) { - const DWORD pathLen = MAX_PATH + 1; - char tempDir[pathLen]; - if (GetTempPath(pathLen, tempDir) == 0) - piddir = "C:\\WINDOWS\\TEMP\\"; - else - piddir = tempDir; - piddir += "qpidd"; - // Only have TCP for now, so don't need this... // ("transport", optValue(transport, "TRANSPORT"), "The transport for which to return the port") addOptions() - ("pid-dir", qpid::optValue(piddir, "DIR"), "Directory where port-specific PID file is stored") ("check,c", qpid::optValue(check), "Prints the broker's process ID to stdout and returns 0 if the broker is running, otherwise returns 1") ("quit,q", qpid::optValue(quit), "Tells the broker to shut down"); } @@ -207,57 +261,50 @@ int QpiddBroker::execute (QpiddOptions *options) { if (myOptions->control.check || myOptions->control.quit) { // Relies on port number being set via --port or QPID_PORT env variable. - qpid::sys::LockFile getPid (brokerPidFile(myOptions->control.piddir, - options->broker.port), - false); - pid_t pid = getPid.readPid(); + NamedSharedMemory<BrokerInfo> info(brokerInfoName(options->broker.port)); + int pid = info.get().pid; if (pid < 0) return 1; if (myOptions->control.check) std::cout << pid << std::endl; if (myOptions->control.quit) { - ShutdownEvent shutter(pid); - HANDLE brokerHandle = OpenProcess(SYNCHRONIZE, false, pid); - QPID_WINDOWS_CHECK_NULL(brokerHandle); + ShutdownEvent shutter(options->broker.port); + shutter.open(); shutter.signal(); - WaitForSingleObject(brokerHandle, INFINITE); - CloseHandle(brokerHandle); + HANDLE brokerHandle = ::OpenProcess(SYNCHRONIZE, false, pid); + QPID_WINDOWS_CHECK_NULL(brokerHandle); + ::WaitForSingleObject(brokerHandle, INFINITE); + ::CloseHandle(brokerHandle); } return 0; } boost::intrusive_ptr<Broker> brokerPtr(new Broker(options->broker)); - // Make sure the pid directory exists, creating if needed. LockFile - // will throw an exception that makes little sense if it can't create - // the file. - if (!CreateDirectory(myOptions->control.piddir.c_str(), 0)) { - DWORD err = GetLastError(); - if (err != ERROR_ALREADY_EXISTS) - throw qpid::Exception(QPID_MSG("Can't create pid-dir " + - myOptions->control.piddir + - ": " + - qpid::sys::strError(err))); - } // Need the correct port number to use in the pid file name. if (options->broker.port == 0) options->broker.port = brokerPtr->getPort(""); - qpid::sys::LockFile myPid(brokerPidFile(myOptions->control.piddir, - options->broker.port), - true); - myPid.writePid(); + + BrokerInfo info; + info.pid = ::GetCurrentProcessId(); + + NamedSharedMemory<BrokerInfo> sharedInfo(brokerInfoName(options->broker.port)); + sharedInfo.create() = info; // Allow the broker to receive a shutdown request via a qpidd --quit // command. Note that when the broker is run as a service this operation // should not be allowed. - - ShutdownHandler waitShut(brokerPtr); + ourPort = options->broker.port; + ShutdownHandler waitShut(ourPort, brokerPtr); + waitShut.create(); qpid::sys::Thread waitThr(waitShut); // Wait for shutdown event - SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); + ::SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); brokerPtr->accept(); std::cout << options->broker.port << std::endl; brokerPtr->run(); waitShut.signal(); // In case we shut down some other way waitThr.join(); + + // CloseHandle(h); return 0; } |
