MASKTEST_OBJ = utils/masktest.o $(LIBSMB_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ)
+MSGTEST_OBJ = utils/msgtest.o $(LIBSMB_OBJ) $(PARAM_OBJ) \
+ $(UBIQX_OBJ) $(LIB_OBJ)
+
LOCKTEST_OBJ = utils/locktest.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(LIB_OBJ)
masktest : CHECK bin/masktest
+msgtest : CHECK bin/msgtest
+
locktest : CHECK bin/locktest
locktest2 : CHECK bin/locktest2
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(LIBS)
+bin/msgtest: $(MSGTEST_OBJ) bin/.dummy
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(LIBS)
+
bin/locktest: $(LOCKTEST_OBJ) bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(LIBS)
void ping_message(int msg_type, pid_t src, void *buf, size_t len);
void debuglevel_message(int msg_type, pid_t src, void *buf, size_t len);
BOOL message_init(void);
-BOOL message_send_pid(pid_t pid, int msg_type, void *buf, size_t len);
+BOOL message_send_pid(pid_t pid, int msg_type, void *buf, size_t len, BOOL duplicates_allowed);
void message_dispatch(void);
void message_register(int msg_type,
void (*fn)(int msg_type, pid_t pid, void *buf, size_t len));
void message_deregister(int msg_type);
-BOOL message_send_all(int msg_type, void *buf, size_t len);
+BOOL message_send_all(int msg_type, void *buf, size_t len, BOOL duplicates_allowed);
/*The following definitions come from lib/ms_fnmatch.c */
****************************************************************************/
void debug_message_send(pid_t pid, int level)
{
- message_send_pid(pid, MSG_DEBUG, &level, sizeof(int));
+ message_send_pid(pid, MSG_DEBUG, &level, sizeof(int), False);
}
void ping_message(int msg_type, pid_t src, void *buf, size_t len)
{
DEBUG(1,("INFO: Received PING message from PID %d\n",src));
- message_send_pid(src, MSG_PONG, buf, len);
+ message_send_pid(src, MSG_PONG, buf, len, True);
}
/****************************************************************************
DEBUG(1,("INFO: Received REQ_DEBUGLEVEL message from PID %d\n",src));
level = DEBUGLEVEL;
- message_send_pid(src, MSG_DEBUGLEVEL, &level, sizeof(int));
+ message_send_pid(src, MSG_DEBUGLEVEL, &level, sizeof(int), True);
}
/****************************************************************************
/****************************************************************************
send a message to a particular pid
****************************************************************************/
-BOOL message_send_pid(pid_t pid, int msg_type, void *buf, size_t len)
+BOOL message_send_pid(pid_t pid, int msg_type, void *buf, size_t len, BOOL duplicates_allowed)
{
TDB_DATA kbuf;
TDB_DATA dbuf;
struct message_rec rec;
void *p;
+ /*
+ * Do an early check for process exists - saves adding into a tdb
+ * and deleting again if the target is not present. JRA.
+ */
+
+ if (kill(pid, 0) == -1) {
+ DEBUG(2,("message_send_pid: pid %d doesn't exist\n", (int)pid));
+ return False;
+ }
+
rec.msg_version = MESSAGE_VERSION;
rec.msg_type = msg_type;
rec.dest = pid;
goto ok;
}
+ if (!duplicates_allowed) {
+ char *ptr;
+ struct message_rec *prec;
+
+ for(ptr = (char *)dbuf.dptr, prec = (struct message_rec *)ptr; ptr < dbuf.dptr + dbuf.dsize;
+ ptr += (sizeof(rec) + prec->len), prec = (struct message_rec *)ptr) {
+
+ /*
+ * First check if the message header matches, then, if it's a non-zero
+ * sized message, check if the data matches. If so it's a duplicate and
+ * we can discard it. JRA.
+ */
+
+ if (!memcmp(ptr, &rec, sizeof(rec))) {
+ if (!len || (len && !memcmp( ptr + sizeof(rec), (char *)buf, len))) {
+ DEBUG(10,("message_send_pid: discarding duplicate message.\n"));
+ free(dbuf.dptr);
+ tdb_unlockchain(tdb, kbuf);
+ return True;
+ }
+ }
+ }
+ }
+
/* we're adding to an existing entry */
p = (void *)malloc(dbuf.dsize + len + sizeof(rec));
if (!p) goto failed;
int msg_type;
void *buf;
size_t len;
+ BOOL duplicates;
} msg_all;
/****************************************************************************
memcpy(&crec, dbuf.dptr, sizeof(crec));
if (crec.cnum == -1) return 0;
- message_send_pid(crec.pid, msg_all.msg_type, msg_all.buf, msg_all.len);
+ message_send_pid(crec.pid, msg_all.msg_type, msg_all.buf, msg_all.len, msg_all.duplicates);
return 0;
}
It isn't very efficient, but should be OK for the sorts of applications that
use it. When we need efficient broadcast we can add it.
****************************************************************************/
-BOOL message_send_all(int msg_type, void *buf, size_t len)
+BOOL message_send_all(int msg_type, void *buf, size_t len, BOOL duplicates_allowed)
{
TDB_CONTEXT *the_tdb;
msg_all.msg_type = msg_type;
msg_all.buf = buf;
msg_all.len = len;
+ msg_all.duplicates = duplicates_allowed;
tdb_traverse(the_tdb, traverse_fn, NULL);
tdb_close(the_tdb);
printer_name = PRINTERNAME(snum);
- message_send_all(MSG_PRINTER_NOTIFY, printer_name,
- strlen(printer_name) + 1);
+ message_send_all(MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
return !print_job_exists(jobid);
}
printer_name = PRINTERNAME(snum);
- message_send_all(MSG_PRINTER_NOTIFY, printer_name,
- strlen(printer_name) + 1);
+ message_send_all(MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
/* how do we tell if this succeeded? */
printer_name = PRINTERNAME(snum);
- message_send_all(MSG_PRINTER_NOTIFY, printer_name,
- strlen(printer_name) + 1);
+ message_send_all(MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
return True;
}
printer_name = PRINTERNAME(snum);
- message_send_all(MSG_PRINTER_NOTIFY, printer_name,
- strlen(printer_name) + 1);
+ message_send_all(MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
return True;
}
printer_name = PRINTERNAME(snum);
- message_send_all(MSG_PRINTER_NOTIFY, printer_name,
- strlen(printer_name) + 1);
+ message_send_all(MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
return True;
}
printer_name = PRINTERNAME(snum);
- message_send_all(MSG_PRINTER_NOTIFY, printer_name,
- strlen(printer_name) + 1);
+ message_send_all(MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
return True;
}
printer_name = PRINTERNAME(snum);
- message_send_all(MSG_PRINTER_NOTIFY, printer_name,
- strlen(printer_name) + 1);
+ message_send_all(MSG_PRINTER_NOTIFY, printer_name, strlen(printer_name) + 1, False);
return True;
}
level = 0;
#endif
DEBUG(1,("INFO: Received REQ_PROFILELEVEL message from PID %d\n",src));
- message_send_pid(src, MSG_PROFILELEVEL, &level, sizeof(int));
+ message_send_pid(src, MSG_PROFILELEVEL, &level, sizeof(int), True);
}
/*******************************************************************
/*srv_spoolss_receive_message(printer);*/
DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
- message_send_all(MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1); /* Null terminate... */
+ message_send_all(MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
return True;
}
pong_count++;
}
-
int main(int argc, char *argv[])
{
pid_t pid;
int i, n;
static pstring servicesf = CONFIGFILE;
+ char buf[12];
TimeInit();
setup_logging(argv[0],True);
message_init();
+ if (argc != 3) {
+ fprintf(stderr, "%s: Usage - %s pid count\n", argv[0], argv[0]);
+ exit(1);
+ }
+
pid = atoi(argv[1]);
n = atoi(argv[2]);
message_register(MSG_PONG, pong_message);
for (i=0;i<n;i++) {
- message_send_pid(pid, MSG_PING, NULL, 0);
+ message_send_pid(pid, MSG_PING, NULL, 0, True);
}
while (pong_count < i) {
msleep(1);
}
+ /* Now test that the duplicate filtering code works. */
+ pong_count = 0;
+
+ safe_strcpy(buf, "1234567890", sizeof(buf)-1);
+
+ for (i=0;i<n;i++) {
+ message_send_pid(getpid(), MSG_PING, NULL, 0, False);
+ message_send_pid(getpid(), MSG_PING, buf, 11, False);
+ }
+
+ for (i=0;i<n;i++) {
+ message_dispatch();
+ msleep(1);
+ }
+
+ if (pong_count != 2) {
+ fprintf(stderr, "Duplicate filter failed (%d).\n", pong_count);
+ exit(1);
+ }
+
return (0);
}
/****************************************************************************
send a message to a named destination
****************************************************************************/
-static BOOL send_message(char *dest, int msg_type, void *buf, int len)
+static BOOL send_message(char *dest, int msg_type, void *buf, int len, BOOL duplicates)
{
pid_t pid;
/* "smbd" is the only broadcast operation */
if (strequal(dest,"smbd")) {
- return message_send_all(msg_type, buf, len);
+ return message_send_all(msg_type, buf, len, duplicates);
} else if (strequal(dest,"nmbd")) {
pid = pidfile_pid(dest);
if (pid == 0) {
}
}
- return message_send_pid(pid, msg_type, buf, len);
+ return message_send_pid(pid, msg_type, buf, len, duplicates);
}
/****************************************************************************
return(False);
}
v = atoi(params);
- send_message(dest, MSG_DEBUG, &v, sizeof(int));
+ send_message(dest, MSG_DEBUG, &v, sizeof(int), False);
break;
case MSG_PROFILE:
"MSG_PROFILE parameter must be off, count, on, or flush\n");
return(False);
}
- send_message(dest, MSG_PROFILE, &v, sizeof(int));
+ send_message(dest, MSG_PROFILE, &v, sizeof(int), False);
break;
case MSG_FORCE_ELECTION:
fprintf(stderr,"force-election can only be sent to nmbd\n");
return(False);
}
- send_message(dest, MSG_FORCE_ELECTION, NULL, 0);
+ send_message(dest, MSG_FORCE_ELECTION, NULL, 0, False);
break;
case MSG_REQ_PROFILELEVEL:
profilelevel_registered = True;
}
got_level = False;
- retval = send_message(dest, MSG_REQ_PROFILELEVEL, NULL, 0);
+ retval = send_message(dest, MSG_REQ_PROFILELEVEL, NULL, 0, True);
if (retval) {
timeout_start = time(NULL);
while (!got_level) {
debuglevel_registered = True;
}
got_level = False;
- retval = send_message(dest, MSG_REQ_DEBUGLEVEL, NULL, 0);
+ retval = send_message(dest, MSG_REQ_DEBUGLEVEL, NULL, 0, True);
if (retval) {
timeout_start = time(NULL);
while (!got_level) {
return (False);
}
retval = send_message(dest, MSG_PRINTER_NOTIFY, params,
- strlen(params) + 1);
+ strlen(params) + 1, False);
break;
case MSG_PING:
n = atoi(params);
pong_count = 0;
for (i=0;i<n;i++) {
- retval = send_message(dest, MSG_PING, NULL, 0);
+ retval = send_message(dest, MSG_PING, NULL, 0, True);
if (retval == False) break;
}
if (retval) {