00001
00005 #include <malloc.h>
00006 #include <string.h>
00007
00008 #include "libmgk.h"
00009 #include "allocate.h"
00010
00011 DEFINE_ALLOCATOR(mgk_mask_trigger, 50, next);
00012 DEFINE_ALLOCATOR(mgk_remnode, 50, next);
00013
00014 mgk_node **__mgk_local_nodes = NULL;
00015 int __mgk_num_local_nodes = 0;
00016 static int max_table_size = 0;
00017 static mgk_remnode *stub_list = NULL;
00018
00019 static int
00020 grow_table(void)
00021 {
00022 static int table_alloc = 250;
00023 static int table_alloc_inc = 256;
00024 mgk_node **ntab = malloc(sizeof(mgk_node *) * table_alloc);
00025 if (ntab) {
00026 if (__mgk_num_local_nodes > 0) {
00027 memcpy(ntab,
00028 __mgk_local_nodes,
00029 (sizeof(mgk_node *) * __mgk_num_local_nodes));
00030 }
00031 if (__mgk_local_nodes) {
00032 free(__mgk_local_nodes);
00033 }
00034 __mgk_local_nodes = ntab;
00035 max_table_size = table_alloc;
00036 table_alloc += table_alloc_inc;
00037 table_alloc_inc *= 2;
00038 return (TRUE);
00039 }
00040 return (FALSE);
00041 }
00042
00043 mgk_nodep
00044 mgk_create_node(mgk_script fn, unsigned int nin, unsigned int nout,
00045 unsigned int priority,
00046 mgk_trigger_mode tmode)
00047 {
00048 mgk_node *node;
00049 char *memptr;
00050 int i, crcbyte;
00051 long crc;
00052
00053 if (fn == NULL) {
00054 mgk_errno = E_SCRIPTNOTFOUND;
00055 return (NULL);
00056 }
00057 if ((nin >= MGK_MAX_PORT_COUNT) || (nout >= MGK_MAX_PORT_COUNT)) {
00058 mgk_errno = E_BADPORTIX;
00059 return (NULL);
00060 }
00061 if ((tmode != AT_IFALL) && (tmode != AT_IFANY) && (tmode != AT_SPEC)) {
00062 mgk_errno = E_BADTRIGGER;
00063 return (NULL);
00064 }
00065 if (__mgk_num_local_nodes == max_table_size) {
00066 if (!grow_table()) {
00067 mgk_errno = E_NOMEM;
00068 return (NULL);
00069 }
00070 }
00071 node = malloc((sizeof(mgk_node)) +
00072 (sizeof(mgk_inport) * nin) +
00073 (sizeof(mgk_outport) * nout));
00074 if (!node) {
00075 mgk_errno = E_NOMEM;
00076 return (NULL);
00077 }
00078 memptr = (char *)node;
00079 memset(node, 0, sizeof(mgk_node));
00080 node->tag = OBJ_NODE;
00081 node->script = fn;
00082 node->ins = (mgk_inport *) (memptr += sizeof(mgk_node));
00083 node->outs = (mgk_outport *) (memptr += (sizeof(mgk_inport) * nin));
00084 node->nin = nin;
00085 node->nout = nout;
00086 if (nin > 0) {
00087 int i;
00088 memset(node->ins, 0, (sizeof(mgk_inport) * nin));
00089 for(i = 0; i < (int)nin; i++) {
00090 mgk_set_portmask_bit(node->input_mask,i,1);
00091 }
00092 }
00093 if (nout > 0) {
00094 memset(node->outs, 0, (sizeof(mgk_outport) * nout));
00095 }
00096 node->priority = max(min(priority, MGK_MAX_NODE_PRIORITY),
00097 MGK_NODE_STOP_PRIORITY);
00098 node->tmode = tmode;
00099 __mgk_update(node);
00100 crc = (long)node ^ (long)node->script ^
00101 node->nin ^ node->nout ^
00102 __mgk_num_local_nodes;
00103 for (memptr = (char *)(&crc), i = crcbyte = 0; i < sizeof(crc); i++) {
00104 crcbyte ^= memptr[i];
00105 }
00106 node->ID = __mgk_num_local_nodes | ((long)crcbyte << 24);
00107 __mgk_local_nodes[__mgk_num_local_nodes++] = node;
00108 return (node);
00109 }
00110
00111 mgk_nodep
00112 mgk_create_node_indirect(char *scriptname,
00113 unsigned int nin, unsigned int nout,
00114 unsigned int priority,
00115 mgk_trigger_mode tmode, mgk_hostp host)
00116 {
00117 if ((host == MGK_LOCALHOST) || (host == __mgk_local_host)) {
00118 return (mgk_create_node(__mgk_lookup_script(scriptname),
00119 nin, nout, priority, tmode));
00120 }
00121 if (__mgk_check_host(host)) {
00122 mgk_value *args[5], *rargs[2];
00123 args[0] = __mgk_build_value(scriptname, T_STRING);
00124 args[1] = __mgk_build_value(&nin, T_INTEGER);
00125 args[2] = __mgk_build_value(&nout, T_INTEGER);
00126 args[3] = __mgk_build_value(&priority, T_INTEGER);
00127 args[4] = __mgk_build_value(&tmode, T_INTEGER);
00128 if (__mgk_remote_call(host,
00129 cmd_create_node_indirect,
00130 5, args,
00131 2, rargs)) {
00132 mgk_data_type t1, t2;
00133 mgk_scalar s1, s2;
00134 long *idp = __mgk_extract_value(rargs[0], &t1, &s1);
00135 int *errp = __mgk_extract_value(rargs[1], &t2, &s2);
00136 if ((t1 == T_LONGINT) &&
00137 (t2 == T_INTEGER) &&
00138 ((mgk_errno = *errp) == E_SUCCESS)) {
00139 return ((mgk_node *) __mgk_remnode_stub(host, *idp));
00140 }
00141 return (NULL);
00142 }
00143 mgk_errno = E_COMM;
00144 return (NULL);
00145 }
00146 mgk_errno = E_NOTHOST;
00147 return (NULL);
00148 }
00149
00150 DEFSVC(create_node_indirect)
00151 {
00152 if ((argc == 5) && (rargc == 2)) {
00153 mgk_data_type t1, t2, t3, t4, t5;
00154 char *sname = __mgk_parse_value(argv[0], &t1);
00155 int *ninp = __mgk_parse_value(argv[1], &t2);
00156 int *noutp = __mgk_parse_value(argv[2], &t3);
00157 int *priop = __mgk_parse_value(argv[3], &t4);
00158 int *tmodep = __mgk_parse_value(argv[4], &t5);
00159 if ((t1 == (T_CHAR | T_BUFFER)) &&
00160 (t2 == T_INTEGER) &&
00161 (t3 == T_INTEGER) &&
00162 (t4 == T_INTEGER) &&
00163 (t5 == T_INTEGER)) {
00164 mgk_node *res = mgk_create_node_indirect(sname,
00165 *ninp, *noutp, *priop,
00166 (mgk_trigger_mode) (*tmodep),
00167 MGK_LOCALHOST);
00168 long ID = res ? res->ID : 0;
00169 rargv[0] = __mgk_build_value(&ID, T_LONGINT);
00170 rargv[1] = __mgk_build_value(&mgk_errno, T_INTEGER);
00171 return (TRUE);
00172 }
00173 }
00174 return (FALSE);
00175 }
00176
00177 mgk_error_code
00178 mgk_add_node_trigger_mask_disp(mgk_nodep node,
00179 mgk_portmask mask,
00180 mgk_script fn)
00181 {
00182 mgk_mask_trigger *tm;
00183 if (!__mgk_check_node(node)) {
00184 return (E_NOTNODE);
00185 }
00186 if (!fn) {
00187 return (E_SCRIPTNOTFOUND);
00188 }
00189 if (node->tmode != AT_SPEC) {
00190 return (E_BADTRIGGER);
00191 }
00192 if (!(tm = ALLOC_mgk_mask_trigger())) {
00193 return (E_NOMEM);
00194 }
00195 memcpy(tm->mask, mask, sizeof(mgk_portmask));
00196 tm->script = fn;
00197 tm->next = node->trigger_list;
00198 node->trigger_list = tm;
00199 __mgk_update(node);
00200 return (E_SUCCESS);
00201 }
00202
00203 mgk_error_code
00204 mgk_add_node_trigger_mask(mgk_nodep node, mgk_portmask mask)
00205 {
00206 if (__mgk_check_remnode(node)) {
00207 mgk_remnode *rn = (mgk_remnode *) node;
00208 mgk_value *args[2];
00209 mgk_value *rargs[1];
00210 args[0] = __mgk_build_value(&rn->ID, T_LONGINT);
00211 args[1] = __mgk_build_value(mask, (T_INTEGER | T_ARRAY(itemsof(mask))));
00212 if (__mgk_remote_call(rn->host,
00213 cmd_add_node_trigger_mask,
00214 2, args,
00215 1, rargs)) {
00216 mgk_data_type t;
00217 mgk_scalar s;
00218 int *errp = __mgk_extract_value(rargs[0], &t, &s);
00219 if (t == T_INTEGER) {
00220 return (mgk_errno = *errp);
00221 }
00222 }
00223 return (mgk_errno = E_COMM);
00224 }
00225 if (!__mgk_check_node(node)) {
00226 return (E_NOTNODE);
00227 }
00228 return (mgk_add_node_trigger_mask_disp(node, mask, node->script));
00229 }
00230
00231 DEFSVC(add_node_trigger_mask)
00232 {
00233 if ((argc == 2) && (rargc == 1)) {
00234 mgk_data_type t1, t2;
00235 long *idp = __mgk_parse_value(argv[0], &t1);
00236 int *maskp = __mgk_parse_value(argv[1], &t2);
00237 if ((t1 == T_LONGINT) &&
00238 (t2 == (T_INTEGER | T_BUFFER)) &&
00239 (mgk_buffer_size(maskp) == sizeof(mgk_portmask))) {
00240 mgk_node *np = __mgk_retrieve_node_by_ID(*idp);
00241 mgk_add_node_trigger_mask(np, maskp);
00242 rargv[0] = __mgk_build_value(&mgk_errno, T_INTEGER);
00243 return (TRUE);
00244 }
00245 }
00246 return (FALSE);
00247 }
00248
00249 mgk_error_code
00250 mgk_add_node_trigger_mask_disp_indirect(mgk_nodep node,
00251 mgk_portmask mask,
00252 char *scriptname)
00253 {
00254 if (__mgk_check_remnode(node)) {
00255 mgk_remnode *rn = (mgk_remnode *) node;
00256 mgk_value *args[3];
00257 mgk_value *rargs[1];
00258 args[0] = __mgk_build_value(&rn->ID, T_LONGINT);
00259 args[1] = __mgk_build_value(mask, (T_INTEGER | T_ARRAY(itemsof(mask))));
00260 args[2] = __mgk_build_value(scriptname, T_STRING);
00261 if (__mgk_remote_call(rn->host,
00262 cmd_add_node_trigger_mask_disp_indirect,
00263 3, args,
00264 1, rargs)) {
00265 mgk_data_type t;
00266 mgk_scalar s;
00267 int *errp = __mgk_extract_value(rargs[0], &t, &s);
00268 if (t == T_INTEGER) {
00269 return (mgk_errno = *errp);
00270 }
00271 }
00272 return (mgk_errno = E_COMM);
00273 }
00274 return (mgk_add_node_trigger_mask_disp(node, mask,
00275 __mgk_lookup_script(scriptname)));
00276 }
00277
00278 DEFSVC(add_node_trigger_mask_disp_indirect)
00279 {
00280 if ((argc == 3) && (rargc == 1)) {
00281 mgk_data_type t1, t2, t3;
00282 long *idp = __mgk_parse_value(argv[0], &t1);
00283 int *maskp = __mgk_parse_value(argv[1], &t2);
00284 char *sc = __mgk_parse_value(argv[2], &t3);
00285 if ((t1 == T_LONGINT) &&
00286 (t2 == (T_INTEGER | T_BUFFER)) &&
00287 (t3 == (T_CHAR | T_BUFFER)) &&
00288 (mgk_buffer_size(maskp) == sizeof(mgk_portmask))) {
00289 mgk_node *np = __mgk_retrieve_node_by_ID(*idp);
00290 mgk_add_node_trigger_mask_disp_indirect(np, maskp, sc);
00291 rargv[0] = __mgk_build_value(&mgk_errno, T_INTEGER);
00292 return (TRUE);
00293 }
00294 }
00295 return (FALSE);
00296 }
00297
00298 mgk_error_code
00299 mgk_set_node_priority(mgk_nodep node, unsigned int priority)
00300 {
00301 if (__mgk_check_remnode(node)) {
00302 mgk_remnode *rn = (mgk_remnode *) node;
00303 mgk_value *args[2];
00304 mgk_value *rargs[1];
00305 args[0] = __mgk_build_value(&rn->ID, T_LONGINT);
00306 args[1] = __mgk_build_value(&priority, T_INTEGER);
00307 if (__mgk_remote_call(rn->host,
00308 cmd_set_node_priority,
00309 2, args,
00310 1, rargs)) {
00311 mgk_data_type t;
00312 mgk_scalar s;
00313 int *errp = __mgk_extract_value(rargs[0], &t, &s);
00314 if (t == T_INTEGER) {
00315 return (mgk_errno = *errp);
00316 }
00317 }
00318 return (mgk_errno = E_COMM);
00319 }
00320 if (!__mgk_check_node(node)) {
00321 return (E_NOTNODE);
00322 }
00323 priority = max(min(priority, MGK_MAX_NODE_PRIORITY), MGK_NODE_STOP_PRIORITY);
00324 if (node->priority != priority) {
00325 if (node->status == READY) {
00326 __mgk_dequeue(node);
00327 }
00328 node->priority = priority;
00329 if (node->status == READY) {
00330 __mgk_enqueue(node);
00331 }
00332 }
00333 return (E_SUCCESS);
00334 }
00335
00336 DEFSVC(set_node_priority)
00337 {
00338 if ((argc == 2) && (rargc == 1)) {
00339 mgk_data_type t1, t2;
00340 long *idp = __mgk_parse_value(argv[0], &t1);
00341 int *prip = __mgk_parse_value(argv[1], &t2);
00342 if ((t1 == T_LONGINT) && (t2 == T_INTEGER)) {
00343 mgk_node *np = __mgk_retrieve_node_by_ID(*idp);
00344 mgk_set_node_priority(np, *prip);
00345 rargv[0] = __mgk_build_value(&mgk_errno, T_INTEGER);
00346 return (TRUE);
00347 }
00348 }
00349 return (FALSE);
00350 }
00351
00352 unsigned int
00353 mgk_node_priority(mgk_nodep node)
00354 {
00355 if (__mgk_check_remnode(node)) {
00356 mgk_remnode *rn = (mgk_remnode *) node;
00357 mgk_value *args[1];
00358 mgk_value *rargs[2];
00359 args[0] = __mgk_build_value(&rn->ID, T_LONGINT);
00360 if (__mgk_remote_call(rn->host,
00361 cmd_node_priority,
00362 1, args,
00363 2, rargs)) {
00364 mgk_data_type t1, t2;
00365 mgk_scalar s1, s2;
00366 int *prip = __mgk_extract_value(rargs[0], &t1, &s1);
00367 int *errp = __mgk_extract_value(rargs[1], &t2, &s2);
00368 if ((t1 == T_INTEGER) && (t2 == T_INTEGER)) {
00369 mgk_errno = *errp;
00370 return (*prip);
00371 }
00372 }
00373 mgk_errno = E_COMM;
00374 return (MGK_U_BADVAL);
00375 }
00376 if (!__mgk_check_node(node)) {
00377 mgk_errno = E_NOTNODE;
00378 return (MGK_U_BADVAL);
00379 }
00380 mgk_errno = E_SUCCESS;
00381 return (node->priority);
00382 }
00383
00384 DEFSVC(node_priority)
00385 {
00386 if ((argc == 1) && (rargc == 2)) {
00387 mgk_data_type t;
00388 long *idp = __mgk_parse_value(argv[0], &t);
00389 if (t == T_LONGINT) {
00390 mgk_node *np = __mgk_retrieve_node_by_ID(*idp);
00391 int pri = mgk_node_priority(np);
00392 rargv[0] = __mgk_build_value(&pri, T_INTEGER);
00393 rargv[1] = __mgk_build_value(&mgk_errno, T_INTEGER);
00394 return (TRUE);
00395 }
00396 }
00397 return (FALSE);
00398 }
00399
00400 mgk_error_code
00401 mgk_set_node_context(mgk_nodep node,
00402 void *context, mgk_data_type type)
00403 {
00404 mgk_value *val;
00405 if (__mgk_check_remnode(node)) {
00406 mgk_remnode *rn = (mgk_remnode *) node;
00407 mgk_value *args[2];
00408 mgk_value *rargs[1];
00409 if ((context == NULL) || (type == T_NODATA)) {
00410 int dummy = 0;
00411 val = __mgk_build_value(&dummy, T_INTEGER);
00412 val->type = T_NODATA;
00413 }
00414 else if (!(val = __mgk_build_value(context, type))) {
00415 return (E_BADDATA);
00416 }
00417 args[0] = __mgk_build_value(&rn->ID, T_LONGINT);
00418 args[1] = val;
00419 if (__mgk_remote_call(rn->host,
00420 cmd_set_node_context,
00421 2, args,
00422 1, rargs)) {
00423 mgk_data_type t;
00424 mgk_scalar s;
00425 int *errp = __mgk_extract_value(rargs[0], &t, &s);
00426 if (t == T_INTEGER) {
00427 return (mgk_errno = *errp);
00428 }
00429 }
00430 return (mgk_errno = E_COMM);
00431 }
00432 if (!__mgk_check_node(node)) {
00433 return (E_NOTNODE);
00434 }
00435 if ((context == NULL) || (type == T_NODATA)) {
00436 val = NULL;
00437 }
00438 else if (!(val = __mgk_build_value(context, type))) {
00439 return (E_BADDATA);
00440 }
00441 if (node->context) {
00442 __mgk_free_value(node->context);
00443 }
00444 node->context = val;
00445 return (E_SUCCESS);
00446 }
00447
00448 DEFSVC(set_node_context)
00449 {
00450 if ((argc == 2) && (rargc == 1)) {
00451 mgk_data_type t;
00452 long *idp = __mgk_parse_value(argv[0], &t);
00453 if (t == T_LONGINT) {
00454 mgk_node *np = __mgk_retrieve_node_by_ID(*idp);
00455 if (np) {
00456 if (np->context) {
00457 __mgk_free_value(np->context);
00458 }
00459 if (argv[1]->type == T_NODATA) {
00460 np->context = NULL;
00461 }
00462 else {
00463 np->context = argv[1];
00464 argv[1] = NULL;
00465 }
00466 mgk_errno = E_SUCCESS;
00467 }
00468 else {
00469 mgk_errno = E_NOTNODE;
00470 }
00471 rargv[0] = __mgk_build_value(&mgk_errno, T_INTEGER);
00472 return (TRUE);
00473 }
00474 }
00475 return (FALSE);
00476 }
00477
00478 void *
00479 mgk_node_context(mgk_nodep node, mgk_data_type * typep)
00480 {
00481 if (__mgk_check_remnode(node)) {
00482 mgk_remnode *rn = (mgk_remnode *) node;
00483 mgk_value *args[1];
00484 mgk_value *rargs[2];
00485 args[0] = __mgk_build_value(&rn->ID, T_LONGINT);
00486 if (__mgk_remote_call(rn->host,
00487 cmd_node_priority,
00488 1, args,
00489 2, rargs)) {
00490 mgk_data_type t;
00491 mgk_scalar s;
00492 int *errp = __mgk_extract_value(rargs[1], &t, &s);
00493 if (t == T_INTEGER) {
00494 static mgk_scalar cxts[16];
00495 static int ncxt = 0;
00496 mgk_errno = *errp;
00497 return (__mgk_extract_value(rargs[0], typep, &cxts[++ncxt & 15]));
00498 }
00499 __mgk_free_value(rargs[0]);
00500 }
00501 mgk_errno = E_COMM;
00502 return (NULL);
00503 }
00504 if (!__mgk_check_node(node)) {
00505 mgk_errno = E_NOTNODE;
00506 return (NULL);
00507 }
00508 mgk_errno = E_SUCCESS;
00509 return (node->context ?
00510 __mgk_parse_value(node->context, typep) :
00511 (void*) ((*typep = T_NODATA), NULL));
00512 }
00513
00514 DEFSVC(node_context)
00515 {
00516 if ((argc == 1) && (rargc == 2)) {
00517 mgk_data_type t;
00518 long *idp = __mgk_parse_value(argv[0], &t);
00519 if (t == T_LONGINT) {
00520 mgk_node *np = __mgk_retrieve_node_by_ID(*idp);
00521 if (np && np->context) {
00522 rargv[0] = __mgk_alias_value(np->context);
00523 }
00524 else {
00525 int dummy = 0;
00526 rargv[0] = __mgk_build_value(&dummy, T_INTEGER);
00527 rargv[0]->type = T_NODATA;
00528 }
00529 mgk_errno = np ? E_SUCCESS : E_NOTNODE;
00530 rargv[1] = __mgk_build_value(&mgk_errno, T_INTEGER);
00531 return (TRUE);
00532 }
00533 }
00534 return (FALSE);
00535 }
00536
00537 mgk_node *
00538 __mgk_retrieve_node_by_ID(unsigned long ID)
00539 {
00540 mgk_node *np;
00541 int idx;
00542 return (((__mgk_local_nodes) &&
00543 ((idx = (int)(ID & 0x0ffffffL)) < __mgk_num_local_nodes) &&
00544 ((np = __mgk_local_nodes[idx])) &&
00545 (__mgk_check_node(np)) &&
00546 (np->ID == ID)) ?
00547 np :
00548 NULL);
00549 }
00550
00551 mgk_remnode *
00552 __mgk_remnode_stub(mgk_host * h, unsigned long ID)
00553 {
00554 mgk_remnode *rp;
00555 for (rp = stub_list; rp; rp = rp->next) {
00556 if ((rp->host == h) && (rp->ID == ID)) {
00557 return (rp);
00558 }
00559 }
00560 rp = ALLOC_mgk_remnode();
00561 if (!rp) {
00562 mgk_errno = E_NOMEM;
00563 return (NULL);
00564 }
00565 rp->tag = OBJ_REMNODE;
00566 rp->host = h;
00567 rp->ID = ID;
00568 rp->next = stub_list;
00569 stub_list = rp;
00570 return (rp);
00571 }
00572
00573 mgk_node *
00574 __mgk_locate_node(unsigned int hostidx, unsigned long ID)
00575 {
00576 if (hostidx == (unsigned int)__mgk_local_host->index) {
00577 return (__mgk_retrieve_node_by_ID(ID));
00578 }
00579 if (hostidx < (unsigned int)__mgk_num_hosts) {
00580 return ((mgk_node *) __mgk_remnode_stub(&__mgk_host_table[hostidx], ID));
00581 }
00582 return (NULL);
00583 }