diff options
author | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
commit | 84adefa331c4159d432d22840663c38f155cd4c1 (patch) | |
tree | bff9a9c66adda4df2106dfd0e5c053ab182a12bd /erts/emulator/test/driver_SUITE_data/monitor_drv.c | |
download | otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2 otp-84adefa331c4159d432d22840663c38f155cd4c1.zip |
The R13B03 release.OTP_R13B03
Diffstat (limited to 'erts/emulator/test/driver_SUITE_data/monitor_drv.c')
-rw-r--r-- | erts/emulator/test/driver_SUITE_data/monitor_drv.c | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/erts/emulator/test/driver_SUITE_data/monitor_drv.c b/erts/emulator/test/driver_SUITE_data/monitor_drv.c new file mode 100644 index 0000000000..1da6a56a72 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/monitor_drv.c @@ -0,0 +1,293 @@ +/* ``The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved via the world wide web at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include <stdio.h> +#include <string.h> +#include "erl_driver.h" + +static ErlDrvData monitor_drv_start(ErlDrvPort, char *); +static int monitor_drv_control(ErlDrvData, unsigned int, + char *, int, char **, int); +static void handle_monitor(ErlDrvData drv_data, ErlDrvMonitor *monitor); + +#define OP_I_AM_IPID 1 +#define OP_MONITOR_ME 2 +#define OP_DEMONITOR_ME 3 +#define OP_MONITOR_ME_LATER 4 +#define OP_DO_DELAYED_MONITOR 5 + +typedef struct one_monitor { + ErlDrvTermData pid; + int later_id; + ErlDrvMonitor mon; + struct one_monitor *next; +} OneMonitor; + + +typedef struct { + ErlDrvPort port; + ErlDrvTermData ipid; + int later_counter; + OneMonitor *first; +} MyDrvData; + + +static ErlDrvEntry monitor_drv_entry = { + NULL /* init */, + monitor_drv_start, + NULL /* stop */, + NULL /* output */, + NULL /* ready_input */, + NULL /* ready_output */, + "monitor_drv", + NULL /* finish */, + NULL /* handle */, + monitor_drv_control, + NULL /* timeout */, + NULL /* outputv */, + NULL /* ready_async */, + NULL /* flush */, + NULL /* call */, + NULL /* event */, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, /* handle2 */ + handle_monitor +}; + +DRIVER_INIT(monitor_drv) +{ + return &monitor_drv_entry; +} + +static ErlDrvData +monitor_drv_start(ErlDrvPort port, char *command) { + MyDrvData *data = driver_alloc(sizeof(MyDrvData)); + data->port = port; + data->ipid = driver_term_nil; + data->first = NULL; + data->later_counter = 0; + return (ErlDrvData) data; +} + +static void monitor_drv_stop(ErlDrvData data) +{ + driver_free((void *) data); +} + +static void handle_monitor(ErlDrvData drv_data, ErlDrvMonitor *monitor) +{ + + MyDrvData *data = (MyDrvData *) drv_data; + OneMonitor *p,*o; + for (p = data->first, o = NULL; + p != NULL && driver_compare_monitors(&p->mon,monitor); + o = p, p = p->next) + ; + if (!p) { + fprintf(stderr,"Spooky Monitor executed!\r\n"); + } else { + ErlDrvTermData spec[] = { + ERL_DRV_ATOM, driver_mk_atom("monitor_fired"), + ERL_DRV_PORT, driver_mk_port(data->port), + ERL_DRV_PID, p->pid, + ERL_DRV_TUPLE, TERM_DATA(3) + }; + if (!o) { + data->first = p->next; + } else { + o->next = p->next; + } + driver_free(p); + driver_send_term(data->port, data->ipid, spec, sizeof(spec)/sizeof(ErlDrvTermData)); + } + + return; +} + +static int +monitor_drv_control(ErlDrvData drv_data, + unsigned int command, + char *ibuf, int ilen, + char **rbuf, int rlen) +{ + MyDrvData *data = (MyDrvData *) drv_data; + char *answer = NULL; + char buff[64]; + int alen; + + switch (command) { + case OP_I_AM_IPID: + data->ipid = driver_caller(data->port); + answer = "ok"; + break; + case OP_MONITOR_ME: + { + int res; + OneMonitor *om = driver_alloc(sizeof(OneMonitor)); + om->pid = driver_caller(data->port); + om->later_id = 0; + res = driver_monitor_process(data->port,om->pid,&(om->mon)); + if (res < 0) { + answer = "error"; + driver_free(om); + } else if (res > 0) { + answer = "noproc"; + driver_free(om); + } else { + om->next = data->first; + data->first = om; + answer = "ok"; + } + break; + } + case OP_DEMONITOR_ME: + { + int res; + OneMonitor *p,*q = NULL; + int found = 0; + ErlDrvTermData pid = driver_caller(data->port); + for (p = data->first; p != NULL; p = p->next) { + if (p->pid == pid) { + q = p; + ++found; + } + } + if (q == NULL) { + answer = "not_monitored"; + } else { + if (q->later_id > 0) { + if (found > 1) { + answer = "delayd_but_more"; + } else { + answer = "delayed"; + } + } else { + res = driver_demonitor_process(data->port, &(q->mon)); + if (res < 0) { + answer = "error"; + } else if (res > 0) { + if (found > 1) { + answer = "gone_but_more"; + } else { + answer = "gone"; + } + } else { + if (found > 1) { + answer = "ok_but_more"; + } else { + answer = "ok"; + } + } + } + if (data->first == q) { + data->first = q->next; + } else { + for (p = data->first; p != NULL; p = p->next) { + if (p->next == q) { + p->next = q->next; + break; + } + } + } + driver_free(q); + } + break; + } + case OP_MONITOR_ME_LATER: + { + int res; + OneMonitor *om = driver_alloc(sizeof(OneMonitor)); + om->pid = driver_caller(data->port); + om->later_id = (++(data->later_counter)); + om->next = data->first; + data->first = om; + sprintf(buff,"ok:%d",om->later_id); + answer = buff; + break; + } + case OP_DO_DELAYED_MONITOR: + { + int id = 0, sign = 1, in_number = 0; + OneMonitor *p, *q; + char *bp; + for (bp = ibuf; bp < (ibuf + ilen); ++bp) { + if (*bp <= '9' && *bp >= '0') { + int x = *bp - '0'; + in_number++; + id *= 10; + id += x; + } else if (*bp == '-') { + if (in_number) { + break; + } + sign = -1; + ++in_number; + } else { + if (in_number) { + break; + } + } + } + id *= sign; + q = NULL; + for (p = data->first; p != NULL; q = p, p = p->next) { + if (p->later_id != 0 && p->later_id == id) { + break; + } + } + if (p == NULL) { + answer = "not_found"; + } else { + int res = driver_monitor_process(data->port,p->pid,&(p->mon)); + if (res != 0) { + if (res < 0) { + answer = "error"; + } else { + answer = "noproc"; + } + if (q == NULL) { + data->first = p->next; + } else { + q->next = p->next; + } + driver_free(p); + } else { + p->later_id = 0; + answer = "ok"; + } + } + break; + } + default: + answer = "unknown_op"; + } + if (answer == NULL) { + answer = "internal_error"; + } + alen = strlen(answer); + if (alen >= rlen) { + *rbuf = driver_alloc(alen+1); + } + strcpy(*rbuf,answer); + return alen; +} + + |