This is called by the Redis internals every time we want to fire an * event that can be interceppted by some module. The pointer 'data' is useful * in order to populate the event-specific structure when needed, in order * to return the structure with more information to the callback. * * 'eid' and 'subid' are just the main event ID and the sub event associated * with the event, depending on
| 8455 | * 'eid' and 'subid' are just the main event ID and the sub event associated |
| 8456 | * with the event, depending on what exactly happened. */ |
| 8457 | void moduleFireServerEvent(uint64_t eid, int subid, void *data) { |
| 8458 | /* Fast path to return ASAP if there is nothing to do, avoiding to |
| 8459 | * setup the iterator and so forth: we want this call to be extremely |
| 8460 | * cheap if there are no registered modules. */ |
| 8461 | if (listLength(RedisModule_EventListeners) == 0) return; |
| 8462 | |
| 8463 | aeAcquireLock(); |
| 8464 | |
| 8465 | int real_client_used = 0; |
| 8466 | listIter li; |
| 8467 | listNode *ln; |
| 8468 | listRewind(RedisModule_EventListeners,&li); |
| 8469 | while((ln = listNext(&li))) { |
| 8470 | RedisModuleEventListener *el = (RedisModuleEventListener*)ln->value; |
| 8471 | if (el->event.id == eid) { |
| 8472 | RedisModuleCtx ctx = REDISMODULE_CTX_INIT; |
| 8473 | ctx.module = el->module; |
| 8474 | |
| 8475 | if (eid == REDISMODULE_EVENT_CLIENT_CHANGE) { |
| 8476 | /* In the case of client changes, we're pushing the real client |
| 8477 | * so the event handler can mutate it if needed. For example, |
| 8478 | * to change its authentication state in a way that does not |
| 8479 | * depend on specific commands executed later. |
| 8480 | */ |
| 8481 | ctx.client = (client *) data; |
| 8482 | real_client_used = 1; |
| 8483 | } else if (ModulesInHooks == 0) { |
| 8484 | ctx.client = moduleFreeContextReusedClient; |
| 8485 | } else { |
| 8486 | ctx.client = createClient(NULL, IDX_EVENT_LOOP_MAIN); |
| 8487 | ctx.client->flags |= CLIENT_MODULE; |
| 8488 | ctx.client->user = NULL; /* Root user. */ |
| 8489 | } |
| 8490 | |
| 8491 | void *moduledata = NULL; |
| 8492 | RedisModuleClientInfoV1 civ1; |
| 8493 | RedisModuleReplicationInfoV1 riv1; |
| 8494 | RedisModuleModuleChangeV1 mcv1; |
| 8495 | /* Start at DB zero by default when calling the handler. It's |
| 8496 | * up to the specific event setup to change it when it makes |
| 8497 | * sense. For instance for FLUSHDB events we select the correct |
| 8498 | * DB automatically. */ |
| 8499 | selectDb(ctx.client, 0); |
| 8500 | |
| 8501 | /* Event specific context and data pointer setup. */ |
| 8502 | if (eid == REDISMODULE_EVENT_CLIENT_CHANGE) { |
| 8503 | modulePopulateClientInfoStructure(&civ1,(client*)data, |
| 8504 | el->event.dataver); |
| 8505 | moduledata = &civ1; |
| 8506 | } else if (eid == REDISMODULE_EVENT_REPLICATION_ROLE_CHANGED) { |
| 8507 | modulePopulateReplicationInfoStructure(&riv1,el->event.dataver); |
| 8508 | moduledata = &riv1; |
| 8509 | } else if (eid == REDISMODULE_EVENT_FLUSHDB) { |
| 8510 | moduledata = data; |
| 8511 | RedisModuleFlushInfoV1 *fi = (RedisModuleFlushInfoV1*)data; |
| 8512 | if (fi->dbnum != -1) |
| 8513 | selectDb(ctx.client, fi->dbnum); |
| 8514 | } else if (eid == REDISMODULE_EVENT_MODULE_CHANGE) { |
no test coverage detected