#include "plaqui/server/plant.h"
#include <glibmm/timer.h>
-#include <sigc++/slot.h>
+#include <sigc++/class_slot.h>
+#include <fstream>
#ifdef DEBUG
# include <iostream>
#endif // DEBUG
Plant::~Plant(void) {
#ifdef DEBUG
- cerr << __FILE__ << ": destructor." << endl;
+ cerr << __FILE__ << "(" << __LINE__ << ")"
+ << ": destructor." << endl;
#endif // DEBUG
- // Termino transmisiones.
- Glib::Mutex::Lock lock(transmissions_mutex);
- for (TransmitterList::iterator trans = transmissions.end();
+ // Mando a terminar todas las transmisiones.
+ transmissions_mutex.lock();
+ for (TransmitterList::iterator trans = transmissions.begin();
trans != transmissions.end(); trans++) {
- (*trans)->finish(true);
+ (*trans)->finish();
+ }
+ TransmitterList::size_type count = transmissions.size();
+ transmissions_mutex.unlock();
+ // Espero que terminen realmente.
+ while (count) {
+ Glib::usleep(10000); // 10 milisegundos
+ transmissions_mutex.lock();
+ count = transmissions.size();
+ transmissions_mutex.unlock();
}
}
-Plant::Plant(const string& filename): simulator(filename) {
+Plant::Plant(const string& filename): simulator(filename), filename(filename),
+ wait_time(DEFAULT_WAIT_TIME), paused(true) {
#ifdef DEBUG
- cerr << __FILE__ << ": constructor. filename = " << filename << endl;
+ cerr << __FILE__ << "(" << __LINE__ << ")"
+ << ": constructor. filename = " << filename << endl;
#endif // DEBUG
- // TODO plant
- simulator.add_pump("bomba1");
- simulator.add_conduct("c");
- simulator.add_conduct("c1");
- simulator.add_drainage("d");
- simulator.add_tank("tanque");
-
- simulator.connect("bomba1", "c", Model::IConector::OUT);
- simulator.connect("c", "tanque", Model::IConector::OUT);
- simulator.connect("tanque", "c1", Model::IConector::OUT);
- simulator.connect("c1", "d", Model::IConector::OUT);
-
}
-void Plant::real_run(void) {
+void Plant::real_run(void) throw() {
#ifdef DEBUG
- cerr << __FILE__ << ": real_run." << endl;
+ cerr << __FILE__ << "(" << __LINE__ << ")"
+ << ": real_run." << endl;
#endif // DEBUG
- while (!stop) {
- simulator.simulate();
- Glib::Mutex::Lock lock(transmissions_mutex);
- for (TransmitterList::iterator i = transmissions.begin();
- i != transmissions.end(); i++) {
- (*i)->send(simulator.get_state_as_xml());
+ unsigned wait;
+ while (!stop()) {
+ if (paused) { // Si está pausada, espera un tiempo sin simular.
+ Glib::usleep(DEFAULT_WAIT_TIME);
+ } else { // Si está andando, simula y manda estado.
+ simulator_mutex.lock();
+ simulator.simulate();
+ string plantstatus = simulator.get_state_as_xml();
+ simulator_mutex.unlock();
+ transmissions_mutex.lock();
+ for (TransmitterList::iterator i = transmissions.begin();
+ i != transmissions.end(); i++) {
+ (*i)->send(plantstatus);
+ }
+ transmissions_mutex.unlock();
+ wait_time_mutex.lock();
+ wait = wait_time;
+ wait_time_mutex.unlock();
+ Glib::usleep(wait);
}
- Glib::usleep(1000000);
}
}
-bool Plant::transmission_start(const string& host,
- const Connection::Port& port) {
+bool Plant::transmission_start(string& host, Connection::Port& port) {
+#ifdef DEBUG
+ cerr << __FILE__ << "(" << __LINE__ << ")"
+ << ": transmission_start(host = " << host <<
+ ", port = " << port << ")." << endl;
+#endif // DEBUG
Glib::Mutex::Lock lock(transmissions_mutex);
for (TransmitterList::iterator i = transmissions.begin();
i != transmissions.end(); i++) {
if (((*i)->get_host() == host) && ((*i)->get_port() == port)) {
+#ifdef DEBUG
+ cerr << __FILE__ << "(" << __LINE__ << ")"
+ << ": transmission_start ERROR: ya existe."
+ << endl;
+#endif // DEBUG
return false;
}
}
Transmitter* trans;
try {
trans = new Transmitter(host, port);
- } catch (...) { // TODO - Hace mas selectivo el catch?
- delete trans;
+ } catch (const sockerr& e) {
+#ifdef DEBUG
+ cerr << __FILE__ << "(" << __LINE__ << ")"
+ << ": transmission_start ERROR (" << e.serrno()
+ << "): " << e.errstr() << endl;
+#endif // DEBUG
return false;
}
transmissions.push_back(trans);
+ trans->signal_finished().connect(SigC::bind(
+ SigC::slot_class(*this, &Plant::on_transmission_finished),
+ trans));
trans->run();
+ host = trans->get_host();
+ port = trans->get_port();
return true;
}
bool Plant::transmission_stop(const string& host,
const Connection::Port& port) {
+#ifdef DEBUG
+ cerr << __FILE__ << "(" << __LINE__ << ")"
+ << ": transmission_stop(host = " << host <<
+ ", port = " << port << ")." << endl;
+#endif // DEBUG
Glib::Mutex::Lock lock(transmissions_mutex);
for (TransmitterList::iterator i = transmissions.begin();
i != transmissions.end(); i++) {
return false; // No la encontró.
}
-/*
-bool Plant::transmission_exists(const string& host,
- const Connection::Port& port) {
+void Plant::on_transmission_finished(Transmitter* transmission) {
+#ifdef DEBUG
+ cerr << __FILE__ << "(" << __LINE__ << ")"
+ << ": on_transmission_finished(transmission = "
+ << transmission << ")" << endl;
+#endif // DEBUG
Glib::Mutex::Lock lock(transmissions_mutex);
+ transmissions.remove(transmission);
+#ifdef DEBUG
+ cerr << __FILE__ << "(" << __LINE__ << ")"
+ << ": lista de conexiones" << endl;
for (TransmitterList::const_iterator i = transmissions.begin();
i != transmissions.end(); i++) {
- if (((*i)->get_host() == host) && ((*i)->get_oprt() == port)) {
- return true;
- }
+ cerr << "\t " << *i << endl;
}
- return false; // No la encontró.
+#endif // DEBUG
+}
+
+bool Plant::set_open(const std::string& element, bool open) {
+#ifdef DEBUG
+ cerr << __FILE__ << "(" << __LINE__ << ")"
+ << ": set_open(element = " << element <<
+ ", open = " << open << ")." << endl;
+#endif // DEBUG
+ Glib::Mutex::Lock lock(simulator_mutex);
+ return simulator.set_open(element, open);
}
-*/
-//const std::string& Plant::get_name(void) const {
-// return name;
-//}
+const string Plant::get_xml(void) const {
+#ifdef DEBUG
+ cerr << __FILE__ << "(" << __LINE__ << ")"
+ << ": get_xml()." << endl;
+#endif // DEBUG
+ ostringstream oss;
+ ifstream ifs(filename.c_str());
+ // FIXME Saco la línea de definición de XML (<?xml ?>), ver si esta hecho muy
+ // feo.
+ ifs.ignore(50, '\n'); // Ignora 50 caracteres o hasta un enter.
+ ifs >> oss.rdbuf();
+ return oss.str();
+}
-/// \todo FIXME esto deberia estar protegido por un mutex.
-//Plant::SignalUpdated& Plant::signal_updated(void) {
-// return updated;
-//}
+void Plant::set_frequency(unsigned hz) {
+ Glib::Mutex::Lock lock(wait_time_mutex);
+ wait_time = hz ? (1000000u/hz) : DEFAULT_WAIT_TIME;
+}
+
+void Plant::set_paused(bool paused_) {
+ Glib::Mutex::Lock lock(paused_mutex);
+ paused = paused_;
+}
} // namespace Server