void PPDropTrigger::do_execute() { tuple_cell tc; xqp_tuple t(1); trigger_name.op->next(t); if (t.is_eos()) throw USER_EXCEPTION(SE1071); tc = trigger_name.get(t); if (!tc.is_atomic() || tc.get_atomic_type() != xs_string) throw USER_EXCEPTION(SE1071); trigger_name.op->next(t); if (!t.is_eos()) throw USER_EXCEPTION(SE1071); tc = tuple_cell::make_sure_light_atomic(tc); local_lock_mrg->put_lock_on_trigger(tc.get_str_mem()); if(find_trigger(tc.get_str_mem()) == XNULL) throw USER_EXCEPTION2(SE3211, (std::string("Trigger '") + tc.get_str_mem() + "'").c_str()); auth_for_drop_object(tc.get_str_mem(), "trigger", false); delete_trigger(tc.get_str_mem()); }
void activate_trigger(const char *name, void **list, const int num) { \ struct trigger_info *info; struct user_trigger *tr; wobject_i *obj; int index; debug(3 , _("activate_trigger(\"%s\", %p, %u)\n"), name, list, num); if (rtl.current_obj == NO_SELECTED_OBJECT) { error(_("You must select a object before use commands.\n")); return; } index = find_trigger(name); if (index == TRNOT_FOUND) { debug(2, _("Trigger not found.\n")); return; } obj = rtl.objects.list[rtl.current_obj]; if (obj->object == NULL && !cmp("new", name)) { if (!rtl.safe_working) out(_("%s%sWarning%s: object is null!\n"), CC_BOLD, CC_RED, CC_RESTORE); else { error(_("%s%sError%s: operation blocked by safe_working. " "(object is null)\n"), CC_BOLD, CC_RED, CC_RESTORE); return; } } tr = obj->triggers[index]; if (tr->minparam != NOLIMIT && num < tr->minparam) { debug(2, _("Skipping trigger: number of parameteres do not" " reach minimum allowed.\n")); return; } if (tr->maxparam != NOLIMIT && num > tr->maxparam) { debug(2, _("Skipping trigger: number of parameteres ultrapass" " maximum allowed.\n")); return; } info = TALLOC(struct trigger_info); assert(info != NULL); info->debug_level = rtl.debuglevel; info->item_size = getsizeof(rtl.type); info->list = list; info->list_num = (size_t) num; info->opcode = (char *) name; info->object = obj->object; debug(3, _("Calling user trigger..\n")); tr->function(info); if (info->object != obj->object) { debug(3, _("\tUpdating object pointer from %p to %p\n"), obj->object, info->object); obj->object = info->object; } free(info); }
void delete_trigger (const char *trigger_title) { trigger_cell_cptr trc = find_trigger(trigger_title); if (trc.found()) { down_concurrent_micro_ops_number(); hl_logical_log_trigger( trc->trigger_time, trc->trigger_event, trc->trigger_path, trc->trigger_granularity, trc->trigger_action, trc->innode, trc->path_to_parent, trc->trigger_title, trc->doc_name, trc->is_doc, false); trc->drop(); up_concurrent_micro_ops_number(); } }
trigger_cell_xptr create_trigger (enum trigger_time tr_time, enum trigger_event tr_event, xpath::PathExpression *trigger_path, enum trigger_granularity tr_gran, scheme_list* action, inserting_node innode, xpath::PathExpression *path_to_parent, doc_schema_node_xptr schemaroot, const char * trigger_title, const char* doc_name, bool is_doc) { // I. Create and fill new trigger cell if (find_trigger(trigger_title) != XNULL) { throw USER_EXCEPTION(SE3200); } down_concurrent_micro_ops_number(); trigger_cell_cptr trc(trigger_cell_object::create(trigger_title, schemaroot), true); schemaroot.modify()->full_trigger_list->add(trc.ptr()); trc->trigger_path = trigger_path; trc->trigger_event = tr_event; trc->trigger_time = tr_time; trc->trigger_granularity = tr_gran; if (rcv_tac != NULL) // recovery mode { trc->trigger_action = rcv_tac; // trigger_action_cell sequence has already been recovered from logical log rcv_tac = NULL; } else { trc->trigger_action = (trigger_action_cell*)malloc(sizeof(trigger_action_cell)); trigger_action_cell* trac = trc->trigger_action; for (std::vector<scm_elem>::size_type i = 0; i < action->size(); i++) { trac->statement = (char*)malloc(strlen(action->at(i).internal.str)+1); strcpy(trac->statement,action->at(i).internal.str); if (i == action->size() - 1) trac->next = NULL; else trac->next = (trigger_action_cell*)malloc(sizeof(trigger_action_cell)); trac = trac->next; RECOVERY_CRASH; } } // if the trigger is on before insert and statement level if((trc->trigger_event == TRIGGER_INSERT_EVENT) && (trc->trigger_time == TRIGGER_BEFORE) && (trc->trigger_granularity == TRIGGER_FOR_EACH_NODE)&& (path_to_parent)) { trc->path_to_parent = path_to_parent; trc->innode = inserting_node(innode.name, innode.type); } else { trc->path_to_parent = NULL; } trc->doc_name = (char*)malloc(strlen(doc_name)+1); strcpy(trc->doc_name,doc_name); trc->is_doc=is_doc; hl_logical_log_trigger(tr_time, tr_event, trigger_path, tr_gran, trc->trigger_action, trc->innode, path_to_parent, trigger_title, doc_name, is_doc, true); //II. Execute abs path (object_path) on the desriptive schema t_scmnodes sobj; executePathExpression(schemaroot, *trigger_path, &sobj, NULL, NULL); //III. For each schema node found (sn_obj) std::vector<xptr> start_nodes; for (size_t i = 0; i < sobj.size(); i++) { sobj[i].modify()->trigger_list->add(trc.ptr()); RECOVERY_CRASH; } up_concurrent_micro_ops_number(); return trc.ptr(); }
void trigger(void *cvoid, zctx_t * context, void * control) { triggerconfig_t * c = (triggerconfig_t*) cvoid; //set up msgpack stuff zclock_log("watch_port started!"); msgpack_zone mempool; msgpack_zone_init(&mempool, 2048); // TODO char * user_id = "17"; // TODO get broker in somehow char * broker = "tcp://au.ninjablocks.com:5773"; mdcli_t * client = mdcli_new(broker, 1); //VERBOSE triggermemory_t trigger_memory; msgpack_object * addins_obj = parse_msgpack(&mempool, c->addins); if(!parse_addins(addins_obj, &trigger_memory)) { //bad message zclock_log("bad trigger definition"); msgpack_object_print(stdout, *addins_obj); send_sync("bad trigger", control); return; } zclock_log("Creating trigger: target %s, rule_id %s, name %s", c->target_worker, c->rule_id, c->trigger_name); dump_trigger(&trigger_memory); triggerfunction trigger_func; if(!(trigger_func = find_trigger(c->channel, c->trigger_name))) { zclock_log("no trigger found for channel %s, trigger %s", c->channel, c->trigger_name); send_sync("no such trigger", control); return; } void * line = zsocket_new(context, ZMQ_SUB); // what line are we on? // this comes in the addins. char * linesocket = to_linesocket(trigger_memory.line_id); zclock_log("trigger is connecting to listen on %s", linesocket); zsocket_connect(line, linesocket); zsockopt_set_unsubscribe(line, ""); zsockopt_set_subscribe(line, "VALUE"); recv_sync("ping", control); send_sync("pong", control); zmq_pollitem_t items [] = { { line, 0, ZMQ_POLLIN, 0 }, { control, 0, ZMQ_POLLIN, 0 } }; while(1) { // listen on control and line zmq_poll (items, 2, -1); if (items[1].revents & ZMQ_POLLIN) { zclock_log("rule %s received message on control pipe", c->rule_id); // control message // really only expecting DESTROY zmsg_t * msg = zmsg_recv(control); char * str = zmsg_popstr(msg); zmsg_destroy(&msg); if (strcmp("Destroy", str) == 0) { zclock_log("rule %s will quit on request", c->rule_id); free(str); send_sync("ok", control); zclock_log("rule %s quitting on request", c->rule_id); break; } else { zclock_log("unexpected command %s for rule %s", str, c->rule_id); free(str); send_sync("ok", control); } } if (items[0].revents & ZMQ_POLLIN) { // serial update zmsg_t * msg = zmsg_recv(line); zframe_t * cmd = zmsg_pop(msg); if(zframe_streq(cmd, "CHANNEL_CHANGE")) { // TODO // must have been dormant to have gotten this char * new_channel = zmsg_popstr(msg); if(strcmp(c->channel, new_channel) == 0) { // oh, happy day! We're relevant again. // reactivate and start looking at reset levels. zclock_log("line %d: changed channel from %s to %s: trigger coming back to life", trigger_memory.line_id, c->channel, new_channel); zsockopt_set_subscribe(line, "VALUE"); zsockopt_set_unsubscribe(line, "CHANNEL_CHANGE"); } free(new_channel); } else if (zframe_streq(cmd, "VALUE")) { zframe_t * vframe = zmsg_pop(msg); int value; memcpy(&value, zframe_data(vframe), sizeof(int)); char * update_channel = zmsg_popstr(msg); if(strcmp(c->channel, update_channel) != 0) { // channel changed, go dormant // this is legit according to my tests at // https://gist.github.com/2042350 zclock_log("line %d: changed channel from %s to %s: trigger going dormant", trigger_memory.line_id, c->channel, update_channel); zsockopt_set_subscribe(line, "CHANNEL_CHANGE"); zsockopt_set_unsubscribe(line, "VALUE"); } else if(trigger_func(&trigger_memory, value)) { send_trigger(client, c->target_worker, c->rule_id, value, user_id); } free(update_channel); } else { // shouldn't ever happen. zclock_log("shouldn't have received command %s\n", zframe_strdup(cmd)); } zmsg_destroy(&msg); zframe_destroy(&cmd); } } msgpack_zone_destroy(&mempool); }