Beispiel #1
0
int tdb_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval,
				   int timeout)
{
	TDB_DATA key = string_term_tdb_data(keyval);

	return tdb_chainlock_with_timeout(tdb, key, timeout);
}
Beispiel #2
0
static BOOL message_send_pid_internal(struct process_id pid, int msg_type,
				      const void *buf, size_t len,
				      BOOL duplicates_allowed,
				      unsigned int timeout)
{
	TDB_DATA kbuf;
	TDB_DATA dbuf;
	TDB_DATA old_dbuf;
	struct message_rec rec;
	char *ptr;
	struct message_rec prec;

	/* NULL pointer means implicit length zero. */
	if (!buf) {
		SMB_ASSERT(len == 0);
	}

	/*
	 * Doing kill with a non-positive pid causes messages to be
	 * sent to places we don't want.
	 */

	SMB_ASSERT(procid_to_pid(&pid) > 0);

	rec.msg_version = MESSAGE_VERSION;
	rec.msg_type = msg_type;
	rec.dest = pid;
	rec.src = procid_self();
	rec.len = buf ? len : 0;

	kbuf = message_key_pid(pid);

	dbuf.dptr = (void *)SMB_MALLOC(len + sizeof(rec));
	if (!dbuf.dptr)
		return False;

	memcpy(dbuf.dptr, &rec, sizeof(rec));
	if (len > 0 && buf)
		memcpy((void *)((char*)dbuf.dptr+sizeof(rec)), buf, len);

	dbuf.dsize = len + sizeof(rec);

	if (duplicates_allowed) {

		/* If duplicates are allowed we can just append the message and return. */

		/* lock the record for the destination */
		if (timeout) {
			if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) {
				DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout));
				return False;
			}
		} else {
			if (tdb_chainlock(tdb, kbuf) == -1) {
				DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n"));
				return False;
			}
		}	
		tdb_append(tdb, kbuf, dbuf);
		tdb_chainunlock(tdb, kbuf);

		SAFE_FREE(dbuf.dptr);
		errno = 0;                    /* paranoia */
		return message_notify(pid);
	}

	/* lock the record for the destination */
	if (timeout) {
		if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) {
			DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout));
			return False;
		}
	} else {
		if (tdb_chainlock(tdb, kbuf) == -1) {
			DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n"));
			return False;
		}
	}	

	old_dbuf = tdb_fetch(tdb, kbuf);

	if (!old_dbuf.dptr) {
		/* its a new record */

		tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
		tdb_chainunlock(tdb, kbuf);

		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_internal: 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;
	}

	/* we're adding to an existing entry */

	tdb_append(tdb, kbuf, dbuf);
	tdb_chainunlock(tdb, kbuf);

	SAFE_FREE(old_dbuf.dptr);
	SAFE_FREE(dbuf.dptr);

	errno = 0;                    /* paranoia */
	return message_notify(pid);
}