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); }
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); }
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); }
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 *)# 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 *)# 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 *)# 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(); }
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; }
/* ---------------------------- */ 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; }
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; }
/** * 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; }
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); }
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); }
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; }
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); }
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(); }
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; }
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; }
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; }
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; }
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); }
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(); }
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); }
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; }
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; }
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(); }
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(); }
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; }
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; };
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; }