mirror of
https://github.com/samba-team/samba.git
synced 2025-07-28 11:42:03 +03:00
Added new message_send_pid() code that uses tdb append to reduce locking
contention on the messaging tdb. Jeremy.
This commit is contained in:
@ -176,8 +176,10 @@ BOOL message_send_pid(pid_t pid, int msg_type, const void *buf, size_t len,
|
|||||||
{
|
{
|
||||||
TDB_DATA kbuf;
|
TDB_DATA kbuf;
|
||||||
TDB_DATA dbuf;
|
TDB_DATA dbuf;
|
||||||
|
TDB_DATA old_dbuf;
|
||||||
struct message_rec rec;
|
struct message_rec rec;
|
||||||
void *p;
|
char *ptr;
|
||||||
|
struct message_rec prec;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Doing kill with a non-positive pid causes messages to be
|
* Doing kill with a non-positive pid causes messages to be
|
||||||
@ -194,78 +196,77 @@ BOOL message_send_pid(pid_t pid, int msg_type, const void *buf, size_t len,
|
|||||||
|
|
||||||
kbuf = message_key_pid(pid);
|
kbuf = message_key_pid(pid);
|
||||||
|
|
||||||
/* lock the record for the destination */
|
dbuf.dptr = (void *)malloc(len + sizeof(rec));
|
||||||
tdb_chainlock(tdb, kbuf);
|
if (!dbuf.dptr)
|
||||||
|
return False;
|
||||||
|
|
||||||
dbuf = tdb_fetch(tdb, kbuf);
|
memcpy(dbuf.dptr, &rec, sizeof(rec));
|
||||||
|
if (len > 0)
|
||||||
|
memcpy((void *)((char*)dbuf.dptr+sizeof(rec)), buf, len);
|
||||||
|
|
||||||
if (!dbuf.dptr) {
|
dbuf.dsize = len + sizeof(rec);
|
||||||
/* its a new record */
|
|
||||||
p = (void *)malloc(len + sizeof(rec));
|
|
||||||
if (!p)
|
|
||||||
goto failed;
|
|
||||||
|
|
||||||
memcpy(p, &rec, sizeof(rec));
|
if (duplicates_allowed) {
|
||||||
if (len > 0)
|
|
||||||
memcpy((void *)((char*)p+sizeof(rec)), buf, len);
|
|
||||||
|
|
||||||
dbuf.dptr = p;
|
/* If duplicates are allowed we can just append the message and return. */
|
||||||
dbuf.dsize = len + sizeof(rec);
|
|
||||||
tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
|
/* lock the record for the destination */
|
||||||
SAFE_FREE(p);
|
tdb_chainlock(tdb, kbuf);
|
||||||
goto ok;
|
tdb_append(tdb, kbuf, dbuf);
|
||||||
|
tdb_chainunlock(tdb, kbuf);
|
||||||
|
|
||||||
|
SAFE_FREE(dbuf.dptr);
|
||||||
|
errno = 0; /* paranoia */
|
||||||
|
return message_notify(pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!duplicates_allowed) {
|
/* lock the record for the destination */
|
||||||
char *ptr;
|
tdb_chainlock(tdb, kbuf);
|
||||||
struct message_rec prec;
|
old_dbuf = tdb_fetch(tdb, kbuf);
|
||||||
|
|
||||||
for(ptr = (char *)dbuf.dptr; ptr < dbuf.dptr + dbuf.dsize; ) {
|
|
||||||
/*
|
|
||||||
* 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 (!old_dbuf.dptr) {
|
||||||
if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) {
|
/* its a new record */
|
||||||
DEBUG(10,("message_send_pid: discarding duplicate message.\n"));
|
|
||||||
SAFE_FREE(dbuf.dptr);
|
tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
|
||||||
tdb_chainunlock(tdb, kbuf);
|
tdb_chainunlock(tdb, kbuf);
|
||||||
return True;
|
|
||||||
}
|
SAFE_FREE(dbuf.dptr);
|
||||||
|
errno = 0; /* paranoia */
|
||||||
|
return message_notify(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not a new record. Check for duplicates. */
|
||||||
|
|
||||||
|
for(ptr = (char *)old_dbuf.dptr; ptr < old_dbuf.dptr + old_dbuf.dsize; ) {
|
||||||
|
/*
|
||||||
|
* 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), buf, len))) {
|
||||||
|
tdb_chainunlock(tdb, kbuf);
|
||||||
|
DEBUG(10,("message_send_pid: discarding duplicate message.\n"));
|
||||||
|
SAFE_FREE(dbuf.dptr);
|
||||||
|
SAFE_FREE(old_dbuf.dptr);
|
||||||
|
return True;
|
||||||
}
|
}
|
||||||
memcpy(&prec, ptr, sizeof(prec));
|
|
||||||
ptr += sizeof(rec) + prec.len;
|
|
||||||
}
|
}
|
||||||
|
memcpy(&prec, ptr, sizeof(prec));
|
||||||
|
ptr += sizeof(rec) + prec.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we're adding to an existing entry */
|
/* we're adding to an existing entry */
|
||||||
p = (void *)malloc(dbuf.dsize + len + sizeof(rec));
|
|
||||||
if (!p)
|
|
||||||
goto failed;
|
|
||||||
|
|
||||||
memcpy(p, dbuf.dptr, dbuf.dsize);
|
tdb_append(tdb, kbuf, dbuf);
|
||||||
memcpy((void *)((char*)p+dbuf.dsize), &rec, sizeof(rec));
|
|
||||||
if (len > 0)
|
|
||||||
memcpy((void *)((char*)p+dbuf.dsize+sizeof(rec)), buf, len);
|
|
||||||
|
|
||||||
SAFE_FREE(dbuf.dptr);
|
|
||||||
dbuf.dptr = p;
|
|
||||||
dbuf.dsize += len + sizeof(rec);
|
|
||||||
tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
|
|
||||||
SAFE_FREE(dbuf.dptr);
|
|
||||||
|
|
||||||
ok:
|
|
||||||
tdb_chainunlock(tdb, kbuf);
|
tdb_chainunlock(tdb, kbuf);
|
||||||
|
|
||||||
|
SAFE_FREE(old_dbuf.dptr);
|
||||||
|
SAFE_FREE(dbuf.dptr);
|
||||||
|
|
||||||
errno = 0; /* paranoia */
|
errno = 0; /* paranoia */
|
||||||
return message_notify(pid);
|
return message_notify(pid);
|
||||||
|
|
||||||
failed:
|
|
||||||
tdb_chainunlock(tdb, kbuf);
|
|
||||||
SAFE_FREE(dbuf.dptr);
|
|
||||||
errno = 0; /* paranoia */
|
|
||||||
return False;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
Reference in New Issue
Block a user