Fawkes API  Fawkes Development Version
openprs_inifin.cpp
1 
2 /***************************************************************************
3  * openprs_inifin.cpp - Fawkes OpenPRSAspect initializer/finalizer
4  *
5  * Created: Mon Aug 18 15:32:20 2014
6  * Copyright 2014 Tim Niemueller [www.niemueller.de]
7  ****************************************************************************/
8 
9 /* This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version. A runtime exception applies to
13  * this software (see LICENSE.GPL_WRE file mentioned below for details).
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
21  */
22 
23 #include <plugins/openprs/aspect/openprs_inifin.h>
24 #include <plugins/openprs/aspect/openprs_kernel_manager.h>
25 #include <plugins/openprs/utils/openprs_comm.h>
26 #include <plugins/openprs/utils/openprs_server_proxy.h>
27 #include <core/threading/thread_finalizer.h>
28 #include <utils/time/time.h>
29 #include <unistd.h>
30 
31 namespace fawkes {
32 #if 0 /* just to make Emacs auto-indent happy */
33 }
34 #endif
35 
36 /** @class OpenPRSAspectIniFin <plugins/openprs/aspect/openprs_inifin.h>
37  * OpenPRSAspect initializer/finalizer.
38  * This initializer/finalizer will provide the OpenPRS node handle to
39  * threads with the OpenPRSAspect.
40  * @author Tim Niemueller
41  */
42 
43 /** Constructor. */
45  : AspectIniFin("OpenPRSAspect")
46 {
47  openprs_comm_ = NULL;
48  // conservative default, better wait a little longer than fail
49  kernel_timeout_sec_ = 30.;
50 }
51 
52 /** Destructor. */
54 {
55  delete openprs_comm_;
56 }
57 
58 
59 
60 void
62 {
63  OpenPRSAspect *openprs_thread;
64  openprs_thread = dynamic_cast<OpenPRSAspect *>(thread);
65  if (openprs_thread == NULL) {
66  throw CannotInitializeThreadException("Thread '%s' claims to have the "
67  "OpenPRSAspect, but RTTI says it "
68  "has not. ", thread->name());
69  }
70 
71  openprs_kernel_mgr_->create_kernel(openprs_thread->openprs_kernel_name,
72  openprs_thread->openprs_kernel_mode == OpenPRSAspect::XOPRS,
73  openprs_thread->openprs_data_paths_,
74  openprs_thread->openprs_gdb_delay_);
75 
76  try {
77  openprs_thread->openprs = new OpenPRSComm(openprs_thread->openprs_local_name.c_str(),
78  openprs_kernel_mgr_->mp_host().c_str(),
79  openprs_kernel_mgr_->mp_port(),
80  openprs_server_proxy_);
81  } catch (Exception &e) {
82  openprs_kernel_mgr_->destroy_kernel(openprs_thread->openprs_kernel_name);
83  throw;
84  }
85 
86  fawkes::Time now, start;
87  while (! openprs_server_proxy_->has_kernel(openprs_thread->openprs_kernel_name)) {
88  now.stamp();
89  if ((now - &start) > kernel_timeout_sec_) {
90  openprs_kernel_mgr_->destroy_kernel(openprs_thread->openprs_kernel_name);
91  throw Exception("OpenPRSAspect: timeout waiting for kernel startup");
92  }
93  usleep(100000);
94  }
95 
96  openprs_comm_->transmit_command_f(openprs_thread->openprs_kernel_name,
97  "add (! (= @@FAWKES_MOD_DIR \"%s\"))", OPENPRS_MOD_DIR);
98  openprs_comm_->transmit_command_f(openprs_thread->openprs_kernel_name,
99  "add (! (= @@FAWKES_HOST \"%s\"))", fawkes_host_.c_str());
100  openprs_comm_->transmit_command_f(openprs_thread->openprs_kernel_name,
101  "add (! (= @@FAWKES_PORT \"%u\"))", fawkes_port_);
102  openprs_comm_->transmit_command_f(openprs_thread->openprs_kernel_name,
103  "declare symbol %s",
104  openprs_thread->openprs_local_name.c_str());
105  openprs_comm_->transmit_command_f(openprs_thread->openprs_kernel_name,
106  "add (! (= @@FAWKES_MP_NAME %s))",
107  openprs_thread->openprs_local_name.c_str());
108 
109  usleep(200000);
110 }
111 
112 void
114 {
115  OpenPRSAspect *openprs_thread;
116  openprs_thread = dynamic_cast<OpenPRSAspect *>(thread);
117  if (openprs_thread == NULL) {
118  throw CannotFinalizeThreadException("Thread '%s' claims to have the "
119  "OpenPRSAspect, but RTTI says it "
120  "has not. ", thread->name());
121  }
122 
123  openprs_kernel_mgr_->destroy_kernel(openprs_thread->openprs_kernel_name);
124  openprs_thread->finalize_OpenPRSAspect();
125 }
126 
127 
128 /** Prepare OpenPRS aspect initializer.
129  * @param fawkes_host Hostname where Fawkes is running
130  * @param fawkes_port TCP port where Fawkes listens on
131  * @param openprs_kernel_mgr OpenPRS kernel manager
132  * @param openprs_server_proxy OpenPRS server proxy
133  * @param openprs_mp_proxy OpenPRS Message Passer proxy
134  */
135 void
136 OpenPRSAspectIniFin::prepare(const std::string &fawkes_host, unsigned short fawkes_port,
137  LockPtr<OpenPRSKernelManager> &openprs_kernel_mgr,
138  OpenPRSServerProxy *openprs_server_proxy,
139  OpenPRSMessagePasserProxy *openprs_mp_proxy)
140 {
141  fawkes_host_ = fawkes_host;
142  fawkes_port_ = fawkes_port;
143  openprs_kernel_mgr_ = openprs_kernel_mgr;
144  openprs_server_proxy_ = openprs_server_proxy;
145  openprs_mp_proxy_ = openprs_mp_proxy;
146 
147  openprs_comm_ = new OpenPRSComm("OpenPRSAspect",
148  openprs_kernel_mgr_->mp_host().c_str(),
149  openprs_kernel_mgr_->mp_port(),
150  openprs_server_proxy_);
151 }
152 
153 
154 /** Set timeout for kernel creation.
155  * @param timeout_sec timeout in seconds after which kernel creation
156  * is assumed to have failed.
157  */
158 void
160 {
161  kernel_timeout_sec_ = timeout_sec;
162 }
163 
164 } // end namespace fawkes
const std::string openprs_local_name
The local message passer name for communication.
Definition: openprs.h:60
virtual void init(Thread *thread)
Initialize thread.
Proxy for the OpenPRS server communication.
virtual void finalize(Thread *thread)
Finalize thread.
OpenPRS communication wrapper.
Definition: openprs_comm.h:41
Fawkes library namespace.
const std::string openprs_kernel_name
The name of the kernel created for this thread.
Definition: openprs.h:58
A class for handling time.
Definition: time.h:91
Thread class encapsulation of pthreads.
Definition: thread.h:42
OpenPRSAspectIniFin()
Constructor.
OpenPRS kernel creation and communication aspect.
Definition: openprs.h:39
LockPtr<> is a reference-counting shared lockable smartpointer.
Definition: lockptr.h:57
graphical mode
Definition: openprs.h:47
Thread cannot be initialized.
Base class for exceptions in Fawkes.
Definition: exception.h:36
const char * name() const
Get name of thread.
Definition: thread.h:95
void prepare(const std::string &fawkes_host, unsigned short fawkes_port, LockPtr< OpenPRSKernelManager > &openprs_kernel_mgr, OpenPRSServerProxy *openprs_server_proxy, OpenPRSMessagePasserProxy *openprs_mp_proxy)
Prepare OpenPRS aspect initializer.
bool has_kernel(const std::string &kernel_name)
Check if a kernel connected to the proxy.
LockPtr< OpenPRSComm > openprs
OpenPRS kernel communication wrapper.
Definition: openprs.h:57
void transmit_command_f(const std::string &recipient, const char *format,...)
Transmit a command to an OpenPRS kernel.
Thread cannot be finalized.
void set_kernel_timeout(float timeout_sec)
Set timeout for kernel creation.
Time & stamp()
Set this time to the current time.
Definition: time.cpp:783
const Mode openprs_kernel_mode
The kernel mode, can be OPRS or XOPRS (with graphical interface).
Definition: openprs.h:59
Proxy for the OpenPRS server communication.
Aspect initializer/finalizer base class.
Definition: inifin.h:36