libzypp 17.31.32
PluginExecutor.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
11#include <iostream>
12#include <zypp/base/LogTools.h>
13#include <zypp/base/NonCopyable.h>
14
15#include <zypp/ZConfig.h>
16#include <zypp/PathInfo.h>
17#include <zypp/PluginExecutor.h>
18
19using std::endl;
20
21#undef ZYPP_BASE_LOGGER_LOGGROUP
22#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::plugin"
23
25namespace zypp
26{
32 {
33 public:
35 {}
36
38 {
39 if ( ! empty() )
40 send( PluginFrame( "PLUGINEND" ) );
41 // ~PluginScript will disconnect all remaining plugins!
42 }
43
44 bool empty() const
45 { return _scripts.empty(); }
46
47 size_t size() const
48 { return _scripts.size(); }
49
50 void load( const Pathname & path_r )
51 {
53 DBG << "+++++++++++++++ load " << pi << endl;
54 if ( pi.isDir() )
55 {
56 std::list<Pathname> entries;
57 if ( filesystem::readdir( entries, pi.path(), false ) != 0 )
58 {
59 WAR << "Plugin dir is not readable: " << pi << endl;
60 return;
61 }
62 for_( it, entries.begin(), entries.end() )
63 {
64 PathInfo pii( *it );
65 if ( pii.isFile() && pii.userMayRX() )
66 doLoad( pii );
67 }
68 }
69 else if ( pi.isFile() )
70 {
71 if ( pi.userMayRX() )
72 doLoad( pi );
73 else
74 WAR << "Plugin file is not executable: " << pi << endl;
75 }
76 else
77 {
78 WAR << "Plugin path is neither dir nor file: " << pi << endl;
79 }
80 DBG << "--------------- load " << pi << endl;
81 }
82
83 void send( const PluginFrame & frame_r )
84 {
85 DBG << "+++++++++++++++ send " << frame_r << endl;
86 for ( auto it = _scripts.begin(); it != _scripts.end(); )
87 {
88 doSend( *it, frame_r );
89 if ( it->isOpen() )
90 ++it;
91 else
92 it = _scripts.erase( it );
93 }
94 DBG << "--------------- send " << frame_r << endl;
95 }
96
97 const std::list<PluginScript> scripts() const
98 { return _scripts; }
99
100 private:
102 void doLoad( const PathInfo & pi_r )
103 {
104 MIL << "Load plugin: " << pi_r << endl;
105 try {
106 PluginScript plugin( pi_r.path() );
107 plugin.open();
108
109 PluginFrame frame( "PLUGINBEGIN" );
110 if ( ZConfig::instance().hasUserData() )
111 frame.setHeader( "userdata", ZConfig::instance().userData() );
112
113 doSend( plugin, frame ); // closes on error
114 if ( plugin.isOpen() )
115 _scripts.push_back( plugin );
116 }
117 catch( const zypp::Exception & e )
118 {
119 WAR << "Failed to load plugin " << pi_r << endl;
120 }
121 }
122
124 {
126
127 try {
128 script_r.send( frame_r );
129 ret = script_r.receive();
130 }
131 catch( const zypp::Exception & e )
132 {
133 ZYPP_CAUGHT(e);
134 WAR << e.asUserHistory() << endl;
135 }
136
137 // Allow using "/bin/cat" as reflector-script for testing
138 if ( ! ( ret.isAckCommand() || ret.isEnomethodCommand() || ( script_r.script() == "/bin/cat" && frame_r.command() != "ERROR" ) ) )
139 {
140 WAR << "Bad plugin response from " << script_r << ": " << ret << endl;
141 WAR << "(Expected " << PluginFrame::ackCommand() << " or " << PluginFrame::enomethodCommand() << ")" << endl;
142 script_r.close();
143 }
144
145 return ret;
146 }
147 private:
148 std::list<PluginScript> _scripts;
149 };
150
152 //
153 // CLASS NAME : PluginExecutor
154 //
156
158 : _pimpl( new Impl() )
159 {}
160
163
165 { return _pimpl->empty(); }
166
167 size_t PluginExecutor::size() const
168 { return _pimpl->size(); }
169
171 { _pimpl->load( path_r ); }
172
174 { _pimpl->send( frame_r ); }
175
176 std::ostream & operator<<( std::ostream & str, const PluginExecutor & obj )
177 { return str << obj._pimpl->scripts(); }
178
179} // namespace zypp
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:94
shared_ptr< Impl > _pimpl
Base class for Exception.
Definition Exception.h:146
PluginExecutor implementation.
PluginFrame doSend(PluginScript &script_r, const PluginFrame &frame_r)
void doLoad(const PathInfo &pi_r)
Launch a plugin sending PLUGINSTART message.
std::list< PluginScript > _scripts
const std::list< PluginScript > scripts() const
void send(const PluginFrame &frame_r)
void load(const Pathname &path_r)
Parallel execution of stateful PluginScripts.
RW_pointer< Impl > _pimpl
Implementation class.
void load(const Pathname &path_r)
Find and launch plugins sending PLUGINBEGIN.
size_t size() const
Number of open plugins.
PluginExecutor()
Default ctor: Empty plugin list.
void send(const PluginFrame &frame_r)
Send PluginFrame to all open plugins.
~PluginExecutor()
Dtor: Send PLUGINEND and close all plugins.
bool empty() const
Whether no plugins are waiting.
Command frame for communication with PluginScript.
Definition PluginFrame.h:41
static const std::string & ackCommand()
"ACK" command.
static const std::string & enomethodCommand()
"_ENOMETHOD" command.
Interface to plugin scripts using a Stomp inspired communication protocol.
static ZConfig & instance()
Singleton ctor.
Definition ZConfig.cc:922
Wrapper class for stat/lstat.
Definition PathInfo.h:221
String related utilities and Regular expression matching.
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition NonCopyable.h:26
int readdir(std::list< std::string > &retlist_r, const Pathname &path_r, bool dots_r)
Return content of directory via retlist.
Definition PathInfo.cc:605
Easy-to use interface to the ZYPP dependency resolver.
std::ostream & operator<<(std::ostream &str, const SerialNumber &obj)
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:28
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition Exception.h:436
#define DBG
Definition Logger.h:95
#define MIL
Definition Logger.h:96
#define WAR
Definition Logger.h:97