summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2006-11-17 15:04:28 +0000
committerBenoit Foucher <benoit@zeroc.com>2006-11-17 15:04:28 +0000
commitaacea143855a7a09e4ba53d09150ed71c7df2a67 (patch)
treeb9b291727307d586d74e5c4204decdc02c77369d /cpp
parentFixed depends Some Makefile cleanup (diff)
downloadice-aacea143855a7a09e4ba53d09150ed71c7df2a67.tar.bz2
ice-aacea143855a7a09e4ba53d09150ed71c7df2a67.tar.xz
ice-aacea143855a7a09e4ba53d09150ed71c7df2a67.zip
Added support for viewing stderr/stdout files from nodes, registries,
servers.
Diffstat (limited to 'cpp')
-rw-r--r--cpp/slice/IceGrid/Admin.ice162
-rw-r--r--cpp/slice/IceGrid/Exception.ice17
-rw-r--r--cpp/src/IceGrid/Activator.cpp14
-rw-r--r--cpp/src/IceGrid/Activator.h4
-rw-r--r--cpp/src/IceGrid/AdminSessionI.cpp165
-rw-r--r--cpp/src/IceGrid/AdminSessionI.h36
-rw-r--r--cpp/src/IceGrid/Client.cpp2
-rw-r--r--cpp/src/IceGrid/Grammar.y27
-rw-r--r--cpp/src/IceGrid/Internal.ice17
-rw-r--r--cpp/src/IceGrid/InternalRegistryI.cpp31
-rw-r--r--cpp/src/IceGrid/InternalRegistryI.h6
-rw-r--r--cpp/src/IceGrid/Makefile1
-rw-r--r--cpp/src/IceGrid/NodeI.cpp68
-rw-r--r--cpp/src/IceGrid/NodeI.h26
-rw-r--r--cpp/src/IceGrid/Parser.cpp219
-rw-r--r--cpp/src/IceGrid/Parser.h9
-rw-r--r--cpp/src/IceGrid/Scanner.l4
-rw-r--r--cpp/src/IceGrid/ServerI.cpp48
-rw-r--r--cpp/src/IceGrid/ServerI.h4
19 files changed, 819 insertions, 41 deletions
diff --git a/cpp/slice/IceGrid/Admin.ice b/cpp/slice/IceGrid/Admin.ice
index e7ab78358fa..a4dff0da42f 100644
--- a/cpp/slice/IceGrid/Admin.ice
+++ b/cpp/slice/IceGrid/Admin.ice
@@ -1066,6 +1066,33 @@ interface Admin
["nonmutating", "cpp:const"] idempotent Ice::SliceChecksumDict getSliceChecksums();
};
+interface FileIterator
+{
+ /**
+ *
+ * Read up to `nlines' lines from the log file.
+ *
+ * @param nlines The maximum number of lines to return.
+ *
+ * @return The lines read from the file. If there was nothing to
+ * read from the file since the last call to read, an empty
+ * sequence is returned.
+ *
+ * @throws FileNotAvailableException Raised if there was a problem
+ * to read lines from the file.
+ *
+ **/
+ Ice::StringSeq read(int nlines)
+ throws FileNotAvailableException;
+
+ /**
+ *
+ * Destroy the iterator.
+ *
+ **/
+ void destroy();
+};
+
interface RegistryObserver;
interface NodeObserver;
interface ApplicationObserver;
@@ -1188,6 +1215,141 @@ interface AdminSession extends Glacier2::Session
*
**/
["cpp:const"] idempotent string getReplicaName();
+
+ /**
+ *
+ * Open the given server stderr file for reading. The file can be
+ * read with the returned file iterator.
+ *
+ * @param id The server id.
+ *
+ * @return An iterator to read the file.
+ *
+ * @throws FileNotAvailableException Raised if the file can't be
+ * read.
+ *
+ * @throws ServerNotExistException Raised if the server doesn't
+ * exist.
+ *
+ * @throws NodeUnreachableException Raised if the node could not
+ * be reached.
+ *
+ * @throws DeploymentException Raised if the server couldn't be
+ * deployed on the node.
+ *
+ **/
+ FileIterator* openServerStdErr(string id)
+ throws FileNotAvailableException, ServerNotExistException, NodeUnreachableException, DeploymentException;
+ /**
+ *
+ * Open the given server stdout file for reading. The file can be
+ * read with the returned file iterator.
+ *
+ * @param id The server id.
+ *
+ * @return An iterator to read the file.
+ *
+ * @throws FileNotAvailableException Raised if the file can't be
+ * read.
+ *
+ * @throws ServerNotExistException Raised if the server doesn't
+ * exist.
+ *
+ * @throws NodeUnreachableException Raised if the node could not
+ * be reached.
+ *
+ * @throws DeploymentException Raised if the server couldn't be
+ * deployed on the node.
+ *
+ **/
+ FileIterator* openServerStdOut(string id)
+ throws FileNotAvailableException, ServerNotExistException, NodeUnreachableException, DeploymentException;
+
+ /**
+ *
+ * Open the given node stderr file for reading. The file can be
+ * read with the returned file iterator.
+ *
+ * @param name The node name.
+ *
+ * @return An iterator to read the file.
+ *
+ * @throws FileNotAvailableException Raised if the file can't be
+ * read.
+ *
+ * @throws NodeNotExistException Raised if the node doesn't exist.
+ *
+ * @throws NodeUnreachableException Raised if the node could not
+ * be reached.
+ *
+ **/
+ FileIterator* openNodeStdErr(string name)
+ throws FileNotAvailableException, NodeNotExistException, NodeUnreachableException;
+
+ /**
+ *
+ * Open the given node stdout file for reading. The file can be
+ * read with the returned file iterator.
+ *
+ * @param name The node name.
+ *
+ * @return An iterator to read the file.
+ *
+ * @throws FileNotAvailableException Raised if the file can't be
+ * read.
+ *
+ * @throws NodeNotExistException Raised if the node doesn't exist.
+ *
+ * @throws NodeUnreachableException Raised if the node could not
+ * be reached.
+ *
+ **/
+ FileIterator* openNodeStdOut(string name)
+ throws FileNotAvailableException, NodeNotExistException, NodeUnreachableException;
+
+ /**
+ *
+ * Open the given registry stderr file for reading. The file can be
+ * read with the returned file iterator.
+ *
+ * @param name The registry name.
+ *
+ * @return An iterator to read the file.
+ *
+ * @throws FileNotAvailableException Raised if the file can't be
+ * read.
+ *
+ * @throws RegistryNotExistException Raised if the registry
+ * doesn't exist.
+ *
+ * @throws RegistryUnreachableException Raised if the registry
+ * could not be reached.
+ *
+ **/
+ FileIterator* openRegistryStdErr(string name)
+ throws FileNotAvailableException, RegistryNotExistException, RegistryUnreachableException;
+
+ /**
+ *
+ * Open the given registry stdout file for reading. The file can be
+ * read with the returned file iterator.
+ *
+ * @param name The registry name.
+ *
+ * @return An iterator to read the file.
+ *
+ * @throws FileNotAvailableException Raised if the file can't be
+ * read.
+ *
+ * @throws RegistryNotExistException Raised if the registry
+ * doesn't exist.
+ *
+ * @throws RegistryUnreachableException Raised if the registry
+ * could not be reached.
+ *
+ **/
+ FileIterator * openRegistryStdOut(string name)
+ throws FileNotAvailableException, RegistryNotExistException, RegistryUnreachableException;
};
};
diff --git a/cpp/slice/IceGrid/Exception.ice b/cpp/slice/IceGrid/Exception.ice
index 4302940f8f7..cd69a7b46d6 100644
--- a/cpp/slice/IceGrid/Exception.ice
+++ b/cpp/slice/IceGrid/Exception.ice
@@ -250,6 +250,23 @@ exception ObserverAlreadyRegisteredException
Ice::Identity id;
};
+/**
+ *
+ * This exception is raised if a file is not available.
+ *
+ * @see AdminSession::openServerStdOut
+ * @see AdminSession::openServerStdErr
+ * @see AdminSession::openNodeStdOut
+ * @see AdminSession::openNodeStdErr
+ * @see AdminSession::openRegistryStdOut
+ * @see AdminSession::openRegistryStdErr
+ *
+ **/
+exception FileNotAvailableException
+{
+ string reason;
+};
+
};
diff --git a/cpp/src/IceGrid/Activator.cpp b/cpp/src/IceGrid/Activator.cpp
index 62dd2c6920f..963d187f87d 100644
--- a/cpp/src/IceGrid/Activator.cpp
+++ b/cpp/src/IceGrid/Activator.cpp
@@ -256,7 +256,6 @@ stringToSignal(const string& str)
Activator::Activator(const TraceLevelsPtr& traceLevels, const PropertiesPtr& properties) :
_traceLevels(traceLevels),
- _properties(properties),
_deactivating(false)
{
#ifdef _WIN32
@@ -288,13 +287,10 @@ Activator::Activator(const TraceLevelsPtr& traceLevels, const PropertiesPtr& pro
fcntl(_fdIntrRead, F_SETFL, flags);
#endif
- _outputDir = _properties->getProperty("IceGrid.Node.Output");
- _redirectErrToOut = (_properties->getPropertyAsInt("IceGrid.Node.RedirectErrToOut") > 0);
-
//
// Parse the properties override property.
//
- string props = _properties->getProperty("IceGrid.Node.PropertiesOverride");
+ string props = properties->getProperty("IceGrid.Node.PropertiesOverride");
if(!props.empty())
{
string::size_type end = 0;
@@ -423,14 +419,6 @@ Activator::activate(const string& name,
args.insert(args.end(), options.begin(), options.end());
args.insert(args.end(), _propertiesOverride.begin(), _propertiesOverride.end());
- if(_outputDir.size() > 0)
- {
- string outFile = _outputDir + "/" + name + ".out";
- string errFile = _redirectErrToOut ? outFile : _outputDir + "/" + name + ".err";
- args.push_back("--Ice.StdOut=" + outFile);
- args.push_back("--Ice.StdErr=" + errFile);
- }
-
if(_traceLevels->activator > 0)
{
Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat);
diff --git a/cpp/src/IceGrid/Activator.h b/cpp/src/IceGrid/Activator.h
index fe2165070dd..750a1f7135d 100644
--- a/cpp/src/IceGrid/Activator.h
+++ b/cpp/src/IceGrid/Activator.h
@@ -75,7 +75,6 @@ private:
};
TraceLevelsPtr _traceLevels;
- Ice::PropertiesPtr _properties;
std::map<std::string, Process> _processes;
bool _deactivating;
@@ -88,9 +87,6 @@ private:
std::vector<std::string> _propertiesOverride;
- std::string _outputDir;
- bool _redirectErrToOut;
-
IceUtil::ThreadPtr _thread;
};
typedef IceUtil::Handle<Activator> ActivatorPtr;
diff --git a/cpp/src/IceGrid/AdminSessionI.cpp b/cpp/src/IceGrid/AdminSessionI.cpp
index de31ff90996..5fe3f014d5f 100644
--- a/cpp/src/IceGrid/AdminSessionI.cpp
+++ b/cpp/src/IceGrid/AdminSessionI.cpp
@@ -19,6 +19,35 @@
using namespace std;
using namespace IceGrid;
+FileIteratorI::FileIteratorI(const AdminSessionIPtr& session, const FileReaderPrx& reader, const string& filename) :
+ _session(session),
+ _reader(reader),
+ _filename(filename),
+ _offset(0)
+{
+}
+
+Ice::StringSeq
+FileIteratorI::read(int nlines, const Ice::Current& current)
+{
+ try
+ {
+ return _reader->readLines(_filename, _offset, nlines, _offset);
+ }
+ catch(const Ice::LocalException& ex)
+ {
+ ostringstream os;
+ os << ex;
+ throw FileNotAvailableException(os.str());
+ }
+}
+
+void
+FileIteratorI::destroy(const Ice::Current& current)
+{
+ _session->removeFileIterator(current.id, current);
+}
+
AdminSessionI::AdminSessionI(const string& id, const DatabasePtr& db, int timeout, const string& replicaName) :
BaseSessionI(id, "admin", db),
_timeout(timeout),
@@ -163,6 +192,74 @@ AdminSessionI::getReplicaName(const Ice::Current& current) const
return _replicaName;
}
+FileIteratorPrx
+AdminSessionI::openServerStdOut(const std::string& id, const Ice::Current& current)
+{
+ return addFileIterator(_database->getServer(id), "stdout", current);
+}
+
+FileIteratorPrx
+AdminSessionI::openServerStdErr(const std::string& id, const Ice::Current& current)
+{
+ return addFileIterator(_database->getServer(id), "stderr", current);
+}
+
+FileIteratorPrx
+AdminSessionI::openNodeStdOut(const std::string& name, const Ice::Current& current)
+{
+ return addFileIterator(_database->getNode(name), "stdout", current);
+}
+
+FileIteratorPrx
+AdminSessionI::openNodeStdErr(const std::string& name, const Ice::Current& current)
+{
+ return addFileIterator(_database->getNode(name), "stderr", current);
+}
+
+FileIteratorPrx
+AdminSessionI::openRegistryStdOut(const std::string& name, const Ice::Current& current)
+{
+ FileReaderPrx reader;
+ if(name == _replicaName)
+ {
+ Ice::Identity internalRegistryId;
+ internalRegistryId.category = _database->getInstanceName();
+ internalRegistryId.name = "InternalRegistry-" + _replicaName;
+
+ Ice::CommunicatorPtr communicator = current.adapter->getCommunicator();
+ string proxyStr = communicator->identityToString(internalRegistryId);
+ reader = FileReaderPrx::uncheckedCast(communicator->stringToProxy(proxyStr));
+ }
+ else
+ {
+ reader = _database->getReplica(name);
+ }
+
+ return addFileIterator(reader, "stdout", current);
+}
+
+FileIteratorPrx
+AdminSessionI::openRegistryStdErr(const std::string& name, const Ice::Current& current)
+{
+ FileReaderPrx reader;
+ if(name == _replicaName)
+ {
+ Ice::Identity internalRegistryId;
+ internalRegistryId.category = _database->getInstanceName();
+ internalRegistryId.name = "InternalRegistry-" + _replicaName;
+
+ Ice::CommunicatorPtr communicator = current.adapter->getCommunicator();
+ string proxyStr = communicator->identityToString(internalRegistryId);
+ reader = FileReaderPrx::uncheckedCast(communicator->stringToProxy(proxyStr));
+ }
+ else
+ {
+ reader = _database->getReplica(name);
+ }
+
+ return addFileIterator(reader, "stderr", current);
+}
+
void
AdminSessionI::destroy(const Ice::Current& current)
{
@@ -190,6 +287,28 @@ AdminSessionI::destroy(const Ice::Current& current)
}
//
+ // Unregister the iterators from the session servant locator or
+ // object adapter.
+ //
+ for(set<Ice::Identity>::const_iterator p = _iterators.begin(); p != _iterators.end(); ++p)
+ {
+ if(_servantLocator)
+ {
+ _servantLocator->remove(*p);
+ }
+ else if(current.adapter)
+ {
+ try
+ {
+ current.adapter->remove(*p);
+ }
+ catch(const Ice::LocalException&)
+ {
+ }
+ }
+ }
+
+ //
// Unsubscribe from the topics.
//
if(current.adapter) // Not shutting down
@@ -335,3 +454,49 @@ AdminSessionI::toProxy(const Ice::Identity& id, const Ice::ConnectionPtr& connec
{
return id.name.empty() ? Ice::ObjectPrx() : connection->createProxy(id);
}
+
+FileIteratorPrx
+AdminSessionI::addFileIterator(const FileReaderPrx& reader, const string& filename, const Ice::Current& current)
+{
+ Lock sync(*this);
+ if(_destroyed)
+ {
+ Ice::ObjectNotExistException ex(__FILE__, __LINE__);
+ ex.id = current.id;
+ throw ex;
+ }
+
+ Ice::ObjectPrx obj;
+ Ice::ObjectPtr servant = new FileIteratorI(this, reader, filename);
+ if(_servantLocator)
+ {
+ obj = _servantLocator->add(servant, current.con);
+ }
+ else
+ {
+ obj = current.adapter->addWithUUID(servant);
+ }
+ _iterators.insert(obj->ice_getIdentity());
+ return FileIteratorPrx::uncheckedCast(obj);
+}
+
+void
+AdminSessionI::removeFileIterator(const Ice::Identity& id, const Ice::Current& current)
+{
+ Lock sync(*this);
+ if(_servantLocator)
+ {
+ _servantLocator->remove(id);
+ }
+ else
+ {
+ try
+ {
+ current.adapter->remove(id);
+ }
+ catch(const Ice::LocalException&)
+ {
+ }
+ }
+ _iterators.erase(id);
+}
diff --git a/cpp/src/IceGrid/AdminSessionI.h b/cpp/src/IceGrid/AdminSessionI.h
index ea03e1d3828..df7802cf960 100644
--- a/cpp/src/IceGrid/AdminSessionI.h
+++ b/cpp/src/IceGrid/AdminSessionI.h
@@ -13,6 +13,7 @@
#include <IceGrid/SessionI.h>
#include <IceGrid/Topics.h>
#include <IceGrid/ReapThread.h>
+#include <IceGrid/Internal.h>
namespace IceGrid
{
@@ -20,6 +21,9 @@ namespace IceGrid
class RegistryI;
typedef IceUtil::Handle<RegistryI> RegistryIPtr;
+class FileIteratorI;
+typedef IceUtil::Handle<FileIteratorI> FileIteratorIPtr;
+
class AdminSessionI : public BaseSessionI, public AdminSession
{
public:
@@ -37,24 +41,37 @@ public:
const AdapterObserverPrx&, const ObjectObserverPrx&, const Ice::Current&);
virtual void setObserversByIdentity(const Ice::Identity&, const Ice::Identity&, const Ice::Identity&,
- const Ice::Identity&, const Ice::Identity&, const Ice::Current&);
+ const Ice::Identity&, const Ice::Identity&, const Ice::Current&);
virtual int startUpdate(const Ice::Current&);
virtual void finishUpdate(const Ice::Current&);
virtual std::string getReplicaName(const Ice::Current&) const;
+ virtual FileIteratorPrx openServerStdOut(const std::string&, const Ice::Current&);
+ virtual FileIteratorPrx openServerStdErr(const std::string&, const Ice::Current&);
+
+ virtual FileIteratorPrx openNodeStdOut(const std::string&, const Ice::Current&);
+ virtual FileIteratorPrx openNodeStdErr(const std::string&, const Ice::Current&);
+
+ virtual FileIteratorPrx openRegistryStdOut(const std::string&, const Ice::Current&);
+ virtual FileIteratorPrx openRegistryStdErr(const std::string&, const Ice::Current&);
+
virtual void destroy(const Ice::Current&);
+ void removeFileIterator(const Ice::Identity&, const Ice::Current&);
+
private:
void setupObserverSubscription(TopicName, const Ice::ObjectPrx&);
Ice::ObjectPrx toProxy(const Ice::Identity&, const Ice::ConnectionPtr&);
+ FileIteratorPrx addFileIterator(const FileReaderPrx&, const std::string&, const Ice::Current&);
const int _timeout;
const AdminPrx _admin;
const std::string _replicaName;
std::map<TopicName, Ice::ObjectPrx> _observers;
+ std::set<Ice::Identity> _iterators;
};
typedef IceUtil::Handle<AdminSessionI> AdminSessionIPtr;
@@ -106,6 +123,23 @@ private:
const AdminSessionFactoryPtr _factory;
};
+class FileIteratorI : public FileIterator
+{
+public:
+
+ FileIteratorI(const AdminSessionIPtr&, const FileReaderPrx&, const std::string&);
+
+ virtual Ice::StringSeq read(int, const Ice::Current&);
+ virtual void destroy(const Ice::Current&);
+
+private:
+
+ AdminSessionIPtr _session;
+ FileReaderPrx _reader;
+ std::string _filename;
+ Ice::Long _offset;
+};
+
};
#endif
diff --git a/cpp/src/IceGrid/Client.cpp b/cpp/src/IceGrid/Client.cpp
index 329d12dc2ab..6d9cb1ae053 100644
--- a/cpp/src/IceGrid/Client.cpp
+++ b/cpp/src/IceGrid/Client.cpp
@@ -406,7 +406,7 @@ Client::run(int argc, char* argv[])
}
}
- ParserPtr p = Parser::createParser(communicator(), admin);
+ ParserPtr p = Parser::createParser(communicator(), session, admin);
int status = EXIT_SUCCESS;
diff --git a/cpp/src/IceGrid/Grammar.y b/cpp/src/IceGrid/Grammar.y
index f91caf80862..4b708aba0d3 100644
--- a/cpp/src/IceGrid/Grammar.y
+++ b/cpp/src/IceGrid/Grammar.y
@@ -71,6 +71,9 @@ yyerror(const char* s)
%token ICE_GRID_SERVICE
%token ICE_GRID_ENABLE
%token ICE_GRID_DISABLE
+%token ICE_GRID_DUMP
+%token ICE_GRID_STDERR
+%token ICE_GRID_STDOUT
%%
@@ -167,6 +170,14 @@ command
{
parser->listAllNodes();
}
+| ICE_GRID_NODE ICE_GRID_DUMP ICE_GRID_STDERR optional_strings ';'
+{
+ parser->dumpFile("node", "stderr", $4);
+}
+| ICE_GRID_NODE ICE_GRID_DUMP ICE_GRID_STDOUT optional_strings ';'
+{
+ parser->dumpFile("node", "stdout", $4);
+}
| ICE_GRID_REGISTRY ICE_GRID_DESCRIBE optional_strings ';'
{
parser->describeRegistry($3);
@@ -183,6 +194,14 @@ command
{
parser->listAllRegistries();
}
+| ICE_GRID_REGISTRY ICE_GRID_DUMP ICE_GRID_STDERR optional_strings ';'
+{
+ parser->dumpFile("registry", "stderr", $4);
+}
+| ICE_GRID_REGISTRY ICE_GRID_DUMP ICE_GRID_STDOUT optional_strings ';'
+{
+ parser->dumpFile("registry", "stdout", $4);
+}
| ICE_GRID_SERVER ICE_GRID_REMOVE optional_strings ';'
{
parser->removeServer($3);
@@ -235,6 +254,14 @@ command
{
parser->listAllServers();
}
+| ICE_GRID_SERVER ICE_GRID_DUMP ICE_GRID_STDERR optional_strings ';'
+{
+ parser->dumpFile("server", "stderr", $4);
+}
+| ICE_GRID_SERVER ICE_GRID_DUMP ICE_GRID_STDOUT optional_strings ';'
+{
+ parser->dumpFile("server", "stdout", $4);
+}
| ICE_GRID_ADAPTER ICE_GRID_ENDPOINTS optional_strings ';'
{
parser->endpointsAdapter($3);
diff --git a/cpp/src/IceGrid/Internal.ice b/cpp/src/IceGrid/Internal.ice
index 4820c2de6ed..90764b0b8d9 100644
--- a/cpp/src/IceGrid/Internal.ice
+++ b/cpp/src/IceGrid/Internal.ice
@@ -97,7 +97,18 @@ exception AdapterExistsException
dictionary<string, Adapter*> AdapterPrxDict;
-interface Server
+interface FileReader
+{
+ /**
+ *
+ * Read and return up to count lines at the specified position.
+ *
+ **/
+ ["cpp:const"] idempotent Ice::StringSeq readLines(string filename, long pos, int count, out long newPos)
+ throws FileNotAvailableException;
+};
+
+interface Server extends FileReader
{
/**
*
@@ -181,7 +192,7 @@ interface Server
interface InternalRegistry;
sequence<InternalRegistry*> InternalRegistryPrxSeq;
-interface Node
+interface Node extends FileReader
{
/**
*
@@ -422,7 +433,7 @@ interface ReplicaSession
void destroy();
};
-interface InternalRegistry
+interface InternalRegistry extends FileReader
{
/**
*
diff --git a/cpp/src/IceGrid/InternalRegistryI.cpp b/cpp/src/IceGrid/InternalRegistryI.cpp
index bdf24718a8f..4a6d55347fd 100644
--- a/cpp/src/IceGrid/InternalRegistryI.cpp
+++ b/cpp/src/IceGrid/InternalRegistryI.cpp
@@ -18,6 +18,7 @@
#include <IceGrid/NodeSessionI.h>
#include <IceGrid/ReplicaSessionI.h>
#include <IceGrid/ReplicaSessionManager.h>
+#include <IceGrid/FileCache.h>
using namespace std;
using namespace IceGrid;
@@ -98,6 +99,7 @@ InternalRegistryI::InternalRegistryI(const RegistryIPtr& registry,
_database(database),
_reaper(reaper),
_wellKnownObjects(wellKnownObjects),
+ _fileCache(new FileCache()),
_session(session)
{
Ice::PropertiesPtr properties = database->getCommunicator()->getProperties();
@@ -183,3 +185,32 @@ InternalRegistryI::shutdown(const Ice::Current& current) const
{
_registry->shutdown();
}
+
+Ice::StringSeq
+InternalRegistryI::readLines(const string& filename, Ice::Long pos, int count, Ice::Long& newPos,
+ const Ice::Current&) const
+{
+ string file;
+ if(filename == "stderr")
+ {
+ file = _database->getCommunicator()->getProperties()->getProperty("Ice.StdErr");
+ if(file.empty())
+ {
+ throw FileNotAvailableException("Ice.StdErr configuration property is not set");
+ }
+ }
+ else if(filename == "stdout")
+ {
+ file = _database->getCommunicator()->getProperties()->getProperty("Ice.StdOut");
+ if(file.empty())
+ {
+ throw FileNotAvailableException("Ice.StdOut configuration property is not set");
+ }
+ }
+ else
+ {
+ throw FileNotAvailableException("unknown file");
+ }
+
+ return _fileCache->read(file, pos, count, newPos);
+}
diff --git a/cpp/src/IceGrid/InternalRegistryI.h b/cpp/src/IceGrid/InternalRegistryI.h
index fd30e1b4baa..a9585b3668d 100644
--- a/cpp/src/IceGrid/InternalRegistryI.h
+++ b/cpp/src/IceGrid/InternalRegistryI.h
@@ -19,6 +19,9 @@ namespace IceGrid
class Database;
typedef IceUtil::Handle<Database> DatabasePtr;
+class FileCache;
+typedef IceUtil::Handle<FileCache> FileCachePtr;
+
class WellKnownObjectsManager;
typedef IceUtil::Handle<WellKnownObjectsManager> WellKnownObjectsManagerPtr;
@@ -49,12 +52,15 @@ public:
virtual void shutdown(const Ice::Current&) const;
+ virtual Ice::StringSeq readLines(const std::string&, Ice::Long, int, Ice::Long&, const Ice::Current&) const;
+
private:
const RegistryIPtr _registry;
const DatabasePtr _database;
const ReapThreadPtr _reaper;
const WellKnownObjectsManagerPtr _wellKnownObjects;
+ const FileCachePtr _fileCache;
ReplicaSessionManager& _session;
int _nodeSessionTimeout;
int _replicaSessionTimeout;
diff --git a/cpp/src/IceGrid/Makefile b/cpp/src/IceGrid/Makefile
index 5ef247a4158..b582b2d3d14 100644
--- a/cpp/src/IceGrid/Makefile
+++ b/cpp/src/IceGrid/Makefile
@@ -46,6 +46,7 @@ COMMON_OBJS = Internal.o \
DescriptorParser.o \
DescriptorBuilder.o \
TraceLevels.o \
+ FileCache.o \
PlatformInfo.o
NODE_OBJS = NodeI.o \
diff --git a/cpp/src/IceGrid/NodeI.cpp b/cpp/src/IceGrid/NodeI.cpp
index 8c08d9b38bb..d787583ed3e 100644
--- a/cpp/src/IceGrid/NodeI.cpp
+++ b/cpp/src/IceGrid/NodeI.cpp
@@ -190,18 +190,22 @@ NodeI::NodeI(const Ice::ObjectAdapterPtr& adapter,
_traceLevels(traceLevels),
_name(name),
_proxy(proxy),
+ _redirectErrToOut(false),
_waitTime(0),
_userAccountMapper(mapper),
- _serial(1),
- _platform("IceGrid.Node", _communicator, _traceLevels)
+ _platform("IceGrid.Node", _communicator, _traceLevels),
+ _fileCache(new FileCache()),
+ _serial(1)
{
- _dataDir = _platform.getDataDir();
- _serversDir = _dataDir + "/servers";
- _tmpDir = _dataDir + "/tmp";
-
Ice::PropertiesPtr properties = _communicator->getProperties();
+
+ const_cast<string&>(_dataDir) = _platform.getDataDir();
+ const_cast<string&>(_serversDir) = _dataDir + "/servers";
+ const_cast<string&>(_tmpDir) = _dataDir + "/tmp";
const_cast<string&>(_instanceName) = _communicator->getDefaultLocator()->ice_getIdentity().category;
const_cast<Ice::Int&>(_waitTime) = properties->getPropertyAsIntWithDefault("IceGrid.Node.WaitTime", 60);
+ const_cast<string&>(_outputDir) = properties->getProperty("IceGrid.Node.Output");
+ const_cast<bool&>(_redirectErrToOut) = properties->getPropertyAsInt("IceGrid.Node.RedirectErrToOut") > 0;
}
NodeI::~NodeI()
@@ -510,6 +514,34 @@ NodeI::shutdown(const Ice::Current&) const
_activator->shutdown();
}
+Ice::StringSeq
+NodeI::readLines(const string& filename, Ice::Long pos, int count, Ice::Long& newPos, const Ice::Current&) const
+{
+ string file;
+ if(filename == "stderr")
+ {
+ file = _communicator->getProperties()->getProperty("Ice.StdErr");
+ if(file.empty())
+ {
+ throw FileNotAvailableException("Ice.StdErr configuration property is not set");
+ }
+ }
+ else if(filename == "stdout")
+ {
+ file = _communicator->getProperties()->getProperty("Ice.StdOut");
+ if(file.empty())
+ {
+ throw FileNotAvailableException("Ice.StdOut configuration property is not set");
+ }
+ }
+ else
+ {
+ throw FileNotAvailableException("unknown file");
+ }
+
+ return _fileCache->read(file, pos, count, newPos);
+}
+
void
NodeI::destroy()
{
@@ -553,6 +585,30 @@ NodeI::getUserAccountMapper() const
return _userAccountMapper;
}
+PlatformInfo&
+NodeI::getPlatformInfo() const
+{
+ return _platform;
+}
+
+FileCachePtr
+NodeI::getFileCache() const
+{
+ return _fileCache;
+}
+
+string
+NodeI::getOutputDir() const
+{
+ return _outputDir;
+}
+
+bool
+NodeI::getRedirectErrToOut() const
+{
+ return _redirectErrToOut;
+}
+
NodeSessionPrx
NodeI::registerWithRegistry(const InternalRegistryPrx& registry)
{
diff --git a/cpp/src/IceGrid/NodeI.h b/cpp/src/IceGrid/NodeI.h
index f10d86627fa..d1d1db2b3f6 100644
--- a/cpp/src/IceGrid/NodeI.h
+++ b/cpp/src/IceGrid/NodeI.h
@@ -10,12 +10,13 @@
#ifndef ICE_GRID_NODE_I_H
#define ICE_GRID_NODE_I_H
+#include <IcePatch2/FileServer.h>
+
#include <IceGrid/Internal.h>
#include <IceGrid/WaitQueue.h>
#include <IceGrid/PlatformInfo.h>
#include <IceGrid/UserAccountMapper.h>
-
-#include <IcePatch2/FileServer.h>
+#include <IceGrid/FileCache.h>
namespace IceGrid
{
@@ -54,6 +55,8 @@ public:
virtual LoadInfo getLoad(const Ice::Current& = Ice::Current()) const;
virtual void shutdown(const Ice::Current&) const;
+ virtual Ice::StringSeq readLines(const std::string&, Ice::Long, int, Ice::Long&, const Ice::Current&) const;
+
void destroy();
WaitQueuePtr getWaitQueue() const;
@@ -62,7 +65,11 @@ public:
ActivatorPtr getActivator() const;
TraceLevelsPtr getTraceLevels() const;
UserAccountMapperPrx getUserAccountMapper() const;
- PlatformInfo& getPlatformInfo() const { return _platform; }
+ PlatformInfo& getPlatformInfo() const;
+ FileCachePtr getFileCache() const;
+
+ std::string getOutputDir() const;
+ bool getRedirectErrToOut() const;
NodeSessionPrx registerWithRegistry(const InternalRegistryPrx&);
void checkConsistency(const NodeSessionPrx&);
@@ -93,18 +100,23 @@ private:
const TraceLevelsPtr _traceLevels;
const std::string _name;
const NodePrx _proxy;
+ const std::string _outputDir;
+ const bool _redirectErrToOut;
const Ice::Int _waitTime;
const std::string _instanceName;
const UserAccountMapperPrx _userAccountMapper;
- std::string _dataDir;
- std::string _serversDir;
- std::string _tmpDir;
+ mutable PlatformInfo _platform;
+ const std::string _dataDir;
+ const std::string _serversDir;
+ const std::string _tmpDir;
+ const FileCachePtr _fileCache;
+
unsigned long _serial;
+
IceUtil::Mutex _observerMutex;
std::map<NodeSessionPrx, NodeObserverPrx> _observers;
std::map<std::string, ServerDynamicInfo> _serversDynamicInfo;
std::map<std::string, AdapterDynamicInfo> _adaptersDynamicInfo;
- mutable PlatformInfo _platform;
IceUtil::Mutex _serversLock;
std::map<std::string, std::set<ServerIPtr> > _serversByApplication;
diff --git a/cpp/src/IceGrid/Parser.cpp b/cpp/src/IceGrid/Parser.cpp
index 4af1b7e7649..f2166371add 100644
--- a/cpp/src/IceGrid/Parser.cpp
+++ b/cpp/src/IceGrid/Parser.cpp
@@ -41,9 +41,9 @@ Parser* parser;
}
ParserPtr
-Parser::createParser(const CommunicatorPtr& communicator, const AdminPrx& admin)
+Parser::createParser(const CommunicatorPtr& communicator, const AdminSessionPrx& session, const AdminPrx& admin)
{
- return new Parser(communicator, admin);
+ return new Parser(communicator, session, admin);
}
void
@@ -81,8 +81,17 @@ Parser::usage()
"node describe NAME Show information about node NAME.\n"
"node ping NAME Ping node NAME.\n"
"node load NAME Print the load of the node NAME.\n"
+ "node dump stderr NAME Dump node NAME stderr.\n"
+ "node dump stdout NAME Dump node NAME stdout.\n"
"node shutdown NAME Shutdown node NAME.\n"
"\n"
+ "registry list List all registered registrys.\n"
+ "registry describe NAME Show information about registry NAME.\n"
+ "registry ping NAME Ping registry NAME.\n"
+ "registry dump stderr NAME Dump registry NAME stderr.\n"
+ "registry dump stdout NAME Dump registry NAME stdout.\n"
+ "registry shutdown NAME Shutdown registry NAME.\n"
+ "\n"
"server list List all registered servers.\n"
"server remove ID Remove server ID.\n"
"server describe ID Describe server ID.\n"
@@ -94,6 +103,8 @@ Parser::usage()
"server signal ID SIGNAL Send SIGNAL (e.g. SIGTERM or 15) to server ID.\n"
"server stdout ID MESSAGE Write MESSAGE on server ID's stdout.\n"
"server stderr ID MESSAGE Write MESSAGE on server ID's stderr.\n"
+ "server dump stderr ID Dump server ID stderr.\n"
+ "server dump stdout ID Dump server ID stdout.\n"
"server enable ID Enable server ID.\n"
"server disable ID Disable server ID (a disabled server can't be\n"
" started on demand or administratively).\n"
@@ -1243,6 +1254,203 @@ Parser::shutdown()
}
void
+Parser::dumpFile(const string& reader, const string& filename, const list<string>& origArgs)
+{
+ list<string> copyArgs = origArgs;
+ copyArgs.push_front("icegridadmin");
+
+ IceUtil::Options opts;
+ opts.addOpt("f", "follow");
+ opts.addOpt("h", "head", IceUtil::Options::NeedArg); //, "20"); // TODO: Fix
+ opts.addOpt("t", "tail", IceUtil::Options::NeedArg); //, "20"); // TODO: Fix
+
+ vector<string> args;
+ try
+ {
+ for(list<string>::const_iterator p = copyArgs.begin(); p != copyArgs.end(); ++p)
+ {
+ args.push_back(*p);
+ }
+ args = opts.parse(args);
+ }
+ catch(const IceUtil::BadOptException& e)
+ {
+ error(e.reason);
+ return;
+ }
+
+ if(args.size() != 1)
+ {
+ invalidCommand("`" + reader + " dump " + filename + "' requires one argument");
+ return;
+ }
+
+ try
+ {
+ string id = *(args.begin());
+ FileIteratorPrx it;
+ if(reader == "node")
+ {
+ if(filename == "stderr")
+ {
+ it = _session->openNodeStdErr(id);
+ }
+ else if(filename == "stdout")
+ {
+ it = _session->openNodeStdOut(id);
+ }
+ }
+ else if(reader == "registry")
+ {
+ if(filename == "stderr")
+ {
+ it = _session->openRegistryStdErr(id);
+ }
+ else if(filename == "stdout")
+ {
+ it = _session->openRegistryStdOut(id);
+ }
+ }
+ else if(reader == "server")
+ {
+ if(filename == "stderr")
+ {
+ it = _session->openServerStdErr(id);
+ }
+ else if(filename == "stdout")
+ {
+ it = _session->openServerStdOut(id);
+ }
+ }
+
+ cout << reader << " `" << id << "' " << filename << ":" << flush;
+ Ice::StringSeq lines;
+
+ bool head = opts.isSet("head");
+ bool tail = opts.isSet("tail");
+ if(head && tail)
+ {
+ invalidCommand("can't specify both -h | --head and -t | --tail options");
+ return;
+ }
+ int lineCount = 20;
+ if(head || tail)
+ {
+ istringstream is(head ? opts.optArg("head") : opts.optArg("tail"));
+ is >> lineCount;
+ if(lineCount <= 0)
+ {
+ invalidCommand("invalid argument for -h | --head or -t | --tail option");
+ return;
+ }
+ }
+
+ bool follow = opts.isSet("follow");
+ if(head)
+ {
+ if(follow)
+ {
+ invalidCommand("can't use -f | --follow option with -h | --head option");
+ return;
+ }
+
+ int i = 0;
+ while(true)
+ {
+ lines = it->read(20);
+
+ Ice::StringSeq::const_iterator p = lines.begin();
+ while(i < lineCount && p != lines.end())
+ {
+ cout << endl << *p++ << flush;
+ ++i;
+ }
+
+ if(i == lineCount || lines.size() < 20)
+ {
+ break;
+ }
+ }
+ }
+ else if(tail)
+ {
+ deque<string> lastLines;
+ while(true)
+ {
+ lines = it->read(20);
+
+ copy(lines.begin(), lines.end(), back_inserter(lastLines));
+ int remove = lastLines.size() - lineCount;
+ if(remove > 0)
+ {
+ lastLines.erase(lastLines.begin(), lastLines.begin() + remove);
+ assert(lastLines.size() == lineCount);
+ }
+
+ if(lines.size() < 20)
+ {
+ break;
+ }
+ }
+
+ for(deque<string>::const_iterator p = lastLines.begin(); p != lastLines.end(); ++p)
+ {
+ cout << endl << *p << flush;
+ }
+ }
+ else
+ {
+ while(true)
+ {
+ lines = it->read(20);
+ for(Ice::StringSeq::const_iterator p = lines.begin(); p != lines.end(); ++p)
+ {
+ cout << endl << *p << flush;
+ }
+
+ if(lines.size() < 20)
+ {
+ break;
+ }
+ }
+ }
+
+ if(follow)
+ {
+ while(true)
+ {
+ lines = it->read(20);
+ for(Ice::StringSeq::const_iterator p = lines.begin(); p != lines.end(); ++p)
+ {
+ cout << *p;
+ if((p + 1) != lines.end())
+ {
+ cout << endl;
+ }
+ else
+ {
+ cout << flush;
+ }
+ }
+
+ IceUtil::ThreadControl::sleep(IceUtil::Time::seconds(2));
+ }
+ }
+
+ if(lines.empty() || !lines.back().empty())
+ {
+ cout << endl;
+ }
+
+ it->destroy();
+ }
+ catch(const Ice::Exception& ex)
+ {
+ exception(ex);
+ }
+}
+
+void
Parser::showBanner()
{
cout << "Ice " << ICE_STRING_VERSION << " Copyright 2003-2006 ZeroC, Inc." << endl;
@@ -1585,8 +1793,9 @@ Parser::parse(const std::string& commands, bool debug)
return status;
}
-Parser::Parser(const CommunicatorPtr& communicator, const AdminPrx& admin) :
+Parser::Parser(const CommunicatorPtr& communicator, const AdminSessionPrx& session, const AdminPrx& admin) :
_communicator(communicator),
+ _session(session),
_admin(admin)
{
}
@@ -1651,6 +1860,10 @@ Parser::exception(const Ice::Exception& ex)
{
error("couldn't update the registry, the session from `" + ex.lockUserId + "' is updating the registry");
}
+ catch(const FileNotAvailableException& ex)
+ {
+ error("couldn't access file:\n" + ex.reason);
+ }
catch(const IceXML::ParserException& ex)
{
ostringstream s;
diff --git a/cpp/src/IceGrid/Parser.h b/cpp/src/IceGrid/Parser.h
index 49756672298..3e800be4d96 100644
--- a/cpp/src/IceGrid/Parser.h
+++ b/cpp/src/IceGrid/Parser.h
@@ -66,7 +66,7 @@ class Parser : public ::IceUtil::SimpleShared
{
public:
- static ParserPtr createParser(const Ice::CommunicatorPtr&, const IceGrid::AdminPrx&);
+ static ParserPtr createParser(const Ice::CommunicatorPtr&, const AdminSessionPrx&, const AdminPrx&);
void usage();
@@ -117,6 +117,8 @@ public:
void shutdown();
+ void dumpFile(const std::string&, const std::string&, const std::list<std::string>&);
+
void showBanner();
void showCopying();
void showWarranty();
@@ -141,12 +143,13 @@ public:
private:
- Parser(const Ice::CommunicatorPtr&, const IceGrid::AdminPrx&);
+ Parser(const Ice::CommunicatorPtr&, const AdminSessionPrx&, const AdminPrx&);
void exception(const Ice::Exception&);
std::string _commands;
Ice::CommunicatorPtr _communicator;
- IceGrid::AdminPrx _admin;
+ AdminSessionPrx _session;
+ AdminPrx _admin;
bool _continue;
int _errors;
int _currentLine;
diff --git a/cpp/src/IceGrid/Scanner.l b/cpp/src/IceGrid/Scanner.l
index d40bbafe415..6bee04e066e 100644
--- a/cpp/src/IceGrid/Scanner.l
+++ b/cpp/src/IceGrid/Scanner.l
@@ -204,6 +204,10 @@ NL [\n]
return ICE_GRID_SHOW;
}
+"dump" {
+ return ICE_GRID_DUMP;
+}
+
"copying" {
return ICE_GRID_COPYING;
}
diff --git a/cpp/src/IceGrid/ServerI.cpp b/cpp/src/IceGrid/ServerI.cpp
index 05c6125ad9a..e64801fc89e 100644
--- a/cpp/src/IceGrid/ServerI.cpp
+++ b/cpp/src/IceGrid/ServerI.cpp
@@ -776,6 +776,31 @@ ServerI::setProcess_async(const AMD_Server_setProcessPtr& amdCB, const Ice::Proc
}
}
+Ice::StringSeq
+ServerI::readLines(const string& filename, Ice::Long pos, int count, Ice::Long& newPos, const Ice::Current&) const
+{
+ if(filename == "stderr")
+ {
+ if(_stdErrFile.empty())
+ {
+ throw FileNotAvailableException("Ice.StdErr configuration property is not set");
+ }
+ return _node->getFileCache()->read(_stdErrFile, pos, count, newPos);
+ }
+ else if(filename == "stdout")
+ {
+ if(_stdOutFile.empty())
+ {
+ throw FileNotAvailableException("Ice.StdOut configuration property is not set");
+ }
+ return _node->getFileCache()->read(_stdOutFile, pos, count, newPos);
+ }
+ else
+ {
+ throw FileNotAvailableException("unknown file");
+ }
+}
+
bool
ServerI::isAdapterActivatable(const string& id, int& timeout) const
{
@@ -2421,6 +2446,17 @@ ServerI::updateConfigFile(const string& serverDir, const CommunicatorDescriptorP
copy(svrDesc->propertySet.properties.begin(), svrDesc->propertySet.properties.end(), back_inserter(props));
//
+ // Add Ice.StdOut, Ice.StdErr if necessary.
+ //
+ string outputDir = _node->getOutputDir();
+ if(!outputDir.empty())
+ {
+ props.push_back(createProperty("Ice.StdOut", outputDir + "/" + _id + ".out"));
+ string suffix = _node->getRedirectErrToOut() ? ".out" : ".err";
+ props.push_back(createProperty("Ice.StdErr", outputDir + "/" + _id + suffix));
+ }
+
+ //
// Add service properties.
//
string servicesStr;
@@ -2496,6 +2532,18 @@ ServerI::updateConfigFile(const string& serverDir, const CommunicatorDescriptorP
{
configfile << r->name << "=" << r->value << endl;
}
+
+ //
+ // Cache the standard output/error file name.
+ //
+ if(r->name == "Ice.StdErr")
+ {
+ _stdErrFile = r->value;
+ }
+ else if(r->name == "Ice.StdOut")
+ {
+ _stdOutFile = r->value;
+ }
}
configfile.close();
}
diff --git a/cpp/src/IceGrid/ServerI.h b/cpp/src/IceGrid/ServerI.h
index 8412d1598a5..38b21d67933 100644
--- a/cpp/src/IceGrid/ServerI.h
+++ b/cpp/src/IceGrid/ServerI.h
@@ -83,6 +83,8 @@ public:
virtual bool isEnabled(const ::Ice::Current& = Ice::Current()) const;
virtual void setProcess_async(const AMD_Server_setProcessPtr&, const ::Ice::ProcessPrx&, const ::Ice::Current&);
+ virtual Ice::StringSeq readLines(const std::string&, Ice::Long, int, Ice::Long&, const Ice::Current&) const;
+
bool isAdapterActivatable(const std::string&, int&) const;
const std::string& getId() const;
DistributionDescriptor getDistribution() const;
@@ -154,6 +156,8 @@ private:
ServerActivation _previousActivation;
WaitItemPtr _timer;
bool _waitForReplication;
+ std::string _stdErrFile;
+ std::string _stdOutFile;
DestroyCommandPtr _destroy;
StopCommandPtr _stop;