pvAccessCPP  7.1.5
server.h
1 /*
2  * Copyright information and license terms for this software can be
3  * found in the file LICENSE that is included with the distribution
4  */
5 #ifndef PVA_SERVER_H
6 #define PVA_SERVER_H
7 
8 #include <string>
9 #include <vector>
10 #include <map>
11 
12 #include <shareLib.h>
13 #include <pv/sharedPtr.h>
14 #include <pv/sharedVector.h>
15 
16 namespace epics{namespace pvAccess{
17 class ChannelProvider;
18 class Channel;
19 class ChannelRequester;
20 struct PeerInfo; // see pv/security.h
21 }} // epics::pvAccess
22 
23 //! See @ref pvas API
24 namespace pvas {
25 
26 /** @addtogroup pvas Server API
27  *
28  * PVA Server Providers, for use with a PVA epics::pvAccess::ServerContext
29  *
30  * These are implementations of epics::pvAccess::ChannelProvider which manage "PVs",
31  * which are sources of epics::pvAccess::Channel instances. Typically SharedPV .
32  *
33  * Two containers are provided StaticProvider, and for some special cases DynamicProvider.
34  * It is recommended to use StaticProvider where possible, with DynamicProvider for exception cases.
35  *
36  * A StaticProvider maintains an internal lookup table of StaticProvider::ChannelBuilder (aka. SharedPV).
37  * This table is manipulated by StaticProvider::add() and StaticProvider::remove(), which can
38  * be called at any time.
39  *
40  * A DynamicProvider does not maintain an internal lookup table. Instead it provides
41  * the DynamicProvider::Handler interface, through which remote search and connection
42  * requests are delivered.
43  *
44  * See @ref examples_mailbox for a working example.
45  *
46  @code
47  namespace pva = epics::pvAccess;
48  pvas::SharedPV::shared_pointer pv(pvas::SharedPV::buildMailbox());
49  pvas::StaticProvider sprov("arbitrary");
50  pva::ServerContext::shared_pointer server(
51  pva::ServerContext::create(
52  pva::ServerContext::Config() .provider(sprov.provider()) ));
53  sprov->add("pv:name", pv);
54  @endcode
55  *
56  * @section pvas_sharedptr Server API shared_ptr Ownership
57  *
58  * shared_ptr<> relationships internal to server API classes.
59  * Solid red lines are shared_ptr<>.
60  * Dashed red lines are shared_ptr<> which may exist safely in user code.
61  * Rectangles are public API classes. Circles are internal classes.
62  * "ChannelProvider" is an arbitrary ChannelProvider, possibly StaticProvider or DynamicProvider.
63  *
64  @dot "Internal shared_ptr<> relationships.
65  digraph sspv {
66  SharedPV [shape="box"];
67  SharedPVHandler [label="SharedPV::Handler", shape="box"];
68  SharedChannel [shape="ellipse"];
69  ChannelOp [label="SharedPut/RPC/MonitorFIFO", shape="ellipse"];
70 
71  DynamicProvider [shape="box"];
72  DynamicHandler [label="DynamicProvider::Handler", shape="box"];
73  StaticProvider [shape="ellipse"];
74 
75  ChannelRequester [shape="ellipse"];
76  ChannelProvider [shape="box"];
77 
78  ServerContext [shape="box"];
79 
80  ChannelProvider -> SharedPV [color="red", style="dashed"];
81  DynamicProvider -> DynamicHandler [color="red"];
82  StaticProvider -> SharedPV [color="red"];
83  ServerContext -> ChannelProvider [color="red"];
84  ServerContext -> DynamicProvider [color="red"];
85  ServerContext -> StaticProvider [color="red"];
86  ServerContext -> ChannelRequester [color="red"];
87  ServerContext -> SharedChannel [color="red"];
88  ServerContext -> ChannelOp [color="red"];
89  SharedPV -> SharedPVHandler [color="red"];
90  SharedChannel -> SharedPV [color="red"];
91  ChannelOp -> SharedChannel [color="red"];
92  }
93  @enddot
94  *
95  * @{
96  */
97 
98 /** @brief A Provider based on a list of SharedPV instance.
99  *
100  * SharedPV instances may be added/removed at any time. So it is only "static"
101  * in the sense that the list of PV names is known to StaticProvider at all times.
102  *
103  * @see @ref pvas_sharedptr
104  */
105 class epicsShareClass StaticProvider {
106 public:
107  POINTER_DEFINITIONS(StaticProvider);
108  struct Impl;
109 private:
110  std::tr1::shared_ptr<Impl> impl; // const after ctor
111 public:
112 
113  //! Interface for something which can provide Channels. aka A "PV". Typically a SharedPV
114  struct epicsShareClass ChannelBuilder {
115  POINTER_DEFINITIONS(ChannelBuilder);
116  virtual ~ChannelBuilder();
117  //! called to create a new Channel through the given ChannelProvider
118  virtual std::tr1::shared_ptr<epics::pvAccess::Channel> connect(const std::tr1::shared_ptr<epics::pvAccess::ChannelProvider>& provider,
119  const std::string& name,
120  const std::tr1::shared_ptr<epics::pvAccess::ChannelRequester>& requester) =0;
121  //! Disconnect all Channels created through the given ChannelProvider.
122  //! destroy==true if the ChannelProvider is shutting down.
123  virtual void disconnect(bool destroy, const epics::pvAccess::ChannelProvider* provider) =0;
124  };
125 private:
126  typedef std::map<std::string, std::tr1::shared_ptr<ChannelBuilder> > builders_t;
127 public:
128  typedef builders_t::const_iterator const_iterator;
129 
130  //! Build a new, empty, provider.
131  //! @param name Provider Name. Only relevant if registerAsServer() is called, then must be unique in this process.
132  explicit StaticProvider(const std::string& name);
133  ~StaticProvider();
134 
135  //! Call Channelbuilder::close(destroy) for all currently added ChannelBuilders.
136  //! @see SharedPV::close()
137  //! @note Provider locking rules apply (@see provider_roles_requester_locking).
138  void close(bool destroy=false);
139 
140  //! Add a PV (eg. SharedPV) to this provider.
141  void add(const std::string& name,
142  const std::tr1::shared_ptr<ChannelBuilder>& builder);
143  //! Remove a PV. Closes any open Channels to it.
144  //! @returns the PV which has been removed.
145  //! @note Provider locking rules apply (@see provider_roles_requester_locking).
146  std::tr1::shared_ptr<ChannelBuilder> remove(const std::string& name);
147 
148  //! Fetch the underlying ChannelProvider. Usually to build a ServerContext around.
149  std::tr1::shared_ptr<epics::pvAccess::ChannelProvider> provider() const;
150 
151  // iterate through currently add()'d PVs. Iteraters are invalidated by concurrent add() or remove()
152  const_iterator begin() const;
153  const_iterator end() const;
154 };
155 
156 /** @brief A Provider which has no pre-configured list of names.
157  *
158  * Through an associated Handler, this provider sees all searchs, and may claim
159  * them.
160  *
161  * @see @ref pvas_sharedptr
162  */
163 class epicsShareClass DynamicProvider {
164 public:
165  POINTER_DEFINITIONS(DynamicProvider);
166  struct Impl;
167 private:
168  std::tr1::shared_ptr<Impl> impl; // const after ctor
169 public:
170  //! A single client serach request. May be associated with more than one name
171  class Search {
172  friend struct Impl;
173  bool isclaimed;
174  std::string cname;
175  const ::epics::pvAccess::PeerInfo* peerinfo;
176  Search(const std::string& name, const ::epics::pvAccess::PeerInfo* peer)
177  :isclaimed(false),cname(name),peerinfo(peer)
178  {}
179  public:
180  //! The name being queried
181  const std::string& name() const { return cname; }
182  //! Stake a claim.
183  bool claimed() const { return isclaimed; }
184  //! Has been claimed()
185  void claim() { isclaimed = true; }
186  //! Information about peer making search request.
187  //! May be NULL if not information is available.
188  //! @since >7.1.0
189  const ::epics::pvAccess::PeerInfo* peer() const { return peerinfo; }
190  };
191  typedef std::vector<Search> search_type;
192 
193  /** Callbacks associated with DynamicProvider.
194  *
195  * For the purposes of locking, this class is a Requester (see @ref provider_roles_requester_locking).
196  * It's methods will not be called with locks held. It may call
197  * methods which lock.
198  */
199  struct epicsShareClass Handler {
200  POINTER_DEFINITIONS(Handler);
201  typedef epics::pvData::shared_vector<std::string> names_type;
202  virtual ~Handler() {}
203  //! Called with name(s) which some client is searching for
204  virtual void hasChannels(search_type& name) =0;
205  //! Called when a client is requesting a list of channel names we provide. Callee should set dynamic=false if this list is exhaustive.
206  virtual void listChannels(names_type& names, bool& dynamic) {}
207  //! Called when a client is attempting to open a new channel to this SharedPV
208  virtual std::tr1::shared_ptr<epics::pvAccess::Channel> createChannel(const std::tr1::shared_ptr<epics::pvAccess::ChannelProvider>& provider,
209  const std::string& name,
210  const std::tr1::shared_ptr<epics::pvAccess::ChannelRequester>& requester) =0;
211  //! Called when the last reference to a DynamicProvider is released. Should close any channels.
212  virtual void destroy() {}
213  };
214 
215  //! Build a new provider.
216  //! @param name Provider Name. Only relevant if registerAsServer() is called, then must be unique in this process.
217  //! @param handler Our callbacks. Internally stored a shared_ptr (strong reference).
218  DynamicProvider(const std::string& name,
219  const std::tr1::shared_ptr<Handler>& handler);
220  ~DynamicProvider();
221 
222  Handler::shared_pointer getHandler() const;
223 
224  //void close();
225 
226  //! Fetch the underlying ChannelProvider. Usually to build a ServerContext around.
227  std::tr1::shared_ptr<epics::pvAccess::ChannelProvider> provider() const;
228 };
229 
230 //! @}
231 
232 } // namespace pvas
233 
234 #endif // PVA_SERVER_H
A Provider based on a list of SharedPV instance.
Definition: server.h:105
A Provider which has no pre-configured list of names.
Definition: server.h:163