示例#1
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);
}
示例#2
0
文件: brlock.c 项目: jophxy/samba
void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum)
{
	TDB_DATA kbuf, dbuf;
	int count, i, j, dcount=0;
	struct lock_struct *locks;

	kbuf = locking_key(dev,ino);

	dbuf.dptr = NULL;

	tdb_chainlock(tdb, kbuf);
	dbuf = tdb_fetch(tdb, kbuf);

	if (!dbuf.dptr) goto fail;

	/* there are existing locks - remove any for this fnum */
	locks = (struct lock_struct *)dbuf.dptr;
	count = dbuf.dsize / sizeof(*locks);

	for (i=0; i<count; i++) {
		struct lock_struct *lock = &locks[i];

		if (lock->context.tid == tid &&
		    lock->context.pid == pid &&
		    lock->fnum == fnum) {

			/* Send unlock messages to any pending waiters that overlap. */
			for (j=0; j<count; j++) {
				struct lock_struct *pend_lock = &locks[j];

				/* Ignore our own or non-pending locks. */
				if (pend_lock->lock_type != PENDING_LOCK)
					continue;

				if (pend_lock->context.tid == tid &&
				    pend_lock->context.pid == pid &&
				    pend_lock->fnum == fnum)
					continue;

				/* We could send specific lock info here... */
				if (brl_pending_overlap(lock, pend_lock))
					message_send_pid(pend_lock->context.pid,
							MSG_SMB_UNLOCK,
							NULL, 0, True);
			}

			/* found it - delete it */
			if (count > 1 && i < count-1) {
				memmove(&locks[i], &locks[i+1], 
					sizeof(*locks)*((count-1) - i));
			}
			count--;
			i--;
			dcount++;
		}
	}

	if (count == 0) {
		tdb_delete(tdb, kbuf);
	} else if (count < (dbuf.dsize / sizeof(*locks))) {
		dbuf.dsize -= dcount * sizeof(*locks);
		tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
	}

	/* we didn't find it */
 fail:
	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
}
示例#3
0
static void speed_tdb(const char *tlimit)
{
	const char *str = "store test", *str2 = "transaction test";
	unsigned timelimit = tlimit?atoi(tlimit):0;
	double t;
	int ops;
	if (timelimit == 0) timelimit = 5;

	ops = 0;
	printf("Testing store speed for %u seconds\n", timelimit);
	_start_timer();
	do {
		long int r = random();
		TDB_DATA key, dbuf;
		key.dptr = discard_const_p(uint8_t, str);
		key.dsize = strlen((char *)key.dptr);
		dbuf.dptr = (uint8_t *) &r;
		dbuf.dsize = sizeof(r);
		tdb_store(tdb, key, dbuf, TDB_REPLACE);
		t = _end_timer();
		ops++;
	} while (t < timelimit);
	printf("%10.3f ops/sec\n", ops/t);

	ops = 0;
	printf("Testing fetch speed for %u seconds\n", timelimit);
	_start_timer();
	do {
		TDB_DATA key;
		key.dptr = discard_const_p(uint8_t, str);
		key.dsize = strlen((char *)key.dptr);
		tdb_fetch(tdb, key);
		t = _end_timer();
		ops++;
	} while (t < timelimit);
	printf("%10.3f ops/sec\n", ops/t);

	ops = 0;
	printf("Testing transaction speed for %u seconds\n", timelimit);
	_start_timer();
	do {
		long int r = random();
		TDB_DATA key, dbuf;
		key.dptr = discard_const_p(uint8_t, str2);
		key.dsize = strlen((char *)key.dptr);
		dbuf.dptr = (uint8_t *) &r;
		dbuf.dsize = sizeof(r);
		tdb_transaction_start(tdb);
		tdb_store(tdb, key, dbuf, TDB_REPLACE);
		tdb_transaction_commit(tdb);
		t = _end_timer();
		ops++;
	} while (t < timelimit);
	printf("%10.3f ops/sec\n", ops/t);

	ops = 0;
	printf("Testing traverse speed for %u seconds\n", timelimit);
	_start_timer();
	do {
		tdb_traverse(tdb, traverse_fn, NULL);
		t = _end_timer();
		ops++;
	} while (t < timelimit);
	printf("%10.3f ops/sec\n", ops/t);
}
示例#4
0
int main(int argc, char *argv[])
{
	unsigned int i, j;
	int num;
	struct trav_data td;
	TDB_DATA k;
	struct tdb_context *tdb;
	union tdb_attribute seed_attr;
	enum TDB_ERROR ecode;

	int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
			TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
			TDB_NOMMAP|TDB_CONVERT };

	seed_attr.base.attr = TDB_ATTRIBUTE_SEED;
	seed_attr.base.next = &tap_log_attr;
	seed_attr.seed.seed = 6334326220117065685ULL;

	plan_tests(sizeof(flags) / sizeof(flags[0])
		   * (NUM_RECORDS*6 + (NUM_RECORDS-1)*3 + 22) + 1);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		tdb = tdb_open("run-traverse.tdb", flags[i],
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &seed_attr);
		ok1(tdb);
		if (!tdb)
			continue;

		ok1(tdb_firstkey(tdb, &k) == TDB_ERR_NOEXIST);

		/* One entry... */
		k.dptr = (unsigned char *)&num;
		k.dsize = sizeof(num);
		num = 0;
		ok1(tdb_store(tdb, k, k, TDB_INSERT) == 0);
		ok1(tdb_firstkey(tdb, &k) == TDB_SUCCESS);
		ok1(k.dsize == sizeof(num));
		ok1(memcmp(k.dptr, &num, sizeof(num)) == 0);
		ok1(tdb_nextkey(tdb, &k) == TDB_ERR_NOEXIST);

		/* Two entries. */
		k.dptr = (unsigned char *)&num;
		k.dsize = sizeof(num);
		num = 1;
		ok1(tdb_store(tdb, k, k, TDB_INSERT) == 0);
		ok1(tdb_firstkey(tdb, &k) == TDB_SUCCESS);
		ok1(k.dsize == sizeof(num));
		memcpy(&num, k.dptr, sizeof(num));
		ok1(num == 0 || num == 1);
		ok1(tdb_nextkey(tdb, &k) == TDB_SUCCESS);
		ok1(k.dsize == sizeof(j));
		memcpy(&j, k.dptr, sizeof(j));
		ok1(j == 0 || j == 1);
		ok1(j != num);
		ok1(tdb_nextkey(tdb, &k) == TDB_ERR_NOEXIST);

		/* Clean up. */
		k.dptr = (unsigned char *)&num;
		k.dsize = sizeof(num);
		num = 0;
		ok1(tdb_delete(tdb, k) == 0);
		num = 1;
		ok1(tdb_delete(tdb, k) == 0);

		/* Now lots of records. */
		ok1(store_records(tdb));
		td.calls = 0;

		num = tdb_traverse(tdb, trav, &td);
		ok1(num == NUM_RECORDS);
		ok1(td.calls == NUM_RECORDS);

		/* Simple loop should match tdb_traverse */
		for (j = 0, ecode = tdb_firstkey(tdb, &k); j < td.calls; j++) {
			int val;

			ok1(ecode == TDB_SUCCESS);
			ok1(k.dsize == sizeof(val));
			memcpy(&val, k.dptr, k.dsize);
			ok1(td.records[j] == val);
			ecode = tdb_nextkey(tdb, &k);
		}

		/* But arbitrary orderings should work too. */
		for (j = td.calls-1; j > 0; j--) {
			k.dptr = (unsigned char *)&td.records[j-1];
			k.dsize = sizeof(td.records[j-1]);
			k = dup_key(k);
			ok1(tdb_nextkey(tdb, &k) == TDB_SUCCESS);
			ok1(k.dsize == sizeof(td.records[j]));
			ok1(memcmp(k.dptr, &td.records[j], k.dsize) == 0);
			free(k.dptr);
		}

		/* Even delete should work. */
		for (j = 0, ecode = tdb_firstkey(tdb, &k);
		     ecode != TDB_ERR_NOEXIST;
		     j++) {
			ok1(ecode == TDB_SUCCESS);
			ok1(k.dsize == 4);
			ok1(tdb_delete(tdb, k) == 0);
			ecode = tdb_nextkey(tdb, &k);
		}

		diag("delete using first/nextkey gave %u of %u records",
		     j, NUM_RECORDS);
		ok1(j == NUM_RECORDS);
		tdb_close(tdb);
	}

	ok1(tap_log_messages == 0);
	return exit_status();
}
示例#5
0
文件: brlock.c 项目: jophxy/samba
NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
		  uint16 smbpid, pid_t pid, uint16 tid,
		  br_off start, br_off size, 
		  enum brl_type lock_type)
{
	TDB_DATA kbuf, dbuf;
	int count, i;
	struct lock_struct lock, *locks;
	char *tp;
	NTSTATUS status = NT_STATUS_OK;
	static int last_failed = -1;
	static br_off last_failed_start;

	kbuf = locking_key(dev,ino);

	dbuf.dptr = NULL;

#if !ZERO_ZERO
	if (start == 0 && size == 0) {
		DEBUG(0,("client sent 0/0 lock - please report this\n"));
	}
#endif

	tdb_chainlock(tdb, kbuf);
	dbuf = tdb_fetch(tdb, kbuf);

	lock.context.smbpid = smbpid;
	lock.context.pid = pid;
	lock.context.tid = tid;
	lock.start = start;
	lock.size = size;
	lock.fnum = fnum;
	lock.lock_type = lock_type;

	if (dbuf.dptr) {
		/* there are existing locks - make sure they don't conflict */
		locks = (struct lock_struct *)dbuf.dptr;
		count = dbuf.dsize / sizeof(*locks);
		for (i=0; i<count; i++) {
			if (brl_conflict(&locks[i], &lock)) {
				status = NT_STATUS_LOCK_NOT_GRANTED;
				goto fail;
			}
#if ZERO_ZERO
			if (lock.start == 0 && lock.size == 0 && 
			    locks[i].size == 0) {
				break;
			}
#endif
		}
	}

	/* no conflicts - add it to the list of locks */
	tp = Realloc(dbuf.dptr, dbuf.dsize + sizeof(*locks));
	if (!tp) {
		status = NT_STATUS_NO_MEMORY;
		goto fail;
	} else {
		dbuf.dptr = tp;
	}
	memcpy(dbuf.dptr + dbuf.dsize, &lock, sizeof(lock));
	dbuf.dsize += sizeof(lock);

#if ZERO_ZERO
	/* sort the lock list */
	qsort(dbuf.dptr, dbuf.dsize/sizeof(lock), sizeof(lock), lock_compare);
#endif

	tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);

	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return NT_STATUS_OK;

 fail:
	/* this is a nasty hack to try to simulate the lock result cache code in w2k.
	   It isn't completely accurate as I haven't yet worked out the correct
	   semantics (tridge)
	*/
	if (last_failed == fnum &&
	    last_failed_start == start &&
	    NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) {
		status = NT_STATUS_FILE_LOCK_CONFLICT;
	}
	last_failed = fnum;
	last_failed_start = start;

	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return status;
}
示例#6
0
/* ---------------------------- */
struct _cnid_db *cnid_tdb_open(struct cnid_open_args *args)
{
    struct stat               st;
    struct _cnid_db           *cdb;
    struct _cnid_tdb_private *db;
    size_t                    len;
    char                      path[MAXPATHLEN + 1];
    TDB_DATA                  key, data;
    int 		      hash_size = 131071;
    int                       tdb_flags = 0;

    if (!args->dir) {
        /* note: dir and path are not used for in memory db */
        return NULL;
    }

    if ((len = strlen(args->dir)) > (MAXPATHLEN - DBLEN - 1)) {
        LOG(log_error, logtype_default, "tdb_open: Pathname too large: %s", args->dir);
        return NULL;
    }
    
    if ((cdb = cnid_tdb_new(args->dir)) == NULL) {
        LOG(log_error, logtype_default, "tdb_open: Unable to allocate memory for tdb");
        return NULL;
    }
    
    strcpy(path, args->dir);
    if (path[len - 1] != '/') {
        strcat(path, "/");
        len++;
    }
 
    strcpy(path + len, DBHOME);
    if (!(args->flags & CNID_FLAG_MEMORY)) {
        if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~args->mask) < 0)) {
            LOG(log_error, logtype_default, "tdb_open: DBHOME mkdir failed for %s", path);
            goto fail;
        }
    }
    else {
        hash_size = 0;
        tdb_flags = TDB_INTERNAL;
    }
    strcat(path, "/");
 
    db = (struct _cnid_tdb_private *)cdb->_private;

    path[len + DBHOMELEN] = '\0';
    strcat(path, DBCNID);

    db->tdb_cnid = tdb_open(path, hash_size, tdb_flags , O_RDWR | O_CREAT, 0666 & ~args->mask);
    if (!db->tdb_cnid) {
        LOG(log_error, logtype_default, "tdb_open: unable to open tdb", path);
        goto fail;
    }
    /* ------------- */
    db->tdb_didname = db->tdb_cnid;
    db->tdb_devino = db->tdb_cnid;

    /* Check for version.  This way we can update the database if we need
     * to change the format in any way. */
    memset(&key, 0, sizeof(key));
    memset(&data, 0, sizeof(data));
    key.dptr = DBVERSION_KEY;
    key.dsize = DBVERSION_KEYLEN;

    data = tdb_fetch(db->tdb_didname, key);
    if (!data.dptr) {
        u_int32_t version = htonl(DBVERSION);

        data.dptr = (char *)&version;
        data.dsize = sizeof(version);
        if (tdb_store(db->tdb_didname, key, data, TDB_REPLACE)) {
            LOG(log_error, logtype_default, "tdb_open: Error putting new version");
            goto fail;
        }
    }
    else {
        free(data.dptr);
    }
        
    return cdb;

fail:
    free(cdb->_private);
    free(cdb->volpath);
    free(cdb);
    
    return NULL;
}
示例#7
0
文件: undo_io.c 项目: ESOS-Lab/MOST
static errcode_t undo_write_tdb(io_channel channel,
				unsigned long long block, int count)

{
	int size, sz;
	unsigned long long block_num, backing_blk_num;
	errcode_t retval = 0;
	ext2_loff_t offset;
	struct undo_private_data *data;
	TDB_DATA tdb_key, tdb_data;
	unsigned char *read_ptr;
	unsigned long long end_block;

	data = (struct undo_private_data *) channel->private_data;

	if (data->tdb == NULL) {
		/*
		 * Transaction database not initialized
		 */
		return 0;
	}

	if (count == 1)
		size = channel->block_size;
	else {
		if (count < 0)
			size = -count;
		else
			size = count * channel->block_size;
	}
	/*
	 * Data is stored in tdb database as blocks of tdb_data_size size
	 * This helps in efficient lookup further.
	 *
	 * We divide the disk to blocks of tdb_data_size.
	 */
	offset = (block * channel->block_size) + data->offset ;
	block_num = offset / data->tdb_data_size;
	end_block = (offset + size) / data->tdb_data_size;

	tdb_transaction_start(data->tdb);
	while (block_num <= end_block ) {

		tdb_key.dptr = (unsigned char *)&block_num;
		tdb_key.dsize = sizeof(block_num);
		/*
		 * Check if we have the record already
		 */
		if (tdb_exists(data->tdb, tdb_key)) {
			/* Try the next block */
			block_num++;
			continue;
		}
		/*
		 * Read one block using the backing I/O manager
		 * The backing I/O manager block size may be
		 * different from the tdb_data_size.
		 * Also we need to recalcuate the block number with respect
		 * to the backing I/O manager.
		 */
		offset = block_num * data->tdb_data_size;
		backing_blk_num = (offset - data->offset) / channel->block_size;

		count = data->tdb_data_size +
				((offset - data->offset) % channel->block_size);
		retval = ext2fs_get_mem(count, &read_ptr);
		if (retval) {
			tdb_transaction_cancel(data->tdb);
			return retval;
		}

		memset(read_ptr, 0, count);
		actual_size = 0;
		if ((count % channel->block_size) == 0)
			sz = count / channel->block_size;
		else
			sz = -count;
		retval = io_channel_read_blk64(data->real, backing_blk_num,
					     sz, read_ptr);
		if (retval) {
			if (retval != EXT2_ET_SHORT_READ) {
				free(read_ptr);
				tdb_transaction_cancel(data->tdb);
				return retval;
			}
			/*
			 * short read so update the record size
			 * accordingly
			 */
			tdb_data.dsize = actual_size;
		} else {
			tdb_data.dsize = data->tdb_data_size;
		}
		tdb_data.dptr = read_ptr +
				((offset - data->offset) % channel->block_size);
#ifdef DEBUG
		printf("Printing with key %lld data %x and size %d\n",
		       block_num,
		       tdb_data.dptr,
		       tdb_data.dsize);
#endif
		if (!data->tdb_written) {
			data->tdb_written = 1;
			/* Write the blocksize to tdb file */
			retval = write_block_size(data->tdb,
						  data->tdb_data_size);
			if (retval) {
				tdb_transaction_cancel(data->tdb);
				retval = EXT2_ET_TDB_ERR_IO;
				free(read_ptr);
				return retval;
			}
		}
		retval = tdb_store(data->tdb, tdb_key, tdb_data, TDB_INSERT);
		if (retval == -1) {
			/*
			 * TDB_ERR_EXISTS cannot happen because we
			 * have already verified it doesn't exist
			 */
			tdb_transaction_cancel(data->tdb);
			retval = EXT2_ET_TDB_ERR_IO;
			free(read_ptr);
			return retval;
		}
		free(read_ptr);
		/* Next block */
		block_num++;
	}
	tdb_transaction_commit(data->tdb);

	return retval;
}
示例#8
0
/**
 * write a record to a normal database
 *
 * This is the server-variant of the ctdb_ltdb_store function.
 * It contains logic to determine whether a record should be
 * stored or deleted. It also sends SCHEDULE_FOR_DELETION
 * controls to the local ctdb daemon if apporpriate.
 */
static int ctdb_ltdb_store_server(struct ctdb_db_context *ctdb_db,
				  TDB_DATA key,
				  struct ctdb_ltdb_header *header,
				  TDB_DATA data)
{
	struct ctdb_context *ctdb = ctdb_db->ctdb;
	TDB_DATA rec;
	int ret;
	bool seqnum_suppressed = false;
	bool keep = false;
	bool schedule_for_deletion = false;
	bool remove_from_delete_queue = false;
	uint32_t lmaster;

	if (ctdb->flags & CTDB_FLAG_TORTURE) {
		struct ctdb_ltdb_header *h2;
		rec = tdb_fetch(ctdb_db->ltdb->tdb, key);
		h2 = (struct ctdb_ltdb_header *)rec.dptr;
		if (rec.dptr && rec.dsize >= sizeof(h2) && h2->rsn > header->rsn) {
			DEBUG(DEBUG_CRIT,("RSN regression! %llu %llu\n",
				 (unsigned long long)h2->rsn, (unsigned long long)header->rsn));
		}
		if (rec.dptr) free(rec.dptr);
	}

	if (ctdb->vnn_map == NULL) {
		/*
		 * Called from a client: always store the record
		 * Also don't call ctdb_lmaster since it uses the vnn_map!
		 */
		keep = true;
		goto store;
	}

	lmaster = ctdb_lmaster(ctdb_db->ctdb, &key);

	/*
	 * If we migrate an empty record off to another node
	 * and the record has not been migrated with data,
	 * delete the record instead of storing the empty record.
	 */
	if (data.dsize != 0) {
		keep = true;
	} else if (header->flags & CTDB_REC_RO_FLAGS) {
		keep = true;
	} else if (ctdb_db->persistent) {
		keep = true;
	} else if (header->flags & CTDB_REC_FLAG_AUTOMATIC) {
		/*
		 * The record is not created by the client but
		 * automatically by the ctdb_ltdb_fetch logic that
		 * creates a record with an initial header in the
		 * ltdb before trying to migrate the record from
		 * the current lmaster. Keep it instead of trying
		 * to delete the non-existing record...
		 */
		keep = true;
		schedule_for_deletion = true;
	} else if (header->flags & CTDB_REC_FLAG_MIGRATED_WITH_DATA) {
		keep = true;
	} else if (ctdb_db->ctdb->pnn == lmaster) {
		/*
		 * If we are lmaster, then we usually keep the record.
		 * But if we retrieve the dmaster role by a VACUUM_MIGRATE
		 * and the record is empty and has never been migrated
		 * with data, then we should delete it instead of storing it.
		 * This is part of the vacuuming process.
		 *
		 * The reason that we usually need to store even empty records
		 * on the lmaster is that a client operating directly on the
		 * lmaster (== dmaster) expects the local copy of the record to
		 * exist after successful ctdb migrate call. If the record does
		 * not exist, the client goes into a migrate loop and eventually
		 * fails. So storing the empty record makes sure that we do not
		 * need to change the client code.
		 */
		if (!(header->flags & CTDB_REC_FLAG_VACUUM_MIGRATED)) {
			keep = true;
		} else if (ctdb_db->ctdb->pnn != header->dmaster) {
			keep = true;
		}
	} else if (ctdb_db->ctdb->pnn == header->dmaster) {
		keep = true;
	}

	if (keep) {
		if (!ctdb_db->persistent &&
		    (ctdb_db->ctdb->pnn == header->dmaster) &&
		    !(header->flags & CTDB_REC_RO_FLAGS))
		{
			header->rsn++;

			if (data.dsize == 0) {
				schedule_for_deletion = true;
			}
		}
		remove_from_delete_queue = !schedule_for_deletion;
	}

store:
	/*
	 * The VACUUM_MIGRATED flag is only set temporarily for
	 * the above logic when the record was retrieved by a
	 * VACUUM_MIGRATE call and should not be stored in the
	 * database.
	 *
	 * The VACUUM_MIGRATE call is triggered by a vacuum fetch,
	 * and there are two cases in which the corresponding record
	 * is stored in the local database:
	 * 1. The record has been migrated with data in the past
	 *    (the MIGRATED_WITH_DATA record flag is set).
	 * 2. The record has been filled with data again since it
	 *    had been submitted in the VACUUM_FETCH message to the
	 *    lmaster.
	 * For such records it is important to not store the
	 * VACUUM_MIGRATED flag in the database.
	 */
	header->flags &= ~CTDB_REC_FLAG_VACUUM_MIGRATED;

	/*
	 * Similarly, clear the AUTOMATIC flag which should not enter
	 * the local database copy since this would require client
	 * modifications to clear the flag when the client stores
	 * the record.
	 */
	header->flags &= ~CTDB_REC_FLAG_AUTOMATIC;

	rec.dsize = sizeof(*header) + data.dsize;
	rec.dptr = talloc_size(ctdb, rec.dsize);
	CTDB_NO_MEMORY(ctdb, rec.dptr);

	memcpy(rec.dptr, header, sizeof(*header));
	memcpy(rec.dptr + sizeof(*header), data.dptr, data.dsize);

	/* Databases with seqnum updates enabled only get their seqnum
	   changes when/if we modify the data */
	if (ctdb_db->seqnum_update != NULL) {
		TDB_DATA old;
		old = tdb_fetch(ctdb_db->ltdb->tdb, key);

		if ( (old.dsize == rec.dsize)
		&& !memcmp(old.dptr+sizeof(struct ctdb_ltdb_header),
			  rec.dptr+sizeof(struct ctdb_ltdb_header),
			  rec.dsize-sizeof(struct ctdb_ltdb_header)) ) {
			tdb_remove_flags(ctdb_db->ltdb->tdb, TDB_SEQNUM);
			seqnum_suppressed = true;
		}
		if (old.dptr) free(old.dptr);
	}

	DEBUG(DEBUG_DEBUG, (__location__ " db[%s]: %s record: hash[0x%08x]\n",
			    ctdb_db->db_name,
			    keep?"storing":"deleting",
			    ctdb_hash(&key)));

	if (keep) {
		ret = tdb_store(ctdb_db->ltdb->tdb, key, rec, TDB_REPLACE);
	} else {
		ret = tdb_delete(ctdb_db->ltdb->tdb, key);
	}

	if (ret != 0) {
		int lvl = DEBUG_ERR;

		if (keep == false &&
		    tdb_error(ctdb_db->ltdb->tdb) == TDB_ERR_NOEXIST)
		{
			lvl = DEBUG_DEBUG;
		}

		DEBUG(lvl, (__location__ " db[%s]: Failed to %s record: "
			    "%d - %s\n",
			    ctdb_db->db_name,
			    keep?"store":"delete", ret,
			    tdb_errorstr(ctdb_db->ltdb->tdb)));

		schedule_for_deletion = false;
		remove_from_delete_queue = false;
	}
	if (seqnum_suppressed) {
		tdb_add_flags(ctdb_db->ltdb->tdb, TDB_SEQNUM);
	}

	talloc_free(rec.dptr);

	if (schedule_for_deletion) {
		int ret2;
		ret2 = ctdb_local_schedule_for_deletion(ctdb_db, header, key);
		if (ret2 != 0) {
			DEBUG(DEBUG_ERR, (__location__ " ctdb_local_schedule_for_deletion failed.\n"));
		}
	}

	if (remove_from_delete_queue) {
		ctdb_local_remove_from_delete_queue(ctdb_db, header, key);
	}

	return ret;
}
示例#9
0
static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd, int flag)
{
	struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
	TDB_CONTEXT 	*pwd_tdb = NULL;
	TDB_DATA 	key, data;
	uint8		*buf = NULL;
	fstring 	keystr;
	fstring		name;
	BOOL		ret = True;
	uint32		user_rid;

	/* invalidate the existing TDB iterator if it is open */
	
	if (tdb_state->passwd_tdb) {
		tdb_close(tdb_state->passwd_tdb);
		tdb_state->passwd_tdb = NULL;
	}

 	/* open the account TDB passwd*/
	
	pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
	
  	if (!pwd_tdb) {
		DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n", 
			tdb_state->tdbsam_location));
		return False;
	}

	if (!pdb_get_group_rid(newpwd)) {
		DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",
			pdb_get_username(newpwd)));
		ret = False;
		goto done;
	}

	if ( !(user_rid = pdb_get_user_rid(newpwd)) ) {
		DEBUG(0,("tdb_update_sam: SAM_ACCOUNT (%s) with no RID!\n", pdb_get_username(newpwd)));
		ret = False;
		goto done;
	}

	/* copy the SAM_ACCOUNT struct into a BYTE buffer for storage */
	if ((data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1) {
		DEBUG(0,("tdb_update_sam: ERROR - Unable to copy SAM_ACCOUNT info BYTE buffer!\n"));
		ret = False;
		goto done;
	}
	data.dptr = (char *)buf;

	fstrcpy(name, pdb_get_username(newpwd));
	strlower_m(name);
	
	DEBUG(5, ("Storing %saccount %s with RID %d\n", flag == TDB_INSERT ? "(new) " : "", name, user_rid));

  	/* setup the USER index key */
	slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
	key.dptr = keystr;
	key.dsize = strlen(keystr) + 1;

	/* add the account */
	if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
		DEBUG(0, ("Unable to modify passwd TDB!"));
		DEBUGADD(0, (" Error: %s", tdb_errorstr(pwd_tdb)));
		DEBUGADD(0, (" occured while storing the main record (%s)\n", keystr));
		ret = False;
		goto done;
	}
	
	/* setup RID data */
	data.dsize = strlen(name) + 1;
	data.dptr = name;

	/* setup the RID index key */
	slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, user_rid);
	key.dptr = keystr;
	key.dsize = strlen (keystr) + 1;
	
	/* add the reference */
	if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
		DEBUG(0, ("Unable to modify TDB passwd !"));
		DEBUGADD(0, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
		DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
		ret = False;
		goto done;
	}

done:	
	/* cleanup */
	tdb_close (pwd_tdb);
	SAFE_FREE(buf);
	
	return (ret);	
}
示例#10
0
static void test_val(struct tdb_context *tdb, uint64_t val)
{
	uint64_t v;
	struct tdb_data key = { (unsigned char *)&v, sizeof(v) };
	struct tdb_data d, data = { (unsigned char *)&v, sizeof(v) };

	/* Insert an entry, then delete it. */
	v = val;
	/* Delete should fail. */
	ok1(tdb_delete(tdb, key) == TDB_ERR_NOEXIST);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Insert should succeed. */
	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Delete should succeed. */
	ok1(tdb_delete(tdb, key) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Re-add it, then add collision. */
	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
	v = val + 1;
	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Can find both? */
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);
	v = val;
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);

	/* Delete second one. */
	v = val + 1;
	ok1(tdb_delete(tdb, key) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Re-add */
	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Now, try deleting first one. */
	v = val;
	ok1(tdb_delete(tdb, key) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* Can still find second? */
	v = val + 1;
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);

	/* Now, this will be ideally placed. */
	v = val + 2;
	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	/* This will collide with both. */
	v = val;
	ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);

	/* We can still find them all, right? */
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);
	v = val + 1;
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);
	v = val + 2;
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);

	/* And if we delete val + 1, that val + 2 should not move! */
	v = val + 1;
	ok1(tdb_delete(tdb, key) == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);

	v = val;
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);
	v = val + 2;
	ok1(tdb_fetch(tdb, key, &d) == TDB_SUCCESS);
	ok1(d.dsize == data.dsize);
	free(d.dptr);

	/* Delete those two, so we are empty. */
	ok1(tdb_delete(tdb, key) == 0);
	v = val;
	ok1(tdb_delete(tdb, key) == 0);

	ok1(tdb_check(tdb, NULL, NULL) == 0);
}
示例#11
0
static int drivers_import(void)
	{
	TDB_CONTEXT *tdb_drivers;
	char *line = NULL;
	int line_available = 256;
	int linenum = 0;
	char keytext[256];
	TDB_DATA key, data;
	char *lineptr;
	char *field_cversion,				/* OS Print Driver Version */
		*field_drivername,				/* Long Name of Printer Driver */
		*field_os,						/* Long OS Name */
		*field_driverpath,				/* Path the Driver DLL */
		*field_datafile,				/* Path the Configuration DLL */
		*field_configfile,				/* Path the PPD file */
		*field_helpfile,				/* Path to .HLP file */
		*field_monitorname,				/* Port Monitor (NULL for Samba) */
		*field_defaultdatatype,			/* Default Data Type (RAW) */
		*field_dependentfile;
	char **packlist[] = {
		&field_drivername,
		&field_os,
		&field_driverpath,
		&field_datafile,
		&field_configfile,
		&field_helpfile,
		&field_monitorname,
		&field_defaultdatatype,
		NULL};
	const char *architecture;
	char *scratch = NULL;
	int scratch_available = 0;
	int scratch_len;

	/* Open the TDB database that contains NT driver information. */
	if(!(tdb_drivers = tdb_open((char*)tdb_drivers_file, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600)))
		{
		fprintf(stderr, "%s: can't open \"%s\", errno=%d (%s)\n", myname, tdb_drivers_file, errno, strerror(errno));
		return EXIT_INTERNAL;
		}

	while((line = gu_getline(line, &line_available, stdin)))
		{
		linenum++;
		lineptr = line;

		if(!(field_os = gu_strsep(&lineptr, ":"))
				|| !(field_cversion = gu_strsep(&lineptr, ":"))
				|| !(field_drivername = gu_strsep(&lineptr, ":"))
				|| !(field_driverpath = gu_strsep(&lineptr, ":"))
				|| !(field_datafile = gu_strsep(&lineptr, ":"))
				|| !(field_configfile = gu_strsep(&lineptr, ":"))
				|| !(field_helpfile = gu_strsep(&lineptr, ":"))
				|| !(field_monitorname = gu_strsep(&lineptr, ":"))
				|| !(field_defaultdatatype = gu_strsep(&lineptr, ":"))
			)
			{
			fprintf(stderr, "%s: parse error on line %d.\n", myname, linenum);
			break;
			}
				
		if(strcmp(field_os, "Windows NT x86") == 0)
			architecture = "W32X86";
		else if(strcmp(field_os, "Windows 4.0") == 0)
			architecture = "WIN40";
		else
			{
			fprintf(stderr, "Unrecognized OS: %s\n", field_os);
			break;
			}

		/* Create the TDB key.  Note that the Samba code converts this to the Unix
		   codepage but we don't. */
		snprintf(keytext, sizeof(keytext), "DRIVERS/%s/%d/%s", architecture, atoi(field_cversion), field_drivername);

		/* Make sure scratch buffer is big enough. */
		if((line_available + 10) > scratch_available)
			{
			scratch_available = line_available + 10;
			scratch = gu_realloc(scratch, scratch_available, sizeof(char));
			}

		scratch_len = 0;

		/* Copy the little-endian 32 bit integer field. */
		{
		unsigned int val = atoi(field_cversion);
		int x;
		for(x=0; x<4; x++)
			{
			scratch[scratch_len++] = val & 0xFF;
			val >>= 8;
			}
		}

		/* Copy the text fields. */
		{
		int x;
		char **p;
		for(x = 0; (p = packlist[x]); x++)
			{
			int len = strlen(*p) + 1;
			memcpy(&scratch[scratch_len], *p, len);
			scratch_len += len;
			}
		}

		/* Now add the list of other files that must be downloaded. */
		for( ; (field_dependentfile = gu_strsep(&lineptr, ":")); )
			{
			int len = strlen(field_dependentfile) + 1;
			memcpy(&scratch[scratch_len], field_dependentfile, len);
			scratch_len += len;
			}

		key.dptr = keytext;
		key.dsize = strlen(keytext)+1;
		data.dptr = scratch;
		data.dsize = scratch_len;
		
		if(tdb_store(tdb_drivers, key, data, TDB_REPLACE))
			{
			fprintf(stderr, "Failed to insert key \"%s\", %s.\n", keytext, tdb_errorstr(tdb_drivers));
			break;
			}
		}

	tdb_close(tdb_drivers);

	/* If the line buffer hasn't been freed, it means there was an error. */
	if(line)
		{
		gu_free(line);
		return EXIT_INTERNAL;
		}

	return EXIT_OK;
	}
示例#12
0
文件: reg_db.c 项目: AllardJ/Tomato
static BOOL regdb_store_keys_internal( const char *key, REGSUBKEY_CTR *ctr )
{
	TDB_DATA kbuf, dbuf;
	char *buffer;
	int i = 0;
	uint32 len, buflen;
	BOOL ret = True;
	uint32 num_subkeys = regsubkey_ctr_numkeys( ctr );
	pstring keyname;
	
	if ( !key )
		return False;

	pstrcpy( keyname, key );
	normalize_reg_path( keyname );

	/* allocate some initial memory */
		
	if (!(buffer = (char *)SMB_MALLOC(sizeof(pstring)))) {
		return False;
	}
	buflen = sizeof(pstring);
	len = 0;
	
	/* store the number of subkeys */
	
	len += tdb_pack(buffer+len, buflen-len, "d", num_subkeys );
	
	/* pack all the strings */
	
	for (i=0; i<num_subkeys; i++) {
		len += tdb_pack( buffer+len, buflen-len, "f", regsubkey_ctr_specific_key(ctr, i) );
		if ( len > buflen ) {
			/* allocate some extra space */
			if ((buffer = (char *)SMB_REALLOC( buffer, len*2 )) == NULL) {
				DEBUG(0,("regdb_store_keys: Failed to realloc memory of size [%d]\n", len*2));
				ret = False;
				goto done;
			}
			buflen = len*2;
					
			len = tdb_pack( buffer+len, buflen-len, "f", regsubkey_ctr_specific_key(ctr, i) );
		}		
	}
	
	/* finally write out the data */
	
	kbuf.dptr = keyname;
	kbuf.dsize = strlen(keyname)+1;
	dbuf.dptr = buffer;
	dbuf.dsize = len;
	if ( tdb_store( tdb_reg, kbuf, dbuf, TDB_REPLACE ) == -1) {
		ret = False;
		goto done;
	}

done:		
	SAFE_FREE( buffer );
	
	return ret;
}
static void addrec_db(void)
{
	int klen, dlen;
	char *k, *d;
	TDB_DATA key, data;

	klen = 1 + (rand() % KEYLEN);
	dlen = 1 + (rand() % DATALEN);

	k = randbuf(klen);
	d = randbuf(dlen);

	key.dptr = (unsigned char *)k;
	key.dsize = klen+1;

	data.dptr = (unsigned char *)d;
	data.dsize = dlen+1;

#if REOPEN_PROB
	if (in_transaction == 0 && random() % REOPEN_PROB == 0) {
		tdb_reopen_all(0);
		goto next;
	}
#endif

#if TRANSACTION_PROB
	if (in_transaction == 0 &&
	    (always_transaction || random() % TRANSACTION_PROB == 0)) {
		if (tdb_transaction_start(db) != 0) {
			fatal("tdb_transaction_start failed");
		}
		in_transaction++;
		goto next;
	}
	if (in_transaction && random() % TRANSACTION_PROB == 0) {
		if (random() % TRANSACTION_PREPARE_PROB == 0) {
			if (tdb_transaction_prepare_commit(db) != 0) {
				fatal("tdb_transaction_prepare_commit failed");
			}
		}
		if (tdb_transaction_commit(db) != 0) {
			fatal("tdb_transaction_commit failed");
		}
		in_transaction--;
		goto next;
	}
	if (in_transaction && random() % TRANSACTION_PROB == 0) {
		if (tdb_transaction_cancel(db) != 0) {
			fatal("tdb_transaction_cancel failed");
		}
		in_transaction--;
		goto next;
	}
#endif

#if DELETE_PROB
	if (random() % DELETE_PROB == 0) {
		tdb_delete(db, key);
		goto next;
	}
#endif

#if STORE_PROB
	if (random() % STORE_PROB == 0) {
		if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
			fatal("tdb_store failed");
		}
		goto next;
	}
#endif

#if APPEND_PROB
	if (random() % APPEND_PROB == 0) {
		if (tdb_append(db, key, data) != 0) {
			fatal("tdb_append failed");
		}
		goto next;
	}
#endif

#if LOCKSTORE_PROB
	if (random() % LOCKSTORE_PROB == 0) {
		tdb_chainlock(db, key);
		data = tdb_fetch(db, key);
		if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
			fatal("tdb_store failed");
		}
		if (data.dptr) free(data.dptr);
		tdb_chainunlock(db, key);
		goto next;
	} 
#endif

#if TRAVERSE_PROB
	if (random() % TRAVERSE_PROB == 0) {
		tdb_traverse(db, cull_traverse, NULL);
		goto next;
	}
#endif

#if TRAVERSE_READ_PROB
	if (random() % TRAVERSE_READ_PROB == 0) {
		tdb_traverse_read(db, NULL, NULL);
		goto next;
	}
#endif

	data = tdb_fetch(db, key);
	if (data.dptr) free(data.dptr);

next:
	free(k);
	free(d);
}
示例#14
0
int main(int argc, char *argv[])
{
	unsigned int i, extra_msgs;
	struct tdb_context *tdb;
	struct tdb_data key = tdb_mkdata("key", 3);
	struct tdb_data data = tdb_mkdata("data", 4);
	int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
			TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT,
			TDB_VERSION1, TDB_NOMMAP|TDB_VERSION1,
			TDB_CONVERT|TDB_VERSION1,
			TDB_NOMMAP|TDB_CONVERT|TDB_VERSION1 };

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 48);

	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		/* RW -> R0 */
		tdb = tdb_open("run-92-get-set-readonly.tdb", flags[i],
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(tdb);
		ok1(!(tdb_get_flags(tdb) & TDB_RDONLY));

		/* TDB1 complains multiple times. */
		if (flags[i] & TDB_VERSION1) {
			extra_msgs = 1;
		} else {
			extra_msgs = 0;
		}

		ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS);

		tdb_add_flag(tdb, TDB_RDONLY);
		ok1(tdb_get_flags(tdb) & TDB_RDONLY);

		/* Can't store, append, delete. */
		ok1(tdb_store(tdb, key, data, TDB_MODIFY) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 1);
		ok1(tdb_append(tdb, key, data) == TDB_ERR_RDONLY);
		tap_log_messages -= extra_msgs;
		ok1(tap_log_messages == 2);
		ok1(tdb_delete(tdb, key) == TDB_ERR_RDONLY);
		tap_log_messages -= extra_msgs;
		ok1(tap_log_messages == 3);

		/* Can't start a transaction, or any write lock. */
		ok1(tdb_transaction_start(tdb) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 4);
		ok1(tdb_chainlock(tdb, key) == TDB_ERR_RDONLY);
		tap_log_messages -= extra_msgs;
		ok1(tap_log_messages == 5);
		ok1(tdb_lockall(tdb) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 6);
		ok1(tdb_wipe_all(tdb) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 7);

		/* Back to RW. */
		tdb_remove_flag(tdb, TDB_RDONLY);
		ok1(!(tdb_get_flags(tdb) & TDB_RDONLY));

		ok1(tdb_store(tdb, key, data, TDB_MODIFY) == TDB_SUCCESS);
		ok1(tdb_append(tdb, key, data) == TDB_SUCCESS);
		ok1(tdb_delete(tdb, key) == TDB_SUCCESS);

		ok1(tdb_transaction_start(tdb) == TDB_SUCCESS);
		ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_SUCCESS);
		ok1(tdb_transaction_commit(tdb) == TDB_SUCCESS);

		ok1(tdb_chainlock(tdb, key) == TDB_SUCCESS);
		tdb_chainunlock(tdb, key);
		ok1(tdb_lockall(tdb) == TDB_SUCCESS);
		tdb_unlockall(tdb);
		ok1(tdb_wipe_all(tdb) == TDB_SUCCESS);
		ok1(tap_log_messages == 7);

		tdb_close(tdb);

		/* R0 -> RW */
		tdb = tdb_open("run-92-get-set-readonly.tdb", flags[i],
			       O_RDONLY, 0600, &tap_log_attr);
		ok1(tdb);
		ok1(tdb_get_flags(tdb) & TDB_RDONLY);

		/* Can't store, append, delete. */
		ok1(tdb_store(tdb, key, data, TDB_INSERT) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 8);
		ok1(tdb_append(tdb, key, data) == TDB_ERR_RDONLY);
		tap_log_messages -= extra_msgs;
		ok1(tap_log_messages == 9);
		ok1(tdb_delete(tdb, key) == TDB_ERR_RDONLY);
		tap_log_messages -= extra_msgs;
		ok1(tap_log_messages == 10);

		/* Can't start a transaction, or any write lock. */
		ok1(tdb_transaction_start(tdb) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 11);
		ok1(tdb_chainlock(tdb, key) == TDB_ERR_RDONLY);
		tap_log_messages -= extra_msgs;
		ok1(tap_log_messages == 12);
		ok1(tdb_lockall(tdb) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 13);
		ok1(tdb_wipe_all(tdb) == TDB_ERR_RDONLY);
		ok1(tap_log_messages == 14);

		/* Can't remove TDB_RDONLY since we opened with O_RDONLY */
		tdb_remove_flag(tdb, TDB_RDONLY);
		ok1(tap_log_messages == 15);
		ok1(tdb_get_flags(tdb) & TDB_RDONLY);
		tdb_close(tdb);

		ok1(tap_log_messages == 15);
		tap_log_messages = 0;
	}
	return exit_status();
}
示例#15
0
int main(int argc, char *argv[])
{
    struct tdb_context *tdb;
    unsigned int log_count;
    TDB_DATA d;
    union tdb_attribute log_attr, jhash_attr, ohash_attr,
              incompat_hash_attr;

    log_attr.base.attr = TDB_ATTRIBUTE_LOG;
    log_attr.base.next = NULL;
    log_attr.log.fn = log_fn;
    log_attr.log.data = &log_count;

    jhash_attr.base.attr = TDB_ATTRIBUTE_HASH;
    jhash_attr.base.next = &log_attr;
    jhash_attr.hash.fn = jenkins_hashfn;

    ohash_attr.base.attr = TDB_ATTRIBUTE_HASH;
    ohash_attr.base.next = &log_attr;
    ohash_attr.hash.fn = old_hash;

    incompat_hash_attr.base.attr = TDB_ATTRIBUTE_HASH;
    incompat_hash_attr.base.next = &log_attr;
    incompat_hash_attr.hash.fn = tdb1_incompatible_hash;

    plan_tests(28);

    /* Create with default hash. */
    log_count = 0;
    tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1,
                   O_CREAT|O_RDWR|O_TRUNC, 0600, &log_attr);
    ok1(tdb);
    ok1(log_count == 0);
    d.dptr = (void *)"Hello";
    d.dsize = 5;
    ok1(tdb_store(tdb, d, d, TDB_INSERT) == TDB_SUCCESS);
    tdb_close(tdb);

    /* Fail to open with different hash. */
    tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1, O_RDWR, 0,
                   &jhash_attr);
    ok1(!tdb);
    ok1(log_count == 1);

    /* Create with different hash. */
    log_count = 0;
    tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1,
                   O_CREAT|O_RDWR|O_TRUNC, 0600, &jhash_attr);
    ok1(tdb);
    ok1(log_count == 0);
    tdb_close(tdb);

    /* Endian should be no problem. */
    log_count = 0;
    tdb = tdb_open("test/jenkins-le-hash.tdb1", TDB_VERSION1, O_RDWR, 0,
                   &ohash_attr);
    ok1(!tdb);
    ok1(log_count == 1);

    log_count = 0;
    tdb = tdb_open("test/jenkins-be-hash.tdb1", TDB_VERSION1, O_RDWR, 0,
                   &ohash_attr);
    ok1(!tdb);
    ok1(log_count == 1);

    log_count = 0;
    /* Fail to open with old default hash. */
    tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1, O_RDWR, 0,
                   &ohash_attr);
    ok1(!tdb);
    ok1(log_count == 1);

    log_count = 0;
    tdb = tdb_open("test/jenkins-le-hash.tdb1", TDB_VERSION1, O_RDONLY,
                   0, &incompat_hash_attr);
    ok1(tdb);
    ok1(log_count == 0);
    ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
    tdb_close(tdb);

    log_count = 0;
    tdb = tdb_open("test/jenkins-be-hash.tdb1", TDB_VERSION1, O_RDONLY,
                   0, &incompat_hash_attr);
    ok1(tdb);
    ok1(log_count == 0);
    ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
    tdb_close(tdb);

    /* It should open with jenkins hash if we don't specify. */
    log_count = 0;
    tdb = tdb_open("test/jenkins-le-hash.tdb1", TDB_VERSION1, O_RDWR, 0,
                   &log_attr);
    ok1(tdb);
    ok1(log_count == 0);
    ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
    tdb_close(tdb);

    log_count = 0;
    tdb = tdb_open("test/jenkins-be-hash.tdb1", TDB_VERSION1, O_RDWR, 0,
                   &log_attr);
    ok1(tdb);
    ok1(log_count == 0);
    ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
    tdb_close(tdb);

    log_count = 0;
    tdb = tdb_open("run-wronghash-fail.tdb1", TDB_VERSION1, O_RDONLY,
                   0, &log_attr);
    ok1(tdb);
    ok1(log_count == 0);
    ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);
    tdb_close(tdb);


    return exit_status();
}
int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
				uint64_t dev,
				uint64_t ino,
				uint64_t extid,
				const struct smb_share_mode_entry *new_entry,
				const char *sharepath, /* Must be absolute utf8 path. */
				const char *filename) /* Must be relative utf8 path. */
{
	TDB_DATA db_data;
	struct locking_key lk;
	TDB_DATA locking_key =  get_locking_key(&lk, dev, ino, extid);
	int orig_num_share_modes = 0;
	struct locking_data *ld = NULL; /* internal samba db state. */
	struct share_mode_entry *shares = NULL;
	uint8 *new_data_p = NULL;
	size_t new_data_size = 0;
	int err = 0;
	uint32_t name_hash = smb_name_hash(sharepath, filename, &err);

	if (err) {
		return -1;
	}

	db_data = tdb_fetch_compat(db_ctx->smb_tdb, locking_key);
	if (!db_data.dptr) {
		/* We must create the entry. */
		db_data.dptr = (uint8 *)malloc(
			sizeof(struct locking_data) +
			sizeof(struct share_mode_entry) +
			strlen(sharepath) + 1 +
			strlen(filename) + 1);
		if (!db_data.dptr) {
			return -1;
		}
		ld = (struct locking_data *)db_data.dptr;
		memset(ld, '\0', sizeof(struct locking_data));
		ld->u.s.num_share_mode_entries = 1;
		ld->u.s.num_delete_token_entries = 0;
		shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct locking_data));
		create_share_mode_entry(shares, new_entry, name_hash);

		memcpy(db_data.dptr + sizeof(struct locking_data) + sizeof(struct share_mode_entry),
			sharepath,
			strlen(sharepath) + 1);
		memcpy(db_data.dptr + sizeof(struct locking_data) + sizeof(struct share_mode_entry) +
			strlen(sharepath) + 1,
			filename,
			strlen(filename) + 1);

		db_data.dsize = sizeof(struct locking_data) + sizeof(struct share_mode_entry) +
					strlen(sharepath) + 1 +
					strlen(filename) + 1;
		if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_INSERT) != 0) {
			free(db_data.dptr);
			return -1;
		}
		free(db_data.dptr);
		return 0;
	}

	/* Entry exists, we must add a new entry. */
	new_data_p = (uint8 *)malloc(
		db_data.dsize + sizeof(struct share_mode_entry));
	if (!new_data_p) {
		free(db_data.dptr);
		return -1;
	}

	ld = (struct locking_data *)db_data.dptr;
	orig_num_share_modes = ld->u.s.num_share_mode_entries;

	/* Copy the original data. */
	memcpy(new_data_p, db_data.dptr, sizeof(struct locking_data) + (orig_num_share_modes * sizeof(struct share_mode_entry)));

	/* Add in the new share mode */
	shares = (struct share_mode_entry *)(new_data_p + sizeof(struct locking_data) +
			(orig_num_share_modes * sizeof(struct share_mode_entry)));

	create_share_mode_entry(shares, new_entry, name_hash);

	ld = (struct locking_data *)new_data_p;
	ld->u.s.num_share_mode_entries++;

	/* Append the original delete_tokens and filenames. */
	memcpy(new_data_p + sizeof(struct locking_data) + (ld->u.s.num_share_mode_entries * sizeof(struct share_mode_entry)),
		db_data.dptr + sizeof(struct locking_data) + (orig_num_share_modes * sizeof(struct share_mode_entry)),
		db_data.dsize - sizeof(struct locking_data) - (orig_num_share_modes * sizeof(struct share_mode_entry)));

	new_data_size = db_data.dsize + sizeof(struct share_mode_entry);

	free(db_data.dptr);

	db_data.dptr = new_data_p;
	db_data.dsize = new_data_size;

	if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) != 0) {
		free(db_data.dptr);
		return -1;
	}
	free(db_data.dptr);
	return 0;
}
示例#17
0
int main(int argc, char *argv[])
{
	struct tdb_context *tdb;
	TDB_DATA key, orig_data, data;
	uint32_t hashval;
	tdb_off_t rec_ptr;
	struct tdb_record rec;
	int ret;

	plan_tests(24);
	tdb = tdb_open_ex("run-36-file.tdb", 1024, TDB_CLEAR_IF_FIRST,
			  O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL);

	ok1(tdb);
	tdb->methods = &large_io_methods;

	key.dsize = strlen("hi");
	key.dptr = (void *)"hi";
	orig_data.dsize = strlen("world");
	orig_data.dptr = (void *)"world";

	/* Enlarge the file (internally multiplies by 2). */
	ret = tdb_expand(tdb, 1500000000);
#ifdef HAVE_INCOHERENT_MMAP
	/* This can fail due to mmap failure on 32 bit systems. */
	if (ret == -1) {
		/* These should now fail. */
		ok1(tdb_store(tdb, key, orig_data, TDB_INSERT) == -1);
		data = tdb_fetch(tdb, key);
		ok1(data.dptr == NULL);
		ok1(tdb_traverse(tdb, test_traverse, &orig_data) == -1);
		ok1(tdb_delete(tdb, key) == -1);
		ok1(tdb_traverse(tdb, test_traverse, NULL) == -1);
		/* Skip the rest... */
		for (ret = 0; ret < 24 - 6; ret++)
			ok1(1);
		tdb_close(tdb);
		return exit_status();
	}
#endif
	ok1(ret == 0);

	/* Put an entry in, and check it. */
	ok1(tdb_store(tdb, key, orig_data, TDB_INSERT) == 0);

	data = tdb_fetch(tdb, key);
	ok1(data.dsize == strlen("world"));
	ok1(memcmp(data.dptr, "world", strlen("world")) == 0);
	free(data.dptr);

	/* That currently fills at the end, make sure that's true. */
	hashval = tdb->hash_fn(&key);
	rec_ptr = tdb_find_lock_hash(tdb, key, hashval, F_RDLCK, &rec);
	ok1(rec_ptr);
	ok1(rec_ptr > 2U*1024*1024*1024);
	tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK);

	/* Traverse must work. */
	ok1(tdb_traverse(tdb, test_traverse, &orig_data) == 1);

	/* Delete should work. */
	ok1(tdb_delete(tdb, key) == 0);

	ok1(tdb_traverse(tdb, test_traverse, NULL) == 0);

	/* Transactions should work. */
	ok1(tdb_transaction_start(tdb) == 0);
	ok1(tdb_store(tdb, key, orig_data, TDB_INSERT) == 0);

	data = tdb_fetch(tdb, key);
	ok1(data.dsize == strlen("world"));
	ok1(memcmp(data.dptr, "world", strlen("world")) == 0);
	free(data.dptr);
	ok1(tdb_transaction_commit(tdb) == 0);

	ok1(tdb_traverse(tdb, test_traverse, &orig_data) == 1);
	tdb_close(tdb);

	return exit_status();
}
int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
				uint64_t dev,
				uint64_t ino,
				uint64_t extid,
				const struct smb_share_mode_entry *del_entry)
{
	TDB_DATA db_data;
	struct locking_key lk;
	TDB_DATA locking_key =  get_locking_key(&lk, dev, ino, extid);
	int orig_num_share_modes = 0;
	struct locking_data *ld = NULL; /* internal samba db state. */
	struct share_mode_entry *shares = NULL;
	uint8 *new_data_p = NULL;
	size_t remaining_size = 0;
	size_t i, num_share_modes;
	const uint8 *remaining_ptr = NULL;

	db_data = tdb_fetch_compat(db_ctx->smb_tdb, locking_key);
	if (!db_data.dptr) {
		return -1; /* Error - missing entry ! */
	}

	ld = (struct locking_data *)db_data.dptr;
	orig_num_share_modes = ld->u.s.num_share_mode_entries;
	shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct locking_data));

	if (orig_num_share_modes == 1) {
		/* Only one entry - better be ours... */
		if (!share_mode_entry_equal(del_entry, shares)) {
			/* Error ! We can't delete someone else's entry ! */
			free(db_data.dptr);
			return -1;
		}
		/* It's ours - just remove the entire record. */
		free(db_data.dptr);
		return tdb_delete(db_ctx->smb_tdb, locking_key) ? -1 : 0;
	}

	/* More than one - allocate a new record minus the one we'll delete. */
	new_data_p = (uint8 *)malloc(
		db_data.dsize - sizeof(struct share_mode_entry));
	if (!new_data_p) {
		free(db_data.dptr);
		return -1;
	}

	/* Copy the header. */
	memcpy(new_data_p, db_data.dptr, sizeof(struct locking_data));

	num_share_modes = 0;
	for (i = 0; i < orig_num_share_modes; i++) {
		struct share_mode_entry *share = &shares[i];
		struct server_id pid = share->pid;

		/* Check this process really exists. */
		if (kill(sharemodes_procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) {
			continue; /* No longer exists. */
		}

		if (share_mode_entry_equal(del_entry, share)) {
			continue; /* This is our delete taget. */
		}

		memcpy(new_data_p + sizeof(struct locking_data) +
				(num_share_modes * sizeof(struct share_mode_entry)),
			share, sizeof(struct share_mode_entry) );

		num_share_modes++;
	}

	if (num_share_modes == 0) {
		/* None left after pruning. Delete record. */
		free(db_data.dptr);
		free(new_data_p);
		return tdb_delete(db_ctx->smb_tdb, locking_key) ? -1 : 0;
	}

	/* Copy any delete tokens plus the terminating filenames. */
	remaining_ptr = db_data.dptr + sizeof(struct locking_data) + (orig_num_share_modes * sizeof(struct share_mode_entry));
	remaining_size = db_data.dsize - (remaining_ptr - db_data.dptr);

	memcpy(new_data_p + sizeof(struct locking_data) + (num_share_modes * sizeof(struct share_mode_entry)),
		remaining_ptr,
		remaining_size);

	free(db_data.dptr);

	db_data.dptr = new_data_p;

	/* Re-save smaller record. */
	ld = (struct locking_data *)db_data.dptr;
	ld->u.s.num_share_mode_entries = num_share_modes;

	db_data.dsize = sizeof(struct locking_data) + (num_share_modes * sizeof(struct share_mode_entry)) + remaining_size;

	if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) != 0) {
		free(db_data.dptr);
		return -1;
	}
	free(db_data.dptr);
	return 0;
}
示例#19
0
文件: speed.c 项目: atlant2011/samba
int main(int argc, char *argv[])
{
	unsigned int i, j, num = 1000, stage = 0, stopat = -1;
	int flags = TDB_DEFAULT;
	bool transaction = false, summary = false;
	TDB_DATA key, data;
	struct tdb_context *tdb;
	struct timeval start, stop;
	union tdb_attribute seed, log;
	bool do_stats = false;
	enum TDB_ERROR ecode;

	/* Try to keep benchmarks even. */
	seed.base.attr = TDB_ATTRIBUTE_SEED;
	seed.base.next = NULL;
	seed.seed.seed = 0;

	log.base.attr = TDB_ATTRIBUTE_LOG;
	log.base.next = &seed;
	log.log.fn = tdb_log;

	if (argv[1] && strcmp(argv[1], "--internal") == 0) {
		flags = TDB_INTERNAL;
		argc--;
		argv++;
	}
	if (argv[1] && strcmp(argv[1], "--transaction") == 0) {
		transaction = true;
		argc--;
		argv++;
	}
	if (argv[1] && strcmp(argv[1], "--no-sync") == 0) {
		flags |= TDB_NOSYNC;
		argc--;
		argv++;
	}
	if (argv[1] && strcmp(argv[1], "--summary") == 0) {
		summary = true;
		argc--;
		argv++;
	}
	if (argv[1] && strcmp(argv[1], "--stats") == 0) {
		do_stats = true;
		argc--;
		argv++;
	}

	tdb = tdb_open("/tmp/speed.tdb", flags, O_RDWR|O_CREAT|O_TRUNC,
		       0600, &log);
	if (!tdb)
		err(1, "Opening /tmp/speed.tdb");

	key.dptr = (void *)&i;
	key.dsize = sizeof(i);
	data = key;

	if (argv[1]) {
		num = atoi(argv[1]);
		argv++;
		argc--;
	}

	if (argv[1]) {
		stopat = atoi(argv[1]);
		argv++;
		argc--;
	}

	/* Add 1000 records. */
	printf("Adding %u records: ", num); fflush(stdout);
	if (transaction && (ecode = tdb_transaction_start(tdb)))
		errx(1, "starting transaction: %s", tdb_errorstr(ecode));
	gettimeofday(&start, NULL);
	for (i = 0; i < num; i++)
		if ((ecode = tdb_store(tdb, key, data, TDB_INSERT)) != 0)
			errx(1, "Inserting key %u in tdb: %s",
			     i, tdb_errorstr(ecode));
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = tdb_transaction_commit(tdb)))
		errx(1, "committing transaction: %s", tdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());

	if (tdb_check(tdb, NULL, NULL))
		errx(1, "tdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (do_stats)
		dump_and_clear_stats(&tdb, flags, &log);

	if (++stage == stopat)
		exit(0);

	/* Finding 1000 records. */
	printf("Finding %u records: ", num); fflush(stdout);
	if (transaction && (ecode = tdb_transaction_start(tdb)))
		errx(1, "starting transaction: %s", tdb_errorstr(ecode));
	gettimeofday(&start, NULL);
	for (i = 0; i < num; i++) {
		struct tdb_data dbuf;
		if ((ecode = tdb_fetch(tdb, key, &dbuf)) != TDB_SUCCESS
		    || *(int *)dbuf.dptr != i) {
			errx(1, "Fetching key %u in tdb gave %u",
			     i, ecode ? ecode : *(int *)dbuf.dptr);
		}
	}
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = tdb_transaction_commit(tdb)))
		errx(1, "committing transaction: %s", tdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());
	if (tdb_check(tdb, NULL, NULL))
		errx(1, "tdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (do_stats)
		dump_and_clear_stats(&tdb, flags, &log);
	if (++stage == stopat)
		exit(0);

	/* Missing 1000 records. */
	printf("Missing %u records: ", num); fflush(stdout);
	if (transaction && (ecode = tdb_transaction_start(tdb)))
		errx(1, "starting transaction: %s", tdb_errorstr(ecode));
	gettimeofday(&start, NULL);
	for (i = num; i < num*2; i++) {
		struct tdb_data dbuf;
		ecode = tdb_fetch(tdb, key, &dbuf);
		if (ecode != TDB_ERR_NOEXIST)
			errx(1, "Fetching key %u in tdb gave %s",
			     i, tdb_errorstr(ecode));
	}
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = tdb_transaction_commit(tdb)))
		errx(1, "committing transaction: %s", tdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());
	if (tdb_check(tdb, NULL, NULL))
		errx(1, "tdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (do_stats)
		dump_and_clear_stats(&tdb, flags, &log);
	if (++stage == stopat)
		exit(0);

	/* Traverse 1000 records. */
	printf("Traversing %u records: ", num); fflush(stdout);
	if (transaction && (ecode = tdb_transaction_start(tdb)))
		errx(1, "starting transaction: %s", tdb_errorstr(ecode));
	i = 0;
	gettimeofday(&start, NULL);
	if (tdb_traverse(tdb, count_record, &i) != num)
		errx(1, "Traverse returned wrong number of records");
	if (i != (num - 1) * (num / 2))
		errx(1, "Traverse tallied to %u", i);
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = tdb_transaction_commit(tdb)))
		errx(1, "committing transaction: %s", tdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());
	if (tdb_check(tdb, NULL, NULL))
		errx(1, "tdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (do_stats)
		dump_and_clear_stats(&tdb, flags, &log);
	if (++stage == stopat)
		exit(0);

	/* Delete 1000 records (not in order). */
	printf("Deleting %u records: ", num); fflush(stdout);
	if (transaction && (ecode = tdb_transaction_start(tdb)))
		errx(1, "starting transaction: %s", tdb_errorstr(ecode));
	gettimeofday(&start, NULL);
	for (j = 0; j < num; j++) {
		i = (j + 100003) % num;
		if ((ecode = tdb_delete(tdb, key)) != TDB_SUCCESS)
			errx(1, "Deleting key %u in tdb: %s",
			     i, tdb_errorstr(ecode));
	}
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = tdb_transaction_commit(tdb)))
		errx(1, "committing transaction: %s", tdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());
	if (tdb_check(tdb, NULL, NULL))
		errx(1, "tdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (do_stats)
		dump_and_clear_stats(&tdb, flags, &log);
	if (++stage == stopat)
		exit(0);

	/* Re-add 1000 records (not in order). */
	printf("Re-adding %u records: ", num); fflush(stdout);
	if (transaction && (ecode = tdb_transaction_start(tdb)))
		errx(1, "starting transaction: %s", tdb_errorstr(ecode));
	gettimeofday(&start, NULL);
	for (j = 0; j < num; j++) {
		i = (j + 100003) % num;
		if ((ecode = tdb_store(tdb, key, data, TDB_INSERT)) != 0)
			errx(1, "Inserting key %u in tdb: %s",
			     i, tdb_errorstr(ecode));
	}
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = tdb_transaction_commit(tdb)))
		errx(1, "committing transaction: %s", tdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());
	if (tdb_check(tdb, NULL, NULL))
		errx(1, "tdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (do_stats)
		dump_and_clear_stats(&tdb, flags, &log);
	if (++stage == stopat)
		exit(0);

	/* Append 1000 records. */
	if (transaction && (ecode = tdb_transaction_start(tdb)))
		errx(1, "starting transaction: %s", tdb_errorstr(ecode));
	printf("Appending %u records: ", num); fflush(stdout);
	gettimeofday(&start, NULL);
	for (i = 0; i < num; i++)
		if ((ecode = tdb_append(tdb, key, data)) != TDB_SUCCESS)
			errx(1, "Appending key %u in tdb: %s",
			     i, tdb_errorstr(ecode));
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = tdb_transaction_commit(tdb)))
		errx(1, "committing transaction: %s", tdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());
	if (tdb_check(tdb, NULL, NULL))
		errx(1, "tdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (++stage == stopat)
		exit(0);

	/* Churn 1000 records: not in order! */
	if (transaction && (ecode = tdb_transaction_start(tdb)))
		errx(1, "starting transaction: %s", tdb_errorstr(ecode));
	printf("Churning %u records: ", num); fflush(stdout);
	gettimeofday(&start, NULL);
	for (j = 0; j < num; j++) {
		i = (j + 1000019) % num;
		if ((ecode = tdb_delete(tdb, key)) != TDB_SUCCESS)
			errx(1, "Deleting key %u in tdb: %s",
			     i, tdb_errorstr(ecode));
		i += num;
		if ((ecode = tdb_store(tdb, key, data, TDB_INSERT)) != 0)
			errx(1, "Inserting key %u in tdb: %s",
			     i, tdb_errorstr(ecode));
	}
	gettimeofday(&stop, NULL);
	if (transaction && (ecode = tdb_transaction_commit(tdb)))
		errx(1, "committing transaction: %s", tdb_errorstr(ecode));
	printf(" %zu ns (%zu bytes)\n",
	       normalize(&start, &stop, num), file_size());

	if (tdb_check(tdb, NULL, NULL))
		errx(1, "tdb_check failed!");
	if (summary) {
		char *sumstr = NULL;
		tdb_summary(tdb, TDB_SUMMARY_HISTOGRAMS, &sumstr);
		printf("%s\n", sumstr);
		free(sumstr);
	}
	if (do_stats)
		dump_and_clear_stats(&tdb, flags, &log);
	if (++stage == stopat)
		exit(0);

	return 0;
}
示例#20
0
BOOL claim_connection(connection_struct *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags)
{
	struct connections_key key;
	struct connections_data crec;
	TDB_DATA kbuf, dbuf;

	if (!tdb)
		tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, 
			       O_RDWR | O_CREAT, 0644);

	if (!tdb)
		return False;

	/*
	 * Enforce the max connections parameter.
	 */

	if (max_connections > 0) {
		struct count_stat cs;

		cs.mypid = sys_getpid();
		cs.curr_connections = 0;
		cs.name = lp_servicename(SNUM(conn));
		cs.Clear = Clear;

		/*
		 * This has a race condition, but locking the chain before hand is worse
		 * as it leads to deadlock.
		 */

		if (tdb_traverse(tdb, count_fn, &cs) == -1) {
			DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n",
				tdb_errorstr(tdb) ));
			return False;
		}

		if (cs.curr_connections >= max_connections) {
			DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n",
				max_connections, name ));
			return False;
		}
	}

	DEBUG(5,("claiming %s %d\n",name,max_connections));

	make_conn_key(conn, name, &kbuf, &key);

	/* fill in the crec */
	ZERO_STRUCT(crec);
	crec.magic = 0x280267;
	crec.pid = sys_getpid();
	crec.cnum = conn?conn->cnum:-1;
	if (conn) {
		crec.uid = conn->uid;
		crec.gid = conn->gid;
		safe_strcpy(crec.name,
			    lp_servicename(SNUM(conn)),sizeof(crec.name)-1);
	}
	crec.start = time(NULL);
	crec.bcast_msg_flags = msg_flags;
	
	safe_strcpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)-1);
	safe_strcpy(crec.addr,conn?conn->client_address:client_addr(),sizeof(crec.addr)-1);

	dbuf.dptr = (char *)&crec;
	dbuf.dsize = sizeof(crec);

	if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
		DEBUG(0,("claim_connection: tdb_store failed with error %s.\n",
			tdb_errorstr(tdb) ));
		return False;
	}

	return True;
}
示例#21
0
文件: util_tdb.c 项目: gojdic/samba
int tdb_store_bystring(struct tdb_context *tdb, const char *keystr, TDB_DATA data, int flags)
{
	TDB_DATA key = string_term_tdb_data(keystr);
	
	return tdb_store(tdb, key, data, flags);
}
示例#22
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct tdb_context *tdb;
	unsigned char *buffer;
	int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
			TDB_CONVERT, TDB_NOMMAP|TDB_CONVERT };
	struct tdb_data key = tdb_mkdata("key", 3);
	struct tdb_data data;

	buffer = malloc(1000);
	for (i = 0; i < 1000; i++)
		buffer[i] = i;

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 20 + 1);

	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		tdb = tdb_open("run-55-transaction.tdb", flags[i],
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(tdb);
		if (!tdb)
			continue;

		ok1(tdb_transaction_start(tdb) == 0);
		data.dptr = buffer;
		data.dsize = 1000;
		ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
		ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
		ok1(data.dsize == 1000);
		ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
		free(data.dptr);

		/* Cancelling a transaction means no store */
		tdb_transaction_cancel(tdb);
		ok1(tdb->file->allrecord_lock.count == 0
		    && tdb->file->num_lockrecs == 0);
		ok1(tdb_check(tdb, NULL, NULL) == 0);
		ok1(tdb_fetch(tdb, key, &data) == TDB_ERR_NOEXIST);

		/* Commit the transaction. */
		ok1(tdb_transaction_start(tdb) == 0);
		data.dptr = buffer;
		data.dsize = 1000;
		ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
		ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
		ok1(data.dsize == 1000);
		ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
		free(data.dptr);
		ok1(tdb_transaction_commit(tdb) == 0);
		ok1(tdb->file->allrecord_lock.count == 0
		    && tdb->file->num_lockrecs == 0);
		ok1(tdb_check(tdb, NULL, NULL) == 0);
		ok1(tdb_fetch(tdb, key, &data) == TDB_SUCCESS);
		ok1(data.dsize == 1000);
		ok1(memcmp(data.dptr, buffer, data.dsize) == 0);
		free(data.dptr);

		tdb_close(tdb);
	}

	ok1(tap_log_messages == 0);
	free(buffer);
	return exit_status();
}
示例#23
0
void TdbDatabase::storePackage(const Package& p) {
    TdbKeyValue kv;

    // check if this package is already indexed
    kv.setKey(p.name() + "-version");
    kv.setValue(tdb_fetch(m_tdbFile, kv.key()));

    if (kv.value_str() == p.version()) {
        kv.setKey(p.name() + "-release");
        kv.setValue(tdb_fetch(m_tdbFile, kv.key()));
        if (kv.value_str() == p.release()) {
            return;
        }
    }

    // OK, we have something new

    int res = 0;

    kv.setKey(p.name() + "-version");
    kv.setValue(p.version());
    res = tdb_store(m_tdbFile, kv.key(), kv.value(), TDB_MODIFY);
    if (res != 0 ) tdb_store(m_tdbFile, kv.key(), kv.value(), TDB_INSERT);

    kv.setKey(p.name() + "-release");
    kv.setValue(p.release());
    res = tdb_store(m_tdbFile, kv.key(), kv.value(), TDB_MODIFY);
    if (res != 0 ) tdb_store(m_tdbFile, kv.key(), kv.value(), TDB_INSERT);

    kv.setKey(p.name() + "-architecture");
    kv.setValue(p.architecture());
    res = tdb_store(m_tdbFile, kv.key(), kv.value(), TDB_MODIFY);
    if (res != 0 ) tdb_store(m_tdbFile, kv.key(), kv.value(), TDB_INSERT);

    kv.setKey(p.name() + "-compression");
    kv.setValue(p.compression());
    res = tdb_store(m_tdbFile, kv.key(), kv.value(), TDB_MODIFY);
    if (res != 0 ) tdb_store(m_tdbFile, kv.key(), kv.value(), TDB_INSERT);

    string filesString;
    bool first = true;

    for (const auto& elem : p.files()) {

        TdbKeyValue fkv(elem, p.name());

        const int ret = tdb_store(m_tdbFile, fkv.key(), fkv.value(),
                                   TDB_INSERT);

        if (ret != 0) {
            fkv.setValue(tdb_fetch(m_tdbFile, fkv.key()));
            vector<string> others;
            istringstream iss(fkv.value_str());
            copy(istream_iterator<string>(iss), istream_iterator<string>(),
                 back_inserter<vector<string> >(others));
            others.push_back(p.name());

            auto uIter = unique(others.begin(), others.end());
            others.resize(uIter - others.begin());

            string newValue;
            bool isthefirst = true;
            for (auto& other : others) {
                if (isthefirst) {
                    isthefirst = false;
                } else {
                    newValue += " ";
                }
                newValue += other;
            }

            fkv.setValue(newValue);

            tdb_store(m_tdbFile, fkv.key(), fkv.value(), TDB_MODIFY);
        }

        if (first) {
            filesString.append(elem);
            first = false;
        } else {
            filesString.append(" " + elem);
        }
    }

    kv.setKey(p.name() + "-files");
    kv.setValue(filesString);
    res = tdb_store(m_tdbFile, kv.key(), kv.value(), TDB_MODIFY);
    if (res != 0 ) tdb_store(m_tdbFile, kv.key(), kv.value(), TDB_INSERT);
}
示例#24
0
文件: messages.c 项目: jophxy/samba
BOOL message_send_pid(pid_t pid, int msg_type, const void *buf, size_t len,
		      BOOL duplicates_allowed)
{
	TDB_DATA kbuf;
	TDB_DATA dbuf;
	struct message_rec rec;
	void *p;

	rec.msg_version = MESSAGE_VERSION;
	rec.msg_type = msg_type;
	rec.dest = pid;
	rec.src = sys_getpid();
	rec.len = len;

	kbuf = message_key_pid(pid);

	/* lock the record for the destination */
	tdb_chainlock(tdb, kbuf);

	dbuf = tdb_fetch(tdb, kbuf);

	if (!dbuf.dptr) {
		/* its a new record */
		p = (void *)malloc(len + sizeof(rec));
		if (!p) goto failed;

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

		dbuf.dptr = p;
		dbuf.dsize = len + sizeof(rec);
		tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
		SAFE_FREE(p);
		goto ok;
	}

	if (!duplicates_allowed) {
		char *ptr;
		struct message_rec prec;
		
		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 (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) {
					DEBUG(10,("message_send_pid: discarding duplicate message.\n"));
					SAFE_FREE(dbuf.dptr);
					tdb_chainunlock(tdb, kbuf);
					return True;
				}
			}
			memcpy(&prec, ptr, sizeof(prec));
			ptr += sizeof(rec) + prec.len;
		}
	}

	/* 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);
	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);
	errno = 0;                    /* paranoia */
	return message_notify(pid);

 failed:
	tdb_chainunlock(tdb, kbuf);
	errno = 0;                    /* paranoia */
	return False;
}
示例#25
0
文件: brlock.c 项目: jophxy/samba
BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
		uint16 smbpid, pid_t pid, uint16 tid,
		br_off start, br_off size,
		BOOL remove_pending_locks_only)
{
	TDB_DATA kbuf, dbuf;
	int count, i, j;
	struct lock_struct *locks;
	struct lock_context context;

	kbuf = locking_key(dev,ino);

	dbuf.dptr = NULL;

	tdb_chainlock(tdb, kbuf);
	dbuf = tdb_fetch(tdb, kbuf);

	if (!dbuf.dptr) {
		DEBUG(10,("brl_unlock: tdb_fetch failed !\n"));
		goto fail;
	}

	context.smbpid = smbpid;
	context.pid = pid;
	context.tid = tid;

	/* there are existing locks - find a match */
	locks = (struct lock_struct *)dbuf.dptr;
	count = dbuf.dsize / sizeof(*locks);

#if ZERO_ZERO
	for (i=0; i<count; i++) {
		struct lock_struct *lock = &locks[i];

		if (lock->lock_type == WRITE_LOCK &&
		    brl_same_context(&lock->context, &context) &&
		    lock->fnum == fnum &&
		    lock->start == start &&
		    lock->size == size) {
			/* found it - delete it */
			if (count == 1) {
				tdb_delete(tdb, kbuf);
			} else {
				if (i < count-1) {
					memmove(&locks[i], &locks[i+1], 
						sizeof(*locks)*((count-1) - i));
				}
				dbuf.dsize -= sizeof(*locks);
				tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
			}

			SAFE_FREE(dbuf.dptr);
			tdb_chainunlock(tdb, kbuf);
			return True;
		}
	}
#endif

	locks = (struct lock_struct *)dbuf.dptr;
	count = dbuf.dsize / sizeof(*locks);
	for (i=0; i<count; i++) {
		struct lock_struct *lock = &locks[i];

		if (brl_same_context(&lock->context, &context) &&
				lock->fnum == fnum &&
				lock->start == start &&
				lock->size == size) {

			if (remove_pending_locks_only && lock->lock_type != PENDING_LOCK)
				continue;

			if (lock->lock_type != PENDING_LOCK) {
				/* Send unlock messages to any pending waiters that overlap. */
				for (j=0; j<count; j++) {
					struct lock_struct *pend_lock = &locks[j];

					/* Ignore non-pending locks. */
					if (pend_lock->lock_type != PENDING_LOCK)
						continue;

					/* We could send specific lock info here... */
					if (brl_pending_overlap(lock, pend_lock)) {
						DEBUG(10,("brl_unlock: sending unlock message to pid %u\n",
									(unsigned int)pend_lock->context.pid ));

						message_send_pid(pend_lock->context.pid,
								MSG_SMB_UNLOCK,
								NULL, 0, True);
					}
				}
			}

			/* found it - delete it */
			if (count == 1) {
				tdb_delete(tdb, kbuf);
			} else {
				if (i < count-1) {
					memmove(&locks[i], &locks[i+1], 
						sizeof(*locks)*((count-1) - i));
				}
				dbuf.dsize -= sizeof(*locks);
				tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
			}

			SAFE_FREE(dbuf.dptr);
			tdb_chainunlock(tdb, kbuf);
			return True;
		}
	}

	/* we didn't find it */

 fail:
	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return False;
}
示例#26
0
int main(int argc, char *argv[])
{
	struct tdb_context *tdb;
	unsigned int log_count;
	TDB_DATA d;
	struct tdb_logging_context log_ctx = { log_fn, &log_count };

	plan_tests(28);

	/* Create with default hash. */
	log_count = 0;
	tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0,
			  O_CREAT|O_RDWR|O_TRUNC, 0600, &log_ctx, NULL);
	ok1(tdb);
	ok1(log_count == 0);
	d.dptr = (void *)"Hello";
	d.dsize = 5;
	ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0);
	tdb_close(tdb);

	/* Fail to open with different hash. */
	tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, O_RDWR, 0,
			  &log_ctx, tdb_jenkins_hash);
	ok1(!tdb);
	ok1(log_count == 1);

	/* Create with different hash. */
	log_count = 0;
	tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0,
			  O_CREAT|O_RDWR|O_TRUNC,
			  0600, &log_ctx, tdb_jenkins_hash);
	ok1(tdb);
	ok1(log_count == 0);
	tdb_close(tdb);

	/* Endian should be no problem. */
	log_count = 0;
	tdb = tdb_open_ex("test/jenkins-le-hash.tdb", 0, 0, O_RDWR, 0,
			  &log_ctx, tdb_old_hash);
	ok1(!tdb);
	ok1(log_count == 1);

	log_count = 0;
	tdb = tdb_open_ex("test/jenkins-be-hash.tdb", 0, 0, O_RDWR, 0,
			  &log_ctx, tdb_old_hash);
	ok1(!tdb);
	ok1(log_count == 1);

	log_count = 0;
	/* Fail to open with old default hash. */
	tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, O_RDWR, 0,
			  &log_ctx, tdb_old_hash);
	ok1(!tdb);
	ok1(log_count == 1);

	log_count = 0;
	tdb = tdb_open_ex("test/jenkins-le-hash.tdb", 0, 0, O_RDONLY,
			  0, &log_ctx, tdb_jenkins_hash);
	ok1(tdb);
	ok1(log_count == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);

	log_count = 0;
	tdb = tdb_open_ex("test/jenkins-be-hash.tdb", 0, 0, O_RDONLY,
			  0, &log_ctx, tdb_jenkins_hash);
	ok1(tdb);
	ok1(log_count == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);

	/* It should open with jenkins hash if we don't specify. */
	log_count = 0;
	tdb = tdb_open_ex("test/jenkins-le-hash.tdb", 0, 0, O_RDWR, 0,
			  &log_ctx, NULL);
	ok1(tdb);
	ok1(log_count == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);

	log_count = 0;
	tdb = tdb_open_ex("test/jenkins-be-hash.tdb", 0, 0, O_RDWR, 0,
			  &log_ctx, NULL);
	ok1(tdb);
	ok1(log_count == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);

	log_count = 0;
	tdb = tdb_open_ex("run-wronghash-fail.tdb", 0, 0, O_RDONLY,
			  0, &log_ctx, NULL);
	ok1(tdb);
	ok1(log_count == 0);
	ok1(tdb_check(tdb, NULL, NULL) == 0);
	tdb_close(tdb);


	return exit_status();
}
示例#27
0
int main(int argc, char *argv[])
{
	unsigned int i;
	struct tdb_context *tdb;
	int flags[] = { TDB_DEFAULT, TDB_NOMMAP,
			TDB_CONVERT,
			TDB_NOMMAP|TDB_CONVERT };

	if (sizeof(off_t) <= 4) {
		plan_tests(1);
		pass("No 64 bit off_t");
		return exit_status();
	}

	plan_tests(sizeof(flags) / sizeof(flags[0]) * 14);
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
		off_t old_size;
		TDB_DATA k, d;
		struct hash_info h;
		struct tdb_used_record rec;
		tdb_off_t off;

		tdb = tdb_open("run-64-bit-tdb.tdb", flags[i],
			       O_RDWR|O_CREAT|O_TRUNC, 0600, &tap_log_attr);
		ok1(tdb);
		if (!tdb)
			continue;

		old_size = tdb->file->map_size;

		/* This makes a sparse file */
		ok1(ftruncate(tdb->file->fd, 0xFFFFFFF0) == 0);
		ok1(add_free_record(tdb, old_size, 0xFFFFFFF0 - old_size,
				    TDB_LOCK_WAIT, false) == TDB_SUCCESS);

		/* Now add a little record past the 4G barrier. */
		ok1(tdb_expand_file(tdb, 100) == TDB_SUCCESS);
		ok1(add_free_record(tdb, 0xFFFFFFF0, 100, TDB_LOCK_WAIT, false)
		    == TDB_SUCCESS);

		ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);

		/* Test allocation path. */
		k = tdb_mkdata("key", 4);
		d = tdb_mkdata("data", 5);
		ok1(tdb_store(tdb, k, d, TDB_INSERT) == 0);
		ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);

		/* Make sure it put it at end as we expected. */
		off = find_and_lock(tdb, k, F_RDLCK, &h, &rec, NULL);
		ok1(off >= 0xFFFFFFF0);
		tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);

		ok1(tdb_fetch(tdb, k, &d) == 0);
		ok1(d.dsize == 5);
		ok1(strcmp((char *)d.dptr, "data") == 0);
		free(d.dptr);

		ok1(tdb_delete(tdb, k) == 0);
		ok1(tdb_check(tdb, NULL, NULL) == TDB_SUCCESS);

		tdb_close(tdb);
	}

	/* We might get messages about mmap failing, so don't test
	 * tap_log_messages */
	return exit_status();
}
示例#28
0
文件: eventlog.c 项目: gojdic/samba
NTSTATUS evlog_push_record_tdb(TALLOC_CTX *mem_ctx,
			       TDB_CONTEXT *tdb,
			       struct eventlog_Record_tdb *r,
			       uint32_t *record_number)
{
	TDB_DATA kbuf, ebuf;
	DATA_BLOB blob;
	enum ndr_err_code ndr_err;
	int ret;

	if (!r) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!can_write_to_eventlog(tdb, r->size)) {
		return NT_STATUS_EVENTLOG_CANT_START;
	}

	/* need to read the record number and insert it into the entry here */

	/* lock */
	ret = tdb_lock_bystring_with_timeout(tdb, EVT_NEXT_RECORD, 1);
	if (ret == -1) {
		return NT_STATUS_LOCK_NOT_GRANTED;
	}

	/* read */
	r->record_number = tdb_fetch_int32(tdb, EVT_NEXT_RECORD);

	ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, r,
		      (ndr_push_flags_fn_t)ndr_push_eventlog_Record_tdb);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
		return ndr_map_error2ntstatus(ndr_err);
	}

	/* increment the record count */

	kbuf.dsize = sizeof(int32_t);
	kbuf.dptr = (uint8_t *)&r->record_number;

	ebuf.dsize = blob.length;
	ebuf.dptr  = blob.data;

	ret = tdb_store(tdb, kbuf, ebuf, 0);
	if (ret == -1) {
		tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
		return NT_STATUS_EVENTLOG_FILE_CORRUPT;
	}

	ret = tdb_store_int32(tdb, EVT_NEXT_RECORD, r->record_number + 1);
	if (ret == -1) {
		tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);
		return NT_STATUS_EVENTLOG_FILE_CORRUPT;
	}
	tdb_unlock_bystring(tdb, EVT_NEXT_RECORD);

	if (record_number) {
		*record_number = r->record_number;
	}

	return NT_STATUS_OK;
}
示例#29
0
static PyObject *add(BaseTDBResolver *self, PyObject *args, PyObject *kwds) {
  char buff[BUFF_SIZE];
  char buff2[BUFF_SIZE];
  static char *kwlist[] = {"urn", "attribute", "value", "unique", NULL};
  TDB_DATA urn;
  TDB_DATA attribute;
  TDB_DATA key;
  PyObject *value_obj, *value_str;
  TDB_DATA value;
  TDB_DATA offset;
  TDB_DATA_LIST i;
  uint32_t previous_offset=0;
  uint32_t new_offset;
  int unique = 0;

  attribute.dsize = 0;
  urn.dsize = 0;
  if(!PyArg_ParseTupleAndKeywords(args, kwds, "s#s#O|L", kwlist, 
				  &urn.dptr, &urn.dsize, 
				  &attribute.dptr, &attribute.dsize,
				  &value_obj, &unique))
    return NULL;

  // Convert the object to a string
  value_str = PyObject_Str(value_obj);
  if(!value_str) return NULL;

  PyString_AsStringAndSize(value_str, (char **)&value.dptr, 
			   &value.dsize);

  /** If the value is already in the list, we just ignore this
      request.
  */
  if(unique && is_value_present(self, urn, attribute, value, 1)) {
    goto exit;
  };

  // Ok if we get here, the value is not already stored there.
  key.dptr = (unsigned char *)buff;
  key.dsize = calculate_key(self, urn, attribute, buff, BUFF_SIZE, 1);

  // Lock the data_db to synchronise access to the store:
  tdb_lockall(self->data_db);

  offset = tdb_fetch(self->data_db, key);
  if(offset.dptr) {
    previous_offset = to_int(offset);
    free(offset.dptr);
  };

  // Go to the end and write the new record
  new_offset = lseek(self->data_store_fd, 0, SEEK_END);
  i.offset = previous_offset;
  i.length = value.dsize;

  write(self->data_store_fd, &i, sizeof(i));
  write(self->data_store_fd, value.dptr, value.dsize);

  // Now store the offset to this in the tdb database
  value.dptr = (unsigned char *)buff2;
  value.dsize = from_int(new_offset, buff2, BUFF_SIZE);

  tdb_store(self->data_db, key, value, TDB_REPLACE);

  // Done
  tdb_unlockall(self->data_db);

  exit:
  Py_DECREF(value_str);
  Py_RETURN_NONE;
};
示例#30
0
BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type)
{
	TDB_DATA dbuf;
	struct locking_data *data;
	char *p=NULL;
	int size;
	BOOL ret = True;

	/* read in the existing share modes if any */
	dbuf = tdb_fetch(tdb, locking_key_fsp(fsp));
	if (!dbuf.dptr) {
		size_t offset;
		/* we'll need to create a new record */
		pstring fname;

		pstrcpy(fname, fsp->conn->connectpath);
		pstrcat(fname, "/");
		pstrcat(fname, fsp->fsp_name);

		size = sizeof(*data) + sizeof(share_mode_entry) + strlen(fname) + 1;
		p = (char *)malloc(size);
		if (!p)
			return False;
		data = (struct locking_data *)p;
		data->u.num_share_mode_entries = 1;

		DEBUG(10,("set_share_mode: creating entry for file %s. num_share_modes = 1\n",
			fsp->fsp_name ));

		offset = sizeof(*data) + sizeof(share_mode_entry);
		safe_strcpy(p + offset, fname, size - offset - 1);
		fill_share_mode(p + sizeof(*data), fsp, port, op_type);
		dbuf.dptr = p;
		dbuf.dsize = size;
		if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1)
			ret = False;

		print_share_mode_table((struct locking_data *)p);

		SAFE_FREE(p);
		return ret;
	}

	/* we're adding to an existing entry - this is a bit fiddly */
	data = (struct locking_data *)dbuf.dptr;

	data->u.num_share_mode_entries++;

	DEBUG(10,("set_share_mode: adding entry for file %s. new num_share_modes = %d\n",
		fsp->fsp_name, data->u.num_share_mode_entries ));

	size = dbuf.dsize + sizeof(share_mode_entry);
	p = malloc(size);
	if (!p)
		return False;
	memcpy(p, dbuf.dptr, sizeof(*data));
	fill_share_mode(p + sizeof(*data), fsp, port, op_type);
	memcpy(p + sizeof(*data) + sizeof(share_mode_entry), dbuf.dptr + sizeof(*data),
	       dbuf.dsize - sizeof(*data));
	SAFE_FREE(dbuf.dptr);
	dbuf.dptr = p;
	dbuf.dsize = size;
	if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1)
		ret = False;
	print_share_mode_table((struct locking_data *)p);
	SAFE_FREE(p);
	return ret;
}