[rygel/wip/basic-management: 13/49] core: Implement BasicManagement NSLookup, improve BMTest
- From: Jussi Kukkonen <jussik src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rygel/wip/basic-management: 13/49] core: Implement BasicManagement NSLookup, improve BMTest
- Date: Wed, 23 Oct 2013 13:14:04 +0000 (UTC)
commit 91e1f1807a5a1a5083dac1edd7a9312944d44b38
Author: Jussi Kukkonen <jku heimdall>
Date: Thu May 30 16:07:30 2013 +0300
core: Implement BasicManagement NSLookup, improve BMTest
configure.ac | 2 +-
src/librygel-core/Makefile.am | 1 +
src/librygel-core/rygel-basic-management.vala | 65 +++---
src/librygel-core/rygel-bm-test-nslookup.vala | 321 ++++++++++++++++++-----
src/librygel-core/rygel-bm-test-ping.vala | 8 -
src/librygel-core/rygel-bm-test-traceroute.vala | 8 -
src/librygel-core/rygel-bm-test.vala | 152 ++++++++++-
7 files changed, 439 insertions(+), 118 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index a460a80..f0f4fbc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -60,7 +60,7 @@ VALAFLAGS="--target-glib=2.32 $VALAFLAGS"
RYGEL_BASE_MODULES="gupnp-1.0 >= $GUPNP_REQUIRED gee-0.8 >= $GEE_REQUIRED"
PKG_CHECK_MODULES([LIBRYGEL_CORE_DEPS], [$RYGEL_BASE_MODULES uuid >= $UUID_REQUIRED gssdp-1.0 >=
$GSSDP_REQUIRED gio-2.0 >= $GIO_REQUIRED gmodule-2.0 libxml-2.0 >= $LIBXML_REQUIRED])
RYGEL_BASE_MODULES_VALAFLAGS='--pkg gupnp-1.0 --pkg gee-0.8'
-LIBRYGEL_CORE_DEPS_VALAFLAGS="$RYGEL_BASE_MODULES_VALAFLAGS --pkg gssdp-1.0 --pkg gio-2.0 --pkg gmodule-2.0"
+LIBRYGEL_CORE_DEPS_VALAFLAGS="$RYGEL_BASE_MODULES_VALAFLAGS --pkg gssdp-1.0 --pkg gio-2.0 --pkg gmodule-2.0
--pkg posix"
AC_SUBST([LIBRYGEL_CORE_DEPS_VALAFLAGS])
RYGEL_COMMON_MODULES="$RYGEL_BASE_MODULES gupnp-av-1.0 >= $GUPNP_AV_REQUIRED"
diff --git a/src/librygel-core/Makefile.am b/src/librygel-core/Makefile.am
index 64194f4..eaca37a 100644
--- a/src/librygel-core/Makefile.am
+++ b/src/librygel-core/Makefile.am
@@ -15,6 +15,7 @@ librygel_core_2_0_la_VALAFLAGS = \
-H rygel-core.h -C --library=rygel-core-2.0 \
--vapidir=$(srcdir) \
--pkg uuid \
+ --pkg posix \
$(LIBRYGEL_CORE_DEPS_VALAFLAGS) \
$(RYGEL_COMMON_VALAFLAGS)
diff --git a/src/librygel-core/rygel-basic-management.vala b/src/librygel-core/rygel-basic-management.vala
index 2d67c01..984902a 100644
--- a/src/librygel-core/rygel-basic-management.vala
+++ b/src/librygel-core/rygel-basic-management.vala
@@ -86,7 +86,7 @@ public class Rygel.BasicManagement : Service {
(this.cancel_test_cb);
}
- private void add_test (BMTest bm_test) {
+ private void add_test_and_return_action (BMTest bm_test, ServiceAction action) {
current_id++;
bm_test.id = current_id.to_string ();
@@ -100,6 +100,22 @@ public class Rygel.BasicManagement : Service {
this.test_ids += "," + test.id;
}
}
+
+ /* TODO: decide if test should really execute now */
+
+ bm_test.execute.begin ((obj,res) => {
+ try {
+ bm_test.execute.end (res);
+ } catch (BMTestError e) {
+ /* already executing */
+ }
+ /* TODO Test is finished, now remove test from active test list */
+ });
+
+ action.set ("TestID",
+ typeof (string),
+ bm_test.id);
+ action.return ();
}
// Error out if 'TestID' is wrong
@@ -215,15 +231,7 @@ public class Rygel.BasicManagement : Service {
}
// test_id to be added to TestIDs and ActiveTestID
- this.add_test (ping as BMTest);
-
- ping.execute ();
-
- action.set ("TestID",
- typeof (string),
- ping.id);
-
- action.return ();
+ this.add_test_and_return_action (ping as BMTest, action);
}
private void ping_result_cb (Service cm,
@@ -302,23 +310,16 @@ public class Rygel.BasicManagement : Service {
typeof (string),
out interval_time_out);
+
BMTestNSLookup nslookup = new BMTestNSLookup();
- if (!nslookup.init (hostname, dns_server, repeat_count,
- interval_time_out)) {
- action.return_error (402, _("Invalid argument"));
+ try {
+ nslookup.init (hostname, dns_server,
+ repeat_count, interval_time_out);
- return;
+ this.add_test_and_return_action (nslookup as BMTest, action);
+ } catch (BMTestError e) {
+ action.return_error (402, _("Invalid argument"));
}
-
- this.add_test (nslookup as BMTest);
-
- nslookup.execute ();
-
- action.set ("TestID",
- typeof (string),
- nslookup.id);
-
- action.return ();
}
private void nslookup_result_cb (Service cm,
@@ -395,15 +396,7 @@ public class Rygel.BasicManagement : Service {
return;
}
- this.add_test (traceroute as BMTest);
-
- traceroute.execute ();
-
- action.set ("TestID",
- typeof (string),
- traceroute.id);
-
- action.return ();
+ this.add_test_and_return_action (traceroute as BMTest, action);
}
private void traceroute_result_cb (Service cm,
@@ -512,7 +505,11 @@ public class Rygel.BasicManagement : Service {
return;
}
- bm_test.cancel();
+ try {
+ bm_test.cancel();
+ } catch (BMTestError e) {
+ warning ("Canceled test was not running\n");
+ }
action.return ();
}
diff --git a/src/librygel-core/rygel-bm-test-nslookup.vala b/src/librygel-core/rygel-bm-test-nslookup.vala
index 6c0e8f9..46faab6 100644
--- a/src/librygel-core/rygel-bm-test-nslookup.vala
+++ b/src/librygel-core/rygel-bm-test-nslookup.vala
@@ -1,10 +1,8 @@
/*
- * Copyright (C) 2008 OpenedHand Ltd.
- * Copyright (C) 2008 Zeeshan Ali <zeenix gmail com>.
* Copyright (C) 2013 Intel Corporation.
*
- * Author: Jorn Baayen <jorn openedhand com>
- * Zeeshan Ali <zeenix gmail com>
+ * Author: Christophe Guiraud,
+ * Jussi Kukkonen
*
* This file is part of Rygel.
*
@@ -25,83 +23,286 @@
using GLib;
-// Helper class for BMTestNSLookup.
internal class Rygel.BMTestNSLookup : BMTest {
+ private const string HEADER =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<bms:NSLookupResult " +
+ "xmlns:bms=\"urn:schemas-upnp-org:dm:bms\" " +
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
+ "xsi:schemaLocation=\"" +
+ "urn:schemas-upnp-org:dm:bms " +
+ "http://www.upnp.org/schemas/dm/bms.xsd\">\n";
- private string hostname;
- private string dns_server;
- private uint repeat_count;
- private uint32 interval_time_out;
-
- private string status;
- private string additional_info;
- private uint success_count;
- private string result;
-
- private static const uint NSLOOKUP_MIN_REPEAT_COUNT = 1;
- private static const uint NSLOOKUP_MAX_REPEAT_COUNT = 100;
- private static const uint NSLOOKUP_DEFAULT_REPEAT_COUNT = 1;
- private static const uint NSLOOKUP_MIN_REQUEST_INTERVAL_TIMEOUT = 1000;
- private static const uint NSLOOKUP_MAX_REQUEST_INTERVAL_TIMEOUT = 30000;
- private static const uint NSLOOKUP_DEFAULT_REQUEST_INTERVAL_TIMEOUT = 10000;
- private static const uint NSLOOKUP_MAX_RESULT_ANSWER_STR_SIZE = 32;
- private static const uint NSLOOKUP_MAX_RESULT_NAME_STR_SIZE = 256;
- private static const uint NSLOOKUP_MAX_RESULT_IPS_STR_SIZE = 1024;
- private static const uint NSLOOKUP_MAX_RESULT_ARRAY_SIZE = 7;
+ private const string FOOTER = "</bms:NSLookupResult>\n";
- public BMTestNSLookup() {
- base("NSLookup");
+ private enum ProcessState {
+ INIT,
+ SERVER,
+ NAME,
}
- public override void execute() {
- stdout.printf("*NSLookup* execute()\n");
+ private enum GenericStatus {
+ SUCCESS,
+ ERROR_DNS_SERVER_NOT_RESOLVED,
+ ERROR_INTERNAL;
+
+ public string to_string() {
+ switch (this) {
+ case SUCCESS:
+ return "Success";
+ case ERROR_DNS_SERVER_NOT_RESOLVED:
+ return "Error_DNSServerNotResolved";
+ case ERROR_INTERNAL:
+ return "Error_Internal";
+ default:
+ assert_not_reached();
+ }
+ }
}
- public override void cancel() {
- stdout.printf("*NSLookup* cancel()\n");
+ private enum ResultStatus {
+ SUCCESS,
+ ERROR_DNS_SERVER_NOT_AVAILABLE,
+ ERROR_HOSTNAME_NOT_RESOLVED,
+ ERROR_TIMEOUT,
+ ERROR_OTHER;
+
+ public string to_string() {
+ switch (this) {
+ case SUCCESS:
+ return "Success";
+ case ERROR_DNS_SERVER_NOT_AVAILABLE:
+ return "Error_DNSServerNotAvailable";
+ case ERROR_HOSTNAME_NOT_RESOLVED:
+ return "Error_HostNameNotResolved";
+ case ERROR_TIMEOUT:
+ return "Error_Timeout";
+ case ERROR_OTHER:
+ return "Error_Other";
+ default:
+ assert_not_reached();
+ }
+ }
}
- public bool init(string hostname, string dns_server, uint repeat_count,
- uint32 interval_time_out) {
- stdout.printf("*NSLookup* init()\n");
+ private enum AnswerType {
+ NONE,
+ AUTHORITATIVE,
+ NON_AUTHORITATIVE;
- if (hostname == null) {
- return false;
+ public string to_string() {
+ switch (this) {
+ case NONE:
+ return "None";
+ case AUTHORITATIVE:
+ return "Authoritative";
+ case NON_AUTHORITATIVE:
+ return "NonAuthoritative";
+ default:
+ assert_not_reached();
+ }
}
+ }
- if (dns_server == null) {
- return false;
- }
+ /* TODO make sure all these are respected */
+ private static const uint MAX_REPEAT_COUNT = 100;
+ private static const uint MIN_INTERVAL_TIMEOUT = 1000;
+ private static const uint MAX_INTERVAL_TIMEOUT = 30000;
+ private static const uint MAX_RESULT_ANSWER_STR_SIZE = 32; // ?
+ private static const uint MAX_RESULT_NAME_STR_SIZE = 256; // ?
+ private static const uint MAX_RESULT_IPS_STR_SIZE = 1024; // length of addresses csv ?
+ private static const uint MAX_RESULT_ARRAY_SIZE = 7; // ?
+
+ private struct Result {
+ private ProcessState state;
+ private string name_server_address;
+ private string returned_host_name;
+ private string[] addresses;
+ private ResultStatus status;
+ private AnswerType answer_type;
+ uint execution_time;
- if (repeat_count == 0) {
- repeat_count = NSLOOKUP_DEFAULT_REPEAT_COUNT;
- } else if (repeat_count < NSLOOKUP_MIN_REPEAT_COUNT &&
- repeat_count > NSLOOKUP_MAX_REPEAT_COUNT) {
- return false;
+ private string get_addresses_csv () {
+ var builder = new StringBuilder ("");
+ foreach (var address in addresses) {
+ if (builder.len != 0)
+ builder.append (",");
+ builder.append (address);
+ }
+ return builder.str;
}
- if (interval_time_out == 0) {
- interval_time_out = NSLOOKUP_DEFAULT_REQUEST_INTERVAL_TIMEOUT;
- } else if (interval_time_out < NSLOOKUP_MIN_REQUEST_INTERVAL_TIMEOUT &&
- interval_time_out > NSLOOKUP_MAX_REQUEST_INTERVAL_TIMEOUT) {
- return false;
+ public string to_xml_fragment() {
+ /* TODO limit the returned values */
+
+ return ("<Result>\n" +
+ "<Status>%s</Status>\n" +
+ "<AnswerType>%s</AnswerType>\n" +
+ "<HostNameReturned>%s</HostNameReturned>\n" +
+ "<IPAddresses>%s</IPAddresses>\n" +
+ "<DNSServerIP>%s</DNSServerIP>\n" +
+ "<ResponseTime>%u</ResponseTime>\n" +
+ "</Result>\n").printf (this.status.to_string(),
+ this.answer_type.to_string(),
+ this.returned_host_name,
+ this.get_addresses_csv (),
+ this.name_server_address,
+ this.execution_time);
}
+ }
+
+ private Result[] results;
+ private GenericStatus generic_status;
+ private Timer timer = new Timer ();
+
+ public BMTestNSLookup() {
+ base("NSLookup");
+ }
+
+
+ public void init(string host_name, string? name_server, uint repetitions,
+ uint32 interval_time_out) throws BMTestError {
+ command = { "nslookup" };
+ generic_status = GenericStatus.ERROR_INTERNAL;
+ results = {};
+
+ /* TODO should invalid values fail now instead of just limit ? */
+ repetitions = uint.max (1, repetitions);
+ this.repetitions = uint.min (repetitions, MAX_REPEAT_COUNT);
+
+ interval_time_out = uint.max (MIN_INTERVAL_TIMEOUT, interval_time_out);
+ interval_time_out = uint.min (interval_time_out, MAX_INTERVAL_TIMEOUT);
+ command += ("-timeout=%u").printf (interval_time_out/1000);
+
+ if (host_name == null || host_name.length < 1)
+ throw new BMTestError.INIT_FAILED ("Host name is required");
+ command += host_name;
+
+ if (name_server != null && name_server.length > 0)
+ command += name_server;
- this.hostname = hostname;
- this.dns_server = dns_server;
- this.repeat_count = repeat_count;
- this.interval_time_out = interval_time_out;
+ }
+
+ protected override void init_iteration () {
+ base.init_iteration ();
+ var result = Result () {
+ state = ProcessState.INIT,
+ name_server_address = "",
+ returned_host_name = "",
+ addresses = {},
+ status = ResultStatus.ERROR_OTHER,
+ answer_type = AnswerType.NONE,
+ execution_time = 0
+ };
+ results += result;
+
+ timer.start ();
+ }
+
+ protected override void finish_iteration () {
+ var execution_time = (uint)Math.round(timer.elapsed (null) * 1000);
+ results[results.length - 1].execution_time = execution_time;
- return true;
+ base.finish_iteration ();
}
+ protected override void handle_output (string line) {
+ var result = results[results.length - 1];
+ line.strip();
+ if (line.has_prefix ("Server:")) {
+ if (result.state != ProcessState.INIT)
+ warning ("nslookup parser: Unexpected 'Server:' line.\n");
+ result.state = ProcessState.SERVER;
+ } else if (line.has_prefix ("Name:")) {
+ if (result.state == ProcessState.INIT)
+ warning ("nslookup parser: Unexpected 'Name:' line");
+ else if (result.state == ProcessState.SERVER)
+ result.returned_host_name = line.substring ("Name:".length).strip();
+ result.state = ProcessState.NAME;
+ } else if (line.has_prefix ("Address:")) {
+ if (result.state == ProcessState.SERVER) {
+ var address = line.substring ("Address:".length).strip();
+ result.name_server_address = address.split ("#", 2)[0];
+ generic_status = GenericStatus.SUCCESS;
+ } else if (result.state == ProcessState.NAME) {
+ result.addresses += line.substring ("Address:".length).strip();
+ result.status = ResultStatus.SUCCESS;
+ if (result.answer_type == AnswerType.NONE)
+ result.answer_type = AnswerType.AUTHORITATIVE;
+ } else
+ warning ("nslookup parser: Unexpected 'Address:' line");
+ } else if (line.has_prefix ("Non-authoritative answer:")) {
+ result.answer_type = AnswerType.NON_AUTHORITATIVE;
+ } else if (line.contains ("server can't find")) {
+ result.status = ResultStatus.ERROR_HOSTNAME_NOT_RESOLVED;
+ } else if (line.contains ("couldn't get address for")) {
+ generic_status = GenericStatus.ERROR_DNS_SERVER_NOT_RESOLVED;
+ result.status = ResultStatus.ERROR_DNS_SERVER_NOT_AVAILABLE;
+ /* TODO should cancel here: future iterations won't help */
+ } else if (line.contains ("no servers could be reached")) {
+ result.status = ResultStatus.ERROR_DNS_SERVER_NOT_AVAILABLE;
+ }
+
+ /* there has to be a nicer way to do this... */
+ results[results.length - 1] = result;
+ }
+
+
public void get_results(out string status, out string additional_info,
- out uint success_count, out string result) {
- stdout.printf("*NSLookup* get_results()\n");
+ out uint success_count, out string result_string) {
+ success_count = 0;
+ StringBuilder builder = new StringBuilder (HEADER);
+
+ foreach (var result in results) {
+ builder.append (result.to_xml_fragment ());
+ if (result.status == ResultStatus.SUCCESS)
+ success_count++;
+ }
+ builder.append (FOOTER);
+ result_string = builder.str;
+
+ status = generic_status.to_string();
+ additional_info = "";
+ }
+
+/*
+ //valac --pkg gio-2.0 --pkg posix -X -lm rygel-bm-test-nslookup.vala rygel-bm-test.vala
+
+ private static int main(string[] args) {
+ MainLoop loop = new MainLoop();
+ BMTestNSLookup nslookup = new BMTestNSLookup ();
+
+ if (args.length < 2) {
+ print ("Usage: %s <hostname> [<nameserver> [<repetitions> [<timeout>]]]\n", args[0]);
+ return 0;
+ }
+
+ try {
+ nslookup.init (args[1],
+ args.length > 2 ? args[2] : null,
+ args.length > 3 ? int.parse (args[3]): 0,
+ args.length > 4 ? int.parse (args[4]) : 0);
+ } catch (BMTestError e) {
+ warning ("Incorrect parameters");
+ }
+
+ nslookup.execute.begin((obj, res)=> {
+ try {
+ string status;
+ string info;
+ string results;
+ uint count;
+ nslookup.execute.end(res);
+ nslookup.get_results (out status, out info, out count, out results);
+ print ("\nStatus: %s, %u successful iterations.\nResults:\n%s", status, count, results);
+ } catch (Error e) {
+ print ("Oops: %s\n", e.message);
+ }
+ loop.quit();
+ });
+ loop.run();
- status = this.status;
- additional_info = this.additional_info;
- success_count = this.success_count;
- result = this.result;
+ return 0;
}
+*/
}
diff --git a/src/librygel-core/rygel-bm-test-ping.vala b/src/librygel-core/rygel-bm-test-ping.vala
index 969a2db..fa250bb 100644
--- a/src/librygel-core/rygel-bm-test-ping.vala
+++ b/src/librygel-core/rygel-bm-test-ping.vala
@@ -62,14 +62,6 @@ internal class Rygel.BMTestPing : BMTest {
base("Ping");
}
- public override void execute() {
- stdout.printf("*Ping* execute()\n");
- }
-
- public override void cancel() {
- stdout.printf("*Ping* cancel()\n");
- }
-
public bool init(string host, uint repeat_count, uint data_block_size,
uint dscp, uint32 interval_time_out) {
stdout.printf("*Ping* init()\n");
diff --git a/src/librygel-core/rygel-bm-test-traceroute.vala b/src/librygel-core/rygel-bm-test-traceroute.vala
index 963ad7d..e966cb3 100644
--- a/src/librygel-core/rygel-bm-test-traceroute.vala
+++ b/src/librygel-core/rygel-bm-test-traceroute.vala
@@ -58,14 +58,6 @@ internal class Rygel.BMTestTraceroute : BMTest {
base("Traceroute");
}
- public override void execute() {
- stdout.printf("*Traceroute* execute()\n");
- }
-
- public override void cancel() {
- stdout.printf("*Traceroute* cancel()\n");
- }
-
public bool init(string host, uint32 wait_time_out, uint data_block_size,
uint max_hop_count, uint dscp) {
stdout.printf("*Traceroute* init()\n");
diff --git a/src/librygel-core/rygel-bm-test.vala b/src/librygel-core/rygel-bm-test.vala
index fb2f6ae..c3b0307 100644
--- a/src/librygel-core/rygel-bm-test.vala
+++ b/src/librygel-core/rygel-bm-test.vala
@@ -1,10 +1,8 @@
/*
- * Copyright (C) 2008 OpenedHand Ltd.
- * Copyright (C) 2008 Zeeshan Ali <zeenix gmail com>.
* Copyright (C) 2013 Intel Corporation.
*
- * Author: Jorn Baayen <jorn openedhand com>
- * Zeeshan Ali <zeenix gmail com>
+ * Author: Christophe Guiraud,
+ * Jussi Kukkonen
*
* This file is part of Rygel.
*
@@ -25,19 +23,159 @@
using GLib;
-// Helper class for BMTest.
+
+internal errordomain Rygel.BMTestError {
+ NOT_POSSIBLE,
+ INIT_FAILED,
+}
+
internal abstract class Rygel.BMTest : Object {
public string type;
public string state;
public string id;
+ public bool executing { private set; get; default = false; }
+
+ /* properties for implementations to access */
+ protected SpawnFlags flags = SpawnFlags.SEARCH_PATH |
+ SpawnFlags.LEAVE_DESCRIPTORS_OPEN;
+ protected string[] command;
+ protected uint execution_time { private set; get; default = 0; }
+ protected uint repetitions;
+
+ private int std_out;
+ private int std_err;
+ private Pid child_pid;
+ private SourceFunc async_callback;
+ private bool canceled;
+ private uint iteration;
+
+ /* These virtual/abstract functions will be called from execute():
+ * - For every iteration:
+ * - init_iteration()
+ * - calls to handle_output() and handle_error(),
+ * - finish_iteration()
+ * - then finish()
+ */
+ protected virtual void init_iteration () {}
+ protected virtual void handle_output (string line) {}
+ protected virtual void handle_error (string line) {
+ warning ("%s stderr: %s", command[0], line);
+ }
+ protected virtual void finish_iteration () {
+ iteration++;
+ if (iteration < repetitions) {
+ run_iteration ();
+ } else {
+ async_callback ();
+ }
+ }
+ protected virtual void finish (bool canceled) {}
+
+
+ private void child_setup () {
+ /* try to prevent possible changes in output */
+ Environment.set_variable("LC_MESSAGES", "C", true);
+
+ /* Create new session to detach from tty, but set a process
+ * group so all children can be ḱilled if need be */
+ Posix.setsid ();
+ Posix.setpgid (0, 0);
+ }
+
+ private void run_iteration () {
+ try {
+ init_iteration ();
+ Process.spawn_async_with_pipes (null,
+ command,
+ null,
+ flags,
+ child_setup,
+ out child_pid,
+ null,
+ out std_out,
+ out std_err);
+
+ var out_channel = new IOChannel.unix_new (std_out);
+ out_channel.add_watch (IOCondition.OUT | IOCondition.HUP,
+ out_watch);
+
+ var err_channel = new IOChannel.unix_new (std_err);
+ err_channel.add_watch (IOCondition.OUT | IOCondition.HUP,
+ err_watch);
+ } catch (SpawnError e) {
+ /* TODO cancel all iterations and let the implementation know
+ * we failed to spawn */
+ }
+ }
+
+ private bool out_watch (IOChannel channel, IOCondition condition) {
+ try {
+ string line;
+ IOStatus status = channel.read_line (out line, null, null);
+ if (line != null)
+ handle_output (line);
+
+ if (status == IOStatus.EOF) {
+ finish_iteration ();
+ return false;
+ }
+ } catch (Error e) {
+ warning ("Failed readline() from nslookup stdout: %s", e.message);
+ finish_iteration();
+ return false;
+ }
+
+ return true;
+ }
+
+ private bool err_watch (IOChannel channel, IOCondition condition) {
+ try {
+ string line;
+ IOStatus status = channel.read_line (out line, null, null);
+ if (line != null)
+ handle_error (line);
+ if (status == IOStatus.EOF)
+ return false;
+ } catch (Error e) {
+ warning ("Failed readline() from nslookup stderr: %s", e.message);
+ return false;
+ }
+
+ return true;
+ }
+
+
public BMTest(string type) {
this.type = type;
this.state = "Requested";
this.id = null;
}
- public abstract void execute();
+ public async void execute () throws BMTestError {
+ if (executing)
+ throw new BMTestError.NOT_POSSIBLE ("Already executing");
- public abstract void cancel();
+ executing = true;
+ canceled = false;
+ iteration = 0;
+
+ run_iteration ();
+
+ async_callback = execute.callback;
+ yield;
+
+ executing = false;
+ finish (canceled);
+ return ;
+ }
+
+ public void cancel () throws BMTestError {
+ if (!executing)
+ throw new BMTestError.NOT_POSSIBLE ("Not executing");
+
+ Posix.killpg (child_pid, Posix.SIGTERM);
+
+ canceled = true;
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]